Пример #1
0
        private void fromMidiMls(BinaryReader file, int headerTracks, bool normalisation, bool loop, int loopformat)
        {
            events = new List<List<List<int>>>();
            MIDI mid = new MIDI(file);
            int tempo = 0;

            trackCount = mid.TrackCount - headerTracks;

            // search in header tracks for tempo
            for (int i = 0; i < headerTracks; i++ )
            {
                mid.TrackPosition = i;
                int[] status;

                while (true)
                {
                    status = mid.read();
                    status = mid.read();

                    if (status[0] == 0xFF)
                    {
                        // forgot why to divide by 2, maybe because it would go too fast otherwise
                        if (status[1] == 0x51) tempo = (60000000 / ((status[3] << 16) + (status[4] << 8) + (status[5])));
                        else if (status[1] == 0x2F) break;
                    }
                }
            }

            // read the other tracks
            for (int i = headerTracks; i < mid.TrackCount; i++)
            {
                int pos = i - headerTracks;
                mid.TrackPosition = i;

                events.Add(new List<List<int>>());

                bool endOfTrack = false;
                int[] status;

                int rest = 0;
                int note = 0;
                int noteLength = 0;
                decimal noteVolume = 0;
                decimal trackVolume = 0x7F; // this is the standard for each midi, if the volume isn't specified
                int volume = 0;

                int loopStart = 0;

                // always first the tempo to play safe
                if (tempo == 0) events[pos].Add(new List<int> { 0xF9, 0x78 });
                else events[pos].Add(new List<int> { 0xF9, tempo });

                while (!endOfTrack)
                {
                    // ---------- read rest ----------
                    rest = Convert.ToInt32(Convert.ToDecimal(mid.read()[0]) / (Convert.ToDecimal(mid.Devision) / 0x30));

                    if (note != 0) noteLength += rest;
                    if (rest != 0 && note == 0)
                        while (true)
                            if (rest > 0x90) { events[pos].Add(new List<int> { 0xF6, 0x90 }); rest -= 0x90; }
                            else { events[pos].Add(new List<int> { 0xF6, rest }); rest = 0; break; }

                    // ---------- read event ----------
                    status = mid.read();

                    switch (status[0] & 0xF0)
                    {
                        case 0x90:                                                                      // note on
                            if (status[1] == 0x7F) loopStart = events[pos].Count;//first look for a loop
                            else if (note == 0)
                            {
                                note = status[1];
                                noteVolume = status[2];
                                noteLength = 0;
                            }
                            // quick and dirty solution on note normalisation
                            // notice that you cannot normalize a note when the length = 0, thus more notes starting at the same time
                            // this will end up with 0 length notes and will eventually lead to a crash
                            // because 0 length notes are read as extended notes
                            else if (normalisation && noteLength != 0)
                            {
                                // write volume changes
                                int newVolume = Convert.ToInt32(trackVolume / 100 * (noteVolume / 0x7F * 100)) * 2;
                                if (volume != newVolume)
                                {
                                    volume = newVolume;
                                    events[pos].Add(new List<int> { 0xF1, volume });
                                }

                                // write note/notes
                                while (true)
                                    if (noteLength > 0x90) { events[pos].Add(new List<int> { 0x00, note + 0x80, 0x90 }); noteLength -= 0x90; }
                                    else { events[pos].Add(new List<int> { noteLength, note }); break; }

                                // setup new note
                                note = status[1];
                                noteVolume = status[2];
                                noteLength = 0;
                            }
                            break;

                        case 0x80:
                                if (note == status[1] && noteLength != 0)                                                      // note off
                                {
                                    // write volume changes
                                    int newVolume = Convert.ToInt32(trackVolume / 100 * (noteVolume / 0x7F * 100)) * 2;
                                    if (volume != newVolume)
                                    {
                                        volume = newVolume;
                                        events[pos].Add(new List<int> { 0xF1, volume });
                                    }

                                    // write note/notes
                                    while (true)
                                        if (noteLength > 0x90) { events[pos].Add(new List<int> { 0x00, note + 0x80, 0x90 }); noteLength -= 0x90; }
                                        else { events[pos].Add(new List<int> { noteLength, note }); break; }

                                    // this note has been done, clear note to read next note
                                    note = 0;
                                }
                                break;

                        case 0xB0: if (status[1] == 0x07) trackVolume = status[2]; break;                   // channel volume

                        case 0xC0: events[pos].Add(new List<int> { 0xF0, status[1] }); break;               // instrument

                        case 0xF0:
                                if (status[1] == 0x2F)                                                      // end of track
                                {
                                    if (loop)
                                    {
                                        if (loopformat == 0) loopStart = 0;
                                        events[pos].Add(new List<int> { 0xF8, (0xFFFF - Common.giveByteCount(events[pos], loopStart)) });
                                        endOfTrack = true;
                                    }
                                    else events[pos].Add(new List<int> { 0xFF }); endOfTrack = true;
                                }
                                else if (status[1] == 0x51)                                                 // volume
                                {
                                    events[pos].Add(new List<int> { 0xF9, (60000000 / ((status[3] << 16) + (status[4] << 8) + (status[5]))) });
                                }
                                break;
                    }
                }
            }
        }
