Ejemplo n.º 1
0
        public SoundFontSampleData(IReadable input)
        {
            var id = input.Read8BitChars(4);
            var size = input.ReadInt32LE();
            if (id.ToLower() != "list")
                throw new Exception("Invalid soundfont. Could not find sdta LIST chunk.");
            var readTo = input.Position + size;
            id = input.Read8BitChars(4);
            if (id.ToLower() != "sdta")
                throw new Exception("Invalid soundfont. The LIST chunk is not of type sdta.");

            BitsPerSample = 0;
            byte[] rawSampleData = null;
            while (input.Position < readTo)
            {
                var subID = input.Read8BitChars(4);
                size = input.ReadInt32LE();
                switch (subID.ToLower())
                {
                    case "smpl":
                        BitsPerSample = 16;
                        rawSampleData = input.ReadByteArray(size);
                        break;
                    case "sm24":
                        if (rawSampleData == null || size != Math.Ceiling(SampleData.Length / 2.0))
                        {//ignore this chunk if wrong size or if it comes first
                            input.Skip(size);
                        }
                        else
                        {
                            BitsPerSample = 24;
                            for (var x = 0; x < SampleData.Length; x++)
                            {
                                var b = new byte[3];
                                b[0] = (byte)input.ReadByte();
                                b[1] = rawSampleData[2 * x];
                                b[2] = rawSampleData[2 * x + 1];
                            }
                        }
                        if (size % 2 == 1)
                        {
                            if (input.ReadByte() != 0)
                            {
                                input.Position--;
                            }
                        }
                        break;
                    default:
                        throw new Exception("Invalid soundfont. Unknown chunk id: " + subID + ".");
                }
            }

            if (BitsPerSample == 16)
            {
                SampleData = rawSampleData;
            }
            else if (BitsPerSample != 24)
                throw new Exception("Only 16 and 24 bit samples are supported.");

        }
Ejemplo n.º 2
0
        public void Load(IReadable input)
        {
            var id = input.Read8BitChars(4);
            var size = input.ReadInt32LE();
            if (id.ToLower() != "riff")
                throw new Exception("Invalid soundfont. Could not find RIFF header.");
            id = input.Read8BitChars(4);
            if (id.ToLower() != "sfbk")
                throw new Exception("Invalid soundfont. Riff type is invalid.");

            Logger.Debug("Reading info chunk");
            Info = new SoundFontInfo(input);
            Logger.Debug("Reading sampledata chunk");
            SampleData = new SoundFontSampleData(input);
            Logger.Debug("Reading preset chunk");
            Presets = new SoundFontPresets(input);
        }
Ejemplo n.º 3
0
        public void Load(IReadable input)
        {
            var id   = input.Read8BitChars(4);
            var size = input.ReadInt32LE();

            if (id.ToLower() != "riff")
            {
                throw new Exception("Invalid soundfont. Could not find RIFF header.");
            }
            id = input.Read8BitChars(4);
            if (id.ToLower() != "sfbk")
            {
                throw new Exception("Invalid soundfont. Riff type is invalid.");
            }

            Logger.Debug("SF2", "Reading info chunk");
            Info = new SoundFontInfo(input);
            Logger.Debug("SF2", "Reading sampledata chunk");
            SampleData = new SoundFontSampleData(input);
            Logger.Debug("SF2", "Reading preset chunk");
            Presets = new SoundFontPresets(input);
        }
