/// <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
        }
Example #2
0
 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  -​V​V​V​V​V​V​V​    Slot1 - 32.     Volume​     V = Volume(TL)(0 = max)​
            register = (byte)(0x60 + slot);
            value = 0;
            value += desiredvolume;
            bytes[register] = value;
        }
Example #4
0
        public static void SetYM2151Operator(YM2151 ym2151, int slot, TrackConv.YM2151operator op)
        {
            byte register = 0;
            byte value    = 0;

            //$40-$5F	-​D​D​D​M​M​M​M​    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  -​V​V​V​V​V​V​V​    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  K​K​-​A​AA​A​A​     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​-​-​D​D​D​D​D​    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	T​T​-​D​D​D​D​D​    Slot1 - 32.     DeTune2 / Decay​2         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  D​D​D​D​R​R​R​R​    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   L​R​F​F​F​C​C​C​    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	-P​P​P​--​A​A​    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	-​D​D​D​M​M​M​M​    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  K​K​-​A​AA​A​A​     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​-​-​D​D​D​D​D​    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	T​T​-​D​D​D​D​D​    Slot1 - 32.     DeTune2 / Decay​2         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  D​D​D​D​R​R​R​R​    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;
        }
Example #7
0
        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	-P​P​P​--​A​A​    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   L​R​F​F​F​C​C​C​    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 -​O​O​O​N​N​N​N​     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;
                        }
                    }
                }
            }
        }