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; } } } }
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(); }
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(); }
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; } } } }