Ejemplo n.º 4
0
        public SoundFontSampleData(IReadable input)
        {
            var id   = input.Read8BitChars(4);
            var size = input.ReadInt32LE();

            if (id.ToLower() != "list")
            {
                throw new Exception("Invalid soundfont. Could not find sdta LIST chunk.");
            }
            var readTo = input.Position + size;

            id = input.Read8BitChars(4);
            if (id.ToLower() != "sdta")
            {
                throw new Exception("Invalid soundfont. The LIST chunk is not of type sdta.");
            }

            BitsPerSample = 0;
            byte[] rawSampleData = null;
            while (input.Position < readTo)
            {
                var subID = input.Read8BitChars(4);
                size = input.ReadInt32LE();
                switch (subID.ToLower())
                {
                case "smpl":
                    BitsPerSample = 16;
                    rawSampleData = input.ReadByteArray(size);
                    break;

                case "sm24":
                    if (rawSampleData == null || size != Math.Ceiling(SampleData.Length / 2.0))
                    {    //ignore this chunk if wrong size or if it comes first
                        input.Skip(size);
                    }
                    else
                    {
                        BitsPerSample = 24;
                        for (var x = 0; x < SampleData.Length; x++)
                        {
                            var b = new byte[3];
                            b[0] = (byte)input.ReadByte();
                            b[1] = rawSampleData[2 * x];
                            b[2] = rawSampleData[2 * x + 1];
                        }
                    }
                    if (size % 2 == 1)
                    {
                        if (input.ReadByte() != 0)
                        {
                            input.Position--;
                        }
                    }
                    break;

                default:
                    throw new Exception("Invalid soundfont. Unknown chunk id: " + subID + ".");
                }
            }

            if (BitsPerSample == 16)
            {
                SampleData = rawSampleData;
            }
            else if (BitsPerSample != 24)
            {
                throw new Exception("Only 16 and 24 bit samples are supported.");
            }
        }
Ejemplo n.º 5
0
        private static string ReadString(IReadable input)
        {
            var length = ReadVariableLength(input);

            return(input.Read8BitChars(length)); // TODO: check for correct string encoding
        }
Ejemplo n.º 6
0
        private MidiTrack ReadTrack(IReadable input)
        {
            var instList    = new FastList <Byte>();
            var drumList    = new FastList <Byte>();
            var channelList = new FastList <Byte>();
            var eventList   = new FastList <MidiEvent>();
            var noteOnCount = 0;
            var totalTime   = 0;

            while (input.Read8BitChars(4) != "MTrk")
            {
                var length = input.ReadInt32BE();
                while (length > 0)
                {
                    length--;
                    input.ReadByte();
                }
            }

            var endPosition = input.ReadInt32BE() + input.Position;
            var prevStatus  = 0;

            while (input.Position < endPosition)
            {
                var delta = ReadVariableLength(input);
                totalTime += delta;
                var status = input.ReadByte();
                if (status >= 0x80 && status <= 0xEF)
                {//voice message
                    prevStatus = status;
                    eventList.Add(ReadVoiceMessage(input, delta, (byte)status, (byte)input.ReadByte()));
                    noteOnCount = TrackVoiceStats(eventList[eventList.Count - 1], instList, drumList, channelList, noteOnCount);
                }
                else if (status >= 0xF0 && status <= 0xF7)
                {//system common message
                    prevStatus = 0;
                    eventList.Add(ReadSystemCommonMessage(input, delta, (byte)status));
                }
                else if (status >= 0xF8 && status <= 0xFF)
                {//realtime message
                    eventList.Add(ReadRealTimeMessage(input, delta, (byte)status));
                }
                else
                {     //data bytes
                    if (prevStatus == 0)
                    { //if no running status continue to next status byte
                        while ((status & 0x80) != 0x80)
                        {
                            status = input.ReadByte();
                        }
                        if (status >= 0x80 && status <= 0xEF)
                        {//voice message
                            prevStatus = status;
                            eventList.Add(ReadVoiceMessage(input, delta, (byte)status, (byte)input.ReadByte()));
                            noteOnCount = TrackVoiceStats(eventList[eventList.Count - 1], instList, drumList, channelList, noteOnCount);
                        }
                        else if (status >= 0xF0 && status <= 0xF7)
                        {//system common message
                            eventList.Add(ReadSystemCommonMessage(input, delta, (byte)status));
                        }
                        else if (status >= 0xF8 && status <= 0xFF)
                        {//realtime message
                            eventList.Add(ReadRealTimeMessage(input, delta, (byte)status));
                        }
                    }
                    else
                    {//otherwise apply running status
                        eventList.Add(ReadVoiceMessage(input, delta, (byte)prevStatus, (byte)status));
                        noteOnCount = TrackVoiceStats(eventList[eventList.Count - 1], instList, drumList, channelList, noteOnCount);
                    }
                }
            }

            if (input.Position != endPosition)
            {
                throw new Exception("The track length was invalid for the current MTrk chunk.");
            }
            if (channelList.IndexOf(MidiHelper.DrumChannel) != -1)
            {
                if (drumList.IndexOf(0) == -1)
                {
                    drumList.Add(0);
                }
            }
            else
            {
                if (instList.IndexOf(0) == -1)
                {
                    instList.Add(0);
                }
            }
            var track = new MidiTrack(instList.ToArray(),
                                      drumList.ToArray(),
                                      channelList.ToArray(),
                                      eventList.ToArray());

            track.NoteOnCount = noteOnCount;
            track.EndTime     = totalTime;
            return(track);
        }
