Example #1
0
        /// <summary>
        /// Read the RIFF.
        /// </summary>
        /// <param name="r">The reader.</param>
        public override void Read(FileReader r)
        {
            //Init.
            using (RiffReader rr = new RiffReader(r.BaseStream)) {
                //Format.
                rr.OpenChunk(rr.Chunks.Where(x => x.Magic.Equals("fmt ")).FirstOrDefault());
                if (rr.ReadUInt16() != 1)
                {
                    throw new Exception("Unexpected standard WAV data format.");
                }
                int numChannels = rr.ReadUInt16();
                SampleRate = rr.ReadUInt32();
                rr.ReadUInt32(); //Byte rate.
                rr.ReadUInt16(); //Blocks.
                ushort bitsPerSample = rr.ReadUInt16();
                LoopStart = 0;
                LoopEnd   = 0;
                Loops     = false;
                if (bitsPerSample != 8 && bitsPerSample != 16)
                {
                    throw new Exception("This tool only accepts 8-bit or 16-bit WAV files.");
                }

                //Sample.
                var smpl = rr.Chunks.Where(x => x.Magic.Equals("smpl")).FirstOrDefault();
                if (smpl != null)
                {
                    rr.OpenChunk(smpl);
                    rr.ReadUInt32s(7);
                    Loops = rr.ReadUInt32() > 0;
                    if (Loops)
                    {
                        rr.ReadUInt32s(3);
                        LoopStart = r.ReadUInt32(); //(uint)(r.ReadUInt32() / (bitsPerSample / 8));
                        LoopEnd   = r.ReadUInt32(); //(uint)(r.ReadUInt32() / (bitsPerSample / 8));
                    }
                }

                //Data.
                rr.OpenChunk(rr.Chunks.Where(x => x.Magic.Equals("data")).FirstOrDefault());
                uint dataSize  = rr.Chunks.Where(x => x.Magic.Equals("data")).FirstOrDefault().Size;
                uint numBlocks = (uint)(dataSize / numChannels / (bitsPerSample / 8));
                r.Position = rr.Position;
                Audio.Read(r, bitsPerSample == 16 ? typeof(PCM16) : typeof(PCM8), numChannels, numBlocks, (uint)bitsPerSample / 8, 1, (uint)bitsPerSample / 8, 1, 0);
                Audio.ChangeBlockSize(-1);
            }
        }
        /// <summary>
        /// Read the file.
        /// </summary>
        /// <param name="r2">The file reader.</param>
        public override void Read(FileReader r2)
        {
            //Use a RIFF reader.
            using (RiffReader r = new RiffReader(r2.BaseStream)) {
                //Get the number of instruments.
                r.OpenChunk(r.GetChunk("colh"));
                uint numInsts = r.ReadUInt32();

                //Pointer table is skipped since it's just offsets to wave data relative to the first wave identifier.

                //Read wave data.
                Waves = new List <RiffWave>();
                foreach (var c in (r.GetChunk("wvpl") as ListChunk).Chunks)
                {
                    //Open block.
                    r.OpenChunk(c);

                    //Set position for proper RIFF reading.
                    r.BaseStream.Position -= 8;
                    int len = r.ReadInt32() + 8;
                    r.BaseStream.Position -= 8;
                    RiffWave wav = new RiffWave();
                    wav.Read(r.ReadBytes(len));
                    Waves.Add(wav);
                }

                //Read each instrument.
                foreach (ListChunk c in (r.GetChunk("lins") as ListChunk).Chunks)
                {
                    //Open block.
                    r.OpenChunk(c);

                    //New instrument.
                    Instrument inst = new Instrument();

                    //Read header.
                    r.OpenChunk(c.GetChunk("insh"));
                    r.ReadUInt32();
                    inst.BankId       = r.ReadUInt32();
                    inst.InstrumentId = r.ReadUInt32();

                    //Read regions.
                    foreach (ListChunk g in (c.GetChunk("lrgn") as ListChunk).Chunks)
                    {
                        //New region.
                        Region reg = new Region();

                        //Region header.
                        r.OpenChunk(g.GetChunk("rgnh"));
                        reg.NoteLow        = r.ReadUInt16();
                        reg.NoteHigh       = r.ReadUInt16();
                        reg.VelocityLow    = r.ReadUInt16();
                        reg.VelocityHigh   = r.ReadUInt16();
                        reg.DoublePlayback = r.ReadUInt16() > 0;
                        reg.KeyGroup       = (byte)r.ReadUInt16();
                        reg.Layer          = r.ReadUInt16();

                        //Note information.
                        r.OpenChunk(g.GetChunk("wsmp"));
                        r.ReadUInt32();
                        reg.RootNote = (byte)r.ReadUInt16();
                        reg.Tuning   = r.ReadInt16();
                        reg.Gain     = r.ReadInt32();
                        uint flags = r.ReadUInt32();
                        reg.NoTruncation  = (flags & 0b1) > 0;
                        reg.NoCompression = (flags & 0b10) > 0;
                        reg.Loops         = r.ReadUInt32() > 0;
                        if (reg.Loops)
                        {
                            r.ReadUInt32();
                            reg.LoopAndRelease = r.ReadUInt32() > 0;
                            reg.LoopStart      = r.ReadUInt32();
                            reg.LoopLength     = r.ReadUInt32();
                        }

                        //Wave link.
                        r.OpenChunk(g.GetChunk("wlnk"));
                        uint flg = r.ReadUInt16();
                        reg.PhaseMaster  = (flg & 0b1) > 0;
                        reg.MultiChannel = (flg & 0b10) > 0;
                        reg.PhaseGroup   = r.ReadUInt16();
                        reg.ChannelFlags = r.ReadUInt32();
                        reg.WaveId       = r.ReadUInt32();

                        //Loop.
                        Waves[(int)reg.WaveId].Loops = reg.Loops;
                        if (reg.Loops)
                        {
                            Waves[(int)reg.WaveId].LoopStart = reg.LoopStart;
                            Waves[(int)reg.WaveId].LoopEnd   = reg.LoopLength == 0 ? (uint)Waves[(int)reg.WaveId].Audio.NumSamples : reg.LoopStart + reg.LoopLength;
                        }

                        //Articulators.
                        var lar = g.GetChunk("lar2");
                        if (lar == null)
                        {
                            lar = g.GetChunk("lar1");
                        }
                        foreach (Chunk art in (g.GetChunk("lar2") as ListChunk).Chunks)
                        {
                            //Read articulator.
                            Articulator a = new Articulator();
                            r.OpenChunk(art);
                            r.ReadUInt32();
                            uint numCons = r.ReadUInt32();
                            for (uint i = 0; i < numCons; i++)
                            {
                                Connection con = new Connection();
                                con.SourceConnection      = (SourceConnection)r.ReadUInt16();
                                con.ControlConnection     = r.ReadUInt16();
                                con.DestinationConnection = (DestinationConnection)r.ReadUInt16();
                                con.TransformConnection   = (TransformConnection)r.ReadUInt16();
                                con.Scale = r.ReadInt32();
                                a.Connections.Add(con);
                            }
                            reg.Articulators.Add(a);
                        }

                        //Add region.
                        inst.Regions.Add(reg);
                    }

                    //Read name.
                    var info = c.GetChunk("INFO");
                    if (info != null)
                    {
                        var inam = (info as ListChunk).GetChunk("INAM");
                        if (inam != null)
                        {
                            r.OpenChunk(inam);
                            r.BaseStream.Position -= 4;
                            uint siz = r.ReadUInt32();
                            inst.Name = new string(r.ReadChars((int)siz).Where(x => x != 0).ToArray());
                        }
                    }

                    //Add instrument.
                    Instruments.Add(inst);
                }
            }
        }
