public AdLibInstrument(AdLibInstrument copy) { ModCharacteristic = copy.ModCharacteristic; ModScalingOutputLevel = copy.ModScalingOutputLevel; ModAttackDecay = copy.ModAttackDecay; ModSustainRelease = copy.ModSustainRelease; ModWaveformSelect = copy.ModWaveformSelect; CarCharacteristic = copy.CarCharacteristic; CarScalingOutputLevel = copy.CarScalingOutputLevel; CarAttackDecay = copy.CarAttackDecay; CarSustainRelease = copy.CarSustainRelease; CarWaveformSelect = copy.CarWaveformSelect; Feedback = copy.Feedback; FlagsA = copy.FlagsA; ExtraA = new InstrumentExtra(copy.ExtraA); FlagsB = copy.FlagsB; ExtraB = new InstrumentExtra(copy.ExtraB); Duration = copy.Duration; }
void AdlibSetupChannel(int chan, AdLibInstrument instr, byte vol1, byte vol2) { Debug.Assert(chan >= 0 && chan < 9); byte channel = operator1Offsets[chan]; AdlibWrite((byte)(channel + 0x20), instr.ModCharacteristic); AdlibWrite((byte)(channel + 0x40), (byte)((instr.ModScalingOutputLevel | 0x3F) - vol1)); AdlibWrite((byte)(channel + 0x60), (byte)(0xff & (~instr.ModAttackDecay))); AdlibWrite((byte)(channel + 0x80), (byte)(0xff & (~instr.ModSustainRelease))); AdlibWrite((byte)(channel + 0xE0), instr.ModWaveformSelect); channel = operator2Offsets[chan]; AdlibWrite((byte)(channel + 0x20), instr.CarCharacteristic); AdlibWrite((byte)(channel + 0x40), (byte)((instr.CarScalingOutputLevel | 0x3F) - vol2)); AdlibWrite((byte)(channel + 0x60), (byte)(0xff & (~instr.CarAttackDecay))); AdlibWrite((byte)(channel + 0x80), (byte)(0xff & (~instr.CarSustainRelease))); AdlibWrite((byte)(channel + 0xE0), instr.CarWaveformSelect); AdlibWrite((byte)(chan + 0xC0), instr.Feedback #if ENABLE_OPL3 | (_opl3Mode ? 0x30 : 0) #endif ); }
void McKeyOn(AdLibVoice voice, AdLibInstrument instr, byte note, byte velocity, AdLibInstrument second, byte pan) { AdLibPart part = voice.Part; byte vol1, vol2; #if ENABLE_OPL3 byte secVol1 = 0, secVol2 = 0; #endif voice.TwoChan = (byte)(instr.Feedback & 1); voice.Note = note; voice.WaitForPedal = false; voice.Duration = instr.Duration; if (voice.Duration != 0) voice.Duration *= 63; if (!_scummSmallHeader) { #if ENABLE_OPL3 if (_opl3Mode) vol1 = (instr.modScalingOutputLevel & 0x3F) + (velocity * ((instr.modWaveformSelect >> 3) + 1)) / 64; else #endif vol1 = (byte)((instr.ModScalingOutputLevel & 0x3F) + volumeLookupTable[velocity >> 1, instr.ModWaveformSelect >> 2]); } else { vol1 = (byte)(0x3f - (instr.ModScalingOutputLevel & 0x3F)); } if (vol1 > 0x3F) vol1 = 0x3F; voice.Vol1 = vol1; if (!_scummSmallHeader) { #if ENABLE_OPL3 if (_opl3Mode) vol2 = (instr.carScalingOutputLevel & 0x3F) + (velocity * ((instr.carWaveformSelect >> 3) + 1)) / 64; else #endif vol2 = (byte)((instr.CarScalingOutputLevel & 0x3F) + volumeLookupTable[velocity >> 1, instr.CarWaveformSelect >> 2]); } else { vol2 = (byte)(0x3f - (instr.CarScalingOutputLevel & 0x3F)); } if (vol2 > 0x3F) vol2 = 0x3F; voice.Vol2 = vol2; #if ENABLE_OPL3 if (_opl3Mode) { voice._secTwoChan = second.feedback & 1; secVol1 = (second.modScalingOutputLevel & 0x3F) + (velocity * ((second.modWaveformSelect >> 3) + 1)) / 64; if (secVol1 > 0x3F) { secVol1 = 0x3F; } voice._secVol1 = secVol1; secVol2 = (second.carScalingOutputLevel & 0x3F) + (velocity * ((second.carWaveformSelect >> 3) + 1)) / 64; if (secVol2 > 0x3F) { secVol2 = 0x3F; } voice._secVol2 = secVol2; } #endif if (!_scummSmallHeader) { #if ENABLE_OPL3 if (!_opl3Mode) { #endif int c = part._volEff >> 2; vol2 = volumeTable[volumeLookupTable[vol2, c]]; if (voice.TwoChan != 0) vol1 = volumeTable[volumeLookupTable[vol1, c]]; #if ENABLE_OPL3 } else { vol2 = g_volumeTable[((vol2 + 1) * part._volEff) >> 7]; secVol2 = g_volumeTable[((secVol2 + 1) * part._volEff) >> 7]; if (voice._twoChan) vol1 = g_volumeTable[((vol1 + 1) * part._volEff) >> 7]; if (voice._secTwoChan) secVol1 = g_volumeTable[((secVol1 + 1) * part._volEff) >> 7]; } #endif } AdlibSetupChannel(voice.Channel, instr, vol1, vol2); #if ENABLE_OPL3 if (!_opl3Mode) { #endif AdlibNoteOnEx(voice.Channel, /*part._transposeEff + */note, part._detuneEff + (part._pitchBend * part._pitchBendFactor >> 6)); if ((instr.FlagsA & 0x80) != 0) { McInitStuff(voice, voice.S10a, voice.S11a, instr.FlagsA, instr.ExtraA); } else { voice.S10a.Active = 0; } if ((instr.FlagsB & 0x80) != 0) { McInitStuff(voice, voice.S10b, voice.S11b, instr.FlagsB, instr.ExtraB); } else { voice.S10b.Active = 0; } #if ENABLE_OPL3 } else { adlibSetupChannelSecondary(voice._channel, second, secVol1, secVol2, pan); adlibNoteOnEx(voice._channel, note, part._pitchBend >> 1); } #endif }
void PartKeyOn(AdLibPart part, AdLibInstrument instr, byte note, byte velocity, AdLibInstrument second, byte pan) { var voice = AllocateVoice(part._priEff); if (voice == null) return; LinkMc(part, voice); McKeyOn(voice, instr, note, velocity, second, pan); }
// SysEx messages public override void SysExCustomInstrument(uint type, byte[] instr) { // We do not allow custom instruments in OPL3 mode right now. #if ENABLE_OPL3 if (_owner._opl3Mode) { warning("AdLibPercussionChannel::sysEx_customInstrument: Used in OPL3 mode"); return; } #endif if (type == ToType("ADLP")) { byte note = instr[0]; _notes[note] = instr[1]; // Allocate memory for the new instruments if (_customInstruments[note] == null) { _customInstruments[note] = new AdLibInstrument(); } // Save the new instrument data _customInstruments[note].ModCharacteristic = instr[2]; _customInstruments[note].ModScalingOutputLevel = instr[3]; _customInstruments[note].ModAttackDecay = instr[4]; _customInstruments[note].ModSustainRelease = instr[5]; _customInstruments[note].ModWaveformSelect = instr[6]; _customInstruments[note].CarCharacteristic = instr[7]; _customInstruments[note].CarScalingOutputLevel = instr[8]; _customInstruments[note].CarAttackDecay = instr[9]; _customInstruments[note].CarSustainRelease = instr[10]; _customInstruments[note].CarWaveformSelect = instr[11]; _customInstruments[note].Feedback = instr[12]; } }
public AdLibPercussionChannel() { _notes = new byte[256]; _customInstruments = new AdLibInstrument[256]; }
public override void ProgramChange(byte program) { if (program > 127) return; _program = program; #if ENABLE_OPL3 if (!_owner._opl3Mode) { #endif _partInstr = new AdLibInstrument(gmInstruments[program]); #if ENABLE_OPL3 } else { memcpy(&_partInstr, &g_gmInstrumentsOPL3[program][0], sizeof(AdLibInstrument)); memcpy(&_partInstrSecondary, &g_gmInstrumentsOPL3[program][1], sizeof(AdLibInstrument)); } #endif }