public void HandleMidiEvent(MidiEvent me) { if (MidiEvent.IsNoteOn(me)) { HandleNoteOn(((NoteOnEvent)me).NoteNumber); } else if (MidiEvent.IsNoteOff(me)) { HandleNoteOff(((NoteEvent)me).NoteNumber); } else if (me.CommandCode == MidiCommandCode.PitchWheelChange) { HandlePitchWheelChange(((PitchWheelChangeEvent)me).Pitch); } else if (me.CommandCode == MidiCommandCode.ControlChange) { HandleControlChange(((ControlChangeEvent)me).Controller, ((ControlChangeEvent)me).ControllerValue); } else if (me.CommandCode == MidiCommandCode.MetaEvent) { Debug.Assert(me is MetaEvent); if (me is TempoEvent) { HandleTempoChange(((TempoEvent)me).MicrosecondsPerQuarterNote); } } }
/// <summary> /// MIDI in event handler. /// </summary> /// <param name="sender">Calling object.</param> /// <param name="e">Arguments passed.</param> private void MidiInDevice_messageHandler(object sender, MidiInMessageEventArgs e) { // Do nothing if we don't have any tones to play if (tonesAvailable == null || tonesAvailable.Length == 0) { return; } // Call ToggleTone on the UI thread using Invoke ToggleToneDelegate ttd = new ToggleToneDelegate(ToggleTone); Object[] args = new Object[2]; if (MidiEvent.IsNoteOn(e.MidiEvent)) { args[0] = ((NoteOnEvent)e.MidiEvent).NoteNumber; args[1] = Toggle.Play; Invoke(ttd, args); } else if (MidiEvent.IsNoteOff(e.MidiEvent)) { args[0] = ((NoteEvent)e.MidiEvent).NoteNumber; args[1] = Toggle.Stop; Invoke(ttd, args); } }
private void ReadMidiFile(MidiFile midiFile, List <MidiNote> midiNotes) { if (midiFile.Tracks > 1) { Debug.LogWarning("Warning! Midi file has more than one track. Taking first track"); } int totalMidiEvents = midiFile.Events[0].Count; for (int i = 0; i < totalMidiEvents; i++) { MidiEvent midiEvent = midiFile.Events[0][i]; if (timeSignature is null) { try { timeSignature = (TimeSignatureEvent)midiEvent; } catch (InvalidCastException e) when(e.Data != null) { } } if (!MidiEvent.IsNoteOff(midiEvent)) { // Get the final tick of the song if (i == totalMidiEvents - 1) { int eventTime = (int)midiEvent.AbsoluteTime; if (eventTime > finalTick) { finalTick = eventTime; } } // Ensure that the midievent is a note, and not metadata if (midiEvent.CommandCode.ToString() == "NoteOn") { // Note length is retrieved from the next midiEvent's deltaTime float noteLength = 0; // Not at the end yet if (i < totalMidiEvents) { MidiEvent nextMidievent = midiFile.Events[0][i + 1]; noteLength = ((float)nextMidievent.DeltaTime / ticksperQuarterNote); } Debug.Log(noteLength); MidiNote note = GenerateMidiNote(midiEvent.AbsoluteTime, noteLength); midiNotes.Add(note); } } } }
public void MidiEvent(MidiEvent midiEvent) { if (!NoteInputMode.IsMidi()) { return; } if (midiEvent.IsNoteOn()) { var pitch = MidiPitchMapping.Map(midiEvent.Cast <NoteEvent>()); NoteSink.NoteOn(pitch); } else if (midiEvent.IsNoteOff()) { var pitch = MidiPitchMapping.Map(midiEvent.Cast <NoteEvent>()); NoteSink.NoteOff(pitch); } }
public string Describe(string fileName) { MidiFile mf = new MidiFile(fileName, false); StringBuilder sb = new StringBuilder(); sb.AppendFormat("Format {0}, Tracks {1}, Delta Ticks Per Quarter Note {2}\r\n", mf.FileFormat, mf.Tracks, mf.DeltaTicksPerQuarterNote); var timeSignature = mf.Events[0].OfType <NAudio.Midi.TimeSignatureEvent>().FirstOrDefault(); bool found_BPM = false; for (int n = 0; n < mf.Tracks; n++) { foreach (MidiEvent midiEvent in mf.Events[n]) { if (!found_BPM) { if (midiEvent.ToString().Contains("bpm")) { found_BPM = true; String extractMPQ = midiEvent.ToString(); int index = extractMPQ.LastIndexOf('m') + 3; String intermediateString = extractMPQ.Remove(0, index); int indexLastParanthesis = intermediateString.LastIndexOf(')'); String finalString = intermediateString.Remove(indexLastParanthesis, 1); int microsecPerQuartNote = Convert.ToInt32(finalString); milliSecondsPerQuartNote = (float)((microsecPerQuartNote) / 1000.0); //Debug.Log(milliSecondsPerQuartNote + " Milliseconds per quarter note"); //String finalMPQ = extractMPQ.Remove() //Console.WriteLine("Just hit BPM"); } } if (!MidiEvent.IsNoteOff(midiEvent)) { currentMidiEvent = midiEvent; sb.AppendFormat("{0} {1}\r\n", ToMBT(midiEvent.AbsoluteTime, mf.DeltaTicksPerQuarterNote, timeSignature), midiEvent); } } } return(sb.ToString()); }
public bool Process(MidiEvent inEvent, EventRuleArgs args) { NoteOnEvent noteEvent = inEvent as NoteOnEvent; // filter note offs - they will be added by their note-on if (MidiEvent.IsNoteOff(inEvent)) { return(false); } // if it is a note event, special processing if (noteEvent != null) { foreach (IEventRule rule in noteRules) { if (rule.Apply(inEvent, args)) { return(true); } } // an unmatched note event // TODO: configure to have an option to retain these return(false); } // now see if we need to exclude this event foreach (IEventRule rule in excludeRules) { if (rule.Apply(inEvent, args)) { return(false); } } bool updatedEvent = false; foreach (IEventRule rule in eventRules) { updatedEvent |= rule.Apply(inEvent, args); } return(true); // updatedEvent; }
public string Describe(string fileName) { MidiFile mf = new MidiFile(fileName, false); StringBuilder sb = new StringBuilder(); sb.AppendFormat("Format {0}, Tracks {1}, Delta Ticks Per Quarter Note {2}\r\n", mf.FileFormat, mf.Tracks, mf.DeltaTicksPerQuarterNote); var timeSignature = mf.Events[0].OfType <TimeSignatureEvent>().FirstOrDefault(); for (int n = 0; n < mf.Tracks; n++) { foreach (MidiEvent midiEvent in mf.Events[n]) { if (!MidiEvent.IsNoteOff(midiEvent)) { sb.AppendFormat("{0} {1}\r\n", ToMBT(midiEvent.AbsoluteTime, mf.DeltaTicksPerQuarterNote, timeSignature), midiEvent); } } } return(sb.ToString()); }
public string Describe(string fileName) { MidiFile mf = new MidiFile(fileName, false); StringBuilder sb = new StringBuilder(); sb.AppendFormat("Format {0}, Tracks {1}, Delta Ticks Per Quarter Note {2}\r\n", mf.FileFormat, mf.Tracks, mf.DeltaTicksPerQuarterNote); int beatsPerMeasure = FindBeatsPerMeasure(mf.Events[0]); for (int n = 0; n < mf.Tracks; n++) { foreach (MidiEvent midiEvent in mf.Events[n]) { if (!MidiEvent.IsNoteOff(midiEvent)) { sb.AppendFormat("{0} {1}\r\n", ToMBT(midiEvent.AbsoluteTime, mf.DeltaTicksPerQuarterNote, beatsPerMeasure), midiEvent); } } } return(sb.ToString()); }
/// <summary> /// 通过Midi生成时间序列 /// </summary> /// <param name="fileName">Midi文件路径</param> /// <param name="timeLine">时间序列</param> /// <param name="rate">播放速率(New BPM = BPM * rate)</param> /// <param name="synchroTick">节奏间隔(MidiTick),设置此项后将忽略播放速率</param> /// <returns>时间序列</returns> public TimeLine Serialize(string fileName, TimeLine timeLine, double rate = -1, int synchroTick = -1, ShowProgress showProgress = null) { try { if (timeLine == null) { timeLine = new TimeLine(); } var midiFile = new MidiFile(fileName, false); #region HeadParam timeLine.Param["MidiFileFormat"].Value = midiFile.FileFormat; timeLine.Param["MidiTracksCount"].Value = midiFile.Tracks; timeLine.Param["MidiDeltaTicksPerQuarterNote"].Value = midiFile.DeltaTicksPerQuarterNote; #endregion #region Nodes //Public Event var timeSignature = midiFile.Events[0].OfType <TimeSignatureEvent>().FirstOrDefault(); double bpm = 0; timeLine.BeatsPerBar = timeSignature == null ? 4 : timeSignature.Numerator; timeLine.TicksPerBar = timeSignature == null ? midiFile.DeltaTicksPerQuarterNote * 4 : (timeSignature.Numerator * midiFile.DeltaTicksPerQuarterNote * 4) / (1 << timeSignature.Denominator); timeLine.TicksPerBeat = timeLine.TicksPerBar / timeLine.BeatsPerBar; #region MidiFile -> MidiNodes(Unordered) List <MidiNode> MidiNodes = new List <MidiNode>(); //Foreach Events in MidiFile for (int i = 0; i < midiFile.Tracks; i++) { //Track Events var track = ""; var instrument = ""; var vol = -1; var pan = -1; foreach (MidiEvent midiEvent in midiFile.Events[i]) { //Event BPM if (new Regex("(?<=SetTempo )\\d+(?=bpm \\(\\d+\\))").Match(midiEvent.ToString()).Success) { bpm = Int32.Parse(new Regex("(?<=SetTempo )\\d+(?=bpm \\(\\d+\\))").Match(midiEvent.ToString()).Value); if (rate > 0) { bpm *= rate; } MidiNodes.Add(new MidiNode() { IsEvent = true, Param = new Dictionary <string, _Node_INT>() { { "BeatPerMinute", new _Node_INT() { Value = (int)bpm } }, { "DeltaTickStart", new _Node_INT() { Value = midiEvent.DeltaTime } }, { "MinecraftTickStart", new _Node_INT() { Value = 0 } } } }); } //Event Track Name if (new Regex("(?<=SequenceTrackName ).+(?=$)").Match(midiEvent.ToString()).Success) { track = new Regex("(?<=SequenceTrackName ).+(?=$)").Match(midiEvent.ToString()).Value; } //Event Instrument Name if (new Regex("(?<=PatchChange Ch: \\d+ ).+(?=$)").Match(midiEvent.ToString()).Success) { instrument = new Regex("(?<=PatchChange Ch: \\d+ ).+(?=$)").Match(midiEvent.ToString()).Value; } //Event Track Volume if (new Regex("(?<=MainVolume Value )\\d*(?=$)").Match(midiEvent.ToString()).Success) { Int32.TryParse(new Regex("(?<=MainVolume Value )\\d*(?=$)").Match(midiEvent.ToString()).Value, out vol); } //Event Track Pan if (new Regex("(?<=Pan Value )\\d*(?=$)").Match(midiEvent.ToString()).Success) { Int32.TryParse(new Regex("(?<=Pan Value )\\d*(?=$)").Match(midiEvent.ToString()).Value, out pan); } if (!MidiEvent.IsNoteOff(midiEvent)) { //Get Param var MBT = GetMBT(midiEvent.AbsoluteTime, midiFile.DeltaTicksPerQuarterNote, timeSignature); var EventAnalysis = AnalysisEvent(midiEvent, instrument); //Write into MidiNodes if (EventAnalysis != null) { var MidiNode = new MidiNode(); #region Param //Time-related MidiNode.Param["DeltaTickStart"].Value = (int)EventAnalysis.StartTick; //MidiNode Starts Needs more Calculation MidiNode.Param["DeltaTickDuration"].Value = (int)EventAnalysis.Length; MidiNode.Param["MinecraftTickDuration"].Value = (int)MinecraftTickDuration(EventAnalysis.Length, midiFile.DeltaTicksPerQuarterNote, timeSignature, (int)bpm); MidiNode.Param["BeatPerMinute"].Value = (int)bpm; //Bar-related MidiNode.Param["BarIndex"].Value = (int)MBT[0]; MidiNode.Param["BeatDuration"].Value = (int)MBT[1]; //Note-related MidiNode.Param["Channel"].Value = (int)EventAnalysis.Channel; MidiNode.Param["Pitch"].Value = (int)EventAnalysis.Pitch; MidiNode.Param["Velocity"].Value = (int)EventAnalysis.Velocity; MidiNode.Param["Panning"].Value = pan; //Track-related MidiNode.Instrument = EventAnalysis.Instrument; MidiNode.TrackName = track; //PlaySound-related MidiNode.PlaySound = new PlaySoundInfo(); MidiNode.PlaySound.MandaVolume = (vol < 0) ? 100 : vol; MidiNode.PlaySound.SetPan(pan); //Generate Track & Instrument List var currentTrack = timeLine.TrackList.AsEnumerable().FirstOrDefault(t => t.Name == track); if (currentTrack == null) { currentTrack = new TimeLine.MidiSettingInspector { Name = track, Type = TimeLine.MidiSettingType.Track, Enable = true }; timeLine.TrackList.Add(currentTrack); } //Add new Track var currentInstrument = timeLine.InstrumentList.AsEnumerable().FirstOrDefault(ins => ins.Name == EventAnalysis.Instrument); if (currentInstrument == null) { currentInstrument = new TimeLine.MidiSettingInspector { Name = EventAnalysis.Instrument, Type = TimeLine.MidiSettingType.Instrument, Enable = true }; timeLine.InstrumentList.Add(currentInstrument); } //Add new Instrument if (!currentTrack.Instruments.Any(ins => ins.Name == EventAnalysis.Instrument)) { currentTrack.Instruments.Add(currentInstrument); currentTrack.InstrumentsUid.Add(currentInstrument.Uid); }//Line Track if (!currentInstrument.Tracks.Any(t => t.Name == track)) { currentInstrument.Tracks.Add(currentTrack); currentInstrument.TracksUid.Add(currentTrack.Uid); } #endregion MidiNodes.Add(MidiNode); } } } } #endregion #region MidiNodes in Order /* Set Total Progress */ timeLine.totalProgress = MidiNodes.Count * 2; bpm = 0; long bpm_key_t = 0; //When BPM Changes long bpm_key_mt = 0; MidiNodes = (from n in MidiNodes orderby n.Param["DeltaTickStart"].Value select n).ToList(); //Make Nodes in Order int synchroCount = 0; for (int i = 0; i < MidiNodes.Count; i++) //Calculate Tick Start { var n = MidiNodes[i]; if (n.IsEvent) { if (bpm != 0) { bpm_key_mt = MinecraftTickStart(n.Param["DeltaTickStart"].Value, midiFile.DeltaTicksPerQuarterNote, timeSignature, bpm, bpm_key_t, bpm_key_mt); } bpm = n.Param["BeatPerMinute"].Value; bpm_key_t = n.Param["DeltaTickStart"].Value; } else { n.Param["BeatPerMinute"].Value = (int)bpm; } if (synchroTick <= 0) { n.Param["MinecraftTickStart"].Value = (int)MinecraftTickStart(n.Param["DeltaTickStart"].Value, midiFile.DeltaTicksPerQuarterNote, timeSignature, bpm, bpm_key_t, bpm_key_mt); } else { //Using synchroTick n.Param["MinecraftTickStart"].Value = n.Param["DeltaTickStart"].Value / synchroTick; if (n.Param["DeltaTickStart"].Value % synchroTick == 0) { synchroCount++; } } /* Update Current Progress */ timeLine.currentProgress++; if (showProgress != null && timeLine.totalProgress > 0) { showProgress((double)timeLine.currentProgress / timeLine.totalProgress); } } timeLine.SynchronousRate = (double)synchroCount / MidiNodes.Count; #endregion #region MidiNodes -> TickNodes //Creat and Set Lenth of TickNodes if (timeLine.TickNodes == null) { timeLine.TickNodes = new List <TickNode>(); } var maxTick = MidiNodes.Max(n => n.Param["MinecraftTickStart"].Value); if (maxTick >= timeLine.TickNodes.Count) { var nowCount = timeLine.TickNodes.Count; for (int i = 0; i < maxTick - nowCount + 1; i++) { timeLine.TickNodes.Add(new TickNode()); } } //MidiNodes -> TickNodes foreach (MidiNode node in MidiNodes) { var index = node.Param["MinecraftTickStart"].Value; var track = node.TrackName; var instrument = node.Instrument; if (timeLine.TickNodes[index].MidiTracks.ContainsKey(track) == false) { timeLine.TickNodes[index].MidiTracks.Add(track, new Dictionary <string, List <MidiNode> >()); } if (timeLine.TickNodes[index].MidiTracks[track].ContainsKey(instrument) == false) { timeLine.TickNodes[index].MidiTracks[track].Add(instrument, new List <MidiNode>()); } timeLine.TickNodes[index].MidiTracks[track][instrument].Add(node); timeLine.TickNodes[index].BPM = node.Param["BeatPerMinute"].Value; timeLine.TickNodes[index].CurrentTick = index; /* Update Current Progress */ timeLine.currentProgress++; if (showProgress != null && timeLine.totalProgress > 0) { showProgress((double)timeLine.currentProgress / timeLine.totalProgress); } } #endregion timeLine.Param["TotalTicks"].Value = timeLine.TickNodes.Count; return(timeLine); //minecraft tick = AbsoluteTime / (bpm * ticksPerBeat) * 1200 #endregion } catch { return(null); } }
private List <decimal> CalculateMidiRealTime() { var strictMode = false; var mf = new MidiFile("Assets/Audios/Midi Files/AgainYui.mid", strictMode); mf.Events.MidiFileType = 0; List <MidiEvent> midiEvents = new List <MidiEvent>(); List <long> beatsList = new List <long>(); for (int n = 0; n < mf.Tracks; n++) { foreach (var midiEvent in mf.Events[n]) { if (!MidiEvent.IsNoteOff(midiEvent)) { var timeSignature = mf.Events[0].OfType <TimeSignatureEvent>().FirstOrDefault(); long beat = GetBeat(midiEvent.AbsoluteTime, mf.DeltaTicksPerQuarterNote, timeSignature); beatsList.Add(beat); midiEvents.Add(midiEvent); //Debug.Log("Beat: " + beat); if (midiEvent is TempoEvent) { //Debug.Log("Absolute Time " + (midiEvent as TempoEvent).AbsoluteTime); } } } } List <decimal> eventsTimesArr = new List <decimal>(); decimal lastRealTime = 0m; decimal lastAbsoluteTime = 0m; decimal currentMicroSecondsPerTick = 0m; for (int i = 0; i < midiEvents.Count; i++) { MidiEvent midiEvent = midiEvents[i]; TempoEvent tempoEvent = midiEvent as TempoEvent; if (midiEvent.AbsoluteTime > lastAbsoluteTime) { lastRealTime += ((decimal)midiEvent.AbsoluteTime - lastAbsoluteTime) * currentMicroSecondsPerTick; } lastAbsoluteTime = midiEvent.AbsoluteTime; if (tempoEvent != null) { currentMicroSecondsPerTick = (decimal)tempoEvent.MicrosecondsPerQuarterNote / (decimal)mf.DeltaTicksPerQuarterNote; // Remove the tempo event to make events and timings match - index-wise // Do not add to the eventTimes midiEvents.RemoveAt(i); beatsList.RemoveAt(i); i--; continue; } // Add the time to the collection. eventsTimesArr.Add(lastRealTime / 1000000m); Debug.Log("Time: " + lastRealTime / 1000000m); } eventsBeatsArr = beatsList.ToArray(); //Debug.Log("Length: " + eventsBeatsArr.Length); return(eventsTimesArr); }
public static bool IsNoteOff(this MidiEvent midiEvent) => MidiEvent.IsNoteOff(midiEvent);
private static List <TimeSlice> ReadMidiFile(MidiFile mf, ICollection <int> tracksToSkip, double tempoRatio, bool skipDrums) { var timeSliceList = new List <TimeSlice>(); var tempo = (int)Math.Round(120 * tempoRatio); Console.WriteLine("Default Tempo: {0}", tempo); var trackNumber = 0; foreach (var midiEventList in mf.Events) { Console.WriteLine(""); Console.WriteLine("Track #{0}", trackNumber); Console.WriteLine("---------"); if (tracksToSkip.Contains(trackNumber)) { trackNumber++; continue; } Console.WriteLine("Track length: {0}", midiEventList.Count); var drumFilteredMidiEventList = midiEventList.Where(midiEvent => !skipDrums || (midiEvent.Channel != 10)); foreach (var midiEvent in drumFilteredMidiEventList) { if (midiEvent is TextEvent textEvent) // : MetaEvent { Console.WriteLine("{0}: {1}", textEvent.MetaEventType.ToString(), textEvent.Text); } else if (midiEvent is TimeSignatureEvent timeSignatureEvent) // : MetaEvent { //WriteWarningLine("TimeSignatureEvent", timeSignatureEvent.ToString()); } else if (midiEvent is TrackSequenceNumberEvent trackSequenceNumberEvent) // : MetaEvent { WriteWarningLine("TrackSequenceNumberEvent", trackSequenceNumberEvent.ToString()); } else if (midiEvent is KeySignatureEvent keySignatureEvent) // : MetaEvent { //WriteWarningLine("KeySignatureEvent", keySignatureEvent.ToString()); } else if (midiEvent is TempoEvent tempoEvent) // : MetaEvent { tempo = (int)Math.Round(tempoEvent.Tempo * tempoRatio); Console.WriteLine("Tempo: {0}", tempo); } else if (midiEvent is MetaEvent metaEvent) { if ((metaEvent.MetaEventType != MetaEventType.SequencerSpecific) && (metaEvent.MetaEventType != MetaEventType.EndTrack) && (metaEvent.MetaEventType != MetaEventType.MidiChannel) && (metaEvent.MetaEventType != MetaEventType.MidiPort)) { WriteWarningLine("MetaEvent", metaEvent.ToString()); } } else if (midiEvent is ControlChangeEvent controlChangeEvent) { //WriteWarningLine("ControlChangeEvent", controlChangeEvent.ToString()); } else if (midiEvent is PatchChangeEvent patchChangeEvent) { Console.WriteLine("Patch: {0}", PatchChangeEvent.GetPatchName(patchChangeEvent.Patch)); if (skipDrums && (patchChangeEvent.Patch >= 112)) { Console.WriteLine("Skipping track..."); break; } } else if (midiEvent is NoteOnEvent noteEvent1) { if (MidiEvent.IsNoteOff(noteEvent1) == false) { if (noteEvent1.OffEvent != null) { var ticksPerMinute = mf.DeltaTicksPerQuarterNote * tempo; var millisecondsPerTick = 60.0 * 1000.0 / ticksPerMinute; var start = (int)Math.Round(noteEvent1.AbsoluteTime * millisecondsPerTick); var stop = (int)Math.Round(noteEvent1.OffEvent.AbsoluteTime * millisecondsPerTick); timeSliceList.Add(new TimeSlice(start, stop, new Note(noteEvent1.NoteNumber, noteEvent1.Velocity))); } else { WriteWarningLine("NoteOnEvent", "No Corresponding Note Off Event"); } } } else if (midiEvent is NoteEvent noteEvent) { if (noteEvent.CommandCode != MidiCommandCode.NoteOff) { WriteWarningLine("NoteEvent", noteEvent.ToString()); } } else { WriteWarningLine("MIDI Event Type", midiEvent.GetType().ToString()); } } trackNumber++; } timeSliceList.Sort(CompareTimeSlicesByStartTime); return(timeSliceList); }