Ejemplo n.º 7
0
        public SoundFontPresets(IReadable input)
        {
            var id   = input.Read8BitChars(4);
            var size = input.ReadInt32LE();

            if (id.ToLower() != "list")
            {
                throw new Exception("Invalid soundfont. Could not find pdta LIST chunk.");
            }
            var readTo = input.Position + size;

            id = input.Read8BitChars(4);
            if (id.ToLower() != "pdta")
            {
                throw new Exception("Invalid soundfont. The LIST chunk is not of type pdta.");
            }

            Modulator[] presetModulators     = null;
            Generator[] presetGenerators     = null;
            Modulator[] instrumentModulators = null;
            Generator[] instrumentGenerators = null;

            ZoneChunk         pbag = null;
            ZoneChunk         ibag = null;
            PresetHeaderChunk phdr = null;
            InstrumentChunk   inst = null;

            while (input.Position < readTo)
            {
                id   = input.Read8BitChars(4);
                size = input.ReadInt32LE();
                switch (id.ToLower())
                {
                case "phdr":
                    phdr = new PresetHeaderChunk(id, size, input);
                    break;

                case "pbag":
                    pbag = new ZoneChunk(id, size, input);
                    break;

                case "pmod":
                    presetModulators = new ModulatorChunk(id, size, input).Modulators;
                    break;

                case "pgen":
                    presetGenerators = new GeneratorChunk(id, size, input).Generators;
                    break;

                case "inst":
                    inst = new InstrumentChunk(id, size, input);
                    break;

                case "ibag":
                    ibag = new ZoneChunk(id, size, input);
                    break;

                case "imod":
                    instrumentModulators = new ModulatorChunk(id, size, input).Modulators;
                    break;

                case "igen":
                    instrumentGenerators = new GeneratorChunk(id, size, input).Generators;
                    break;

                case "shdr":
                    SampleHeaders = new SampleHeaderChunk(id, size, input).SampleHeaders;
                    break;

                default:
                    throw new Exception("Invalid soundfont. Unrecognized sub chunk: " + id);
                }
            }
            var pZones = pbag.ToZones(presetModulators, presetGenerators);

            PresetHeaders = phdr.ToPresets(pZones);
            var iZones = ibag.ToZones(instrumentModulators, instrumentGenerators);

            Instruments = inst.ToInstruments(iZones);
        }
Ejemplo n.º 8
0
        public SoundFontInfo(IReadable input)
        {
            Tools         = "";
            Comments      = "";
            Copyright     = "";
            TargetProduct = "";
            Author        = "";
            DataRom       = "";
            CreationDate  = "";
            BankName      = "";
            SoundEngine   = "";
            var id   = input.Read8BitChars(4);
            var size = input.ReadInt32LE();

            if (id.ToLower() != "list")
            {
                throw new Exception("Invalid soundfont. Could not find INFO LIST chunk.");
            }
            var readTo = input.Position + size;

            id = input.Read8BitChars(4);
            if (id.ToLower() != "info")
            {
                throw new Exception("Invalid soundfont. The LIST chunk is not of type INFO.");
            }

            while (input.Position < readTo)
            {
                id   = input.Read8BitChars(4);
                size = input.ReadInt32LE();
                switch (id.ToLower())
                {
                case "ifil":
                    SfVersionMajor = input.ReadInt16LE();
                    SfVersionMinor = input.ReadInt16LE();
                    break;

                case "isng":
                    SoundEngine = input.Read8BitStringLength(size);
                    break;

                case "inam":
                    BankName = input.Read8BitStringLength(size);
                    break;

                case "irom":
                    DataRom = input.Read8BitStringLength(size);
                    break;

                case "iver":
                    RomVersionMajor = input.ReadInt16LE();
                    RomVersionMinor = input.ReadInt16LE();
                    break;

                case "icrd":
                    CreationDate = input.Read8BitStringLength(size);
                    break;

                case "ieng":
                    Author = input.Read8BitStringLength(size);
                    break;

                case "iprd":
                    TargetProduct = input.Read8BitStringLength(size);
                    break;

                case "icop":
                    Copyright = input.Read8BitStringLength(size);
                    break;

                case "icmt":
                    Comments = input.Read8BitStringLength(size);
                    break;

                case "isft":
                    Tools = input.Read8BitStringLength(size);
                    break;

                default:
                    throw new Exception("Invalid soundfont. The Chunk: " + id + " was not expected.");
                }
            }
        }
