示例#1
0
        internal M4ASMulti(M4AVoice ks) : base(ks)
        {
            Table = VoiceTable.LoadTable <M4AVoiceTable>(ks.Table, true);

            var keys    = ROM.Instance.ReadBytes(256, ks.Keys);
            var loading = new List <Triple <byte, byte, byte> >(); // Key, min, max
            int prev    = -1;

            for (int i = 0; i < 256; i++)
            {
                byte a  = keys[i];
                byte bi = (byte)i;
                if (prev == a)
                {
                    loading[loading.Count - 1].Item3 = bi;
                }
                else
                {
                    prev = a;
                    loading.Add(new Triple <byte, byte, byte>(a, bi, bi));
                }
            }
            Keys = loading.ToArray();
        }
示例#2
0
        void AddPSG(M4AVoice voice, byte low = 0, byte high = 127)
        {
            dynamic v = voice;
            int     sample;

            if (voice is M4APSG_Square_1 || voice is M4APSG_Square_2)
            {
                sample = AddSample(SongPlayer.Sounds[SongPlayer.SQUARE12_ID - v.Pattern], "Square Wave " + v.Pattern);
            }
            else if (voice is M4APSG_Wave wave)
            {
                sample = AddSample(SongPlayer.Sounds[wave.Address], string.Format("PSG Wave 0x{0:X}", wave.Address));
            }
            else
            {
                sample = AddSample(SongPlayer.Sounds[SongPlayer.NOISE0_ID - v.Pattern], "Noise " + v.Pattern);
            }

            sf2.AddINSTBag();

            // ADSR
            if (v.A != 0)
            {
                // Compute attack time - the sound engine is called 60 times per second
                // and adds "attack" to envelope every time the engine is called
                double att_time = v.A / 5.0;
                double att      = 1200 * Math.Log(att_time, 2);
                sf2.AddINSTGenerator(SF2Generator.attackVolEnv, new GenAmountType((ushort)att));
            }
            if (v.S != 15)
            {
                double sus;
                // Compute attenuation in cB if sustain is non-zero
                if (v.S != 0)
                {
                    sus = 100 * Math.Log(15d / v.S);
                }
                // Special case where attenuation is infinite -> use max value
                else
                {
                    sus = 1000;
                }

                sf2.AddINSTGenerator(SF2Generator.sustainVolEnv, new GenAmountType((ushort)sus));

                double dec_time = v.D / 5d;
                double dec      = 1200 * Math.Log(dec_time + 1, 2);
                sf2.AddINSTGenerator(SF2Generator.decayVolEnv, new GenAmountType((ushort)dec));
            }
            if (v.R != 0)
            {
                double rel_time = v.R / 5d;
                double rel      = 1200 * Math.Log(rel_time, 2);
                sf2.AddINSTGenerator(SF2Generator.releaseVolEnv, new GenAmountType((ushort)rel));
            }

            high = Math.Min((byte)127, high);
            if (!(low == 0 && high == 127))
            {
                sf2.AddINSTGenerator(SF2Generator.keyRange, new GenAmountType(low, high));
            }
            if (voice is M4APSG_Noise noise && noise.Panpot != 0)
            {
                sf2.AddINSTGenerator(SF2Generator.pan, new GenAmountType((ushort)((noise.Panpot - 0xC0) * (500d / 0x80))));
            }
            sf2.AddINSTGenerator(SF2Generator.sampleModes, new GenAmountType(1));
            sf2.AddINSTGenerator(SF2Generator.sampleID, new GenAmountType((ushort)(sample)));
        }
示例#3
0
 internal M4ASDirect(M4AVoice direct) : base(direct) => Sample = new M4ASSample(direct.Address);
示例#4
0
 internal M4ASWave(M4AVoice wave) : base(wave) => sample = ROM.Instance.ReadBytes(16, wave.Address);
示例#5
0
 internal M4ASDrum(M4AVoice d) : base(d)
 {
     Table = VoiceTable.LoadTable <M4AVoiceTable>(d.Table, true);
 }