public static MidiFile Create(string filePath, MidiImportSettings midiImportSettings) { var midiFileAsset = CreateInstance <MidiFile>(); var parsedMidiFile = new ParsedMidiFile(filePath); midiFileAsset.RawData = new MidiRawData { Format = parsedMidiFile.Format, TicksPerQuarterNote = parsedMidiFile.TicksPerQuarterNote, Tracks = parsedMidiFile.Tracks, TracksCount = parsedMidiFile.TracksCount }; var processor = new MidiRawDataProcessor(parsedMidiFile, midiImportSettings); midiFileAsset.Data = new MidiData { Tracks = processor.tracks, Bpm = processor.Bpm }; return(midiFileAsset); }
public MidiRawDataProcessor(ParsedMidiFile midiFile, MidiImportSettings midiImportSettings) { tracks = new List <MidiData.MidiTrack>(midiFile.TracksCount); for (var i = 0; i < midiFile.TracksCount; i++) { tracks.Add(new MidiData.MidiTrack()); _noteTimeMap.Add(new Dictionary <byte, NoteOnEvent>()); } if (midiImportSettings.OverrideBpm) { Bpm = midiImportSettings.Bpm; } foreach (var track in midiFile.Tracks) { var map = _noteTimeMap[track.Index]; foreach (var midiEvent in track.MidiEvents) { var timsMs = MidiUtilities.MidiTimeToMs(Bpm, midiFile.TicksPerQuarterNote, midiEvent.Time); var note = midiEvent.Arg2; switch ((MidiRawData.MidiEventType)midiEvent.Type) { case MidiRawData.MidiEventType.NoteOff: // block end var noteOnEvent = map[note]; // create new block var block = new MidiData.MidiBlock { StartTimeMs = noteOnEvent.StartTimeMs, EndTimeMs = timsMs, Note = note, Velocity = noteOnEvent.Velocity }; tracks[track.Index].AddBlock(block); if (map.TryGetValue(note, out var existingNote)) { if (existingNote.Count == 1) { map.Remove(note); } else { map[note] = new NoteOnEvent { Count = existingNote.Count - 1, Velocity = existingNote.Velocity, StartTimeMs = existingNote.StartTimeMs }; } } else { throw new Exception($"note off event - could not find matching on event"); } allBlocks.Add(block); break; case MidiRawData.MidiEventType.NoteOn: // block start if (map.TryGetValue(note, out var existingNoteOnEvent)) { map[note] = new NoteOnEvent { StartTimeMs = timsMs, Velocity = midiEvent.Arg3, Count = existingNoteOnEvent.Count + 1 }; } else { map.Add(note, new NoteOnEvent { StartTimeMs = timsMs, Velocity = midiEvent.Arg3, Count = 1 }); } break; case MidiRawData.MidiEventType.KeyAfterTouch: break; case MidiRawData.MidiEventType.ControlChange: break; case MidiRawData.MidiEventType.ProgramChange: break; case MidiRawData.MidiEventType.ChannelAfterTouch: break; case MidiRawData.MidiEventType.PitchBendChange: break; case MidiRawData.MidiEventType.MetaEvent: switch (midiEvent.MetaEventType) { case MidiRawData.MetaEventType.Tempo: // only set the bpm if override bpm is off if (!midiImportSettings.OverrideBpm) { // set new bpm Bpm = (byte)midiEvent.Note; } break; case MidiRawData.MetaEventType.TimeSignature: break; case MidiRawData.MetaEventType.KeySignature: break; default: throw new ArgumentOutOfRangeException(); } break; default: throw new ArgumentOutOfRangeException(); } } } foreach (var track in tracks) { if (track.Blocks.Count == 0) { track.MinNote = track.MaxNote = 0; track.MinVelocity = track.MaxVelocity = 0; } } }