Пример #2
0
        private void fromMidiBkg(BinaryReader file, int headerTracks)
        {
            events = new List <List <List <int> > >();
            MIDI mid = new MIDI(file);

            trackCount = mid.TrackCount;

            for (int i = 0; i < trackCount; i++)
            {
                int channelNumber;
                if (i > headerTracks)
                {
                    channelNumber = i - headerTracks;
                }
                else
                {
                    channelNumber = 0;
                }

                mid.TrackPosition = i;
                events.Add(new List <List <int> >());
                bool endOfTrack = false;

                while (!endOfTrack)
                {
                    int rest = 0;
                    if (mid.Devision != 0)
                    {
                        rest = mid.read()[0] / mid.Devision;
                    }
                    else
                    {
                        rest = mid.read()[0];
                    }

                    if (rest > 0x00 && rest <= 0xFF)
                    {
                        events[i].Add(new List <int> {
                            0x01, rest
                        });                                                                       // 8-bit rest
                    }
                    if (rest > 0xFF && rest <= 0xFFFF)
                    {
                        events[i].Add(new List <int> {
                            0x02, rest
                        });                                                                         // 16-bit rest
                    }
                    if (rest > 0xFFFF && rest <= 0xFFFFFF)
                    {
                        events[i].Add(new List <int> {
                            0x03, rest
                        });                                                                             // 16-bit rest
                    }
                    if (rest > 0xFFFFFF)
                    {
                        MessageBox.Show("delta time larger than 0xFFFFFF, not used");
                    }

                    int[] status = mid.read();

                    switch (status[0] & 0xF0)
                    {
                    case 0x80: events[i].Add(new List <int> {
                            (channelNumber << 4) + 0x06, status[1], status[2]
                        }); break;                                                                                            // note off

                    case 0x90: events[i].Add(new List <int> {
                            (channelNumber << 4) + 0x05, status[1], status[2]
                        }); break;                                                                                            // note on

                    case 0xB0: if (status[1] == 0x07)
                        {
                            events[i].Add(new List <int> {
                                (channelNumber << 4) + 0x07, status[1], status[2]
                            });
                        }
                        break;                                                                                                                       // channel volume

                    case 0xC0: events[i].Add(new List <int> {
                            (channelNumber << 4) + 0x08, status[1]
                        }); break;                                                                                 // instrument

                    case 0xE0: events[i].Add(new List <int> {
                            (channelNumber << 4) + 0x0A, status[2] * 0x80
                        }); break;                                                                                        // pitch bend

                    case 0xF0: if (status[1] == 0x2F)
                        {
                            events[i].Add(new List <int> {
                                0x0B
                            }); endOfTrack = true;
                        }                                                                                               // end of track
                        else if (status[1] == 0x51)
                        {
                            events[i].Add(new List <int> {
                                0x00, (status[3] << 16) + (status[4] << 8) + (status[5])
                            });
                        }                                                                                                                              // tempo
                        break;
                    }
                }
            }

            mid.close();
        }