Ejemplo n.º 9
0
        public SoundFontPresets(IReadable input)
        {
            var id = input.Read8BitChars(4);
            var size = input.ReadInt32LE();
            if (id.ToLower() != "list")
                throw new Exception("Invalid soundfont. Could not find pdta LIST chunk.");
            var readTo = input.Position + size;
            id = input.Read8BitChars(4);
            if (id.ToLower() != "pdta")
                throw new Exception("Invalid soundfont. The LIST chunk is not of type pdta.");

            Modulator[] presetModulators = null;
            Generator[] presetGenerators = null;
            Modulator[] instrumentModulators = null;
            Generator[] instrumentGenerators = null;

            ZoneChunk pbag = null;
            ZoneChunk ibag = null;
            PresetHeaderChunk phdr = null;
            InstrumentChunk inst = null;

            while (input.Position < readTo)
            {
                id = input.Read8BitChars(4);
                size = input.ReadInt32LE();
                switch (id.ToLower())
                {
                    case "phdr":
                        phdr = new PresetHeaderChunk(id, size, input);
                        break;
                    case "pbag":
                        pbag = new ZoneChunk(id, size, input);
                        break;
                    case "pmod":
                        presetModulators = new ModulatorChunk(id, size, input).Modulators;
                        break;
                    case "pgen":
                        presetGenerators = new GeneratorChunk(id, size, input).Generators;
                        break;
                    case "inst":
                        inst = new InstrumentChunk(id, size, input);
                        break;
                    case "ibag":
                        ibag = new ZoneChunk(id, size, input);
                        break;
                    case "imod":
                        instrumentModulators = new ModulatorChunk(id, size, input).Modulators;
                        break;
                    case "igen":
                        instrumentGenerators = new GeneratorChunk(id, size, input).Generators;
                        break;
                    case "shdr":
                        SampleHeaders = new SampleHeaderChunk(id, size, input).SampleHeaders;
                        break;
                    default:
                        throw new Exception("Invalid soundfont. Unrecognized sub chunk: " + id);
                }
            }
            var pZones = pbag.ToZones(presetModulators, presetGenerators);
            PresetHeaders = phdr.ToPresets(pZones);
            var iZones = ibag.ToZones(instrumentModulators, instrumentGenerators);
            Instruments = inst.ToInstruments(iZones);
        }
Ejemplo n.º 10
0
        public SoundFontInfo(IReadable input)
        {
            Tools = "";
            Comments = "";
            Copyright = "";
            TargetProduct = "";
            Author = "";
            DataRom = "";
            CreationDate = "";
            BankName = "";
            SoundEngine = "";
            var id = input.Read8BitChars(4);
            var size = input.ReadInt32LE();
            if (id.ToLower() != "list")
                throw new Exception("Invalid soundfont. Could not find INFO LIST chunk.");
            var readTo = input.Position + size;
            id = input.Read8BitChars(4);
            if (id.ToLower() != "info")
                throw new Exception("Invalid soundfont. The LIST chunk is not of type INFO.");

            while (input.Position < readTo)
            {
                id = input.Read8BitChars(4);
                size = input.ReadInt32LE();
                switch (id.ToLower())
                {
                    case "ifil":
                        SfVersionMajor = input.ReadInt16LE();
                        SfVersionMinor = input.ReadInt16LE();
                        break;
                    case "isng":
                        SoundEngine = input.Read8BitStringLength(size);
                        break;
                    case "inam":
                        BankName = input.Read8BitStringLength(size);
                        break;
                    case "irom":
                        DataRom = input.Read8BitStringLength(size);
                        break;
                    case "iver":
                        RomVersionMajor = input.ReadInt16LE();
                        RomVersionMinor = input.ReadInt16LE();
                        break;
                    case "icrd":
                        CreationDate = input.Read8BitStringLength(size);
                        break;
                    case "ieng":
                        Author = input.Read8BitStringLength(size);
                        break;
                    case "iprd":
                        TargetProduct = input.Read8BitStringLength(size);
                        break;
                    case "icop":
                        Copyright = input.Read8BitStringLength(size);
                        break;
                    case "icmt":
                        Comments = input.Read8BitStringLength(size);
                        break;
                    case "isft":
                        Tools = input.Read8BitStringLength(size);
                        break;
                    default:
                        throw new Exception("Invalid soundfont. The Chunk: " + id + " was not expected.");
                }
            }
        }
