diff options
Diffstat (limited to 'src/devices/sound/sid.cpp')
-rw-r--r-- | src/devices/sound/sid.cpp | 200 |
1 files changed, 76 insertions, 124 deletions
diff --git a/src/devices/sound/sid.cpp b/src/devices/sound/sid.cpp index 1535c56a69e..7f7292a57be 100644 --- a/src/devices/sound/sid.cpp +++ b/src/devices/sound/sid.cpp @@ -29,96 +29,54 @@ float filterResTable[16]; #define maxLogicalVoices 4 -const int mix16monoMiddleIndex = 256*maxLogicalVoices/2; -uint16_t mix16mono[256*maxLogicalVoices]; - -uint16_t zero16bit=0; /* either signed or unsigned */ -//uint32_t splitBufferLen; - -void MixerInit(int threeVoiceAmplify) +inline sound_stream::sample_t mix_mono(uint16_t usum) { - long si; - uint16_t ui; - long ampDiv = maxLogicalVoices; - - if (threeVoiceAmplify) - { - ampDiv = (maxLogicalVoices-1); - } - - /* Mixing formulas are optimized by sample input value. */ - - si = (-128*maxLogicalVoices) * 256; - for (ui = 0; ui < sizeof(mix16mono)/sizeof(uint16_t); ui++ ) - { - mix16mono[ui] = (uint16_t)(si/ampDiv) + zero16bit; - si+=256; - } - + return sound_stream::sample_t(int16_t(usum - maxLogicalVoices*128)) * (1.0 / (256 * maxLogicalVoices)); } - } // anonymous namespace inline void SID6581_t::syncEm() { - bool const sync1(optr1.modulator->cycleLenCount <= 0); - bool const sync2(optr2.modulator->cycleLenCount <= 0); - bool const sync3(optr3.modulator->cycleLenCount <= 0); - - optr1.cycleLenCount--; - optr2.cycleLenCount--; - optr3.cycleLenCount--; - - if (optr1.sync && sync1) + bool sync[3]; + for (int v = 0; v < max_voices; v++) { - optr1.cycleLenCount = 0; - optr1.outProc = &sidOperator::wave_calc_normal; -#if defined(DIRECT_FIXPOINT) - optr1.waveStep.l = 0; -#else - optr1.waveStep = optr1.waveStepPnt = 0; -#endif + sync[v] = optr[v].modulator->cycleLenCount <= 0; + optr[v].cycleLenCount--; } - if (optr2.sync && sync2) - { - optr2.cycleLenCount = 0; - optr2.outProc = &sidOperator::wave_calc_normal; -#if defined(DIRECT_FIXPOINT) - optr2.waveStep.l = 0; -#else - optr2.waveStep = optr2.waveStepPnt = 0; -#endif - } - if (optr3.sync && sync3) + + for (int v = 0; v < max_voices; v++) { - optr3.cycleLenCount = 0; - optr3.outProc = &sidOperator::wave_calc_normal; + if (optr[v].sync && sync[v]) + { + optr[v].cycleLenCount = 0; + optr[v].outProc = &sidOperator::wave_calc_normal; #if defined(DIRECT_FIXPOINT) - optr3.waveStep.l = 0; + optr[v].waveStep.l = 0; #else - optr3.waveStep = optr3.waveStepPnt = 0; + optr[v].waveStep = optr[v].waveStepPnt = 0; #endif + } } } -void SID6581_t::fill_buffer(stream_sample_t *buffer, uint32_t bufferLen) +void SID6581_t::fill_buffer(sound_stream &stream) { //void* SID6581_t::fill16bitMono(void* buffer, uint32_t numberOfSamples) - for ( ; bufferLen > 0; bufferLen-- ) + for (int sampindex = 0; sampindex < stream.samples(); sampindex++) { - *buffer++ = (int16_t) mix16mono[unsigned(mix16monoMiddleIndex - +(*optr1.outProc)(&optr1) - +(*optr2.outProc)(&optr2) - +(optr3.outProc(&optr3)&optr3_outputmask) + stream.put(0, sampindex, mix_mono( + (*optr[0].outProc)(&optr[0]) + +(*optr[1].outProc)(&optr[1]) + +((*optr[2].outProc)(&optr[2])&optr3_outputmask) /* hack for digi sounds does n't seam to come from a tone operator ghostbusters and goldrunner everything except volume zeroed */ +(masterVolume<<2) // +(*sampleEmuRout)() - )]; + )); syncEm(); } } @@ -130,12 +88,11 @@ void SID6581_t::fill_buffer(stream_sample_t *buffer, uint32_t bufferLen) bool SID6581_t::reset() { - optr1.clear(); - enveEmuResetOperator( &optr1 ); - optr2.clear(); - enveEmuResetOperator( &optr2 ); - optr3.clear(); - enveEmuResetOperator( &optr3 ); + for (int v = 0; v < max_voices; v++) + { + optr[v].clear(); + enveEmuResetOperator(&optr[v]); + } optr3_outputmask = ~0; /* on */ //sampleEmuReset(); @@ -144,17 +101,24 @@ bool SID6581_t::reset() filter.Value = 0; filter.Dy = filter.ResDy = 0; - optr1.set(); - optr2.set(); - optr3.set(); - - optr1.set2(); - optr2.set2(); - optr3.set2(); + for (int v = 0; v < max_voices; v++) + { + optr[v].set(); + optr[v].set2(); + } return true; } +void SID6581_t::postload() +{ + for (int v = 0; v < max_voices; v++) + { + optr[v].set(); + optr[v].set2(); + } +} + static void filterTableInit(running_machine &machine) { @@ -177,13 +141,13 @@ static void filterTableInit(running_machine &machine) bandPassParam = std::make_unique<float[]>(0x800); uk = 0; - for ( rk = 0; rk < 0x800; rk++ ) + for (rk = 0; rk < 0x800; rk++) { filterTable[uk] = (((expf(rk/0x800*logf(400.0f))/60.0f)+0.05f) *filterRefFreq) / sample_rate; - if ( filterTable[uk] < yMin ) + if (filterTable[uk] < yMin) filterTable[uk] = yMin; - if ( filterTable[uk] > yMax ) + if (filterTable[uk] > yMax) filterTable[uk] = yMax; uk++; } @@ -195,7 +159,7 @@ static void filterTableInit(running_machine &machine) yTmp = yMin; uk = 0; /* Some C++ compilers still have non-local scope! */ - for ( rk2 = 0; rk2 < 0x800; rk2++ ) + for (rk2 = 0; rk2 < 0x800; rk2++) { bandPassParam[uk] = (yTmp*filterRefFreq) / sample_rate; yTmp += yAdd; @@ -206,10 +170,10 @@ static void filterTableInit(running_machine &machine) resDyMax = 1.0f; resDyMin = 2.0f; resDy = resDyMin; - for ( uk = 0; uk < 16; uk++ ) + for (uk = 0; uk < 16; uk++) { filterResTable[uk] = resDy; - resDy -= (( resDyMin - resDyMax ) / 15 ); + resDy -= ((resDyMin - resDyMax) / 15); } filterResTable[0] = resDyMin; filterResTable[15] = resDyMax; @@ -217,22 +181,15 @@ static void filterTableInit(running_machine &machine) void SID6581_t::init() { - optr1.sid = this; - optr2.sid = this; - optr3.sid = this; - - optr1.modulator = &optr3; - optr3.carrier = &optr1; - optr1.filtVoiceMask = 1; - - optr2.modulator = &optr1; - optr1.carrier = &optr2; - optr2.filtVoiceMask = 2; - - optr3.modulator = &optr2; - optr2.carrier = &optr3; - optr3.filtVoiceMask = 4; + for (int v = 0; v < max_voices; v++) + { + optr[v].sid = this; + u8 const mod_voi = ((v + max_voices) - 1) % max_voices; + optr[v].modulator = &optr[mod_voi]; + optr[mod_voi].carrier = &optr[v]; + optr[v].filtVoiceMask = 1 << v; + } PCMsid = uint32_t(PCMfreq * (16777216.0 / clock)); PCMsidNoise = uint32_t((clock * 256.0) / PCMfreq); @@ -246,8 +203,6 @@ void SID6581_t::init() enveEmuInit(PCMfreq, true); - MixerInit(0); - reset(); } @@ -275,7 +230,7 @@ void SID6581_t::port_w(int offset, int data) masterVolume = reg[0x18] & 15; masterVolumeAmplIndex = masterVolume << 8; - if ((reg[0x18] & 0x80) && !(reg[0x17] & optr3.filtVoiceMask)) + if ((reg[0x18] & 0x80) && !(reg[0x17] & optr[2].filtVoiceMask)) optr3_outputmask = 0; /* off */ else optr3_outputmask = ~0; /* on */ @@ -284,11 +239,10 @@ void SID6581_t::port_w(int offset, int data) if (filter.Type != filter.CurType) { filter.CurType = filter.Type; - optr1.filtLow = optr1.filtRef = 0; - optr2.filtLow = optr2.filtRef = 0; - optr3.filtLow = optr3.filtRef = 0; + for (int v = 0; v < max_voices; v++) + optr[v].filtLow = optr[v].filtRef = 0; } - if (filter.Enabled ) + if (filter.Enabled) { filter.Value = 0x7ff & ((reg[0x15] & 7) | (uint16_t(reg[0x16]) << 3)); if (filter.Type == 0x20) @@ -300,14 +254,13 @@ void SID6581_t::port_w(int offset, int data) filter.ResDy = 1.0f; } - optr1.set(); - optr3.set(); - optr2.set(); + for (int v = 0; v < max_voices; v++) + { + optr[v].set(); - // relies on sidEmuSet also for other channels! - optr1.set2(); - optr2.set2(); - optr3.set2(); + // relies on sidEmuSet also for other channels! + optr[v].set2(); + } break; default: @@ -315,20 +268,19 @@ void SID6581_t::port_w(int offset, int data) reg[offset] = data; if (offset < 7) - optr1.reg[offset] = data; + optr[0].reg[offset] = data; else if (offset < 14) - optr2.reg[offset - 7] = data; + optr[1].reg[offset - 7] = data; else if (offset < 21) - optr3.reg[offset - 14] = data; + optr[2].reg[offset - 14] = data; - optr1.set(); - optr3.set(); - optr2.set(); + for (int v = 0; v < max_voices; v++) + { + optr[v].set(); - // relies on sidEmuSet also for other channels! - optr1.set2(); - optr2.set2(); - optr3.set2(); + // relies on sidEmuSet also for other channels! + optr[v].set2(); + } break; } } @@ -348,11 +300,11 @@ int SID6581_t::port_r(running_machine &machine, int offset) break; case 0x1b: mixer_channel->update(); - data = optr3.output; + data = optr[2].output; break; case 0x1c: mixer_channel->update(); - data = optr3.enveVol; + data = optr[2].enveVol; break; default: data = reg[offset]; |