private static SampleSoundGenerator ImportPreset(SoundFont sf2, Preset preset, SampleGeneratingArgs args)
 {
     /*
      *  == Aproximate Pesdo Code of importing a preset from sf2 ==
      *  -    Get all preset zones from soundfont (sf2)
      *  -    get the instrument and double check if it's not null (if it is, "continue" the method)
      *  -    is the instrument grabbed the same as what args is asking for? (if not, "continue" method)
      *  -    get each zone within instrument and create wav file from information
      *      -   get Sample Header of instrument zone and double check if null (if so, "continue")
      *      -   get the Key range of spesified zone and create high and low keys 8 bit's in difference.
      *          -   is the key not the same as what the args asked for? (yes, then "continue")
      *      -   Get the velocity range of spesified zone and create high and low keys 8 bits' in difference.
      *          -   is the velocity not the same as what the args asked for? (yes, then "continue")
      *      -   Find the closest key from instrument zone to the key spesified from args.
      *          - is the closest key lower than the maximum integer value or, is the key of args just not spesified?
      *              - if so, set the closest zone (initial = null) to the current zone,
      *              - if so, set the bdist (initial = maximum integer value) to the closest key.
      *      -   Is there a zone found from above?
      *          - If so, create a wave from zone information using the SampleData.
      */
     return(ImportInstruments(sf2, preset.Zones.Select(z => z.Instrument()), args));
 }
Exemple #2
0
        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);
            }
        }
Exemple #3
0
        /// <summary>
        /// Imports all samples specified by <see cref="SampleGeneratingArgs"/> and returns a dictionary which maps the <see cref="SampleGeneratingArgs"/>
        /// to their <see cref="SampleSoundGenerator"/>. If a sample couldn't be imported then it has a null instead.
        /// </summary>
        /// <param name="argsList"></param>
        /// <returns></returns>
        public static Dictionary <SampleGeneratingArgs, SampleSoundGenerator> ImportSamples(IEnumerable <SampleGeneratingArgs> argsList)
        {
            var samples         = new Dictionary <SampleGeneratingArgs, SampleSoundGenerator>();
            var separatedByPath = new Dictionary <string, HashSet <SampleGeneratingArgs> >();

            foreach (var args in argsList)
            {
                if (separatedByPath.TryGetValue(args.Path, out HashSet <SampleGeneratingArgs> value))
                {
                    value.Add(args);
                }
                else
                {
                    separatedByPath.Add(args.Path, new HashSet <SampleGeneratingArgs> {
                        args
                    });
                }
            }

            foreach (var pair in separatedByPath)
            {
                var path = pair.Key;
                if (!ValidateSampleArgs(path))
                {
                    foreach (var args in pair.Value)
                    {
                        samples.Add(args, null);
                    }
                    continue;
                }

                try {
                    switch (Path.GetExtension(path))
                    {
                    case ".sf2": {
                        var sf2 = new SoundFont(path);
                        foreach (var args in pair.Value)
                        {
                            var sample = ImportFromSoundFont(args, sf2);
                            samples.Add(args, sample);
                        }

                        break;
                    }

                    case ".ogg": {
                        foreach (var args in pair.Value)
                        {
                            samples.Add(args, ImportFromVorbis(args));
                        }

                        break;
                    }

                    default: {
                        foreach (var args in pair.Value)
                        {
                            samples.Add(args, ImportFromAudio(args));
                        }

                        break;
                    }
                    }
                } catch (Exception ex) {
                    Console.WriteLine(ex.Message);

                    foreach (var args in pair.Value)
                    {
                        samples.Add(args, null);
                    }
                }
                GC.Collect();
            }
            return(samples);
        }
Exemple #4
0
 private static SampleSoundGenerator ImportInstruments(SoundFont sf2, SampleGeneratingArgs args)
 {
     return(ImportInstruments(sf2, sf2.Instruments, args));
 }
