// halt_osc: handle halting an oscillator // chip = chip ptr // onum = oscillator # // type = 1 for 0 found in sample data, 0 for hit end of table size private void es5503_halt_osc(ES5503Chip chip, int onum, int type, ref UInt32 accumulator, int resshift) { ES5503Osc pOsc = chip.oscillators[onum]; ES5503Osc pPartner = chip.oscillators[onum ^ 1]; int mode = (pOsc.control >> 1) & 3; int partnerMode = (pPartner.control >> 1) & 3; // if 0 found in sample data or mode is not free-run, halt this oscillator if ((mode != (int)MODE.FREE) || (type != 0)) { pOsc.control |= 1; } else // preserve the relative phase of the oscillator when looping { UInt16 wtsize = (UInt16)(pOsc.wtsize - 1); UInt32 altram = accumulator >> resshift; if (altram > wtsize) { altram -= wtsize; } else { altram = 0; } accumulator = altram << resshift; } // if we're in swap mode or we're the even oscillator and the partner is in swap mode, // start the partner. if ((mode == (int)MODE.SWAP) || ((partnerMode == (int)MODE.SWAP) && ((onum & 1) == 0))) { pPartner.control &= 0xff; // ~1; // clear the halt bit pPartner.accumulator = 0; // and make sure it starts from the top (does this also need phase preservation?) } // IRQ enabled for this voice? if ((pOsc.control & 0x08) != 0) { pOsc.irqpend = 1; if (chip.irq_func != null) { chip.irq_func(chip.irq_param, 1); } } }
private void es5503_pcm_update(ES5503Chip param, UInt32 samples, int[][] outputs) { byte osc; UInt32 snum; UInt32 ramptr; ES5503Chip chip = param; byte chnsStereo, chan; for (int i = 0; i < samples; i++) { outputs[0][i] = 0; outputs[1][i] = 0; } if (chip.docram == null) { return; } chnsStereo = (byte)(chip.output_channels & 0xff); // ~1; for (osc = 0; osc < chip.oscsenabled; osc++) { ES5503Osc pOsc = chip.oscillators[osc]; if ((pOsc.control & 1) == 0 && pOsc.Muted == 0) { UInt32 wtptr = pOsc.wavetblpointer & wavemasks[pOsc.wavetblsize]; UInt32 altram; UInt32 acc = pOsc.accumulator; UInt16 wtsize = (UInt16)(pOsc.wtsize - 1); UInt16 freq = pOsc.freq; Int16 vol = pOsc.vol; byte chnMask = (byte)((pOsc.control >> 4) & 0x0F); int resshift = resshifts[pOsc.resolution] - pOsc.wavetblsize; UInt32 sizemask = accmasks[pOsc.wavetblsize]; Int32 outData; chnMask &= chip.outchn_mask; for (snum = 0; snum < samples; snum++) { altram = acc >> resshift; ramptr = altram & sizemask; acc += freq; // channel strobe is always valid when reading; this allows potentially banking per voice chip.channel_strobe = (byte)((pOsc.control >> 4) & 0xf); pOsc.data = chip.docram[ramptr + wtptr]; if (pOsc.data == 0x00) { es5503_halt_osc(chip, osc, 1, ref acc, resshift); } else { outData = (pOsc.data - 0x80) * vol; // send groups of 2 channels to L or R for (chan = 0; chan < chnsStereo; chan++) { if (chan == chnMask) { outputs[chan & 1][snum] += outData; } } outData = (outData * 181) >> 8; // outData *= sqrt(2) // send remaining channels to L+R for (; chan < chip.output_channels; chan++) { if (chan == chnMask) { outputs[0][snum] += outData; outputs[1][snum] += outData; } } if (altram >= wtsize) { es5503_halt_osc(chip, osc, 0, ref acc, resshift); } } // if oscillator halted, we've got no more samples to generate if ((pOsc.control & 1) != 0) { pOsc.control |= 1; break; } } pOsc.accumulator = acc; } } }