Ejemplo n.º 11
0
 private static string ReadString(IReadable input)
 {
     var length = ReadVariableLength(input);
     return input.Read8BitChars(length); // TODO: check for correct string encoding
 }
Ejemplo n.º 12
0
        private MidiTrack ReadTrack(IReadable input)
        {
            var instList = new FastList<Byte>();
            var drumList = new FastList<Byte>();
            var channelList = new FastList<Byte>();
            var eventList = new FastList<MidiEvent>();
            var noteOnCount = 0;
            var totalTime = 0;
            while (input.Read8BitChars(4) != "MTrk")
            {
                var length = input.ReadInt32BE();
                while (length > 0)
                {
                    length--;
                    input.ReadByte();
                }
            }

            var endPosition = input.ReadInt32BE() + input.Position;
            var prevStatus = 0;
            while (input.Position < endPosition)
            {
                var delta = ReadVariableLength(input);
                totalTime += delta;
                var status = input.ReadByte();
                if (status >= 0x80 && status <= 0xEF)
                {//voice message
                    prevStatus = status;
                    eventList.Add(ReadVoiceMessage(input, delta, (byte)status, (byte)input.ReadByte()));
                    noteOnCount = TrackVoiceStats(eventList[eventList.Count - 1], instList, drumList, channelList, noteOnCount);
                }
                else if (status >= 0xF0 && status <= 0xF7)
                {//system common message
                    prevStatus = 0;
                    eventList.Add(ReadSystemCommonMessage(input, delta, (byte)status));
                }
                else if (status >= 0xF8 && status <= 0xFF)
                {//realtime message
                    eventList.Add(ReadRealTimeMessage(input, delta, (byte)status));
                }
                else
                {//data bytes
                    if (prevStatus == 0)
                    {//if no running status continue to next status byte
                        while ((status & 0x80) != 0x80)
                        {
                            status = input.ReadByte();
                        }
                        if (status >= 0x80 && status <= 0xEF)
                        {//voice message
                            prevStatus = status;
                            eventList.Add(ReadVoiceMessage(input, delta, (byte)status, (byte)input.ReadByte()));
                            noteOnCount = TrackVoiceStats(eventList[eventList.Count - 1], instList, drumList, channelList, noteOnCount);
                        }
                        else if (status >= 0xF0 && status <= 0xF7)
                        {//system common message
                            eventList.Add(ReadSystemCommonMessage(input, delta, (byte)status));
                        }
                        else if (status >= 0xF8 && status <= 0xFF)
                        {//realtime message
                            eventList.Add(ReadRealTimeMessage(input, delta, (byte)status));
                        }
                    }
                    else
                    {//otherwise apply running status
                        eventList.Add(ReadVoiceMessage(input, delta, (byte)prevStatus, (byte)status));
                        noteOnCount = TrackVoiceStats(eventList[eventList.Count - 1], instList, drumList, channelList, noteOnCount);
                    }
                }
            }

            if (input.Position != endPosition)
                throw new Exception("The track length was invalid for the current MTrk chunk.");
            if (channelList.IndexOf(MidiHelper.DrumChannel) != -1)
            {
                if (drumList.IndexOf(0) == -1)
                    drumList.Add(0);
            }
            else
            {
                if (instList.IndexOf(0) == -1)
                    instList.Add(0);
            }
            var track = new MidiTrack(instList.ToArray(),
                drumList.ToArray(),
                channelList.ToArray(),
                eventList.ToArray());
            track.NoteOnCount = noteOnCount;
            track.EndTime = totalTime;
            return track;
        }