private void envelope_generator_calc(_MultiPCM ptChip, _slot_t slot) { Int32 octave = ((slot.regs[3] >> 4) - 1) & 0xf; Int32 rate; if ((octave & 8) != 0) { octave = octave - 16; } if (slot.sample.key_rate_scale != 0xf) { rate = (octave + slot.sample.key_rate_scale) * 2 + ((slot.regs[3] >> 3) & 1); } else { rate = 0; } slot.envelope_gen.attack_rate = (Int32)get_rate(ptChip.attack_step, (UInt32)rate, slot.sample.attack_reg); slot.envelope_gen.decay1_rate = (Int32)get_rate(ptChip.decay_release_step, (UInt32)rate, slot.sample.decay1_reg); slot.envelope_gen.decay2_rate = (Int32)get_rate(ptChip.decay_release_step, (UInt32)rate, slot.sample.decay2_reg); slot.envelope_gen.release_rate = (Int32)get_rate(ptChip.decay_release_step, (UInt32)rate, slot.sample.release_reg); slot.envelope_gen.decay_level = 0xf - slot.sample.decay_level; }
//WRITE8_DEVICE_HANDLER( multipcm_w ) private void multipcm_w(byte ChipID, Int32 offset, byte data) { //MultiPCM *ptChip = get_safe_token(device); _MultiPCM ptChip = MultiPCMData[ChipID]; switch (offset) { case 0: //Data write WriteSlot(ptChip, ptChip.Slots[ptChip.CurSlot], (Int32)ptChip.Address, data); break; case 1: ptChip.CurSlot = (UInt32)val2chan[data & 0x1f]; //Console.WriteLine("CurSlot{0}", ptChip.CurSlot); break; case 2: ptChip.Address = (UInt32)((data > 7) ? 7 : data); break; } /*ptChip->CurSlot = val2chan[(offset >> 3) & 0x1F]; * ptChip->Address = offset & 0x07; * WriteSlot(ptChip, ptChip->Slots + ptChip->CurSlot, ptChip->Address, data);*/ }
public void multipcm_write_rom2(byte ChipID, UInt32 ROMSize, UInt32 offset, UInt32 length, byte[] data, Int32 srcStartAddress) { _MultiPCM ptChip = MultiPCMData[ChipID]; if (ptChip.ROM == null || ptChip.ROM.Length < ROMSize) { multipcm_alloc_rom(ChipID, ROMSize); } if (offset > ptChip.ROMSize) { return; } if (offset + length > ptChip.ROMSize) { length = (uint)(ptChip.ROMSize - offset); } for (int i = 0; i < length; i++) { if (data.Length <= i + srcStartAddress) { break; } ptChip.ROM[i + offset] = data[i + srcStartAddress]; } return; }
/* MAME/M1 access functions */ //void multipcm_set_bank(running_device *device, UINT32 leftoffs, UINT32 rightoffs) public void multipcm_set_bank(byte ChipID, UInt32 leftoffs, UInt32 rightoffs) { //MultiPCM *ptChip = get_safe_token(device); _MultiPCM ptChip = MultiPCMData[ChipID]; ptChip.BankL = leftoffs; ptChip.BankR = rightoffs; }
public void device_stop_multipcm(byte ChipID) { _MultiPCM ptChip = MultiPCMData[ChipID]; //free(ptChip->ROM); ptChip.ROM = null; return; }
public void multipcm_set_mute_mask(byte ChipID, UInt32 MuteMask) { _MultiPCM ptChip = MultiPCMData[ChipID]; byte CurChn; for (CurChn = 0; CurChn < 28; CurChn++) { ptChip.Slots[CurChn].Muted = (byte)((MuteMask >> CurChn) & 0x01); } return; }
private void multipcm_w_quick(byte ChipID, byte offset, byte data) { _MultiPCM ptChip = MultiPCMData[ChipID]; ptChip.cur_slot = VALUE_TO_CHANNEL[(offset >> 3) & 0x1F]; ptChip.address = offset & 0x07; if (ptChip.cur_slot == -1) { return; } write_slot(ptChip, ptChip.slots[ptChip.cur_slot], ptChip.address, data); }
public void device_reset_multipcm(byte ChipID) { _MultiPCM ptChip = MultiPCMData[ChipID]; int i; for (i = 0; i < 28; ++i) { ptChip.Slots[i].Num = (byte)i; ptChip.Slots[i].Playing = 0; } return; }
public void multipcm_bank_write(byte ChipID, byte offset, UInt16 data) { _MultiPCM ptChip = MultiPCMData[ChipID]; if ((offset & 0x01) != 0) { ptChip.BankL = (UInt32)(data << 16); } if ((offset & 0x02) != 0) { ptChip.BankR = (UInt32)(data << 16); } return; }
private void lfo_compute_step(_MultiPCM ptChip, _lfo_t lfo, UInt32 lfo_frequency, UInt32 lfo_scale, Int32 amplitude_lfo) { float step = (float)(LFO_FREQ[lfo_frequency] * 256.0f / (float)ptChip.rate); lfo.phase_step = (UInt32)((float)(1 << LFO_SHIFT) * step); if (amplitude_lfo != 0) { lfo.table = amplitude_table; lfo.scale = amplitude_scale_tables[lfo_scale]; } else { lfo.table = pitch_table; lfo.scale = pitch_scale_tables[lfo_scale]; } }
private void LFO_ComputeStep(_MultiPCM ptChip, _LFO LFO, UInt32 LFOF, UInt32 LFOS, Int32 ALFO) { float step = (float)(LFOFreq[LFOF] * 256.0 / (float)ptChip.Rate); LFO.phase_step = (UInt32)((float)(1 << LFO_SHIFT) * step); if (ALFO != 0) { LFO.table = ALFO_TRI; LFO.scale = ASCALES[LFOS]; } else { LFO.table = PLFO_TRI; LFO.scale = PSCALES[LFOS]; } }
private void init_sample(_MultiPCM ptChip, _Sample sample, UInt16 index) { UInt32 address = (UInt32)((index * 12) & ptChip.ROMMask); sample.start = (uint)((ptChip.ROM[address + 0] << 16) | (ptChip.ROM[address + 1] << 8) | ptChip.ROM[address + 2]); sample.format = (byte)((sample.start >> 20) & 0xfe); sample.start &= 0x3fffff; sample.loop = (uint)((ptChip.ROM[address + 3] << 8) | ptChip.ROM[address + 4]); sample.end = (uint)(0xffff - ((ptChip.ROM[address + 5] << 8) | ptChip.ROM[address + 6])); sample.attack_reg = (byte)((ptChip.ROM[address + 8] >> 4) & 0xf); sample.decay1_reg = (byte)(ptChip.ROM[address + 8] & 0xf); sample.decay2_reg = (byte)(ptChip.ROM[address + 9] & 0xf); sample.decay_level = (byte)((ptChip.ROM[address + 9] >> 4) & 0xf); sample.release_reg = (byte)(ptChip.ROM[address + 10] & 0xf); sample.key_rate_scale = (byte)((ptChip.ROM[address + 10] >> 4) & 0xf); sample.lfo_vibrato_reg = ptChip.ROM[address + 7]; sample.lfo_amplitude_reg = (byte)(ptChip.ROM[address + 11] & 0xf); }
public void multipcm_write_rom(byte ChipID, UInt32 offset, UInt32 length, byte[] data) { _MultiPCM ptChip = MultiPCMData[ChipID]; if (offset > ptChip.ROMSize) { return; } if (offset + length > ptChip.ROMSize) { length = (uint)(ptChip.ROMSize - offset); } for (int i = 0; i < length; i++) { ptChip.ROM[i + offset] = data[i]; } return; }
/* MAME/M1 access functions */ public void multipcm_alloc_rom(byte ChipID, UInt32 memsize) { _MultiPCM ptChip = MultiPCMData[ChipID]; if (ptChip.ROMSize == memsize) { return; } ptChip.ROM = new byte[memsize]; ptChip.ROMSize = memsize; for (int i = 0; i < memsize; i++) { ptChip.ROM[i] = 0xFF; } ptChip.ROMMask = common.pow2_mask(memsize); return; }
//WRITE8_DEVICE_HANDLER( multipcm_w ) private void multipcm_write(byte ChipID, Int32 offset, byte data) { //MultiPCM *ptChip = get_safe_token(device); _MultiPCM ptChip = MultiPCMData[ChipID]; switch (offset) { case 0: //Data write if (ptChip.cur_slot == -1) { return; } write_slot(ptChip, ptChip.slots[ptChip.cur_slot], ptChip.address, data); break; case 1: ptChip.cur_slot = VALUE_TO_CHANNEL[data & 0x1f]; break; case 2: ptChip.address = (data > 7) ? 7 : data; break; // special SEGA banking case 0x10: // 1 MB banking (Sega Model 1) ptChip.sega_banking = 1; ptChip.bank0 = (uint)((data << 20) | 0x000000); ptChip.bank1 = (uint)((data << 20) | 0x080000); break; case 0x11: // 512 KB banking - low bank (Sega Multi 32) ptChip.sega_banking = 1; ptChip.bank0 = (uint)(data << 19); break; case 0x12: // 512 KB banking - high bank (Sega Multi 32) ptChip.sega_banking = 1; ptChip.bank1 = (uint)(data << 19); break; } }
private void EG_Calc(_MultiPCM ptChip, _SLOT slot) { Int32 octave = ((slot.Regs[3] >> 4) - 1) & 0xf; Int32 rate; if ((octave & 8) != 0) { octave = octave - 16; } if (slot.Sample.KRS != 0xf) { rate = (octave + slot.Sample.KRS) * 2 + ((slot.Regs[3] >> 3) & 1); } else { rate = 0; } slot.EG.AR = (Int32)Get_RATE(ptChip.ARStep, (UInt32)rate, slot.Sample.AR); slot.EG.D1R = (Int32)Get_RATE(ptChip.DRStep, (UInt32)rate, slot.Sample.DR1); slot.EG.D2R = (Int32)Get_RATE(ptChip.DRStep, (UInt32)rate, slot.Sample.DR2); slot.EG.RR = (Int32)Get_RATE(ptChip.DRStep, (UInt32)rate, slot.Sample.RR); slot.EG.DL = 0xf - slot.Sample.DL; }
public void multipcm_write_rom2(byte ChipID, Int32 ROMSize, Int32 DataStart, Int32 DataLength, byte[] ROMData, Int32 srcStartAddress) { _MultiPCM ptChip = MultiPCMData[ChipID]; UInt16 CurSmpl; _Sample TempSmpl; //byte[] ptSample; Int32 ptSample; if (ptChip.ROMSize != ROMSize) { ptChip.ROM = new sbyte[ROMSize];// (INT8*)realloc(ptChip.ROM, ROMSize); ptChip.ROMSize = (UInt32)ROMSize; for (ptChip.ROMMask = 1; ptChip.ROMMask < ROMSize; ptChip.ROMMask <<= 1) { ; } ptChip.ROMMask--; for (int i = 0; i < ROMSize; i++) { ptChip.ROM[i] = -1; //0xff; } //memset(ptChip.ROM, 0xFF, ROMSize); } if (DataStart > ROMSize) { return; } if (DataStart + DataLength > ROMSize) { DataLength = ROMSize - DataStart; } for (int i = 0; i < DataLength; i++) { ptChip.ROM[i + DataStart] = (sbyte)ROMData[i + srcStartAddress]; } //memcpy(ptChip.ROM + DataStart, ROMData, DataLength); if (DataStart < 0x200 * 12) { for (CurSmpl = 0; CurSmpl < 512; CurSmpl++) { TempSmpl = ptChip.Samples[CurSmpl]; //ptSample = (byte*)ptChip.ROM + CurSmpl * 12; ptSample = CurSmpl * 12; TempSmpl.Start = (UInt32)(((byte)ptChip.ROM[ptSample + 0] << 16) | ((byte)ptChip.ROM[ptSample + 1] << 8) | ((byte)ptChip.ROM[ptSample + 2] << 0)); TempSmpl.Loop = (UInt32)(((byte)ptChip.ROM[ptSample + 3] << 8) | ((byte)ptChip.ROM[ptSample + 4] << 0)); TempSmpl.End = (UInt32)(0xffff - (((byte)ptChip.ROM[ptSample + 5] << 8) | ((byte)ptChip.ROM[ptSample + 6] << 0))); TempSmpl.LFOVIB = (byte)ptChip.ROM[ptSample + 7]; TempSmpl.DR1 = (byte)((byte)ptChip.ROM[ptSample + 8] & 0xf); TempSmpl.AR = (byte)(((byte)ptChip.ROM[ptSample + 8] >> 4) & 0xf); TempSmpl.DR2 = (byte)((byte)ptChip.ROM[ptSample + 9] & 0xf); TempSmpl.DL = (byte)(((byte)ptChip.ROM[ptSample + 9] >> 4) & 0xf); TempSmpl.RR = (byte)((byte)ptChip.ROM[ptSample + 10] & 0xf); TempSmpl.KRS = (byte)(((byte)ptChip.ROM[ptSample + 10] >> 4) & 0xf); TempSmpl.AM = (byte)(ptChip.ROM[ptSample + 11]); //Console.WriteLine("LFOVIB{0} AM{1}", ptChip.ROM[ptSample + 7], ptChip.ROM[ptSample + 11]); } } return; }
//static STREAM_UPDATE( MultiPCM_update ) public void MultiPCM_update(byte ChipID, Int32[][] outputs, Int32 samples) { //MultiPCM *ptChip = (MultiPCM *)param; _MultiPCM ptChip = MultiPCMData[ChipID]; Int32[][] datap = new Int32[2][]; Int32 i, sl; datap[0] = outputs[0]; datap[1] = outputs[1]; for (int j = 0; j < samples; j++) { datap[0][j] = 0; datap[1][j] = 0; } //memset(datap[0], 0, sizeof(*datap[0]) * samples); //memset(datap[1], 0, sizeof(*datap[1]) * samples); for (i = 0; i < samples; ++i) { Int32 smpl = 0; Int32 smpr = 0; for (sl = 0; sl < 28; ++sl) { _SLOT slot = ptChip.Slots[sl]; if (slot.Playing != 0 && slot.Muted == 0) { UInt32 vol = (slot.TL >> SHIFT) | (slot.Pan << 7); UInt32 adr = slot.offset >> SHIFT; Int32 sample; UInt32 step = slot.step; Int32 csample = (Int16)(ptChip.ROM[(slot.Base + adr) & ptChip.ROMMask] << 8); Int32 fpart = (Int32)(slot.offset & ((1 << SHIFT) - 1)); sample = (csample * fpart + slot.Prev * ((1 << SHIFT) - fpart)) >> SHIFT; if ((slot.Regs[6] & 7) != 0) //Vibrato enabled { step = (UInt32)(step * PLFO_Step(slot.PLFO)); step >>= SHIFT; } slot.offset += step; if (slot.offset >= (slot.Sample.End << SHIFT)) { slot.offset = slot.Sample.Loop << SHIFT; } if ((adr ^ (slot.offset >> SHIFT)) != 0) { slot.Prev = csample; } if ((slot.TL >> SHIFT) != slot.DstTL) { slot.TL += (UInt32)slot.TLStep; } if ((slot.Regs[7] & 7) != 0) //Tremolo enabled { sample = sample * ALFO_Step(slot.ALFO); sample >>= SHIFT; } sample = (sample * EG_Update(slot)) >> 10; smpl += (LPANTABLE[vol] * sample) >> SHIFT; smpr += (RPANTABLE[vol] * sample) >> SHIFT; } } /*#define ICLIP16(x) (x<-32768)?-32768:((x>32767)?32767:x) * datap[0][i]=ICLIP16(smpl); * datap[1][i]=ICLIP16(smpr);*/ datap[0][i] = smpl; datap[1][i] = smpr; } }
private void WriteSlot(_MultiPCM ptChip, _SLOT slot, Int32 reg, byte data) { slot.Regs[reg] = data; switch (reg) { case 0: //PANPOT slot.Pan = (UInt32)((data >> 4) & 0xf); break; case 1: //Sample //according to YMF278 sample write causes some base params written to the regs (envelope+lfos) //the game should never change the sample while playing. { _Sample Sample = ptChip.Samples[slot.Regs[1]]; WriteSlot(ptChip, slot, 6, Sample.LFOVIB); WriteSlot(ptChip, slot, 7, Sample.AM); } break; case 2: //Pitch case 3: { UInt32 oct = (UInt32)(((slot.Regs[3] >> 4) - 1) & 0xf); UInt32 pitch = (UInt32)(((slot.Regs[3] & 0xf) << 6) | (slot.Regs[2] >> 2)); pitch = ptChip.FNS_Table[pitch]; if ((oct & 0x8) != 0) { pitch >>= (Int32)(16 - oct); } else { pitch <<= (Int32)oct; } slot.step = (UInt32)(pitch / ptChip.Rate); } break; case 4: //KeyOn/Off (and more?) { if ((data & 0x80) != 0) //KeyOn { slot.Sample = ptChip.Samples[slot.Regs[1]]; slot.Playing = 1; slot.Base = slot.Sample.Start; slot.offset = 0; slot.Prev = 0; slot.TL = slot.DstTL << SHIFT; EG_Calc(ptChip, slot); slot.EG.state = _STATE.ATTACK; slot.EG.volume = 0; if (slot.Base >= 0x100000) { if ((slot.Pan & 8) != 0) { slot.Base = (slot.Base & 0xfffff) | (ptChip.BankL); } else { slot.Base = (slot.Base & 0xfffff) | (ptChip.BankR); } } } else { if (slot.Playing != 0) { if (slot.Sample.RR != 0xf) { slot.EG.state = _STATE.RELEASE; } else { slot.Playing = 0; } } } } break; case 5: //TL+Interpolation { slot.DstTL = (UInt32)((data >> 1) & 0x7f); if ((data & 1) == 0) //Interpolate TL { if ((slot.TL >> SHIFT) > slot.DstTL) { slot.TLStep = TLSteps[0]; //decrease } else { slot.TLStep = TLSteps[1]; //increase } } else { slot.TL = slot.DstTL << SHIFT; } } break; case 6: //LFO freq+PLFO { if (data != 0) { LFO_ComputeStep(ptChip, slot.PLFO, (UInt32)(slot.Regs[6] >> 3) & 7, (UInt32)(slot.Regs[6] & 7), 0); LFO_ComputeStep(ptChip, slot.ALFO, (UInt32)(slot.Regs[6] >> 3) & 7, (UInt32)(slot.Regs[7] & 7), 1); } } break; case 7: //ALFO { if (data != 0) { LFO_ComputeStep(ptChip, slot.PLFO, (UInt32)(slot.Regs[6] >> 3) & 7, (UInt32)(slot.Regs[6] & 7), 0); LFO_ComputeStep(ptChip, slot.ALFO, (UInt32)(slot.Regs[6] >> 3) & 7, (UInt32)(slot.Regs[7] & 7), 1); } } break; } }
//static STREAM_UPDATE( MultiPCM_update ) public void MultiPCM_update(byte ChipID, Int32[][] outputs, Int32 samples) { //MultiPCM *ptChip = (MultiPCM *)param; _MultiPCM ptChip = MultiPCMData[ChipID]; //Int32[][] datap = new Int32[2][]; Int32 i, sl; //datap[0] = outputs[0]; //datap[1] = outputs[1]; for (int j = 0; j < samples; j++) { outputs[0][j] = 0; outputs[1][j] = 0; } //memset(datap[0], 0, sizeof(*datap[0]) * samples); //memset(datap[1], 0, sizeof(*datap[1]) * samples); for (i = 0; i < samples; ++i) { Int32 smpl = 0; Int32 smpr = 0; for (sl = 0; sl < 28; ++sl) { _slot_t slot = ptChip.slots[sl]; if (slot.playing != 0 && slot.muted == 0) { UInt32 vol = (slot.total_level >> TL_SHIFT) | (slot.pan << 7); UInt32 spos = slot.offset >> TL_SHIFT; UInt32 step = slot.step; Int32 csample = 0; Int32 fpart = (Int32)(slot.offset & ((1 << TL_SHIFT) - 1)); Int32 sample;// = (csample * fpart + slot.prev_sample * ((1 << SHIFT) - fpart)) >> SHIFT; if ((slot.format & 8) != 0) // 12-bit linear { UInt32 adr = slot.Base + (spos >> 2) * 6; switch (spos & 3) { case 0: { // ab.c .... .... Int16 w0 = (short)(read_byte(ptChip, adr) << 8 | ((read_byte(ptChip, adr + 1) & 0xf) << 4)); csample = w0; break; } case 1: { // ..C. AB.. .... Int16 w0 = (short)((read_byte(ptChip, adr + 2) << 8) | (read_byte(ptChip, adr + 1) & 0xf0)); csample = w0; break; } case 2: { // .... ..ab .c.. Int16 w0 = (short)(read_byte(ptChip, adr + 3) << 8 | ((read_byte(ptChip, adr + 4) & 0xf) << 4)); csample = w0; break; } case 3: { // .... .... C.AB Int16 w0 = (short)((read_byte(ptChip, adr + 5) << 8) | (read_byte(ptChip, adr + 4) & 0xf0)); csample = w0; break; } } } else { csample = (Int16)(read_byte(ptChip, slot.Base + spos) << 8); } sample = (csample * fpart + slot.prev_sample * ((1 << TL_SHIFT) - fpart)) >> TL_SHIFT; if ((slot.regs[6] & 7) != 0) // Vibrato enabled { step = (uint)(step * pitch_lfo_step(slot.pitch_lfo)); step >>= TL_SHIFT; } slot.offset += step; if (slot.offset >= (slot.sample.end << TL_SHIFT)) { slot.offset = slot.sample.loop << TL_SHIFT; } if ((spos ^ (slot.offset >> TL_SHIFT)) != 0) { slot.prev_sample = csample; } if ((slot.total_level >> TL_SHIFT) != slot.dest_total_level) { slot.total_level += (uint)slot.total_level_step; } if ((slot.regs[7] & 7) != 0) // Tremolo enabled { sample = sample * amplitude_lfo_step(slot.amplitude_lfo); sample >>= TL_SHIFT; } sample = (sample * envelope_generator_update(slot)) >> 10; smpl += (left_pan_table[vol] * sample) >> TL_SHIFT; smpr += (right_pan_table[vol] * sample) >> TL_SHIFT; } } outputs[0][i] = smpl; outputs[1][i] = smpr; } }
private byte read_byte(_MultiPCM ptChip, UInt32 addr) { return(ptChip.ROM[addr & ptChip.ROMMask]); }
private void write_slot(_MultiPCM ptChip, _slot_t slot, Int32 reg, byte data) { slot.regs[reg] = data; switch (reg) { case 0: //PANPOT slot.pan = (UInt32)((data >> 4) & 0xf); break; case 1: //Sample //according to YMF278 sample write causes some base params written to the regs (envelope+lfos) //the game should never change the sample while playing. // patched to load all sample data here, so registers 6 and 7 aren't overridden by KeyOn -Valley Bell init_sample(ptChip, slot.sample, (ushort)(slot.regs[1] | ((slot.regs[2] & 1) << 8))); write_slot(ptChip, slot, 6, slot.sample.lfo_vibrato_reg); write_slot(ptChip, slot, 7, slot.sample.lfo_amplitude_reg); break; case 2: //Pitch case 3: { UInt32 oct = (UInt32)(((slot.regs[3] >> 4) - 1) & 0xf); UInt32 pitch = (UInt32)(((slot.regs[3] & 0xf) << 6) | (slot.regs[2] >> 2)); pitch = ptChip.freq_step_table[pitch]; if ((oct & 0x8) != 0) { pitch >>= (Int32)(16 - oct); } else { pitch <<= (Int32)oct; } slot.step = (UInt32)(pitch / ptChip.rate); } break; case 4: //KeyOn/Off (and more?) { if ((data & 0x80) != 0) //KeyOn { slot.playing = 1; slot.Base = slot.sample.start; slot.offset = 0; slot.prev_sample = 0; slot.total_level = slot.dest_total_level << TL_SHIFT; slot.format = slot.sample.format; envelope_generator_calc(ptChip, slot); slot.envelope_gen.state = _STATE.ATTACK; slot.envelope_gen.volume = 0; if (ptChip.sega_banking != 0) { slot.Base &= 0x1fffff; if (slot.Base >= 0x100000) { if ((slot.Base & 0x080000) != 0) { slot.Base = (slot.Base & 0x07ffff) | ptChip.bank1; } else { slot.Base = (slot.Base & 0x07ffff) | ptChip.bank0; } } } } else { if (slot.playing != 0) { if (slot.sample.release_reg != 0xf) { slot.envelope_gen.state = _STATE.RELEASE; } else { slot.playing = 0; } } } } break; case 5: //TL+Interpolation { slot.dest_total_level = (UInt32)((data >> 1) & 0x7f); if ((data & 1) == 0) //Interpolate TL { if ((slot.total_level >> TL_SHIFT) > slot.dest_total_level) { slot.total_level_step = ptChip.total_level_steps[0]; // decrease } else { slot.total_level_step = ptChip.total_level_steps[1]; // increase } } else { slot.total_level = slot.dest_total_level << TL_SHIFT; } } break; case 6: //LFO freq+PLFO { if (data != 0) { lfo_compute_step(ptChip, slot.pitch_lfo, (UInt32)(slot.regs[6] >> 3) & 7, (UInt32)(slot.regs[6] & 7), 0); lfo_compute_step(ptChip, slot.amplitude_lfo, (UInt32)(slot.regs[6] >> 3) & 7, (UInt32)(slot.regs[7] & 7), 1); } } break; case 7: //ALFO { if (data != 0) { lfo_compute_step(ptChip, slot.pitch_lfo, (UInt32)(slot.regs[6] >> 3) & 7, (UInt32)(slot.regs[6] & 7), 0); lfo_compute_step(ptChip, slot.amplitude_lfo, (UInt32)(slot.regs[6] >> 3) & 7, (UInt32)(slot.regs[7] & 7), 1); } } break; } }