Пример #3
0
        private void fromMidiBkg(BinaryReader file, int headerTracks)
        {
            events = new List<List<List<int>>>();
            MIDI mid = new MIDI(file);

            trackCount = mid.TrackCount;

            for (int i = 0; i < trackCount; i++)
            {
                int channelNumber;
                if (i > headerTracks) channelNumber = i - headerTracks;
                else channelNumber = 0;

                mid.TrackPosition = i;
                events.Add(new List<List<int>>());
                bool endOfTrack = false;

                while (!endOfTrack)
                {
                    int rest = 0;
                    if (mid.Devision != 0) rest = mid.read()[0] / mid.Devision;
                    else rest = mid.read()[0];

                    if (rest > 0x00 && rest <= 0xFF) events[i].Add(new List<int> { 0x01, rest }); // 8-bit rest
                    if (rest > 0xFF && rest <= 0xFFFF) events[i].Add(new List<int> { 0x02, rest }); // 16-bit rest
                    if (rest > 0xFFFF && rest <= 0xFFFFFF) events[i].Add(new List<int> { 0x03, rest }); // 16-bit rest
                    if (rest > 0xFFFFFF) MessageBox.Show("delta time larger than 0xFFFFFF, not used");

                    int[] status = mid.read();

                    switch(status[0] & 0xF0)
                    {
                        case 0x80: events[i].Add(new List<int> { (channelNumber << 4) + 0x06, status[1], status[2] }); break; // note off
                        case 0x90: events[i].Add(new List<int> { (channelNumber << 4) + 0x05, status[1], status[2] }); break; // note on
                        case 0xB0: if (status[1] == 0x07) events[i].Add(new List<int> { (channelNumber << 4) + 0x07, status[1], status[2] }); break; // channel volume
                        case 0xC0: events[i].Add(new List<int> { (channelNumber << 4) + 0x08, status[1] }); break; // instrument
                        case 0xE0: events[i].Add(new List<int> { (channelNumber << 4) + 0x0A, status[2] * 0x80 }); break; // pitch bend
                        case 0xF0: if (status[1] == 0x2F) { events[i].Add(new List<int> { 0x0B }); endOfTrack = true; } // end of track
                            else if (status[1] == 0x51) { events[i].Add(new List<int> { 0x00, (status[3] << 16) + (status[4] << 8) + (status[5]) }); } // tempo
                            break;
                    }
                }
            }

            mid.close();
        }
