コード例 #1
0
            // chunk = <chunk_id> + <chunk_length> + <chunk_bytes>
            public Chunk(Stream stream)
            {
                Id = StreamHelperBe.ReadString(stream, 4);

                Length = (int)StreamHelperBe.ReadUInt32(stream);
//				DebugConsole.WriteLine("Padding " + (Length & 1));
                Bytes = new byte[Length];
                stream.Read(Bytes, 0, Length);
            }
コード例 #2
0
        public MidiFile(Stream stream)
        {
            // header_chunk = "MThd" + <header_length> + <format> + <n> + <division>
            var chunk = new Chunk(stream);

            if (chunk.Id != "MThd")
            {
                throw new FileFormatException("MidiFile.chunk.Id", chunk.Id, "MThd");
            }

            using (var header = chunk.GetStream()) {
                Format         = (MidiFileFormat)StreamHelperBe.ReadInt16(header);
                NumberOfTracks = StreamHelperBe.ReadUInt16(header);

                var division = StreamHelperBe.ReadInt16(header);
                if (division > 0)
                {
                    TicksPerBeat = division;
                }
                else
                {
                    throw new Exception("STMPE based time is not supported");
                }
            }

            // track_chunk = "MTrk" + <track_length> [+ <delta_time> + <event> ...]
            for (int track = 0; track < NumberOfTracks; track++)
            {
                chunk = new Chunk(stream);
                if (chunk.Id != "MTrk")
                {
                    throw new FileFormatException("MidiFile.chunk.Id", chunk.Id, "MTrk");
                }

                using (var trackStream = chunk.GetStream()) {
                    BuildTrack(trackStream, track);
                }
            }

            Sort();
            Rebase();
            Trim();
        }
コード例 #3
0
        void BuildTrack(Stream stream, int track)
        {
            int  tick          = 0;
            byte runningStatus = 0x00;

            while (stream.Position < stream.Length)
            {
                tick += (int)StreamHelperBe.ReadVlv(stream);
                var statusByte = (byte)stream.ReadByte();

                if (statusByte < 0xF0)                   // Midi events (status bytes 0x8n - 0xEn)
                {
                    byte dataByte1;
                    if (statusByte < 0x80)                       // If the first byte < 0x80, running status is in effect, and this byte is actually the first data byte.
                    {
                        dataByte1  = statusByte;
                        statusByte = runningStatus;
                    }
                    else
                    {
                        dataByte1     = (byte)stream.ReadByte();
                        runningStatus = statusByte;
                    }

                    var midiEvent = new MidiEvent(track, tick, statusByte);

                    switch (statusByte & 0xF0)
                    {
                    case 0x80:                     // Note Off
                    case 0x90:                     // Note On
                    case 0xA0:                     // Aftertouch
                    case 0xB0:                     // Controller Change
                    case 0xE0:                     // Pitch Bend
                        midiEvent.DataByte1 = dataByte1;
                        midiEvent.DataByte2 = (byte)stream.ReadByte();
                        break;

                    case 0xC0:                     // Program Change
                    case 0xD0:                     // Channel Aftertouch
                        midiEvent.DataByte1 = dataByte1;
                        break;

                    default:
                        throw new FileFormatException("MidiFile.statusByte", statusByte.ToString("X"), "[midi statusByte]");
                    }

                    if (midiEvent.Type == MidiEventType.NoteOn && midiEvent.Velocity == 0)
                    {
                        midiEvent.StatusByte = (byte)(0x80 | midiEvent.Channel);
                    }

                    MidiEvents.Add(midiEvent);
                }
                else if (statusByte == 0xF0 || statusByte == 0xF7)                     // SysEx events (status bytes 0xF0 and 0xF7)
                {
                    runningStatus = 0x00;

                    var sysExEvent =
                        new SysExEvent(track, tick, (int)StreamHelperBe.ReadVlv(stream));
                    stream.Read(sysExEvent.Bytes, 0, sysExEvent.Length);

                    SysExEvents.Add(sysExEvent);
                }
                else if (statusByte == 0xFF)                     // Meta events (status byte 0xFF)
                {
                    runningStatus = 0x00;

                    var metaEvent =
                        new MetaEvent(track, tick, (byte)stream.ReadByte(), (int)StreamHelperBe.ReadVlv(stream));
                    stream.Read(metaEvent.Data, 0, metaEvent.Length);

                    MetaEvents.Add(metaEvent);
                }
                else
                {
                    throw new FileFormatException("MidiFile.statusByte", statusByte.ToString("X"), "[midi statusByte]");
                }
            }

            Length = Math.Max(Length, tick);
        }