public void Load(Sf2Region region, AssetManager assets) { ExclusiveGroup = region.Generators[(int)GeneratorEnum.ExclusiveClass]; ExclusiveGroupTarget = ExclusiveGroup; iniFilterFc = region.Generators[(int)GeneratorEnum.InitialFilterCutoffFrequency]; filterQ = SynthHelper.DBtoLinear(region.Generators[(int)GeneratorEnum.InitialFilterQ] / 10.0); initialAttn = -region.Generators[(int)GeneratorEnum.InitialAttenuation] / 10f; keyOverride = region.Generators[(int)GeneratorEnum.KeyNumber]; velOverride = region.Generators[(int)GeneratorEnum.Velocity]; keynumToModEnvHold = region.Generators[(int)GeneratorEnum.KeyNumberToModulationEnvelopeHold]; keynumToModEnvDecay = region.Generators[(int)GeneratorEnum.KeyNumberToModulationEnvelopeDecay]; keynumToVolEnvHold = region.Generators[(int)GeneratorEnum.KeyNumberToVolumeEnvelopeHold]; keynumToVolEnvDecay = region.Generators[(int)GeneratorEnum.KeyNumberToVolumeEnvelopeDecay]; pan = new PanComponent(); pan.SetValue(region.Generators[(int)GeneratorEnum.Pan] / 500f, PanFormulaEnum.Neg3dBCenter); modLfoToPitch = region.Generators[(int)GeneratorEnum.ModulationLFOToPitch]; vibLfoToPitch = region.Generators[(int)GeneratorEnum.VibratoLFOToPitch]; modEnvToPitch = region.Generators[(int)GeneratorEnum.ModulationEnvelopeToPitch]; modLfoToFilterFc = region.Generators[(int)GeneratorEnum.ModulationLFOToFilterCutoffFrequency]; modEnvToFilterFc = region.Generators[(int)GeneratorEnum.ModulationEnvelopeToFilterCutoffFrequency]; modLfoToVolume = region.Generators[(int)GeneratorEnum.ModulationLFOToVolume] / 10f; LoadGen(region, assets); LoadEnvelopes(region); LoadLfos(region); LoadFilter(region); }
public void LoadSf2(IReadable input) { Reset(); Logger.Debug("Reading SF2"); var sf = new SoundFont(); sf.Load(input); Logger.Debug("Building patchbank"); Name = sf.Info.BankName; Comments = sf.Info.Comments; //load samples foreach (var sampleHeader in sf.Presets.SampleHeaders) { _assets.SampleAssets.Add(new SampleDataAsset(sampleHeader, sf.SampleData)); } //create instrument regions first var sfinsts = ReadSf2Instruments(sf.Presets.Instruments); //load each patch foreach (var p in sf.Presets.PresetHeaders) { Generator[] globalGens = null; int i; if (p.Zones[0].Generators.Length == 0 || p.Zones[0].Generators[p.Zones[0].Generators.Length - 1].GeneratorType != GeneratorEnum.Instrument) { globalGens = p.Zones[0].Generators; i = 1; } else { i = 0; } var regionList = new FastList<Sf2Region>(); while (i < p.Zones.Length) { byte presetLoKey = 0; byte presetHiKey = 127; byte presetLoVel = 0; byte presetHiVel = 127; if (p.Zones[i].Generators[0].GeneratorType == GeneratorEnum.KeyRange) { if (TypeUtils.IsLittleEndian) { presetLoKey = TypeUtils.ToUInt8(p.Zones[i].Generators[0].AmountInt16 & 0xFF); presetHiKey = TypeUtils.ToUInt8((p.Zones[i].Generators[0].AmountInt16 >> 8) & 0xFF); } else { presetHiKey = TypeUtils.ToUInt8(p.Zones[i].Generators[0].AmountInt16 & 0xFF); presetLoKey = TypeUtils.ToUInt8((p.Zones[i].Generators[0].AmountInt16 >> 8) & 0xFF); } if (p.Zones[i].Generators.Length > 1 && p.Zones[i].Generators[1].GeneratorType == GeneratorEnum.VelocityRange) { if (TypeUtils.IsLittleEndian) { presetLoVel = TypeUtils.ToUInt8(p.Zones[i].Generators[1].AmountInt16 & 0xFF); presetHiVel = TypeUtils.ToUInt8((p.Zones[i].Generators[1].AmountInt16 >> 8) & 0xFF); } else { presetHiVel = TypeUtils.ToUInt8(p.Zones[i].Generators[1].AmountInt16 & 0xFF); presetLoVel = TypeUtils.ToUInt8((p.Zones[i].Generators[1].AmountInt16 >> 8) & 0xFF); } } } else if (p.Zones[i].Generators[0].GeneratorType == GeneratorEnum.VelocityRange) { if (TypeUtils.IsLittleEndian) { presetLoVel = TypeUtils.ToUInt8(p.Zones[i].Generators[0].AmountInt16 & 0xFF); presetHiVel = TypeUtils.ToUInt8((p.Zones[i].Generators[0].AmountInt16 >> 8) & 0xFF); } else { presetHiVel = TypeUtils.ToUInt8(p.Zones[i].Generators[0].AmountInt16 & 0xFF); presetLoVel = TypeUtils.ToUInt8((p.Zones[i].Generators[0].AmountInt16 >> 8) & 0xFF); } } if (p.Zones[i].Generators[p.Zones[i].Generators.Length - 1].GeneratorType == GeneratorEnum.Instrument) { var insts = sfinsts[p.Zones[i].Generators[p.Zones[i].Generators.Length - 1].AmountInt16]; foreach (var inst in insts) { byte instLoKey; byte instHiKey; byte instLoVel; byte instHiVel; if (TypeUtils.IsLittleEndian) { instLoKey = TypeUtils.ToUInt8(inst.Generators[(int)GeneratorEnum.KeyRange] & 0xFF); instHiKey = TypeUtils.ToUInt8((inst.Generators[(int)GeneratorEnum.KeyRange] >> 8) & 0xFF); instLoVel = TypeUtils.ToUInt8(inst.Generators[(int)GeneratorEnum.VelocityRange] & 0xFF); instHiVel = TypeUtils.ToUInt8((inst.Generators[(int)GeneratorEnum.VelocityRange] >> 8) & 0xFF); } else { instHiKey = TypeUtils.ToUInt8(inst.Generators[(int)GeneratorEnum.KeyRange] & 0xFF); instLoKey = TypeUtils.ToUInt8((inst.Generators[(int)GeneratorEnum.KeyRange] >> 8) & 0xFF); instHiVel = TypeUtils.ToUInt8(inst.Generators[(int)GeneratorEnum.VelocityRange] & 0xFF); instLoVel = TypeUtils.ToUInt8((inst.Generators[(int)GeneratorEnum.VelocityRange] >> 8) & 0xFF); } if ((instLoKey <= presetHiKey && presetLoKey <= instHiKey) && (instLoVel <= presetHiVel && presetLoVel <= instHiVel)) { var r = new Sf2Region(); Std.ArrayCopy(inst.Generators, 0, r.Generators, 0, r.Generators.Length); ReadSf2Region(r, globalGens, p.Zones[i].Generators, true); regionList.Add(r); } } } i++; } var mp = new MultiPatch(p.Name); mp.LoadSf2(regionList.ToArray(), _assets); _assets.PatchAssets.Add(new PatchAsset(mp.Name, mp)); AssignPatchToBank(mp, p.BankNumber, p.PatchNumber, p.PatchNumber); } }
private void ReadSf2Region(Sf2Region region, Generator[] globals, Generator[] gens, bool isRelative) { if (!isRelative) { if (globals != null) { for (int x = 0; x < globals.Length; x++) { region.Generators[(int) globals[x].GeneratorType] = globals[x].AmountInt16; } } for (int x = 0; x < gens.Length; x++) { region.Generators[(int) gens[x].GeneratorType] = gens[x].AmountInt16; } } else { var genList = new FastList<Generator>(); foreach (var generator in gens) { genList.Add(generator); } if (globals != null) { for (int x = 0; x < globals.Length; x++) { var found = false; for (int i = 0; i < genList.Count; i++) { if (genList[i].GeneratorType == globals[x].GeneratorType) { found = true; break; } } if (!found) { genList.Add(globals[x]); } } } for (int x = 0; x < genList.Count; x++) { var value = (int)genList[x].GeneratorType; if (value < 5 || value == 12 || value == 45 || value == 46 || value == 47 || value == 50 || value == 54 || value == 57 || value == 58) { continue; } else if (value == 43 || value == 44) { byte lo_a; byte hi_a; byte lo_b; byte hi_b; if (TypeUtils.IsLittleEndian) { lo_a = TypeUtils.ToUInt8(region.Generators[value] & 0xFF); hi_a = TypeUtils.ToUInt8((region.Generators[value] >> 8) & 0xFF); lo_b = TypeUtils.ToUInt8(genList[x].AmountInt16 & 0xFF); hi_b = TypeUtils.ToUInt8((genList[x].AmountInt16 >> 8) & 0xFF); } else { hi_a = TypeUtils.ToUInt8(region.Generators[value] & 0xFF); lo_a = TypeUtils.ToUInt8((region.Generators[value] >> 8) & 0xFF); hi_b = TypeUtils.ToUInt8(genList[x].AmountInt16 & 0xFF); lo_b = TypeUtils.ToUInt8((genList[x].AmountInt16 >> 8) & 0xFF); } lo_a = (byte) Math.Max(lo_a, lo_b); hi_a = Math.Min(hi_a, hi_b); if (lo_a > hi_a) { throw new Exception("Invalid sf2 region. The range generators do not intersect."); } if (TypeUtils.IsLittleEndian) { region.Generators[value] = TypeUtils.ToInt16((lo_a | (hi_a << 8))); } else { region.Generators[value] = TypeUtils.ToInt16((lo_a << 8) | hi_a); } } else { region.Generators[value] = TypeUtils.ToInt16(region.Generators[value] + genList[x].AmountInt16); } } } }
private Sf2Region[][] ReadSf2Instruments(Instrument[] instruments) { var regions = new Sf2Region[instruments.Length][]; for (int x = 0; x < instruments.Length; x++) { Generator[] globalGens = null; int i; if (instruments[x].Zones[0].Generators.Length == 0 || instruments[x].Zones[0].Generators[instruments[x].Zones[0].Generators.Length - 1].GeneratorType != GeneratorEnum.SampleID) { globalGens = instruments[x].Zones[0].Generators; i = 1; } else i = 0; regions[x] = new Sf2Region[instruments[x].Zones.Length - i]; for (int j = 0; j < regions[x].Length; j++) { var r = new Sf2Region(); r.ApplyDefaultValues(); ReadSf2Region(r, globalGens, instruments[x].Zones[j + i].Generators, false); regions[x][j] = r; } } return regions; }
private void LoadLfos(Sf2Region region) { mod_lfo = new LfoDescriptor(); mod_lfo.DelayTime = (float)Math.Pow(2, region.Generators[(int)GeneratorEnum.DelayModulationLFO] / 1200.0); mod_lfo.Frequency = (float)(Math.Pow(2, region.Generators[(int)GeneratorEnum.FrequencyModulationLFO] / 1200.0) * 8.176); mod_lfo.Generator = DefaultGenerators.DefaultSine; vib_lfo = new LfoDescriptor(); vib_lfo.DelayTime = (float)Math.Pow(2, region.Generators[(int)GeneratorEnum.DelayVibratoLFO] / 1200.0); vib_lfo.Frequency = (float)(Math.Pow(2, region.Generators[(int)GeneratorEnum.FrequencyVibratoLFO] / 1200.0) * 8.176); vib_lfo.Generator = DefaultGenerators.DefaultSine; }
private void LoadGen(Sf2Region region, AssetManager assets) { SampleDataAsset sda = assets.SampleAssets[region.Generators[(int)GeneratorEnum.SampleID]]; gen = new SampleGenerator(); gen.EndPhase = sda.End + region.Generators[(int)GeneratorEnum.EndAddressOffset] + 32768 * region.Generators[(int)GeneratorEnum.EndAddressCoarseOffset]; gen.Frequency = sda.SampleRate; gen.KeyTrack = region.Generators[(int)GeneratorEnum.ScaleTuning]; gen.LoopEndPhase = sda.LoopEnd + region.Generators[(int)GeneratorEnum.EndLoopAddressOffset] + 32768 * region.Generators[(int)GeneratorEnum.EndLoopAddressCoarseOffset]; switch (region.Generators[(int)GeneratorEnum.SampleModes] & 0x3) { case 0x0: case 0x2: gen.LoopMode = LoopMode.NoLoop; break; case 0x1: gen.LoopMode = LoopMode.Continuous; break; case 0x3: gen.LoopMode = LoopMode.LoopUntilNoteOff; break; } gen.LoopStartPhase = sda.LoopStart + region.Generators[(int)GeneratorEnum.StartLoopAddressOffset] + 32768 * region.Generators[(int)GeneratorEnum.StartLoopAddressCoarseOffset]; gen.Offset = 0; gen.Period = 1.0; if (region.Generators[(int)GeneratorEnum.OverridingRootKey] > -1) gen.RootKey = region.Generators[(int)GeneratorEnum.OverridingRootKey]; else gen.RootKey = sda.RootKey; gen.StartPhase = sda.Start + region.Generators[(int)GeneratorEnum.StartAddressOffset] + 32768 * region.Generators[(int)GeneratorEnum.StartAddressCoarseOffset]; gen.Tune = (short)(sda.Tune + region.Generators[(int)GeneratorEnum.FineTune] + 100 * region.Generators[(int)GeneratorEnum.CoarseTune]); gen.VelocityTrack = 0; ((SampleGenerator)gen).Samples = sda.SampleData; }
private void LoadFilter(Sf2Region region) { fltr = new FilterDescriptor(); fltr.FilterMethod = FilterType.BiquadLowpass; fltr.CutOff = (float)SynthHelper.KeyToFrequency(region.Generators[(int)GeneratorEnum.InitialFilterCutoffFrequency] / 100.0, 69); fltr.Resonance = (float)SynthHelper.DBtoLinear(region.Generators[(int)GeneratorEnum.InitialFilterQ] / 10.0); }
private void LoadEnvelopes(Sf2Region region) { // //mod env mod_env = new EnvelopeDescriptor(); mod_env.AttackTime = (float)Math.Pow(2, region.Generators[(int)GeneratorEnum.AttackModulationEnvelope] / 1200.0); mod_env.AttackGraph = 3; mod_env.DecayTime = (float)Math.Pow(2, region.Generators[(int)GeneratorEnum.DecayModulationEnvelope] / 1200.0); mod_env.DelayTime = (float)Math.Pow(2, region.Generators[(int)GeneratorEnum.DelayModulationEnvelope] / 1200.0); mod_env.HoldTime = (float)Math.Pow(2, region.Generators[(int)GeneratorEnum.HoldModulationEnvelope] / 1200.0); mod_env.PeakLevel = 1; mod_env.ReleaseTime = (float)Math.Pow(2, region.Generators[(int)GeneratorEnum.ReleaseModulationEnvelope] / 1200.0); mod_env.StartLevel = 0; mod_env.SustainLevel = 1f - SynthHelper.ClampS(region.Generators[(int)GeneratorEnum.SustainModulationEnvelope], (short)0, (short)1000) / 1000f; //checks if (mod_env.AttackTime < 0.001f) mod_env.AttackTime = 0.001f; else if (mod_env.AttackTime > 100f) mod_env.AttackTime = 100f; if (mod_env.DecayTime < 0.001f) mod_env.DecayTime = 0; else if (mod_env.DecayTime > 100f) mod_env.DecayTime = 100f; if (mod_env.DelayTime < 0.001f) mod_env.DelayTime = 0; else if (mod_env.DelayTime > 20f) mod_env.DelayTime = 20f; if (mod_env.HoldTime < 0.001f) mod_env.HoldTime = 0; else if (mod_env.HoldTime > 20f) mod_env.HoldTime = 20f; if (mod_env.ReleaseTime < 0.001f) mod_env.ReleaseTime = 0.001f; else if (mod_env.ReleaseTime > 100f) mod_env.ReleaseTime = 100f; // // volume env vel_env = new EnvelopeDescriptor(); vel_env.AttackTime = (float)Math.Pow(2, region.Generators[(int)GeneratorEnum.AttackVolumeEnvelope] / 1200.0); vel_env.AttackGraph = 3; vel_env.DecayTime = (float)Math.Pow(2, region.Generators[(int)GeneratorEnum.DecayVolumeEnvelope] / 1200.0); vel_env.DelayTime = (float)Math.Pow(2, region.Generators[(int)GeneratorEnum.DelayVolumeEnvelope] / 1200.0); vel_env.HoldTime = (float)Math.Pow(2, region.Generators[(int)GeneratorEnum.HoldVolumeEnvelope] / 1200.0); vel_env.PeakLevel = 0; vel_env.ReleaseTime = (float)Math.Pow(2, region.Generators[(int)GeneratorEnum.ReleaseVolumeEnvelope] / 1200.0); vel_env.StartLevel = -100; vel_env.SustainLevel = SynthHelper.ClampS(region.Generators[(int)GeneratorEnum.SustainVolumeEnvelope], (short)0, (short)1000) / -10f; // checks if (vel_env.AttackTime < 0.001f) vel_env.AttackTime = 0.001f; else if (vel_env.AttackTime > 100f) vel_env.AttackTime = 100f; if (vel_env.DecayTime < 0.001f) vel_env.DecayTime = 0; else if (vel_env.DecayTime > 100f) vel_env.DecayTime = 100f; if (vel_env.DelayTime < 0.001f) vel_env.DelayTime = 0; else if (vel_env.DelayTime > 20f) vel_env.DelayTime = 20f; if (vel_env.HoldTime < 0.001f) vel_env.HoldTime = 0; else if (vel_env.HoldTime > 20f) vel_env.HoldTime = 20f; if (vel_env.ReleaseTime < 0.001f) vel_env.ReleaseTime = 0.001f; else if (vel_env.ReleaseTime > 100f) vel_env.ReleaseTime = 100f; }
public void LoadSf2(Sf2Region[] regions, AssetManager assets) { _intervalList = new PatchInterval[regions.Length]; for (int x = 0; x < regions.Length; x++) { byte loKey; byte hiKey; byte loVel; byte hiVel; if (TypeUtils.IsLittleEndian) { loKey = TypeUtils.ToUInt8(regions[x].Generators[(int)GeneratorEnum.KeyRange] & 0xFF); hiKey = TypeUtils.ToUInt8((regions[x].Generators[(int)GeneratorEnum.KeyRange] >> 8) & 0xFF); loVel = TypeUtils.ToUInt8(regions[x].Generators[(int)GeneratorEnum.VelocityRange] & 0xFF); hiVel = TypeUtils.ToUInt8((regions[x].Generators[(int)GeneratorEnum.VelocityRange] >> 8) & 0xFF); } else { hiKey = TypeUtils.ToUInt8(regions[x].Generators[(int)GeneratorEnum.KeyRange] & 0xFF); loKey = TypeUtils.ToUInt8((regions[x].Generators[(int)GeneratorEnum.KeyRange] >> 8) & 0xFF); hiVel = TypeUtils.ToUInt8(regions[x].Generators[(int)GeneratorEnum.VelocityRange] & 0xFF); loVel = TypeUtils.ToUInt8((regions[x].Generators[(int)GeneratorEnum.VelocityRange] >> 8) & 0xFF); } var sf2 = new Sf2Patch(Name + "_" + x); sf2.Load(regions[x], assets); _intervalList[x] = new PatchInterval(sf2, 0, 15, loKey, hiKey, loVel, hiVel); } DetermineIntervalType(); }