#include <stdio.h>
#include "module.h"

/**********************************************************************
The ModPlay function will play the specified module using the current
sound settings. The sound device must have already been initialised.
The sound device should be deinitialised before the program exits.
**********************************************************************/

void ModPlay(moduleinfo * m)
{
	////////////////////////////////////////////////////////////
	// The MOD has default initial conditions set here. The
	// default speed is defined in the MOD specification. The
	// default channel setups prevent noise occuring before the
	// first note.
	////////////////////////////////////////////////////////////
	m->ticksperline = 6;
	m->beatsperminute = 125;
	for (int i = 0; i < m->numchannels; i++)
	{
		m->channelnoise[i] = NULL;
		m->channelreppnt[i] = NULL;
		m->channelreplen[i] = 0;
		m->channellength[i] = 0;
		m->channelperiod[i] = 0;
		m->channelfntune[i] = 0;
		m->channelposition[i] = 0;
		m->channelperiod[i] = 0;
		m->channelsample[i] = 0;
	}

	////////////////////////////////////////////////////////////
	// The frequency of output samples is determined by the
	// Amigas internal video frequency. This unfortunately is
	// different between PAL and NTSC Amigas. I use the PAL
	// 7093789Hz: some MODs require NTSC 7159090Hz.
	//
	// Finetune values are implemented using 16 different base
	// frequencies.  The specifications say that one finetune
	// value equals 1/8th semitone. Seeing as one semitone is
	// the 1/12th root of two you can figure out why Ive used
	// the following formulae.
	////////////////////////////////////////////////////////////
	for (i = 0; i < 8; i++)
		m->periodmodifier[i] = (7093789 + i*52727) * 128 / samplerate;
	for (i = 8; i < 16; i++)
		m->periodmodifier[i] = (7093789 + (i-16)*52727) * 128 / samplerate;

	////////////////////////////////////////////////////////////
	// Certain tables are pregenerated for speed reasons. They
	// remove multiplies and divisions which would have slowed
	// down the player horribly. They cant be generated during
	// compilation because each MOD requires different tables.
	//
	// Each sample byte equals the channel sum divided by the
	// channel number. This division occurs once per byte, ie
	// 20khz means 20000 divisions per second. Precalculating
	// all possible divisions requires 8kb maximum.
	////////////////////////////////////////////////////////////
	for (i = 0; i < 256 * m->numchannels; i++)
		OutputMap[i] = i / m->numchannels;

	////////////////////////////////////////////////////////////
	// Each channel byte equals the original sample byte times
	// the volume ratio. This means one multiplication and one
	// shift per channel byte, ie 20khz and 4 channels equals
	// 80000 multiplication/shifts per second. Precalculating
	// all possible volume maps requires 16kb maximum.
	////////////////////////////////////////////////////////////
	for (i = 0; i <= 64; i++)
		for (int j = 0; j < 256; j++)
			VolumeMap[i][j] = i * j / 64;

	////////////////////////////////////////////////////////////
	// The main MOD playing loop is quite simple. Playing a
	// song requires playing all the tracks. Playing a track
	// requires playing all the divisions. Playing a division
	// requires playing all the ticks. Extra work exists for
	// each division and tick; handled through external calls.
	////////////////////////////////////////////////////////////
	for (m->songposition = -1; ++m->songposition < m->numpositions;)
	{
		for (m->lineposition = -1; ++m->lineposition < 64;)
		{
			ModTrack(m);
			for (m->tickposition = -1; ++m->tickposition < m->ticksperline;)
				ModTick(m);
		}
	}
}