Example #3
0
        /// <summary>
        /// Read the file.
        /// </summary>
        /// <param name="r2">The reader.</param>
        public override void Read(FileReader r2)
        {
            //Use a RIFF reader.
            using (RiffReader r = new RiffReader(r2.BaseStream)) {
                //Get INFO data.
                var info = (ListChunk)r.GetChunk("INFO");

                //Sound engine.
                r.OpenChunk(info.GetChunk("isng"));
                SoundEngine = r.ReadNullTerminated();

                //Bank name.
                r.OpenChunk(info.GetChunk("INAM"));
                BankName = r.ReadNullTerminated();

                //ROM name.
                if (info.GetChunk("irom") != null)
                {
                    r.OpenChunk(info.GetChunk("irom"));
                    RomName = r.ReadNullTerminated();
                }

                //ROM version.
                if (info.GetChunk("iver") != null)
                {
                    r.OpenChunk(info.GetChunk("iver"));
                    RomVersion = new Tuple <ushort, ushort>(r.ReadUInt16(), r.ReadUInt16());
                }

                //Creation date.
                if (info.GetChunk("ICRD") != null)
                {
                    r.OpenChunk(info.GetChunk("ICRD"));
                    CreationDate = r.ReadNullTerminated();
                }

                //Sound designer.
                if (info.GetChunk("IENG") != null)
                {
                    r.OpenChunk(info.GetChunk("IENG"));
                    SoundDesigner = r.ReadNullTerminated();
                }

                //Product.
                if (info.GetChunk("IPRD") != null)
                {
                    r.OpenChunk(info.GetChunk("IPRD"));
                    Product = r.ReadNullTerminated();
                }

                //Copyright.
                if (info.GetChunk("ICOP") != null)
                {
                    r.OpenChunk(info.GetChunk("ICOP"));
                    Copyright = r.ReadNullTerminated();
                }

                //Comment.
                if (info.GetChunk("ICMT") != null)
                {
                    r.OpenChunk(info.GetChunk("ICMT"));
                    Comment = r.ReadNullTerminated();
                }

                //Tools.
                if (info.GetChunk("ISFT") != null)
                {
                    r.OpenChunk(info.GetChunk("ISFT"));
                    Tools = r.ReadNullTerminated();
                }

                //Get wave table position.
                long waveTablePos = ((ListChunk)r.GetChunk("sdta")).GetChunk("smpl").Pos;

                //The hydra.
                Presets     = new List <Preset>();
                Instruments = new List <Instrument>();
                Samples     = new List <SampleItem>();
                var hydra = (ListChunk)r.GetChunk("pdta");

                //Get presets.
                r.OpenChunk(hydra.GetChunk("phdr"));
                uint numPresets = hydra.GetChunk("phdr").Size / 38 - 1;
                for (uint i = 0; i < numPresets; i++)
                {
                    Presets.Add(r.Read <Preset>());
                }

                //Get preset bags.
                List <Tuple <ushort, ushort> > presetGenModIndices = new List <Tuple <ushort, ushort> >();
                List <Zone> presetZones = new List <Zone>();
                r.OpenChunk(hydra.GetChunk("pbag"));
                uint numPbags = hydra.GetChunk("pbag").Size / 4 - 1;
                for (uint i = 0; i < numPbags; i++)
                {
                    presetGenModIndices.Add(new Tuple <ushort, ushort>(r.ReadUInt16(), r.ReadUInt16()));
                    presetZones.Add(new Zone());
                }

                //Get preset modulators.
                List <Modulator> pMods = new List <Modulator>();
                r.OpenChunk(hydra.GetChunk("pmod"));
                uint numPmods = hydra.GetChunk("pmod").Size / 10 - 1;
                for (uint i = 0; i < numPmods; i++)
                {
                    pMods.Add(r.Read <Modulator>());
                }

                //Get preset generators.
                List <Generator> pGens = new List <Generator>();
                r.OpenChunk(hydra.GetChunk("pgen"));
                uint numPgens = hydra.GetChunk("pgen").Size / 4 - 1;
                for (uint i = 0; i < numPgens; i++)
                {
                    pGens.Add(r.Read <Generator>());
                }

                //Get true generators and modulators.
                for (int i = 0; i < presetGenModIndices.Count; i++)
                {
                    //Index.
                    int startGen = presetGenModIndices[i].Item1;
                    int startMod = presetGenModIndices[i].Item2;
                    int numGen   = pGens.Count - startGen;
                    int numMod   = pMods.Count - startMod;
                    if (i + 1 <= presetGenModIndices.Count - 1)
                    {
                        numGen = presetGenModIndices[i + 1].Item1 - startGen;
                        numMod = presetGenModIndices[i + 1].Item2 - startMod;
                    }

                    //Get stuff.
                    for (int j = startGen; j < startGen + numGen; j++)
                    {
                        presetZones[i].Generators.Add(pGens[j]);
                    }
                    for (int j = startMod; j < startMod + numMod; j++)
                    {
                        presetZones[i].Modulators.Add(pMods[j]);
                    }
                }

                //Add the zones to the presets.
                for (int i = 0; i < Presets.Count; i++)
                {
                    //Index.
                    int startZone = Presets[i].ReadingBagIndex;
                    int numZones  = presetGenModIndices.Count - startZone;
                    if (i + 1 <= Presets.Count - 1)
                    {
                        numZones = Presets[i + 1].ReadingBagIndex - startZone;
                    }

                    //Get stuff.
                    for (int j = startZone; j < startZone + numZones; j++)
                    {
                        if (Presets[i].Zones.Count == 0 && presetZones[j].Generators.Where(x => x.Gen == SF2Generators.Instrument).Where(x => x.Gen == SF2Generators.Instrument).Count() < 1)
                        {
                            Presets[i].GlobalZone = presetZones[j];
                        }
                        else
                        {
                            Presets[i].Zones.Add(presetZones[j]);
                        }
                    }
                }

                //Get instruments.
                r.OpenChunk(hydra.GetChunk("inst"));
                uint numInstruments = hydra.GetChunk("inst").Size / 22 - 1;
                for (uint i = 0; i < numInstruments; i++)
                {
                    Instruments.Add(r.Read <Instrument>());
                }

                //Get instrument bags.
                List <Tuple <ushort, ushort> > instrumentGenModIndices = new List <Tuple <ushort, ushort> >();
                List <Zone> instrumentZones = new List <Zone>();
                r.OpenChunk(hydra.GetChunk("ibag"));
                uint numIbags = hydra.GetChunk("ibag").Size / 4 - 1;
                for (uint i = 0; i < numIbags; i++)
                {
                    instrumentGenModIndices.Add(new Tuple <ushort, ushort>(r.ReadUInt16(), r.ReadUInt16()));
                    instrumentZones.Add(new Zone());
                }

                //Get instrument modulators.
                List <Modulator> iMods = new List <Modulator>();
                r.OpenChunk(hydra.GetChunk("imod"));
                uint numImods = hydra.GetChunk("imod").Size / 10 - 1;
                for (uint i = 0; i < numImods; i++)
                {
                    iMods.Add(r.Read <Modulator>());
                }

                //Get instrument generators.
                List <Generator> iGens = new List <Generator>();
                r.OpenChunk(hydra.GetChunk("igen"));
                uint numIgens = hydra.GetChunk("igen").Size / 4 - 1;
                for (uint i = 0; i < numIgens; i++)
                {
                    iGens.Add(r.Read <Generator>());
                }

                //Get true generators and modulators.
                for (int i = 0; i < instrumentGenModIndices.Count; i++)
                {
                    //Index.
                    int startGen = instrumentGenModIndices[i].Item1;
                    int startMod = instrumentGenModIndices[i].Item2;
                    int numGen   = iGens.Count - startGen;
                    int numMod   = iMods.Count - startMod;
                    if (i + 1 <= instrumentGenModIndices.Count - 1)
                    {
                        numGen = instrumentGenModIndices[i + 1].Item1 - startGen;
                        numMod = instrumentGenModIndices[i + 1].Item2 - startMod;
                    }

                    //Get stuff.
                    for (int j = startGen; j < startGen + numGen; j++)
                    {
                        instrumentZones[i].Generators.Add(iGens[j]);
                    }
                    for (int j = startMod; j < startMod + numMod; j++)
                    {
                        instrumentZones[i].Modulators.Add(iMods[j]);
                    }
                }

                //Add the zones to the instruments.
                for (int i = 0; i < Instruments.Count; i++)
                {
                    //Index.
                    int startZone = Instruments[i].ReadingBagIndex;
                    int numZones  = instrumentGenModIndices.Count - startZone;
                    if (i + 1 <= Instruments.Count - 1)
                    {
                        numZones = Instruments[i + 1].ReadingBagIndex - startZone;
                    }

                    //Get stuff.
                    for (int j = startZone; j < startZone + numZones; j++)
                    {
                        if (Instruments[i].Zones.Count == 0 && instrumentZones[j].Generators.Where(x => x.Gen == SF2Generators.SampleID).Count() < 1)
                        {
                            Instruments[i].GlobalZone = instrumentZones[j];
                        }
                        else
                        {
                            Instruments[i].Zones.Add(instrumentZones[j]);
                        }
                    }
                }

                //Get samples.
                r.OpenChunk(hydra.GetChunk("shdr"));
                uint numSamples = hydra.GetChunk("shdr").Size / 46 - 1;
                r.CurrentOffset = waveTablePos;
                for (uint i = 0; i < numSamples; i++)
                {
                    Samples.Add(r.Read <SampleItem>());
                }
            }
        }