public M4AWrappedKeySplit(M4AVoiceEntry keySplit) : base(keySplit) { try { Table = VoiceTable.LoadTable <M4AVoiceTable>(keySplit.Address - ROM.Pak, true); var keys = ROM.Instance.Reader.ReadBytes(128, keySplit.Keys - ROM.Pak); var loading = new List <Triple <byte, byte, byte> >(); // Key, min, max int prev = -1; for (int i = 0; i < 128; 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(); } catch { Table = null; Keys = null; } }
public M4AWrappedDrum(M4AVoiceEntry drum) : base(drum) { try { Table = VoiceTable.LoadTable <M4AVoiceTable>(drum.Address - ROM.Pak, true); } catch { Table = null; } }
public M4AWrappedDirect(M4AVoiceEntry direct) : base(direct) => Sample = new M4AWrappedSample(direct.Address - ROM.Pak);
void AddPSG(M4AVoiceEntry entry, byte low = 0, byte high = 0x7F) { int sample; M4AVoiceType type = (M4AVoiceType)(entry.Type & 0x7); if (type == M4AVoiceType.Square1 || type == M4AVoiceType.Square2) { sample = (int)entry.SquarePattern; } else if (type == M4AVoiceType.Wave) { sample = AddWave(entry.Address - ROM.Pak); } else if (type == M4AVoiceType.Noise) { sample = (int)entry.NoisePattern + 4; } else { return; } sf2.AddInstrumentBag(); high = Math.Min((byte)0x7F, high); if (!(low == 0 && high == 0x7F)) { sf2.AddInstrumentGenerator(SF2Generator.KeyRange, new SF2GeneratorAmount { LowByte = low, HighByte = high }); } // ADSR if (entry.ADSR.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 = entry.ADSR.A / 5d; double att = 1200 * Math.Log(att_time, 2); sf2.AddInstrumentGenerator(SF2Generator.AttackVolEnv, new SF2GeneratorAmount { Amount = (short)att }); } if (entry.ADSR.S != 15) { double sus; // Compute attenuation in cB if sustain is non-zero if (entry.ADSR.S != 0) { sus = 100 * Math.Log(15d / entry.ADSR.S); } // Special case where attenuation is infinite -> use max value else { sus = 1000; } sf2.AddInstrumentGenerator(SF2Generator.SustainVolEnv, new SF2GeneratorAmount { Amount = (short)sus }); double dec_time = entry.ADSR.D / 5d; double dec = 1200 * Math.Log(dec_time + 1, 2); sf2.AddInstrumentGenerator(SF2Generator.DecayVolEnv, new SF2GeneratorAmount { Amount = (short)dec }); } if (entry.ADSR.R != 0) { double rel_time = entry.ADSR.R / 5d; double rel = 1200 * Math.Log(rel_time, 2); sf2.AddInstrumentGenerator(SF2Generator.ReleaseVolEnv, new SF2GeneratorAmount { Amount = (short)rel }); } if (type == M4AVoiceType.Noise && entry.Panpot != 0) { sf2.AddInstrumentGenerator(SF2Generator.Pan, new SF2GeneratorAmount { Amount = (short)((entry.Panpot - 0xC0) * (500d / 0x80)) }); } sf2.AddInstrumentGenerator(SF2Generator.SampleModes, new SF2GeneratorAmount { Amount = 1 }); sf2.AddInstrumentGenerator(SF2Generator.SampleID, new SF2GeneratorAmount { Amount = (short)sample }); }