private void LoadFilter(Sf2Region region)
 {
     fltr = new FilterDescriptor();
     fltr.FilterMethod = FilterTypeEnum.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.Clamp(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.Clamp(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;
 }
 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 = AudioSynthesis.Bank.Components.Generators.Generator.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 = AudioSynthesis.Bank.Components.Generators.Generator.DefaultSine;
 }
 private void LoadGen(Sf2Region region, AssetManager assets)
 {
     SampleDataAsset sda = assets.SampleAssetList[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 = LoopModeEnum.NoLoop;
             break;
         case 0x1:
             gen.LoopMode = LoopModeEnum.Continuous;
             break;
         case 0x3:
             gen.LoopMode = LoopModeEnum.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;
 }
 public void Load(Sf2Region region, AssetManager assets)
 {
     this.exGroup = region.Generators[(int)GeneratorEnum.ExclusiveClass];
     this.exTarget = exGroup;
     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(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);
 }
        private void ReadSf2Region(Sf2Region region, Generator[] globals, Generator[] gens, bool isRelative)
        {
            if (isRelative == false)
            {
                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
            {
                List<Generator> genList = new List<Generator>(gens);
                if (globals != null)
                {
                    for (int x = 0; x < globals.Length; x++)
                    {
                        bool 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++)
                {
                    int 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)
                    {//calculate intersect
                        byte lo_a;
                        byte hi_a;
                        byte lo_b;
                        byte hi_b;
                        if (BitConverter.IsLittleEndian)
                        {
                            lo_a = (byte)(region.Generators[value] & 0xFF);
                            hi_a = (byte)((region.Generators[value] >> 8) & 0xFF);
                            lo_b = (byte)(genList[x].AmountInt16 & 0xFF);
                            hi_b = (byte)((genList[x].AmountInt16 >> 8) & 0xFF);
                        }
                        else
                        {
                            hi_a = (byte)(region.Generators[value] & 0xFF);
                            lo_a = (byte)((region.Generators[value] >> 8) & 0xFF);
                            hi_b = (byte)(genList[x].AmountInt16 & 0xFF);
                            lo_b = (byte)((genList[x].AmountInt16 >> 8) & 0xFF);
                        }
                        lo_a = 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 (BitConverter.IsLittleEndian)
                            region.Generators[value] = (short)(lo_a | (hi_a << 8));
                        else
                            region.Generators[value] = (short)((lo_a << 8) | hi_a);
                    }
                    else
                        region.Generators[value] += genList[x].AmountInt16;
                }
            }
        }
 private Sf2Region[][] ReadSf2Instruments(Instrument[] instruments)
 {
     Sf2Region[][] regions = new Sf2Region[instruments.Length][];
     for (int x = 0; x < regions.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++)
         {
             Sf2Region r = new Sf2Region();
             r.ApplyDefaultValues();
             ReadSf2Region(r, globalGens, instruments[x].Zones[j + i].Generators, false);
             regions[x][j] = r;
         }
     }
     return regions;
 }
 private void LoadSf2(Stream stream)
 {
     SoundFont sf = new SoundFont(stream);
     bankName = sf.Info.BankName;
     comment = sf.Info.Comments;
     //load samples
     for (int x = 0; x < sf.Presets.SampleHeaders.Length; x++)
         assets.SampleAssetList.Add(new SampleDataAsset(sf.Presets.SampleHeaders[x], sf.SampleData));
     //create instrument regions first
     Sf2Region[][] inst = ReadSf2Instruments(sf.Presets.Instruments);
     //load each patch
     foreach (PresetHeader 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;
         List<Sf2Region> regionList = new List<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 (BitConverter.IsLittleEndian)
                 {
                     presetLoKey = (byte)(p.Zones[i].Generators[0].AmountInt16 & 0xFF);
                     presetHiKey = (byte)((p.Zones[i].Generators[0].AmountInt16 >> 8) & 0xFF);
                 }
                 else
                 {
                     presetHiKey = (byte)(p.Zones[i].Generators[0].AmountInt16 & 0xFF);
                     presetLoKey = (byte)((p.Zones[i].Generators[0].AmountInt16 >> 8) & 0xFF);
                 }
                 if (p.Zones[i].Generators.Length > 1 && p.Zones[i].Generators[1].GeneratorType == GeneratorEnum.VelocityRange)
                 {
                     if (BitConverter.IsLittleEndian)
                     {
                         presetLoVel = (byte)(p.Zones[i].Generators[1].AmountInt16 & 0xFF);
                         presetHiVel = (byte)((p.Zones[i].Generators[1].AmountInt16 >> 8) & 0xFF);
                     }
                     else
                     {
                         presetHiVel = (byte)(p.Zones[i].Generators[1].AmountInt16 & 0xFF);
                         presetLoVel = (byte)((p.Zones[i].Generators[1].AmountInt16 >> 8) & 0xFF);
                     }
                 }
             }
             else if (p.Zones[i].Generators[0].GeneratorType == GeneratorEnum.VelocityRange)
             {
                 if (BitConverter.IsLittleEndian)
                 {
                     presetLoVel = (byte)(p.Zones[i].Generators[0].AmountInt16 & 0xFF);
                     presetHiVel = (byte)((p.Zones[i].Generators[0].AmountInt16 >> 8) & 0xFF);
                 }
                 else
                 {
                     presetHiVel = (byte)(p.Zones[i].Generators[0].AmountInt16 & 0xFF);
                     presetLoVel = (byte)((p.Zones[i].Generators[0].AmountInt16 >> 8) & 0xFF);
                 }
             }
             if(p.Zones[i].Generators[p.Zones[i].Generators.Length - 1].GeneratorType == GeneratorEnum.Instrument)
             {
                 Sf2Region[] insts = inst[p.Zones[i].Generators[p.Zones[i].Generators.Length - 1].AmountInt16];
                 for (int x = 0; x < insts.Length; x++)
                 {
                     byte instLoKey;
                     byte instHiKey;
                     byte instLoVel;
                     byte instHiVel;
                     if (BitConverter.IsLittleEndian)
                     {
                         instLoKey = (byte)(insts[x].Generators[(int)GeneratorEnum.KeyRange] & 0xFF);
                         instHiKey = (byte)((insts[x].Generators[(int)GeneratorEnum.KeyRange] >> 8) & 0xFF);
                         instLoVel = (byte)(insts[x].Generators[(int)GeneratorEnum.VelocityRange] & 0xFF);
                         instHiVel = (byte)((insts[x].Generators[(int)GeneratorEnum.VelocityRange] >> 8) & 0xFF);
                     }
                     else
                     {
                         instHiKey = (byte)(insts[x].Generators[(int)GeneratorEnum.KeyRange] & 0xFF);
                         instLoKey = (byte)((insts[x].Generators[(int)GeneratorEnum.KeyRange] >> 8) & 0xFF);
                         instHiVel = (byte)(insts[x].Generators[(int)GeneratorEnum.VelocityRange] & 0xFF);
                         instLoVel = (byte)((insts[x].Generators[(int)GeneratorEnum.VelocityRange] >> 8) & 0xFF);
                     }
                     if ((instLoKey <= presetHiKey && presetLoKey <= instHiKey) && (instLoVel <= presetHiVel && presetLoVel <= instHiVel))
                     {
                         Sf2Region r = new Sf2Region();
                         Array.Copy(insts[x].Generators, r.Generators, r.Generators.Length);
                         ReadSf2Region(r, globalGens, p.Zones[i].Generators, true);
                         regionList.Add(r);
                     }
                 }
             }
             i++;
         }
         MultiPatch mp = new MultiPatch(p.Name);
         mp.LoadSf2(regionList.ToArray(), assets);
         assets.PatchAssetList.Add(new PatchAsset(mp.Name, mp));
         AssignPatchToBank(mp, p.BankNumber, p.PatchNumber, p.PatchNumber);
     }
 }