blob: 8b1f7d5bd1676d7b71aa8cadd5fb9a00fd88efcf [file] [log] [blame] [raw]
#include "sound.h"
#include "tedmem.h"
#define PRECISION 4
#define OSCRELOADVAL (0x3FF << PRECISION)
static int Volume;
static int Snd1Status;
static int Snd2Status;
static int SndNoiseStatus;
static int DAStatus;
static unsigned short Freq1;
static unsigned short Freq2;
static int NoiseCounter;
static int FlipFlop[2];
static int oscCount1;
static int oscCount2;
static int OscReload[2];
static int oscStep;
static unsigned char noise[256]; // 0-8
static unsigned int MixingFreq;
static unsigned int originalFreq;
void TED::tedSoundInit(unsigned int mixingFreq)
{
originalFreq = TED_SOUND_CLOCK / 8;
oscStep = (int) (( TED_SOUND_CLOCK / 8 * (double) (1 << PRECISION) ) / (double) (mixingFreq) + 0.5);
FlipFlop[0] = 0;
FlipFlop[1] = 0;
oscCount1 = 0;
oscCount2 = 0;
NoiseCounter = 0;
Freq1 = Freq2 = 0;
DAStatus = 0;
MixingFreq = mixingFreq;
/* initialise im with 0xa8 */
int im = 0xa8;
for (int i=0; i<256; i++) {
noise[i] = im & 1;
im = (im<<1)+(1^((im>>7)&1)^((im>>5)&1)^((im>>4)&1)^((im>>1)&1));
}
}
void TED::setFrequency(unsigned int frequency)
{
originalFreq = frequency;
oscStep = (int)((frequency * (double)(1 << PRECISION)) / (double)(MixingFreq)+0.5);
}
void TED::setSampleRate(unsigned int sampleRate)
{
MixingFreq = sampleRate;
oscStep = (int)((originalFreq * (double)(1 << PRECISION)) / (double)(MixingFreq)+0.5);
}
void TED::calcSamples(short *buffer, unsigned int nrsamples)
{
// Rendering...
// Calculate the buffer...
if (DAStatus) {// digi?
short sample = 0;
if (Snd1Status) sample = Volume;
if (Snd2Status) sample += Volume;
for (;nrsamples--;) {
*buffer++ = sample;
}
} else {
unsigned int result1, result2;
for (;nrsamples--;) {
// Channel 1
if ((oscCount1 += oscStep) >= OSCRELOADVAL) {
if (OscReload[0] != (0x3FF << PRECISION))
FlipFlop[0] ^= 1;
oscCount1 = OscReload[0] + (oscCount1 - OSCRELOADVAL);
}
// Channel 2
if ((oscCount2 += oscStep) >= OSCRELOADVAL) {
if (OscReload[1] != (0x3FF << PRECISION)) {
FlipFlop[1] ^= 1;
if (NoiseCounter++==256)
NoiseCounter=0;
}
oscCount2 = OscReload[1] + (oscCount2 - OSCRELOADVAL);
}
result1 = (FlipFlop[0] && Snd1Status) ? Volume : 0;
if (Snd2Status) {
result2 = FlipFlop[1] ? Volume : 0;
} else if (SndNoiseStatus) {
result2 = noise[NoiseCounter] ? Volume : 0;
} else {
result2 = 0;
}
*buffer++ = result1 + result2;
} // for
}
}
inline void setFreq(unsigned int channel, int freq)
{
if (freq == 0x3FF) {
freq = -1;
} else if (freq == 0x3FE) {
FlipFlop[channel] = 1;
}
OscReload[channel] = ((freq + 1)&0x3FF) << PRECISION;
}
void TED::writeSoundReg(ClockCycle cycle, unsigned int reg, unsigned char value)
{
flushBuffer(cycle, TED_SOUND_CLOCK);
switch (reg) {
case 0:
Freq1 = (Freq1 & 0x300) | value;
setFreq(0, Freq1);
break;
case 1:
Freq2 = (Freq2 & 0x300) | value;
setFreq(1, Freq2);
break;
case 2:
Freq2 = (Freq2 & 0xFF) | (value << 8);
setFreq(1, Freq2);
break;
case 3:
if ((DAStatus = (value & 0x80))) {
FlipFlop[0] = 1;
FlipFlop[1] = 1;
oscCount1 = OscReload[0];
oscCount2 = OscReload[1];
NoiseCounter = 0xFF;
}
Volume = value & 0x0F;
if (Volume > 8) Volume = 8;
Volume <<= 10;
Snd1Status = value & 0x10;
Snd2Status = value & 0x20;
SndNoiseStatus = value & 0x40;
break;
case 4:
Freq1 = (Freq1 & 0xFF) | (value << 8);
setFreq(0, Freq1);
break;
}
}