Exemple #5
0
        // TODO: format soundfont import to detect file versions and types of files.
        public static SampleSoundGenerator ImportFromSoundFont(SampleGeneratingArgs args, SoundFont sf2)
        {
            SampleSoundGenerator wave = null;

            foreach (var preset in sf2.Presets)
            {
                if (preset.PatchNumber != args.Patch && args.Patch != -1)
                {
                    continue;
                }
                if (preset.Bank != args.Bank && args.Bank != -1)
                {
                    continue;
                }

                wave = ImportPreset(sf2, preset, args);
                if (wave != null)
                {
                    break;
                }
            }

            return(wave ?? ImportInstruments(sf2, args));
        }
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            SetContentView(Resource.Layout.SoundFontDetails);

            var sf = Intent.GetStringExtra("soundfont");

            var model = ApplicationModel.Instance;

            var mod    = model.Database.Modules.First(m => m.Name == sf);
            var sfFile = model.Files.FirstOrDefault(p => p.Value == mod.Name).Key;

            if (!File.Exists(sfFile))
            {
                Toast.MakeText(this, string.Format("SoundFont file '{0}' was not found. Details not shown", sfFile), ToastLength.Long).Show();
            }
            else
            {
                var sf2 = new SoundFont(new MemoryStream(File.ReadAllBytes(sfFile)));

                var infoList = new JavaList <IDictionary <string, object> > ();
                var map      = mod.Instrument.Maps.First();

                var labels = new string [] { "BankName", "FileName", "Author", "Copyright", "Comments", "Created", "SFVersion", "ROMVersion", "WaveTableEngine", "Tools", "TargetProduct", "DataROM" };
                var values = new string [] {
                    mod.Name,
                    sfFile,
                    sf2.FileInfo.Author,
                    sf2.FileInfo.Copyright,
                    sf2.FileInfo.Comments,
                    sf2.FileInfo.SoundFontVersion == null ? null : string.Format("{0}.{1}", sf2.FileInfo.SoundFontVersion.Major, sf2.FileInfo.SoundFontVersion.Minor),
                    sf2.FileInfo.ROMVersion == null ? null : string.Format("{0}.{1}", sf2.FileInfo.ROMVersion.Major, sf2.FileInfo.ROMVersion.Minor),
                    sf2.FileInfo.CreationDate,
                    sf2.FileInfo.WaveTableSoundEngine,
                    sf2.FileInfo.Tools,
                    sf2.FileInfo.TargetProduct,
                    sf2.FileInfo.DataROM,
                };
                for (int i = 0; i < labels.Length; i++)
                {
                    var items = new JavaDictionary <string, object> ();
                    items.Add("text1", labels [i]);
                    items.Add("text2", values [i]);
                    infoList.Add(items);
                }

                var bankList = new JavaList <IDictionary <string, object> > ();
                foreach (var p in map.Programs)
                {
                    foreach (var b in p.Banks)
                    {
                        var items = new JavaDictionary <string, object> ();
                        items.Add("text1", string.Format("{0:D03}.{1:D03}.{2:D03}", p.Index, b.Msb, b.Lsb));
                        items.Add("text2", b.Name);
                        bankList.Add(items);
                    }
                }

                var fromKeys = new string [] { "text1", "text2" };
                var toIds    = new int [] { Resource.Id.soundFontDetailFileInfoLabel, Resource.Id.soundFontDetailFileInfoValue };

                var lvfi = FindViewById <ListView> (Resource.Id.soundFontDetailsFileInfo);
                lvfi.Adapter = new SimpleAdapter(this, infoList, Resource.Layout.SoundFontFileInfoItem, fromKeys, toIds);

                var lvbanks = FindViewById <ListView> (Resource.Id.soundFontDetailsBankList);
                lvbanks.Adapter = new SimpleAdapter(this, bankList, Resource.Layout.SoundFontFileInfoItem, fromKeys, toIds);
            }
        }
Exemple #7
0
        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);
            }
        }
Exemple #8
0
        public IMidiRenderer GetNewRenderer()
        {
            if (!FluidsynthInitialized)
            {
                InitializeFluidsynth();

                if (!FluidsynthInitialized) // init failed
                {
                    return(null);
                }
            }

            var soundfontLoader = SoundFontLoader.NewDefaultSoundFontLoader(_settings);

            // Just making double sure these don't get GC'd.
            // They shouldn't, MidiRenderer keeps a ref, but making sure...
            var handle = GCHandle.Alloc(soundfontLoader);

            try
            {
                soundfontLoader.SetCallbacks(_soundfontLoaderCallbacks);

                var renderer = new MidiRenderer(_settings, soundfontLoader);

                // Since the last loaded soundfont takes priority, we load the fallback soundfont first.
                renderer.LoadSoundfont(FallbackSoundfont);

                if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                {
                    foreach (var filepath in LinuxSoundfonts)
                    {
                        if (!File.Exists(filepath) || !SoundFont.IsSoundFont(filepath))
                        {
                            continue;
                        }

                        try
                        {
                            renderer.LoadSoundfont(filepath, true);
                        }
                        catch (Exception)
                        {
                            continue;
                        }

                        break;
                    }
                }
                else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
                {
                    if (File.Exists(OsxSoundfont) && SoundFont.IsSoundFont(OsxSoundfont))
                    {
                        renderer.LoadSoundfont(OsxSoundfont, true);
                    }
                }
                else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    if (File.Exists(WindowsSoundfont) && SoundFont.IsSoundFont(WindowsSoundfont))
                    {
                        renderer.LoadSoundfont(WindowsSoundfont, true);
                    }
                }

                lock (_renderers)
                    _renderers.Add(renderer);

                return(renderer);
            }
            finally
            {
                handle.Free();
            }
        }