Пример #4
0
        private void fromMidiMls(BinaryReader file, int headerTracks, bool normalisation, bool loop, int loopformat)
        {
            events = new List <List <List <int> > >();
            MIDI mid   = new MIDI(file);
            int  tempo = 0;

            trackCount = mid.TrackCount - headerTracks;

            // search in header tracks for tempo
            for (int i = 0; i < headerTracks; i++)
            {
                mid.TrackPosition = i;
                int[] status;

                while (true)
                {
                    status = mid.read();
                    status = mid.read();

                    if (status[0] == 0xFF)
                    {
                        // forgot why to divide by 2, maybe because it would go too fast otherwise
                        if (status[1] == 0x51)
                        {
                            tempo = (60000000 / ((status[3] << 16) + (status[4] << 8) + (status[5])));
                        }
                        else if (status[1] == 0x2F)
                        {
                            break;
                        }
                    }
                }
            }

            // read the other tracks
            for (int i = headerTracks; i < mid.TrackCount; i++)
            {
                int pos = i - headerTracks;
                mid.TrackPosition = i;

                events.Add(new List <List <int> >());

                bool  endOfTrack = false;
                int[] status;

                int     rest        = 0;
                int     note        = 0;
                int     noteLength  = 0;
                decimal noteVolume  = 0;
                decimal trackVolume = 0x7F; // this is the standard for each midi, if the volume isn't specified
                int     volume      = 0;

                int loopStart = 0;

                // always first the tempo to play safe
                if (tempo == 0)
                {
                    events[pos].Add(new List <int> {
                        0xF9, 0x78
                    });
                }
                else
                {
                    events[pos].Add(new List <int> {
                        0xF9, tempo
                    });
                }

                while (!endOfTrack)
                {
                    // ---------- read rest ----------
                    rest = Convert.ToInt32(Convert.ToDecimal(mid.read()[0]) / (Convert.ToDecimal(mid.Devision) / 0x30));

                    if (note != 0)
                    {
                        noteLength += rest;
                    }
                    if (rest != 0 && note == 0)
                    {
                        while (true)
                        {
                            if (rest > 0x90)
                            {
                                events[pos].Add(new List <int> {
                                    0xF6, 0x90
                                }); rest -= 0x90;
                            }
                            else
                            {
                                events[pos].Add(new List <int> {
                                    0xF6, rest
                                }); rest = 0; break;
                            }
                        }
                    }

                    // ---------- read event ----------
                    status = mid.read();

                    switch (status[0] & 0xF0)
                    {
                    case 0x90:                                                                          // note on
                        if (status[1] == 0x7F)
                        {
                            loopStart = events[pos].Count;                       //first look for a loop
                        }
                        else if (note == 0)
                        {
                            note       = status[1];
                            noteVolume = status[2];
                            noteLength = 0;
                        }
                        // quick and dirty solution on note normalisation
                        // notice that you cannot normalize a note when the length = 0, thus more notes starting at the same time
                        // this will end up with 0 length notes and will eventually lead to a crash
                        // because 0 length notes are read as extended notes
                        else if (normalisation && noteLength != 0)
                        {
                            // write volume changes
                            int newVolume = Convert.ToInt32(trackVolume / 100 * (noteVolume / 0x7F * 100)) * 2;
                            if (volume != newVolume)
                            {
                                volume = newVolume;
                                events[pos].Add(new List <int> {
                                    0xF1, volume
                                });
                            }

                            // write note/notes
                            while (true)
                            {
                                if (noteLength > 0x90)
                                {
                                    events[pos].Add(new List <int> {
                                        0x00, note + 0x80, 0x90
                                    }); noteLength -= 0x90;
                                }
                                else
                                {
                                    events[pos].Add(new List <int> {
                                        noteLength, note
                                    }); break;
                                }
                            }

                            // setup new note
                            note       = status[1];
                            noteVolume = status[2];
                            noteLength = 0;
                        }
                        break;

                    case 0x80:
                        if (note == status[1] && noteLength != 0)                                                              // note off
                        {
                            // write volume changes
                            int newVolume = Convert.ToInt32(trackVolume / 100 * (noteVolume / 0x7F * 100)) * 2;
                            if (volume != newVolume)
                            {
                                volume = newVolume;
                                events[pos].Add(new List <int> {
                                    0xF1, volume
                                });
                            }

                            // write note/notes
                            while (true)
                            {
                                if (noteLength > 0x90)
                                {
                                    events[pos].Add(new List <int> {
                                        0x00, note + 0x80, 0x90
                                    }); noteLength -= 0x90;
                                }
                                else
                                {
                                    events[pos].Add(new List <int> {
                                        noteLength, note
                                    }); break;
                                }
                            }

                            // this note has been done, clear note to read next note
                            note = 0;
                        }
                        break;

                    case 0xB0: if (status[1] == 0x07)
                        {
                            trackVolume = status[2];
                        }
                        break;                                                                              // channel volume

                    case 0xC0: events[pos].Add(new List <int> {
                            0xF0, status[1]
                        }); break;                                                                          // instrument

                    case 0xF0:
                        if (status[1] == 0x2F)                                                              // end of track
                        {
                            if (loop)
                            {
                                if (loopformat == 0)
                                {
                                    loopStart = 0;
                                }
                                events[pos].Add(new List <int> {
                                    0xF8, (0xFFFF - Common.giveByteCount(events[pos], loopStart))
                                });
                                endOfTrack = true;
                            }
                            else
                            {
                                events[pos].Add(new List <int> {
                                    0xFF
                                });
                            } endOfTrack = true;
                        }
                        else if (status[1] == 0x51)                                                         // volume
                        {
                            events[pos].Add(new List <int> {
                                0xF9, (60000000 / ((status[3] << 16) + (status[4] << 8) + (status[5])))
                            });
                        }
                        break;
                    }
                }
            }
        }