| #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; |
| } |
| } |
| |