Exemple #9
0
 public bool IsSoundfontFile(string filename)
 {
     return(SoundFont.IsSoundFont(filename));
 }
Exemple #10
0
 public bool IsMidiFile(string filename)
 {
     return(SoundFont.IsMidiFile(filename));
 }
Exemple #11
0
        void ImportSamples(SoundFont sf2, Preset preset, XInstrument xrni)
        {
            var xl = new List <XSample> ();
            var ml = new List <SampleMap> ();
            var il = new List <int> ();

            foreach (var pzone in preset.Zones)               // perc. bank likely has more than one instrument here.
            {
                var i  = pzone.Instrument();
                var kr = pzone.KeyRange();                  // FIXME: where should I use it?
                if (i == null)
                {
                    continue;                     // FIXME: is it possible?
                }
                var vr = pzone.VelocityRange();

                // an Instrument contains a set of zones that contain sample headers.
                int sampleCount = 0;
                foreach (var izone in i.Zones)
                {
                    var ikr = izone.KeyRange();
                    var ivr = izone.VelocityRange();
                    var sh  = izone.SampleHeader();
                    if (sh == null)
                    {
                        continue;                         // FIXME: is it possible?
                    }
                    // FIXME: sample data must become monoral (panpot neutral)
                    var xs = ConvertSample(sampleCount++, sh, sf2.SampleData, izone);
                    xs.Name = NormalizePathName(sh.SampleName);
                    ml.Add(new SampleMap(ikr, ivr, xs, sh));
                }
            }

            ml.Sort((m1, m2) =>
                    m1.KeyLowRange != m2.KeyLowRange ? m1.KeyLowRange - m2.KeyLowRange :
                    m1.KeyHighRange != m2.KeyHighRange ? m1.KeyHighRange - m2.KeyHighRange :
                    m1.VelocityLowRange != m2.VelocityLowRange ? m1.VelocityLowRange - m2.VelocityLowRange :
                    m1.VelocityHighRange - m2.VelocityHighRange);

            int prev = -1;

            foreach (var m in ml)
            {
                prev = m.KeyLowRange;
                il.Add(m.KeyLowRange);
                xl.Add(m.Sample);
            }

            xrni.SampleSplitMap = new SampleSplitMap();
            xrni.SampleSplitMap.NoteOnMappings = new SampleSplitMapNoteOnMappings();
            var nm = new SampleSplitMapping [ml.Count];

            xrni.SampleSplitMap.NoteOnMappings.NoteOnMapping = nm;
            for (int i = 0; i < ml.Count; i++)
            {
                var m = ml [i];
                var n = new SampleSplitMapping();
                n.BaseNote    = m.Sample.BaseNote;
                n.NoteStart   = m.KeyLowRange;
                n.NoteEnd     = m.KeyHighRange <= 0 ? 128 : m.KeyHighRange;
                n.SampleIndex = i;
                if (m.VelocityHighRange > 0)
                {
                    n.MapVelocityToVolume = true;
                    n.VelocityStart       = m.VelocityLowRange;
                    n.VelocityEnd         = m.VelocityHighRange;
                }
                nm [i] = n;
            }

            xrni.Samples        = new RenoiseInstrumentSamples();
            xrni.Samples.Sample = xl.ToArray();
        }
        /// <summary>
        /// Create a DLS from a sound font.
        /// </summary>
        /// <param name="sf2">The SF2 file.</param>
        public DownloadableSounds(SoundFont sf2)
        {
            //Get waves.
            List <string>            waveMd5s     = new List <string>();
            Dictionary <int, string> newWaveIds   = new Dictionary <int, string>();
            Dictionary <int, sbyte>  tunings      = new Dictionary <int, sbyte>();
            Dictionary <int, byte>   origPitches  = new Dictionary <int, byte>();
            Dictionary <int, uint>   channelFlags = new Dictionary <int, uint>();

            Waves = new List <RiffWave>();
            foreach (var i in sf2.Instruments)
            {
                foreach (var z in i.GetAllZones())
                {
                    foreach (var g in z.Generators.Where(x => x.Gen == SF2Generators.SampleID))
                    {
                        var      s   = sf2.Samples[g.Amount.UAmount];
                        RiffWave wav = new RiffWave();
                        wav.Loops          = s.Wave.Loops;
                        wav.LoopStart      = s.Wave.LoopStart;
                        wav.LoopEnd        = s.Wave.LoopEnd;
                        wav.SampleRate     = s.Wave.SampleRate;
                        wav.Audio.Channels = new List <List <GotaSoundIO.Sound.Encoding.IAudioEncoding> >();
                        switch (s.LinkType)
                        {
                        case SF2LinkTypes.Left:
                            wav.Audio.Channels.Add(s.Wave.Audio.Channels[0]);
                            try {
                                wav.Audio.Channels.Add(sf2.Samples.Where(x => x.Link == s.Link && x.LinkType == SF2LinkTypes.Right).FirstOrDefault().Wave.Audio.Channels[0]);
                            } catch { }
                            if (!channelFlags.ContainsKey(g.Amount.UAmount))
                            {
                                channelFlags.Add(g.Amount.UAmount, 0b11);
                            }
                            break;

                        case SF2LinkTypes.Right:
                            try {
                                wav.Audio.Channels.Add(sf2.Samples.Where(x => x.Link == s.Link && x.LinkType == SF2LinkTypes.Left).FirstOrDefault().Wave.Audio.Channels[0]);
                            } catch { }
                            wav.Audio.Channels.Add(s.Wave.Audio.Channels[0]);
                            if (!channelFlags.ContainsKey(g.Amount.UAmount))
                            {
                                channelFlags.Add(g.Amount.UAmount, 0b11);
                            }
                            break;

                        case SF2LinkTypes.Mono:
                            wav.Audio.Channels.Add(s.Wave.Audio.Channels[0]);
                            if (!channelFlags.ContainsKey(g.Amount.UAmount))
                            {
                                channelFlags.Add(g.Amount.UAmount, 0b1);
                            }
                            break;

                        case SF2LinkTypes.Linked:
                            foreach (var w in sf2.Samples)
                            {
                                if (w.LinkType == SF2LinkTypes.Linked && w.Link == s.Link)
                                {
                                    wav.Audio.Channels.Add(w.Wave.Audio.Channels[0]);
                                    if (!channelFlags.ContainsKey(g.Amount.UAmount))
                                    {
                                        channelFlags.Add(g.Amount.UAmount, 0);
                                    }
                                    channelFlags[g.Amount.UAmount] <<= 1;
                                    channelFlags[g.Amount.UAmount]  |= 0b1;
                                }
                            }
                            break;
                        }
                        string md5 = wav.Md5Sum;
                        if (!newWaveIds.ContainsKey(g.Amount.UAmount))
                        {
                            newWaveIds.Add(g.Amount.UAmount, md5);
                            tunings.Add(g.Amount.UAmount, sf2.Samples[g.Amount.UAmount].PitchCorrection);
                            origPitches.Add(g.Amount.UAmount, sf2.Samples[g.Amount.UAmount].OriginalPitch);
                        }
                        if (!waveMd5s.Contains(md5))
                        {
                            waveMd5s.Add(md5);
                            Waves.Add(wav);
                        }
                    }
                }
            }

            //Get instruments.
            Instruments = new List <Instrument>();
            int instId = 0;

            foreach (var inst in sf2.Instruments)
            {
                //Instrument.
                Instrument i = new Instrument();
                i.Name    = inst.Name;
                i.Regions = new List <Region>();
                i.BankId  = 0;
                foreach (var p in sf2.Presets)
                {
                    foreach (var z in p.GetAllZones())
                    {
                        foreach (var g in z.Generators)
                        {
                            if (g.Gen == SF2Generators.Instrument && g.Amount.Amount == instId)
                            {
                                i.BankId       = p.Bank;
                                i.InstrumentId = p.PresetNumber;
                            }
                        }
                    }
                }
                instId++;

                //Get regions.
                foreach (var z in inst.Zones)
                {
                    var reg = GetInstrumentRegion(z, inst.GlobalZone);
                    if (reg != null)
                    {
                        i.Regions.Add(reg);
                    }
                }
                if (i.Regions.Count < 1)
                {
                    var reg = GetInstrumentRegion(inst.GlobalZone, null);
                    if (reg != null)
                    {
                        i.Regions.Add(reg);
                    }
                }

                //Add instrument.
                Instruments.Add(i);
            }

            //Get an instrument region from an SF2 zone.
            Region GetInstrumentRegion(Zone z, Zone g)
            {
                //Null region.
                if (z == null)
                {
                    return(null);
                }

                //New region.
                Region r = new Region();

                //Get sample.
                int sampleNumRaw = SF2Value(SF2Generators.SampleID).UAmount;
                int sampleNum    = waveMd5s.IndexOf(newWaveIds[sampleNumRaw]);

                r.WaveId       = (uint)sampleNum;
                r.Tuning       = (short)(tunings[sampleNumRaw] % 12 * 65536);
                r.RootNote     = (byte)(origPitches[sampleNumRaw] + tunings[sampleNumRaw] / 12);
                r.ChannelFlags = channelFlags[sampleNumRaw];
                r.Loops        = Waves[sampleNum].Loops;
                r.LoopStart    = Waves[sampleNum].LoopStart;
                r.LoopLength   = Waves[sampleNum].LoopEnd - Waves[sampleNum].LoopStart;
                Articulator art = new Articulator();

                art.Connections = new List <Connection>();
                var c = art.Connections;

                //Get generators.
                foreach (var gen in z.Generators)
                {
                    DestinationConnection d = DestinationConnection.Center;
                    switch (gen.Gen)
                    {
                    case SF2Generators.OverridingRootKey:
                        r.RootNote = (byte)(gen.Amount.Amount + tunings[sampleNumRaw] / 12);
                        continue;

                    case SF2Generators.KeyRange:
                        r.NoteLow  = gen.Amount.LowByte;
                        r.NoteHigh = gen.Amount.HighByte;
                        continue;

                    case SF2Generators.VelRange:
                        r.VelocityLow  = gen.Amount.LowByte;
                        r.VelocityHigh = gen.Amount.HighByte;
                        continue;

                    case SF2Generators.ChorusEffectsSend:
                        d = DestinationConnection.Chorus;
                        break;

                    case SF2Generators.AttackVolEnv:
                        d = DestinationConnection.EG1AttackTime;
                        break;

                    case SF2Generators.DecayVolEnv:
                        d = DestinationConnection.EG1DecayTime;
                        break;

                    case SF2Generators.DelayVolEnv:
                        d = DestinationConnection.EG1DelayTime;
                        break;

                    case SF2Generators.HoldVolEnv:
                        d = DestinationConnection.EG1HoldTime;
                        break;

                    case SF2Generators.ReleaseVolEnv:
                        d = DestinationConnection.EG1ReleaseTime;
                        break;

                    case SF2Generators.SustainVolEnv:
                        d = DestinationConnection.EG1SustainLevel;
                        c.Add(new Connection()
                        {
                            DestinationConnection = d, Scale = (int)((1 - (gen.Amount.Amount / 1000d)) * 1000 * 65536)
                        });
                        continue;

                    case SF2Generators.Keynum:
                        d = DestinationConnection.KeyNumber;
                        break;

                    case SF2Generators.Pan:
                        d = DestinationConnection.Pan;
                        break;

                    case SF2Generators.FreqModLFO:
                        d = DestinationConnection.LFOFrequency;
                        break;

                    case SF2Generators.DelayModLFO:
                        d = DestinationConnection.LFOStartDelayTime;
                        break;

                    default:
                        continue;
                    }
                    c.Add(new Connection()
                    {
                        DestinationConnection = d, Scale = gen.Amount.Amount * 65536
                    });
                }

                //Get the SF2 value.
                SF2GeneratorAmount SF2Value(SF2Generators gen)
                {
                    var ret = new SF2GeneratorAmount();

                    if (g != null)
                    {
                        var a = g.Generators.Where(x => x.Gen == gen).FirstOrDefault();
                        if (a != null)
                        {
                            ret.Amount += a.Amount.Amount;
                        }
                    }
                    var b = z.Generators.Where(x => x.Gen == gen).FirstOrDefault();

                    if (b != null)
                    {
                        ret.Amount = b.Amount.Amount;
                    }
                    return(ret);
                }

                //Add articulators.
                r.Articulators = new List <Articulator>()
                {
                    art
                };

                //Return the region.
                return(r);
            }
        }