void AddTable(M4AVoiceTable table, bool saveAfter7F, bool isNewInst) { int amt = saveAfter7F ? 0xFF : 0x7F; for (ushort i = 0; i <= amt; i++) { var voice = table[i]; if (instruments.Contains(voice)) { continue; } instruments.Add(voice); if (isNewInst) { string name = "Instrument " + i; AddPreset(name, i); sf2.AddInstrument(name); } if (voice is M4ASDirect direct) { if (!isNewInst) { AddDirect(direct, (byte)i, (byte)i); sf2.AddINSTGenerator(SF2Generator.overridingRootKey, new GenAmountType((ushort)(i - (direct.Voice.GetRootNote() - 60)))); } else { AddDirect(direct); } } else if (voice.Voice is M4APSG_Square_1 || voice.Voice is M4APSG_Square_2 || voice.Voice is M4APSG_Wave || voice.Voice is M4APSG_Noise) { var m4 = (M4AVoice)voice.Voice; if (!isNewInst) { if (voice.Voice is M4APSG_Noise) { AddPSG(m4, (byte)i, (byte)i); sf2.AddINSTGenerator(SF2Generator.overridingRootKey, new GenAmountType((ushort)(i - (m4.RootNote - 60)))); } } else { AddPSG(m4); if (!(voice.Voice is M4APSG_Noise)) { sf2.AddINSTGenerator(SF2Generator.overridingRootKey, new GenAmountType(69)); } } } else if (isNewInst && voice is M4ASMulti multi) { foreach (var key in multi.Keys) { if (key.Item1 > amt || key.Item2 > amt) { continue; } var subvoice = multi.Table[key.Item1]; if (subvoice is M4ASDirect subdirect) { AddDirect(subdirect, key.Item2, key.Item3); } } } else if (voice is M4ASDrum drum) { AddTable(drum.Table, saveAfter7F, false); } } }