/*
 * Generates the sine table used for sound emulation
 */

#include <stdio.h>
#include <math.h>

#define MAX_LINE 4

main()
{
	int ampl, i, j;
	int sinetabs[16][256];
	int sktab[1024];
	FILE *f;
	
	/* My sine tables contain 16-bit signed data, with 16 distinct
	   amplitude levels (including zero amplitude). Each sine table
	   is 256 samples long */
	for (ampl = 0; ampl < 16; ampl++)
		for (i = 0; i < 256; i++)
		{
			// Range from 0 to 2pi radians in 256 samples
			// i.e. 128 = M_PI
			/*sinetabs[ampl][i] = (int)((32768.0/(16.0*4.0))*((double)ampl)*
				sin ((((double)i)/128.0)*M_PI));*/
			if (i > 127)
				sinetabs[ampl][i] = (int)((32768.0/(16.0*4.0))*((double)ampl));
			else
				sinetabs[ampl][i] = -(int)((32768.0/(16.0*4.0))*((double)ampl));
		}
	/* Now write out the sine tables */
	f = fopen ("sinetab.h", "w");
	fprintf (f, "/* Computer-generated sine table data - do not edit. */\n"
		"#include \"types.h\"\n"
		"\n"
		"static sword sinetabs[16][256] =\n"
		"{\n");
	for (ampl = 0; ampl < 16; ampl++)
	{
		fprintf (f, "\t{\n\t\t// Amplitude %d\n\t\t", ampl);
		for (i = j = 0; i < 256; i++, j++)
		{
			if (j == MAX_LINE)
			{
				fprintf (f, "\n\t\t");
				j = 0;
			}
			fprintf (f, "0x%04x%s", (sinetabs[ampl][i] >= 0) ?
				sinetabs[ampl][i] : 0x10000+sinetabs[ampl][i],
				(i == 255) ? "" : ((j == (MAX_LINE-1)) ? "," : ", "));
		}
		fprintf (f, "\n\t}%s", (ampl == 15) ? "\n" : ",\n\t\n");
	}
	
	/* Now write the frequency offsets table */
	/* If the "frequency" is f then the formula with
	   n=125000/f, s=22050, w=256 is
	   skip=(w/s)*n=(256/22050)*125000/f roughly 1451.25/f
	   
	   In fact the formula becomes sk=v/f
	   where v=3200000/22050=640000/441
	   
	   See notes/Sound2 for derivation of the formula etc.
	 */
	// NB i cannot be zero [division by zero]
	fprintf (f, "};\n\nstatic word sktab[1024] =\n{\n\t");
	for (i = j = 0; i < 1024; i++)
	{
		fprintf (f, "0x%04x%s", (i) ?
			(int)(256.0*((640000.0/441.0)/((double)i))) & 0xffff : 0,
			(i != 1023) ? ((j++ == 3) ? (j = 0, ",\n\t") : ", ") : "\n");
	}
	
	fprintf (f, "};\n\n/* End of file. */\n");
	fclose (f);
}

/* End of file. */
