154 lines
3.1 KiB
C
154 lines
3.1 KiB
C
#include "sidfx.h"
|
|
|
|
enum SIDFXState
|
|
{
|
|
SIDFX_IDLE,
|
|
SIDFX_RESET_0,
|
|
SIDFX_RESET_1,
|
|
SIDFX_READY,
|
|
SIDFX_PLAY,
|
|
SIDFX_WAIT
|
|
};
|
|
|
|
static struct SIDFXChannel
|
|
{
|
|
SIDFX * com;
|
|
byte delay, cnt;
|
|
SIDFXState state;
|
|
unsigned freq, pwm;
|
|
|
|
} channels[3];
|
|
|
|
void sidfx_init(void)
|
|
{
|
|
for(char i=0; i<3; i++)
|
|
{
|
|
channels[i].com = nullptr;
|
|
channels[i].state = SIDFX_IDLE;
|
|
}
|
|
}
|
|
|
|
void sidfx_play(byte chn, SIDFX * fx, byte cnt)
|
|
{
|
|
if (channels[chn].state == SIDFX_IDLE)
|
|
channels[chn].state = SIDFX_READY;
|
|
else
|
|
channels[chn].state = SIDFX_RESET_0;
|
|
|
|
channels[chn].com = fx;
|
|
channels[chn].cnt = cnt - 1;
|
|
}
|
|
|
|
void sidfx_stop(byte chn)
|
|
{
|
|
channels[chn].com = nullptr;
|
|
if (channels[chn].state != SIDFX_IDLE)
|
|
channels[chn].state = SIDFX_RESET_0;
|
|
}
|
|
|
|
inline void sidfx_loop_ch(byte ch)
|
|
{
|
|
switch (channels[ch].state)
|
|
{
|
|
case SIDFX_IDLE:
|
|
break;
|
|
case SIDFX_RESET_0:
|
|
sid.voices[ch].ctrl = 0;
|
|
sid.voices[ch].attdec = 0;
|
|
sid.voices[ch].susrel = 0;
|
|
channels[ch].state = SIDFX_RESET_1;
|
|
break;
|
|
case SIDFX_RESET_1:
|
|
sid.voices[ch].ctrl = SID_CTRL_TEST;
|
|
channels[ch].state = SIDFX_READY;
|
|
break;
|
|
case SIDFX_READY:
|
|
if (channels[ch].com)
|
|
{
|
|
channels[ch].freq = channels[ch].com->freq;
|
|
channels[ch].pwm = channels[ch].com->pwm;
|
|
|
|
sid.voices[ch].freq = channels[ch].com->freq;
|
|
sid.voices[ch].pwm = channels[ch].com->pwm;
|
|
sid.voices[ch].attdec = channels[ch].com->attdec;
|
|
sid.voices[ch].susrel = channels[ch].com->susrel;
|
|
sid.voices[ch].ctrl = channels[ch].com->ctrl;
|
|
|
|
channels[ch].delay = channels[ch].com->time1;
|
|
channels[ch].state = SIDFX_PLAY;
|
|
}
|
|
else
|
|
channels[ch].state = SIDFX_IDLE;
|
|
break;
|
|
case SIDFX_PLAY:
|
|
if (channels[ch].com->dfreq)
|
|
{
|
|
channels[ch].freq += channels[ch].com->dfreq;
|
|
sid.voices[ch].freq = channels[ch].freq;
|
|
}
|
|
if (channels[ch].com->dpwm)
|
|
{
|
|
channels[ch].pwm += channels[ch].com->dpwm;
|
|
sid.voices[ch].pwm = channels[ch].pwm;
|
|
}
|
|
|
|
if (channels[ch].delay)
|
|
channels[ch].delay--;
|
|
else if (channels[ch].com->time0)
|
|
{
|
|
sid.voices[ch].ctrl = channels[ch].com->ctrl & ~SID_CTRL_GATE;
|
|
channels[ch].delay = channels[ch].com->time0;
|
|
channels[ch].state = SIDFX_WAIT;
|
|
}
|
|
else if (channels[ch].cnt)
|
|
{
|
|
channels[ch].cnt--;
|
|
channels[ch].com++;
|
|
channels[ch].state = SIDFX_READY;
|
|
}
|
|
else
|
|
{
|
|
channels[ch].com = nullptr;
|
|
channels[ch].state = SIDFX_RESET_0;
|
|
}
|
|
break;
|
|
case SIDFX_WAIT:
|
|
if (channels[ch].com->dfreq)
|
|
{
|
|
channels[ch].freq += channels[ch].com->dfreq;
|
|
sid.voices[ch].freq = channels[ch].freq;
|
|
}
|
|
if (channels[ch].com->dpwm)
|
|
{
|
|
channels[ch].pwm += channels[ch].com->dpwm;
|
|
sid.voices[ch].pwm = channels[ch].pwm;
|
|
}
|
|
|
|
if (channels[ch].delay)
|
|
channels[ch].delay--;
|
|
else if (channels[ch].cnt)
|
|
{
|
|
channels[ch].cnt--;
|
|
channels[ch].com++;
|
|
channels[ch].state = SIDFX_RESET_0;
|
|
}
|
|
else
|
|
{
|
|
channels[ch].com = nullptr;
|
|
channels[ch].state = SIDFX_RESET_0;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void sidfx_loop_2(void)
|
|
{
|
|
sidfx_loop_ch(2);
|
|
}
|
|
|
|
void sidfx_loop(void)
|
|
{
|
|
for(byte ch=0; ch<3; ch++)
|
|
sidfx_loop_ch(ch);
|
|
}
|