/// <summary> /// http://www.deflemask.com/DMP_SPECS.txt /// </summary> public void ReadFromDMP(byte[] data) { int position = 0; //START OF DMP FORMAT // 1 Byte: FILE_VERSION, must be 11(0x0B) for DefleMask v0.12.0 FILE_VERSION = data[position]; position++; // 1 Byte: System: //SYSTEM_YM2151 0x08 SYSTEM_YM2151 = data[position]; position++; // 1 Byte: Instrument Mode(1 = FM, 0 = STANDARD) INSTRUMENT_MODE = data[position]; position++; // IF INSTRUMENT MODE IS FM ( = 1) // 1 Byte: LFO(FMS on YM2612, PMS on YM2151) PMS = data[position]; position++; // 1 Byte: FB FB = data[position]; position++; // 1 Byte: ALG CON = data[position]; position++; // 1 Byte: LFO2(AMS on YM2612, AMS on YM2151) AMS = data[position]; position++; // Repeat this TOTAL_OPERATORS times for (int i = 0; i < 4; i++) { //1 Byte: MULT OPS[i].MULT = data[position]; position++; //1 Byte: TL OPS[i].TL = data[position]; position++; //1 Byte: AR OPS[i].AR = data[position]; position++; //1 Byte: DR OPS[i].D1R = data[position]; position++; //1 Byte: SL OPS[i].D1L = data[position]; position++; //1 Byte: RR OPS[i].RR = data[position]; position++; //1 Byte: AM OPS[i].AM = data[position]; position++; //1 Byte: RS //Probably Key Scale OPS[i].KS = data[position]; position++; //1 Byte: DT(DT2 << 4 | DT on YM2151) OPS[i].DT = data[position]; position++; OPS[i].DT2 = (byte)(OPS[i].DT >> 4); //1 Byte: D2R OPS[i].D2R = data[position]; position++; //1 Byte: SSGEG_Enabled << 3 | SSGEG OPS[i].SSGEG_Enabled = data[position]; position++; } //For some reason Operator 1 and 2 are swapped in the DMP file... YM2151operator op = OPS[1]; OPS[1] = OPS[2]; OPS[2] = op; //END OF DMP FORMAT }
public static void LoadFromYM3812Operator(TrackConv.YM2151operator ym2151op, YM3812OperatorStats ym3812op) { ym2151op.AM = ym3812op.AmpMod ? (byte)1 : (byte)0; ym2151op.AR = (byte)(ym3812op.Attack << 1); ym2151op.D1L = (byte)ym3812op.Sustain; ym2151op.D1R = (byte)(ym3812op.Decay << 1); ym2151op.D2R = (byte)(ym3812op.Release << 1); ym2151op.DT = 0; ym2151op.DT2 = 0; ym2151op.KS = (byte)ym3812op.KeyScaling; ym2151op.MULT = (byte)ym3812op.Mult; ym2151op.RR = (byte)(ym3812op.Release << 1); ym2151op.TL = (byte)(ym3812op.TotalLevel << 1); }
private void SetVolumeToBytes(Dictionary<byte, byte> bytes, int slot, YM2151operator op, byte volume) { byte register, value = 0; //Liner volume - forget it. Little Japanese designer can't do it simply. //byte desiredvolume = (byte)(127 - ((127 - op.TL) * volume) / 64); //Nonlinear volume byte desiredvolume = op.TL > 64 ? op.TL : (byte)(127 - (63 + ((63 - op.TL) * volume / 64))); //$60-$7F -VVVVVVV Slot1 - 32. Volume V = Volume(TL)(0 = max) register = (byte)(0x60 + slot); value = 0; value += desiredvolume; bytes[register] = value; }
public static void SetYM2151Operator(YM2151 ym2151, int slot, TrackConv.YM2151operator op) { byte register = 0; byte value = 0; //$40-$5F -DDDMMMM Slot1 - 32. Detune / Mult D = Detune D1T, M = Mult register = (byte)(0x40 + slot); value = 0; value += (byte)(op.DT << 4); value += op.MULT; ym2151.registers[register] = value; //$60-$7F -VVVVVVV Slot1 - 32. Volume V = Volume(TL)(0 = max) register = (byte)(0x60 + slot); value = 0; value += op.TL; ym2151.registers[register] = value; volumestat.Add(value); //$80-$9F KK-AAAAA Slot1 - 32. Keyscale / Attack K = Keycale, A = attack register = (byte)(0x80 + slot); value = 0; value += (byte)(op.KS << 6); value += op.AR; ym2151.registers[register] = value; //$A0-$BF A--DDDDD Slot1 - 32. AMS Enable / Decay A = AMS - EN, D = Decay D1R register = (byte)(0xA0 + slot); value = 0; value += (byte)(op.AM << 7); value += op.D1R; ym2151.registers[register] = value; //$C0-$DF TT-DDDDD Slot1 - 32. DeTune2 / Decay2 T = Detune DT2, D = Decay D2R register = (byte)(0xC0 + slot); value = 0; value += (byte)(op.DT2 << 6); value += op.D2R; ym2151.registers[register] = value; //$E0-$FF DDDDRRRR Slot1 - 32. Decay Level/ Release D = Decay D1L, R = Release Rate register = (byte)(0xE0 + slot); value = 0; value += (byte)(op.D1L << 4); value += op.RR; ym2151.registers[register] = value; }
public void SetVolumeToBytes(Dictionary<byte, byte> bytes, int channel, byte volume) { foreach (SlotByOperator sbo in OutSlotByAlg[CON]) { int slot = (int)sbo * 8 + channel; YM2151operator op = OPS[(int)sbo]; SetVolumeToBytes(bytes, slot, op, volume); } //Set volume for all operators - less good //for (int i = 0; i < 4; i++) //{ // int slot = i * 8 + channel; // YM2151operator op = OPS[i]; // SetVolumeToBytes(bytes, slot, op, volume); //} }
public Dictionary<byte, byte> ToControlBytes(int channel, byte volume = 64, bool left = true, bool right = true) { byte register, value = 0; Dictionary<byte, byte> bytes = new Dictionary<byte, byte>(); channel = (byte)channel & 0b00000111; //$20-$27 LRFFFCCC Channel 0-7 L = Left, R = Right, F = Feedback, C = Connection register = (byte)(0x20 + channel); value = 0; value += (byte)(left ? 0b10000000 : 0); value += (byte)(right ? 0b01000000 : 0); value += (byte)(FB << 3); value += CON; bytes[register] = value; //$38-$3F -PPP--AA Channel 0-7 PMS / AMS P = PMS , A = AMS register = (byte)(0x38 + channel); value = 0; value += (byte)(PMS << 4); value += AMS; bytes[register] = value; for (int i = 0; i < 4; i++) { int slot = i * 8 + channel; YM2151operator op = OPS[i]; //$40-$5F -DDDMMMM Slot1 - 32. Detune / Mult D = Detune D1T, M = Mult register = (byte)(0x40 + slot); value = 0; value += (byte)(op.DT << 4); value += op.MULT; bytes[register] = value; SetVolumeToBytes(bytes, slot, op, volume); //$80-$9F KK-AAAAA Slot1 - 32. Keyscale / Attack K = Keycale, A = attack register = (byte)(0x80 + slot); value = 0; value += (byte)(op.KS << 6); value += op.AR; bytes[register] = value; //$A0-$BF A--DDDDD Slot1 - 32. AMS Enable / Decay A = AMS - EN, D = Decay D1R register = (byte)(0xA0 + slot); value = 0; value += (byte)(op.AM << 7); value += op.D1R; bytes[register] = value; //$C0-$DF TT-DDDDD Slot1 - 32. DeTune2 / Decay2 T = Detune DT2, D = Decay D2R register = (byte)(0xC0 + slot); value = 0; value += (byte)(op.DT2 << 6); value += op.D2R; bytes[register] = value; //$E0-$FF DDDDRRRR Slot1 - 32. Decay Level/ Release D = Decay D1L, R = Release Rate register = (byte)(0xE0 + slot); value = 0; value += (byte)(op.D1L << 4); value += op.RR; bytes[register] = value; } return bytes; }
public static void ConvertYM3812stateToYM2151state(YM3812 ym3812, YM2151 ym2151) { for (int channel = 0; channel < 9; channel++) { //int channel = 0; //var chs = ym3812.GetChannelStats(4); var chs = ym3812.GetChannelStats(channel); if (channel <= 7) { //Operator settings { int opnum = 0; TrackConv.YM2151operator op0 = new TrackConv.YM2151operator(); LoadFromYM3812Operator(op0, chs.OPR1); int slot = opnum * 8 + channel; SetYM2151Operator(ym2151, slot, op0); opnum = 2; TrackConv.YM2151operator op2 = new TrackConv.YM2151operator(); LoadFromYM3812Operator(op2, chs.OPR2); slot = opnum * 8 + channel; SetYM2151Operator(ym2151, slot, op2); } //PMS and AMS { byte PMS = chs.OPR2.Vibrato ? (byte)0x04 : (byte)0x00; byte AMS = chs.OPR2.AmpMod ? (byte)0x02 : (byte)0x00; //$38-$3F -PPP--AA Channel 0-7 PMS / AMS P = PMS , A = AMS byte register = (byte)(0x38 + channel); byte value = 0; value += (byte)(PMS << 4); value += AMS; ym2151.registers[register] = value; } //Connection and feedback { byte CON = 7; if (chs.Connection == 0) { CON = 6; } byte FB = (byte)chs.Feedback; //$20-$27 LRFFFCCC Channel 0-7 L = Left, R = Right, F = Feedback, C = Connection byte register = (byte)(0x20 + channel); byte value = 0b11000000; value += (byte)(FB << 3); value += CON; ym2151.registers[register] = value; } //Note (note octave cent) { var note = Tools.FrequencyToNote(chs.Freq); if (!note.OutOfRange) { int note_ = note.note; int octave_ = note.octave; int cent_ = note.cent; if (note.cent_sign < 0) { note_ -= 1; if (note_ < 0) { note_ = 11; octave_ -= 1; if (octave_ < 0) { note_ = 0; octave_ = 0; cent_ = -100; } } cent_ = 100 + cent_; } cent_ = cent_ * 64 / 100; //$28 -$2F -OOONNNN Chn0 - 7 KeyCode O = Octive, N = Note byte register = (byte)(0x28 + channel); byte value = 0; value += (byte)((note_ & 0b00000111) << 4); value += (byte)(octave_ & 0b00001111); ym2151.registers[register] = value; //$30 -$38 FFFFFF-- Chn0 - 7 F = keyFraction register = (byte)(0x30 + channel); value = 0; value += (byte)((cent_ & 0b00111111) << 2); ym2151.registers[register] = value; } } } } }