/// <summary> /// Handles and filters the incoming midi events. /// </summary> /// <param name="events">The midi events for the current cycle.</param> public void Process(VstEventCollection events) { foreach (VstEvent evnt in events) { if (evnt.EventType == VstEventTypes.MidiEvent) { VstMidiEvent midiEvent = (VstMidiEvent)evnt; //System.Diagnostics.Debug.WriteLine("Receiving Midi Event:" + midiEvent.MidiData[0], "VST.NET"); // pass note on and note off to the sample manager if ((midiEvent.Data[0] & 0xF0) == 0x80) { NoteOff?.Invoke(midiEvent.Data[1]); } if ((midiEvent.Data[0] & 0xF0) == 0x90) { // note on with velocity = 0 is a note off if (midiEvent.Data[2] == 0) { NoteOff?.Invoke(midiEvent.Data[1]); } else { NoteOn?.Invoke(midiEvent.Data[1]); } } } } }
/// <summary> /// play the detected chords /// </summary> /// <param name="volume"></param> public void AddChordNotesToModel(int volume = 127) { var channel = _midi.Tracks[0].Channels[11]; foreach (var beat in _beats) { var baseNote = (int)beat.Chord.Tone + 4 * 12; var notes = new[] { baseNote - 12, baseNote, baseNote + (beat.Chord.Scale == Scale.Major ? 4 : 3), baseNote + 7 }; foreach (var pitch in notes) { var note = new NoteOn { ChannelNumber = 11, NoteNumber = (byte)pitch, Volume = (byte)(volume * (1 - beat.Level * 0.125)), AbsoluteTime = beat.AbsoluteTime, AbsoluteRealTime = beat.AbsoluteRealTime, RealTimeLength = beat.Length, End = beat.AbsoluteRealTime + beat.Length }; channel.Events.Add(note); } } var collector = new VolumeChangeCollector(_midi); collector.DetermineVolumes(); }
private void Decode(byte[] message) { byte status = message[0]; switch (status & 0b1111_0000) { case Midi.Status.NoteOffBitmask: if (NoteOffMessage.TryDecode(message, out var noteOffMessage)) { NoteOff?.Invoke(this, in noteOffMessage); } break; case Midi.Status.NoteOnBitmask: if (NoteOnMessage.TryDecoce(message, out var noteOnMessage)) { NoteOn?.Invoke(this, in noteOnMessage); } break; case Midi.Status.PolyphonicKeyPressureBitmask: if (PolyphonicKeyPressureMessage.TryDecode(message, out var polyphonicKeyPressureMessage)) { PolyphonicKeyPressure?.Invoke(this, in polyphonicKeyPressureMessage); } break; case Midi.Status.ControlChangeBitmask: if (ControlChangeMessage.TryDecode(message, out var controlChangeMessage)) { _nrpnInterpreters[(int)controlChangeMessage.Channel].HandleControlChangeMessage(in controlChangeMessage); } break; case Midi.Status.ProgramChangeBitmask: if (ProgramChangeMessage.TryDecode(message, out var programChangeMessage)) { ProgramChange?.Invoke(this, in programChangeMessage); } break; case Midi.Status.ChannelPressureBitmask: if (ChannelPressureMessage.TryDecode(message, out var channelPressureMessage)) { ChannelPressure?.Invoke(this, in channelPressureMessage); } break; case Midi.Status.PitchBendChange: if (PitchBendMessage.TryDecode(message, out var pitchBendMessage)) { PitchBend?.Invoke(this, in pitchBendMessage); } break; default: Log.Error("Unknown message type {Bitmask}", $"{status & 0b1111_0000:X2}"); break; } }
/// <summary> /// Create percussion sounds for the detected meter /// </summary> /// <param name="midi"></param> /// <param name="prolongSustainedNotes"></param> /// <param name="volume"></param> public static void AddBeats(Model midi, bool prolongSustainedNotes = false, int volume = 127) { var channel = midi.Tracks[0].Channels[Channel.PercussionChannelNumber]; var beatEvents = midi.EventsOfType <BeatEvent>().OrderBy(b => b.AbsoluteRealTime); foreach (var beat in beatEvents) { var length = TimeSpan.FromMilliseconds(beat.Length.TotalMilliseconds * 0.25); var note = new NoteOn { ChannelNumber = Channel.PercussionChannelNumber, NoteNumber = beat.Level == 0 ? (byte)36 : (byte)44, Volume = beat.Level == 2 ? (byte)(0.75 * volume) : (byte)volume, AbsoluteRealTime = beat.AbsoluteRealTime, AbsoluteTime = beat.AbsoluteTime, RealTimeLength = length, End = beat.AbsoluteRealTime + length }; channel.Events.Add(note); } var collector = new VolumeChangeCollector(midi); collector.DetermineVolumes(); if (prolongSustainedNotes) { var sustainer = new Sustainer(midi); sustainer.ProlongSustainedNotes(); } }
private void Update() { foreach (var key in virtualKeysDict.Keys) { if (Input.GetKeyDown(key)) { NoteOn?.Invoke(virtualKeysDict[key], 1f); } if (Input.GetKeyUp(key)) { NoteOff?.Invoke(virtualKeysDict[key]); } } }
private void DrawNote(SKCanvas canvas, TimeSpan offset, NoteOn note) { _notePaint.Color = note.AbsoluteRealTime - offset <= _background.StartOffset ? BaseChannelColors[note.ChannelNumber].WithAlpha((byte)((note.RealVolume / _player.MaxVolume) * 255.999)) : DesaturatedChannelColors[note.ChannelNumber].WithAlpha((byte)((note.RealVolume / _player.MaxVolume) * 255.999)); if (note.Bends.Count > 0) { DrawPitchBend(canvas, offset, _notePaint, note); return; } var start = note.AbsoluteRealTime - offset; var end = start + note.RealTimeLength; DrawNoteRect(canvas, start, end, note.NoteNumber, _notePaint); }
protected override void OnMouseMove(MouseEventArgs e) { if (dataEntryPressed) { InternalEntryDataValue = (SystemInformation.MouseWheelScrollDelta * 127 * (Height - e.Y)) / Height; Invalidate(new Rectangle(0, 0, wKeyW, Height)); } else { for (int keyNum = 0; keyNum < 128; keyNum++) { bool black; GraphicsPath path = getKeyPath(keyNum, out black); var r = new Region(path); if (r.IsVisible(e.Location)) { if (lastKeyOn >= 0) { if (lastKeyOn != keyNum) { lastKeyOff(); lastKeyOn = keyNum; var rect = path.GetBounds(); var velo = (127 * (e.Y - (Height / 6))) / (Height / 3); if (velo < 1) { velo = 1; } if (velo > 127) { velo = 127; } var noe = new TaggedNoteOnEvent((SevenBitNumber)keyNum, (SevenBitNumber)velo); NoteOn?.Invoke(this, noe); } } } } } }
private void DrawPitchBend(SKCanvas canvas, TimeSpan offset, SKPaint paint, NoteOn note) { // draw the beginning of the note without bend var start = note.AbsoluteRealTime - offset; var end = note.Bends[0].AbsoluteRealTime - offset; DrawNoteRect(canvas, start, end, note.NoteNumber, paint); // draw bends for (var i = 0; i < note.Bends.Count - 1; i++) { start = note.Bends[i].AbsoluteRealTime - offset; end = note.Bends[i + 1].AbsoluteRealTime - offset; DrawNoteRect(canvas, start, end, Pitch(note, note.Bends[i]), paint); } // draw last bend start = note.Bends.Last().AbsoluteRealTime - offset; end = note.AbsoluteRealTime + note.RealTimeLength - offset; DrawNoteRect(canvas, start, end, Pitch(note, note.Bends.Last()), paint); }
private void DrawNote(double top, double left, string note) { MidiPlayer.OpenMidi(); MidiPlayer.Play(new ProgramChange(0, 1, GeneralMidiInstruments.AcousticGrand)); NoteOn G3 = new NoteOn(35, 1, "G3", 127); NoteOn A3 = new NoteOn(35, 1, "A3", 127); NoteOn B3 = new NoteOn(35, 1, "B3", 127); NoteOn C4 = new NoteOn(35, 1, "C4", 127); NoteOn D4 = new NoteOn(35, 1, "D4", 127); NoteOn E4 = new NoteOn(35, 1, "E4", 127); NoteOn F4 = new NoteOn(35, 1, "F4", 127); NoteOn G4 = new NoteOn(35, 1, "G4", 127); NoteOn A4 = new NoteOn(35, 1, "A4", 127); NoteOn B4 = new NoteOn(35, 1, "B4", 127); NoteOn C5 = new NoteOn(35, 1, "C5", 127); NoteOn D5 = new NoteOn(35, 1, "D5", 127); NoteOn E5 = new NoteOn(35, 1, "E5", 127); NoteOn F5 = new NoteOn(35, 1, "F5", 127); NoteOn G5 = new NoteOn(35, 1, "G5", 127); NoteOn A5 = new NoteOn(35, 1, "A5", 127); NoteOn B5 = new NoteOn(35, 1, "B5", 127); NoteOn C6 = new NoteOn(35, 1, "C6", 127); int WHOLE = 1600; int HALF = WHOLE / 2; int QUARTER = HALF / 2; int EIGHTH = QUARTER / 2; int SIXTEENTH = EIGHTH / 2; BitmapImage TwoExtraBitImg = new BitmapImage(new Uri("/Resources/TwoExtraBar.png", UriKind.Relative)); Image G3TwoExtraBar = new Image(); G3TwoExtraBar.Source = TwoExtraBitImg; G3TwoExtraBar.SetValue(Canvas.TopProperty, top - 10); G3TwoExtraBar.SetValue(Canvas.LeftProperty, left); Image A3TwoExtraBar = new Image(); A3TwoExtraBar.Source = TwoExtraBitImg; A3TwoExtraBar.SetValue(Canvas.TopProperty, top - 5); A3TwoExtraBar.SetValue(Canvas.LeftProperty, left); Image C6TwoExtraBar = new Image(); C6TwoExtraBar.Source = TwoExtraBitImg; C6TwoExtraBar.SetValue(Canvas.TopProperty, top + 5); C6TwoExtraBar.SetValue(Canvas.LeftProperty, left); BitmapImage OneExtraBitImg = new BitmapImage(new Uri("/Resources/OneExtraBar.png", UriKind.Relative)); Image B3OneExtraBar = new Image(); B3OneExtraBar.Source = OneExtraBitImg; B3OneExtraBar.SetValue(Canvas.TopProperty, top - 10); B3OneExtraBar.SetValue(Canvas.LeftProperty, left); Image C4OneExtraBar = new Image(); C4OneExtraBar.Source = OneExtraBitImg; C4OneExtraBar.SetValue(Canvas.TopProperty, top - 5); C4OneExtraBar.SetValue(Canvas.LeftProperty, left); Image B5OneExtraBar = new Image(); B5OneExtraBar.Source = OneExtraBitImg; B5OneExtraBar.SetValue(Canvas.TopProperty, top); B5OneExtraBar.SetValue(Canvas.LeftProperty, left); Image A5OneExtraBar = new Image(); A5OneExtraBar.Source = OneExtraBitImg; A5OneExtraBar.SetValue(Canvas.TopProperty, top - 5); A5OneExtraBar.SetValue(Canvas.LeftProperty, left); switch (TagStaff) { case 0: BitmapImage SixBitImg = new BitmapImage(new Uri("/Resources/SixteenthNote.png", UriKind.Relative)); Image SixImage = new Image(); SixImage.Source = SixBitImg; SixImage.SetValue(Canvas.TopProperty, top - 35); SixImage.SetValue(Canvas.LeftProperty, left + 1); BitmapImage SixBitImgReverse = new BitmapImage(new Uri("/Resources/SixteenthNoteReverse.png", UriKind.Relative)); Image SixImageReverse = new Image(); SixImageReverse.Source = SixBitImgReverse; SixImageReverse.SetValue(Canvas.TopProperty, top); SixImageReverse.SetValue(Canvas.LeftProperty, left + 1); switch (note) { case "G3": Music.Add(new Note(G3, SIXTEENTH)); MainCanvas.Children.Add(SixImage); MainCanvas.Children.Add(G3TwoExtraBar); break; case "A3": Music.Add(new Note(A3, SIXTEENTH)); MainCanvas.Children.Add(SixImage); MainCanvas.Children.Add(A3TwoExtraBar); break; case "B3": Music.Add(new Note(B3, SIXTEENTH)); MainCanvas.Children.Add(SixImage); MainCanvas.Children.Add(B3OneExtraBar); break; case "C4": Music.Add(new Note(C4, SIXTEENTH)); MainCanvas.Children.Add(SixImage); MainCanvas.Children.Add(C4OneExtraBar); break; case "D4": Music.Add(new Note(D4, SIXTEENTH)); MainCanvas.Children.Add(SixImage); break; case "E4": Music.Add(new Note(E4, SIXTEENTH)); MainCanvas.Children.Add(SixImage); break; case "F4": Music.Add(new Note(F4, SIXTEENTH)); MainCanvas.Children.Add(SixImage); break; case "G4": Music.Add(new Note(G4, SIXTEENTH)); MainCanvas.Children.Add(SixImage); break; case "A4": Music.Add(new Note(A4, SIXTEENTH)); MainCanvas.Children.Add(SixImage); break; case "B4": Music.Add(new Note(B4, SIXTEENTH)); MainCanvas.Children.Add(SixImageReverse); break; case "C5": Music.Add(new Note(C5, SIXTEENTH)); MainCanvas.Children.Add(SixImageReverse); break; case "D5": Music.Add(new Note(D5, SIXTEENTH)); MainCanvas.Children.Add(SixImageReverse); break; case "E5": Music.Add(new Note(E5, SIXTEENTH)); MainCanvas.Children.Add(SixImageReverse); break; case "F5": Music.Add(new Note(F5, SIXTEENTH)); MainCanvas.Children.Add(SixImageReverse); break; case "G5": Music.Add(new Note(G5, SIXTEENTH)); MainCanvas.Children.Add(SixImageReverse); break; case "A5": Music.Add(new Note(A5, SIXTEENTH)); MainCanvas.Children.Add(SixImageReverse); MainCanvas.Children.Add(A5OneExtraBar); break; case "B5": Music.Add(new Note(B5, SIXTEENTH)); MainCanvas.Children.Add(SixImageReverse); MainCanvas.Children.Add(B5OneExtraBar); break; case "C6": Music.Add(new Note(C6, SIXTEENTH)); MainCanvas.Children.Add(SixImageReverse); MainCanvas.Children.Add(C6TwoExtraBar); break; default: break; } break; case 1: BitmapImage EightBitImg = new BitmapImage(new Uri("/Resources/EighthNote.png", UriKind.Relative)); Image EightImage = new Image(); EightImage.Source = EightBitImg; EightImage.SetValue(Canvas.TopProperty, top - 35); EightImage.SetValue(Canvas.LeftProperty, left + 1); BitmapImage EightBitImgReverse = new BitmapImage(new Uri("/Resources/EighthNoteReverse.png", UriKind.Relative)); Image EightImageReverse = new Image(); EightImageReverse.Source = EightBitImgReverse; EightImageReverse.SetValue(Canvas.TopProperty, top); EightImageReverse.SetValue(Canvas.LeftProperty, left + 1); switch (note) { case "G3": Music.Add(new Note(G3, EIGHTH)); MainCanvas.Children.Add(EightImage); MainCanvas.Children.Add(G3TwoExtraBar); break; case "A3": Music.Add(new Note(A3, EIGHTH)); MainCanvas.Children.Add(EightImage); MainCanvas.Children.Add(A3TwoExtraBar); break; case "B3": Music.Add(new Note(B3, EIGHTH)); MainCanvas.Children.Add(EightImage); MainCanvas.Children.Add(B3OneExtraBar); break; case "C4": Music.Add(new Note(C4, EIGHTH)); MainCanvas.Children.Add(EightImage); MainCanvas.Children.Add(C4OneExtraBar); break; case "D4": Music.Add(new Note(D4, EIGHTH)); MainCanvas.Children.Add(EightImage); break; case "E4": Music.Add(new Note(E4, EIGHTH)); MainCanvas.Children.Add(EightImage); break; case "F4": Music.Add(new Note(F4, EIGHTH)); MainCanvas.Children.Add(EightImage); break; case "G4": Music.Add(new Note(G4, EIGHTH)); MainCanvas.Children.Add(EightImage); break; case "A4": Music.Add(new Note(A4, EIGHTH)); MainCanvas.Children.Add(EightImage); break; case "B4": Music.Add(new Note(B4, EIGHTH)); MainCanvas.Children.Add(EightImageReverse); break; case "C5": Music.Add(new Note(C5, EIGHTH)); MainCanvas.Children.Add(EightImageReverse); break; case "D5": Music.Add(new Note(D5, EIGHTH)); MainCanvas.Children.Add(EightImageReverse); break; case "E5": Music.Add(new Note(E5, EIGHTH)); MainCanvas.Children.Add(EightImageReverse); break; case "F5": Music.Add(new Note(F5, EIGHTH)); MainCanvas.Children.Add(EightImageReverse); break; case "G5": Music.Add(new Note(G5, EIGHTH)); MainCanvas.Children.Add(EightImageReverse); break; case "A5": Music.Add(new Note(A5, EIGHTH)); MainCanvas.Children.Add(EightImageReverse); MainCanvas.Children.Add(A5OneExtraBar); break; case "B5": Music.Add(new Note(B5, EIGHTH)); MainCanvas.Children.Add(EightImageReverse); MainCanvas.Children.Add(B5OneExtraBar); break; case "C6": Music.Add(new Note(C6, EIGHTH)); MainCanvas.Children.Add(EightImageReverse); MainCanvas.Children.Add(C6TwoExtraBar); break; default: break; } break; case 2: BitmapImage QtrBitImg = new BitmapImage(new Uri("/Resources/QuarterNote.png", UriKind.Relative)); Image QtrImage = new Image(); QtrImage.Source = QtrBitImg; QtrImage.SetValue(Canvas.TopProperty, top - 35); QtrImage.SetValue(Canvas.LeftProperty, left + 1); BitmapImage QtrBitImgReverse = new BitmapImage(new Uri("/Resources/QuarterNoteReverse.png", UriKind.Relative)); Image QtrImageReverse = new Image(); QtrImageReverse.Source = QtrBitImgReverse; QtrImageReverse.SetValue(Canvas.TopProperty, top); QtrImageReverse.SetValue(Canvas.LeftProperty, left + 1); switch (note) { case "G3": Music.Add(new Note(G3, QUARTER)); MainCanvas.Children.Add(QtrImage); MainCanvas.Children.Add(G3TwoExtraBar); break; case "A3": Music.Add(new Note(A3, QUARTER)); MainCanvas.Children.Add(QtrImage); MainCanvas.Children.Add(A3TwoExtraBar); break; case "B3": Music.Add(new Note(B3, QUARTER)); MainCanvas.Children.Add(QtrImage); MainCanvas.Children.Add(B3OneExtraBar); break; case "C4": Music.Add(new Note(C4, QUARTER)); MainCanvas.Children.Add(QtrImage); MainCanvas.Children.Add(C4OneExtraBar); break; case "D4": Music.Add(new Note(D4, QUARTER)); MainCanvas.Children.Add(QtrImage); break; case "E4": Music.Add(new Note(E4, QUARTER)); MainCanvas.Children.Add(QtrImage); break; case "F4": Music.Add(new Note(F4, QUARTER)); MainCanvas.Children.Add(QtrImage); break; case "G4": Music.Add(new Note(G4, QUARTER)); MainCanvas.Children.Add(QtrImage); break; case "A4": Music.Add(new Note(A4, QUARTER)); MainCanvas.Children.Add(QtrImage); break; case "B4": Music.Add(new Note(B4, QUARTER)); MainCanvas.Children.Add(QtrImageReverse); break; case "C5": Music.Add(new Note(C5, QUARTER)); MainCanvas.Children.Add(QtrImageReverse); break; case "D5": Music.Add(new Note(D5, QUARTER)); MainCanvas.Children.Add(QtrImageReverse); break; case "E5": Music.Add(new Note(E5, QUARTER)); MainCanvas.Children.Add(QtrImageReverse); break; case "F5": Music.Add(new Note(F5, QUARTER)); MainCanvas.Children.Add(QtrImageReverse); break; case "G5": Music.Add(new Note(G5, QUARTER)); MainCanvas.Children.Add(QtrImageReverse); break; case "A5": Music.Add(new Note(A5, QUARTER)); MainCanvas.Children.Add(QtrImageReverse); MainCanvas.Children.Add(A5OneExtraBar); break; case "B5": Music.Add(new Note(B5, QUARTER)); MainCanvas.Children.Add(QtrImageReverse); MainCanvas.Children.Add(B5OneExtraBar); break; case "C6": Music.Add(new Note(C6, QUARTER)); MainCanvas.Children.Add(QtrImageReverse); MainCanvas.Children.Add(C6TwoExtraBar); break; default: break; } break; case 3: BitmapImage HalfBitImg = new BitmapImage(new Uri("/Resources/HalfNote.png", UriKind.Relative)); Image HalfImage = new Image(); HalfImage.Source = HalfBitImg; HalfImage.SetValue(Canvas.TopProperty, top - 35); HalfImage.SetValue(Canvas.LeftProperty, left + 1); BitmapImage HalfBitImgReverse = new BitmapImage(new Uri("/Resources/HalfNoteReverse.png", UriKind.Relative)); Image HalfImageReverse = new Image(); HalfImageReverse.Source = HalfBitImgReverse; HalfImageReverse.SetValue(Canvas.TopProperty, top); HalfImageReverse.SetValue(Canvas.LeftProperty, left + 1); switch (note) { case "G3": Music.Add(new Note(G3, HALF)); MainCanvas.Children.Add(HalfImage); MainCanvas.Children.Add(G3TwoExtraBar); break; case "A3": Music.Add(new Note(A3, HALF)); MainCanvas.Children.Add(HalfImage); MainCanvas.Children.Add(A3TwoExtraBar); break; case "B3": Music.Add(new Note(B3, HALF)); MainCanvas.Children.Add(HalfImage); MainCanvas.Children.Add(B3OneExtraBar); break; case "C4": Music.Add(new Note(C4, HALF)); MainCanvas.Children.Add(HalfImage); MainCanvas.Children.Add(C4OneExtraBar); break; case "D4": Music.Add(new Note(D4, HALF)); MainCanvas.Children.Add(HalfImage); break; case "E4": Music.Add(new Note(E4, HALF)); MainCanvas.Children.Add(HalfImage); break; case "F4": Music.Add(new Note(F4, HALF)); MainCanvas.Children.Add(HalfImage); break; case "G4": Music.Add(new Note(G4, HALF)); MainCanvas.Children.Add(HalfImage); break; case "A4": Music.Add(new Note(A4, HALF)); MainCanvas.Children.Add(HalfImage); break; case "B4": Music.Add(new Note(B4, HALF)); MainCanvas.Children.Add(HalfImageReverse); break; case "C5": Music.Add(new Note(C5, HALF)); MainCanvas.Children.Add(HalfImageReverse); break; case "D5": Music.Add(new Note(D5, HALF)); MainCanvas.Children.Add(HalfImageReverse); break; case "E5": Music.Add(new Note(E5, HALF)); MainCanvas.Children.Add(HalfImageReverse); break; case "F5": Music.Add(new Note(F5, HALF)); MainCanvas.Children.Add(HalfImageReverse); break; case "G5": Music.Add(new Note(G5, HALF)); MainCanvas.Children.Add(HalfImageReverse); break; case "A5": Music.Add(new Note(A5, HALF)); MainCanvas.Children.Add(HalfImageReverse); MainCanvas.Children.Add(A5OneExtraBar); break; case "B5": Music.Add(new Note(B5, HALF)); MainCanvas.Children.Add(HalfImageReverse); MainCanvas.Children.Add(B5OneExtraBar); break; case "C6": Music.Add(new Note(C6, HALF)); MainCanvas.Children.Add(HalfImageReverse); MainCanvas.Children.Add(C6TwoExtraBar); break; default: break; } break; case 4: BitmapImage bitmapImage4 = new BitmapImage(new Uri("/Resources/WholeNote.png", UriKind.Relative)); Image image4 = new Image(); image4.Source = bitmapImage4; image4.SetValue(Canvas.TopProperty, top - 35); image4.SetValue(Canvas.LeftProperty, left + 1); MainCanvas.Children.Add(image4); switch (note) { case "G3": Music.Add(new Note(G3, WHOLE)); MainCanvas.Children.Add(G3TwoExtraBar); break; case "A3": Music.Add(new Note(A3, WHOLE)); MainCanvas.Children.Add(A3TwoExtraBar); break; case "B3": Music.Add(new Note(B3, WHOLE)); MainCanvas.Children.Add(B3OneExtraBar); break; case "C4": Music.Add(new Note(C4, WHOLE)); MainCanvas.Children.Add(C4OneExtraBar); break; case "D4": Music.Add(new Note(D4, WHOLE)); break; case "E4": Music.Add(new Note(E4, WHOLE)); break; case "F4": Music.Add(new Note(F4, WHOLE)); break; case "G4": Music.Add(new Note(G4, WHOLE)); break; case "A4": Music.Add(new Note(A4, WHOLE)); break; case "B4": Music.Add(new Note(B4, WHOLE)); break; case "C5": Music.Add(new Note(C5, WHOLE)); break; case "D5": Music.Add(new Note(D5, WHOLE)); break; case "E5": Music.Add(new Note(E5, WHOLE)); break; case "F5": Music.Add(new Note(F5, WHOLE)); break; case "G5": Music.Add(new Note(G5, WHOLE)); break; case "A5": Music.Add(new Note(A5, WHOLE)); MainCanvas.Children.Add(A5OneExtraBar); break; case "B5": Music.Add(new Note(B5, WHOLE)); MainCanvas.Children.Add(B5OneExtraBar); break; case "C6": Music.Add(new Note(C6, WHOLE)); MainCanvas.Children.Add(C6TwoExtraBar); break; default: break; } break; default: break; } }
/// <summary>Creates an object creation expression for an event.</summary> /// <param name="ev">The event to create.</param> /// <returns>The object creation expression for the event.</returns> private static CodeObjectCreateExpression CreateVoiceEvent(MidiEvent ev) { CodeObjectCreateExpression newEvent = null; CodeExpression delta = new CodePrimitiveExpression(ev.DeltaTime); // NOTE ON if (ev is NoteOn) { NoteOn midiEvent = (NoteOn)ev; newEvent = new CodeObjectCreateExpression( typeof(NoteOn), new CodeExpression[] { delta, new CodePrimitiveExpression(midiEvent.Channel), new CodePrimitiveExpression(MidiEvent.GetNoteName(midiEvent.Note)), new CodePrimitiveExpression(midiEvent.Velocity) }); } // NOTE OFF else if (ev is NoteOff) { NoteOff midiEvent = (NoteOff)ev; newEvent = new CodeObjectCreateExpression( typeof(NoteOff), new CodeExpression[] { delta, new CodePrimitiveExpression(midiEvent.Channel), new CodePrimitiveExpression(MidiEvent.GetNoteName(midiEvent.Note)), new CodePrimitiveExpression(midiEvent.Velocity) }); } // AFTERTOUCH else if (ev is Aftertouch) { Aftertouch midiEvent = (Aftertouch)ev; newEvent = new CodeObjectCreateExpression( typeof(Aftertouch), new CodeExpression[] { delta, new CodePrimitiveExpression(midiEvent.Channel), new CodePrimitiveExpression(MidiEvent.GetNoteName(midiEvent.Note)), new CodePrimitiveExpression(midiEvent.Pressure) }); } // PROGRAM CHANGE else if (ev is ProgramChange) { ProgramChange midiEvent = (ProgramChange)ev; newEvent = new CodeObjectCreateExpression( typeof(ProgramChange), new CodeExpression[] { delta, new CodePrimitiveExpression(midiEvent.Channel), new CodeCastExpression(typeof(GeneralMidiInstruments), new CodePrimitiveExpression(midiEvent.Number)) }); } // CONTROLLER else if (ev is Controller) { Controller midiEvent = (Controller)ev; newEvent = new CodeObjectCreateExpression( typeof(Controller), new CodeExpression[] { delta, new CodePrimitiveExpression(midiEvent.Channel), new CodeCastExpression(typeof(Controllers), new CodePrimitiveExpression(midiEvent.Number)), new CodePrimitiveExpression(midiEvent.Value), }); } // CHANNEL PRESSURE else if (ev is ChannelPressure) { ChannelPressure midiEvent = (ChannelPressure)ev; newEvent = new CodeObjectCreateExpression( typeof(ChannelPressure), new CodeExpression[] { delta, new CodePrimitiveExpression(midiEvent.Channel), new CodePrimitiveExpression(midiEvent.Pressure) }); } // PITCH WHEEL else if (ev is PitchWheel) { PitchWheel midiEvent = (PitchWheel)ev; newEvent = new CodeObjectCreateExpression( typeof(PitchWheel), new CodeExpression[] { delta, new CodePrimitiveExpression(midiEvent.Channel), new CodePrimitiveExpression(midiEvent.UpperBits), new CodePrimitiveExpression(midiEvent.LowerBits) }); } // Return the event return(newEvent); }
private void SetChordOn(int channel, List<byte> midiPitches, List<byte> midiVelocities) { for(int i = 0; i < midiPitches.Count; i++) { NoteOn noteOn = new NoteOn(channel, midiPitches[i], midiVelocities[i]); ChordOn.AddNote(noteOn); } }
private float Pitch(NoteOn note, PitchBend bend) { return(note.NoteNumber + bend.RealPitchChange); }
private TrackEvent ReadTrackEvent() { var deltaTime = ReadVariableLengthEncoding(); // "Running Status": The last status byte is implied var statusByte = _lastStatusByte; var firstByte = _source.ReadByte(); // Check for new status byte if ((firstByte & 0x80) == 1) { statusByte = firstByte; firstByte = _source.ReadByte(); } var statusUpper = statusByte >> 4; // Save running status if (statusUpper > 0x7 && statusUpper < 0xF) { _lastStatusByte = statusByte; } // Parse the event var statusLower = (byte)(statusByte & 0xF); MidiEvent ev = null; switch (statusUpper) { case 0x8: ev = new NoteOff(statusLower, firstByte, _source.ReadByte()); break; case 0x9: ev = new NoteOn(statusLower, firstByte, _source.ReadByte()); break; case 0xA: ev = new PolyphonicKeyPressure(statusLower, firstByte, _source.ReadByte()); break; case 0xB: if (firstByte < 120) { ev = new ControlChange(statusLower, firstByte, _source.ReadByte()); } else { ev = new ChannelMode(statusLower, firstByte, _source.ReadByte()); } break; case 0xC: ev = new ProgramChange(statusLower, firstByte); break; case 0xD: ev = new ChannelPressure(statusLower, firstByte); break; case 0xE: ev = new PitchBend(statusLower, firstByte, _source.ReadByte()); break; case 0xF: switch (statusLower) { case 0x0: case 0x7: ev = new SysEx(statusLower == 0, _source.ReadBytes(ReadVariableLengthEncoding(firstByte))); break; case 0xF: var len = ReadVariableLengthEncoding(); var data = _source.ReadBytes(len); switch (firstByte) { case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0A: case 0x0B: case 0x0C: case 0x0D: case 0x0E: case 0x0F: ev = new TextEvent(Encoding.UTF8.GetString(data)); // TODO: Let user choose encoding break; case 0x20: ev = new ChannelPrefix(data[0]); break; case 0x2F: ev = new EndOfTrack(); break; case 0x51: ev = new SetTempo(MidiBytesConverter.ReadBigEndian24Bit(data)); break; case 0x54: ev = new SmpteOffset((byte)((data[0] >> 5) & 0x3), (byte)(data[0] & 0x1F), data[1], data[2], data[3], data[4]); break; case 0x58: ev = new TimeSignature(data[0], data[1], data[2], data[3]); break; case 0x59: ev = new KeySignature((sbyte)data[0], data[1] == 1); break; case 0x7F: ev = new SequencerSpecificMetaEvent(data); break; default: // TODO: Unrecognized metadata kind, non-fatal error break; } break; default: // At this point, if the event was not recognized: FATAL ERROR! throw new NotImplementedException(); } break; default: // At this point, if the event was not recognized: FATAL ERROR! throw new NotImplementedException(); } return(new TrackEvent(deltaTime, ev)); }
public Note(NoteOn note, int tempo) { Tone = note; Tempo = tempo; }
private void HandleNoteOn(int noteNumber) { currentNoteNumbers.Add(noteNumber); NoteOn?.Invoke(noteNumber); }
private MIDI ConvertToFormat1(MIDI src) { try { Track srcTrack = src.TrackList[0]; var newTracks = new List <Track>(); int cnt = 0; // event counter var eventlist = new LinkedList <Event>(); uint deltaTime = 0; // Create Conductor track foreach (Event ev in srcTrack.EventList) { deltaTime += ev.DeltaTime; if (ev is MetaEvent) { MetaEvent modEv; if (ev is SetTempo) { var st = (SetTempo)ev; modEv = new SetTempo(deltaTime, st.Value); } else if (ev is TimeSignature) { var ts = (TimeSignature)ev; modEv = new TimeSignature(deltaTime, ts.Numerator, ts.DenominatorBitShift, ts.MIDIClockPerMetronomeTick, ts.NumberOfNotesPerClocks); } else if (ev is KeySignature) { var ks = (KeySignature)ev; modEv = new KeySignature(deltaTime, ks.SignatureNumber, ks.MinorFlagNumber); } else if (ev is SequenceTrackName) { var stn = (SequenceTrackName)ev; modEv = new SequenceTrackName(deltaTime, stn.Name); } else if (ev is EndOfTrack) { modEv = new EndOfTrack(deltaTime); } else { modEv = new MetaEvent(deltaTime); } eventlist.AddLast(modEv); deltaTime = 0; if (!(ev is EndOfTrack)) { cnt++; } } } newTracks.Add(new Track(eventlist)); eventlist = new LinkedList <Event>(); deltaTime = 0; // Create System Setup track foreach (Event ev in srcTrack.EventList) { deltaTime += ev.DeltaTime; if (ev is SysExEvent) { eventlist.AddLast(new SysExEvent(deltaTime)); deltaTime = 0; cnt++; } else if (ev is EndOfTrack) { eventlist.AddLast(new EndOfTrack(deltaTime)); } } newTracks.Add(new Track(eventlist)); // Create Notes track for (int ch = 0; cnt + 1 < srcTrack.EventList.Count; ch++) { eventlist = new LinkedList <Event>(); deltaTime = 0; foreach (Event ev in srcTrack.EventList) { deltaTime += ev.DeltaTime; if (ev is MIDIEvent) { var midiEv = (MIDIEvent)ev; if (midiEv.Channel == ch) { MIDIEvent modEv; if (midiEv is NoteOn) { var nton = (NoteOn)midiEv; modEv = new NoteOn(deltaTime, nton.Channel, nton.Number, nton.Velocity); } else if (midiEv is NoteOff) { var ntoff = (NoteOff)midiEv; modEv = new NoteOff(deltaTime, ntoff.Channel, ntoff.Number, ntoff.Velocity); } else if (midiEv is ProgramChange) { var pc = (ProgramChange)midiEv; modEv = new ProgramChange(deltaTime, pc.Channel, pc.Number); } else if (midiEv is Volume) { var vol = (Volume)midiEv; modEv = new Volume(deltaTime, vol.Channel, vol.Value); } else if (midiEv is Pan) { var pan = (Pan)midiEv; modEv = new Pan(deltaTime, pan.Channel, pan.Value); } else if (midiEv is ControlChange) { var cc = (ControlChange)midiEv; modEv = new ControlChange(deltaTime, cc.Channel, cc.Value); } else { modEv = new MIDIEvent(deltaTime, midiEv.Channel); } eventlist.AddLast(modEv); deltaTime = 0; cnt++; } } else if (ev is EndOfTrack) { eventlist.AddLast(new EndOfTrack(deltaTime)); } } newTracks.Add(new Track(eventlist)); } return(new MIDI(newTracks, 1, newTracks.Count, src.TimeDivision)); } catch (Exception ex) { throw new Exception(Resources.ErrorMIDIFormat1, ex); } }
public void AddNote(NoteOn note) { NotesInLevel2Beats.AddNote(note); }
public NoteWrapper(NoteOn note, float volume) { Note = note; Volume = volume; EffectiveLength = Math.Min(Math.Max(Length, Rioi), Globals.MaxEffectiveLength); }
/// <summary> /// Метод, вызывающий событие NoteOn с заданными параметрами. /// </summary> /// <param name="noteNo"></param> /// <param name="velocity"></param> private void OnNoteOn(byte noteNo, byte velocity) { NoteOn?.Invoke(this, new MidiNoteEventArgs(noteNo, velocity, pressedNotesCount)); }
private void Decode(byte[] message) { byte status = message[0]; switch (status & 0b1111_0000) { case Midi.Status.NoteOffBitmask: if (NoteOffMessage.TryDecode(message, out var noteOffMessage)) { NoteOff?.Invoke(this, in noteOffMessage); } break; case Midi.Status.NoteOnBitmask: if (NoteOnMessage.TryDecode(message, out var noteOnMessage)) { NoteOn?.Invoke(this, in noteOnMessage); } break; case Midi.Status.PolyphonicKeyPressureBitmask: if (PolyphonicKeyPressureMessage.TryDecode(message, out var polyphonicKeyPressureMessage)) { PolyphonicKeyPressure?.Invoke(this, in polyphonicKeyPressureMessage); } break; case Midi.Status.ControlChangeBitmask: if (ControlChangeMessage.TryDecode(message, out var controlChangeMessage)) { _nrpnInterpreters[(int)controlChangeMessage.Channel].HandleControlChangeMessage(in controlChangeMessage); } break; case Midi.Status.ProgramChangeBitmask: if (ProgramChangeMessage.TryDecode(message, out var programChangeMessage)) { ProgramChange?.Invoke(this, in programChangeMessage); } break; case Midi.Status.ChannelPressureBitmask: if (ChannelPressureMessage.TryDecode(message, out var channelPressureMessage)) { ChannelPressure?.Invoke(this, in channelPressureMessage); } break; case Midi.Status.PitchBendChange: if (PitchBendMessage.TryDecode(message, out var pitchBendMessage)) { PitchBend?.Invoke(this, in pitchBendMessage); } break; case Midi.Status.System: switch (status) { case Midi.Status.SysExStart: if (SysExMessage.TryDecode(message, out var sysExMessage)) { SysEx?.Invoke(this, in sysExMessage); } break; case Midi.Status.MidiTimeCodeQuarterFrame: if (MidiTimeCodeQuarterFrameMessage.TryDecode(message, out var timeCodeQuarterFrameMessage)) { MidiTimeCodeQuarterFrame?.Invoke(this, in timeCodeQuarterFrameMessage); } break; case Midi.Status.SongPositionPointer: if (SongPositionPointerMessage.TryDecode(message, out var songPositionPointerMessage)) { SongPositionPointer?.Invoke(this, in songPositionPointerMessage); } break; case Midi.Status.SongSelect: if (SongSelectMessage.TryDecode(message, out var songSelectMessage)) { SongSelect?.Invoke(this, in songSelectMessage); } break; case Midi.Status.TuneRequest: if (TuneRequestMessage.TryDecode(message, out var tuneRequestMessage)) { TuneRequest?.Invoke(this, in tuneRequestMessage); } break; default: Log.Error("Unknown system message type {Status}", $"{status:X2}"); break; } break; default: Log.Error("Unknown message type {Bitmask}", $"{status & 0b1111_0000:X2}"); break; } }
/// <summary>Parse a voice event from the data stream.</summary> /// <param name="deltaTime">The previously parsed delta-time for this event.</param> /// <param name="messageType">The previously parsed type of message we're expecting to find.</param> /// <param name="channel">The previously parsed channel for this message.</param> /// <param name="data">The data stream from which to read the event information.</param> /// <param name="pos">The position of the start of the event information.</param> /// <returns>The parsed voice MIDI event.</returns> private static MidiEvent ParseVoiceEvent(long deltaTime, byte messageType, byte channel, byte [] data, ref long pos) { try { MidiEvent tempEvent = null; // Create the correct voice event based on its message id/type switch (messageType) { // NOTE OFF case 0x8: // **Adding this check seems to make GH1 mids work....GH2s are // a little more complicated** if (pos < data.GetLength(0) - 1) { tempEvent = new NoteOff(deltaTime, channel, data[pos], data[pos + 1]); } pos += 2; break; // NOTE ON case 0x9: tempEvent = new NoteOn(deltaTime, channel, data[pos], data[pos + 1]); pos += 2; break; // AFTERTOUCH case 0xA: tempEvent = new Aftertouch(deltaTime, channel, data[pos], data[pos + 1]); pos += 2; break; // CONTROLLER case 0xB: tempEvent = new Controller(deltaTime, channel, data[pos], data[pos + 1]); pos += 2; break; // PROGRAM CHANGE case 0xC: tempEvent = new ProgramChange(deltaTime, channel, data[pos]); pos += 1; break; // CHANNEL PRESSURE case 0xD: tempEvent = new ChannelPressure(deltaTime, channel, data[pos]); pos += 1; break; // PITCH WHEEL case 0xE: int position = ((data[pos] << 8) | data[pos + 1]); byte upper, lower; MidiEvent.Split14BitsToBytes(position, out upper, out lower); tempEvent = new PitchWheel(deltaTime, channel, upper, lower); pos += 2; break; // UH OH! default: throw new ArgumentOutOfRangeException("messageType", messageType, "Not a voice message."); } // Return the newly parsed event return(tempEvent); } // Something bad happened; wrap it in a parser exception catch (Exception exc) { throw new MidiParserException("Unable to parse voice MIDI event.", exc, pos); } }
public static Model Parse(string filename, int frameRateMillis = 50, bool showBeats = false, bool showChords = false, bool randomize = true) { var track = new Track(); var midi = new Model { Tracks = new[] { track } }; byte[] fileBytes = File.ReadAllBytes(filename); var random = new Random(123456); var timeMillis = 0; var beatLength = 12 * frameRateMillis; var actualNotes = new NoteOn[16, 128]; var actualPercussion = new NoteOn[128]; var instrumentsOnChannels = new MusicalInstrument[16]; for (byte i = 0; i < Model.NumberOfChannels; i++) { track.Channels[i].Events.Add(new Controller { AbsoluteRealTime = TimeSpan.Zero, AbsoluteTime = 0, ChannelNumber = i, ControllerNumber = 7, ControllerValue = 64 }); } for (int i = 0; i < fileBytes.Length; i += 4) { var eventType = (EventType)(fileBytes[i] & 0x0F); if (i == 400 * 4) { track.MetaEvents.Add(new ImprovisationStartMetaEvent { AbsoluteRealTime = TimeSpan.FromMilliseconds(timeMillis) }); } switch (eventType) { case EventType.NoteOnEvent: { var channel = (byte)(fileBytes[i] >> 4); var pitch = (byte)(fileBytes[i + 1] + ClusterRanges.Min((InstrumentCluster)channel)); var instrument = (MusicalInstrument)Instrument.TypicalInstrument((InstrumentCluster)channel); var volume = fileBytes[i + 2] / 128.0 - 1; volume = Math.Pow(volume, 2) * Math.Sign(volume); if (randomize) { volume = (byte)(volume * (0.9 + random.NextDouble() * 0.1)); } volume = 64.0 + 64.0 * volume; if (!instrument.Equals(instrumentsOnChannels[channel])) { track.Channels[channel].Events.Add(new InstrumentChange { AbsoluteRealTime = TimeSpan.FromMilliseconds(timeMillis - 1), AbsoluteTime = (uint)(timeMillis / frameRateMillis + 0.5), ChannelNumber = channel, Instrument = instrument }); instrumentsOnChannels[channel] = instrument; } var prevNote = actualNotes[channel, pitch]; if (prevNote != null) { TimeSpan end; if (timeMillis < prevNote.AbsoluteRealTime.TotalMilliseconds + 5000) { end = TimeSpan.FromMilliseconds(timeMillis); } else { end = prevNote.AbsoluteRealTime + TimeSpan.FromMilliseconds(5000); } prevNote.End = end; prevNote.RealTimeLength = end - prevNote.AbsoluteRealTime; prevNote.Length = (uint)(prevNote.RealTimeLength.TotalMilliseconds / frameRateMillis); track.Channels[prevNote.ChannelNumber].Events.Add(new NoteOff { ChannelNumber = prevNote.ChannelNumber, AbsoluteRealTime = prevNote.End, AbsoluteTime = (uint)(timeMillis / frameRateMillis + 0.5), NoteNumber = prevNote.NoteNumber, Velocity = 64 }); } var note = new NoteOn { ChannelNumber = channel, NoteNumber = pitch, Volume = (byte)Calc.Clamp((int)(volume + 0.5), 0, 127), AbsoluteTime = (uint)(timeMillis / frameRateMillis + 0.5), Length = (uint)(4800 / frameRateMillis), AbsoluteRealTime = TimeSpan.FromMilliseconds(timeMillis), End = TimeSpan.FromMilliseconds(timeMillis + 4800), RealTimeLength = TimeSpan.FromMilliseconds(4800) }; track.Channels[channel].Events.Add(note); actualNotes[channel, pitch] = note; break; } case EventType.NoteOffEvent: { var channel = (byte)fileBytes[i + 2]; var pitch = (byte)(fileBytes[i + 1] + ClusterRanges.Min((InstrumentCluster)channel)); var note = actualNotes[channel, pitch]; if (note == null) //throw new Exception("neni na co navazovat"); { continue; } TimeSpan end; if (timeMillis < note.AbsoluteRealTime.TotalMilliseconds + 5000) { end = TimeSpan.FromMilliseconds(timeMillis); } else { end = note.AbsoluteRealTime + TimeSpan.FromMilliseconds(5000); } note.End = end; note.RealTimeLength = end - note.AbsoluteRealTime; note.Length = (uint)(note.RealTimeLength.TotalMilliseconds / frameRateMillis); track.Channels[note.ChannelNumber].Events.Add(new NoteOff { ChannelNumber = note.ChannelNumber, AbsoluteRealTime = note.End, AbsoluteTime = (uint)(timeMillis / frameRateMillis + 0.5), NoteNumber = note.NoteNumber, Velocity = 64 }); actualNotes[channel, pitch] = null; break; } case EventType.PercussionOnEvent: { var percussionType = (byte)(fileBytes[i + 1] + Percussion.MinNoteNumber); //var volume = (byte)(clusterVolumes[InstrumentCluster.Percussion] * 128.0); var volume = fileBytes[i + 2] / 128.0 - 1; volume = Math.Pow(volume, 2) * Math.Sign(volume); if (randomize) { volume = (byte)(volume * (0.9 + random.NextDouble() * 0.1)); } volume = 64.0 + 64.0 * volume; var prevNote = actualPercussion[percussionType]; if (prevNote != null) { TimeSpan end; if (timeMillis < prevNote.AbsoluteRealTime.TotalMilliseconds + 4800) { end = TimeSpan.FromMilliseconds(timeMillis); } else { end = prevNote.AbsoluteRealTime + TimeSpan.FromMilliseconds(4800); } prevNote.End = end; prevNote.RealTimeLength = end - prevNote.AbsoluteRealTime; prevNote.Length = (uint)(prevNote.RealTimeLength.TotalMilliseconds / frameRateMillis); track.Channels[prevNote.ChannelNumber].Events.Add(new NoteOff { ChannelNumber = prevNote.ChannelNumber, AbsoluteRealTime = prevNote.End, AbsoluteTime = (uint)(timeMillis / frameRateMillis + 0.5), NoteNumber = prevNote.NoteNumber, Velocity = 64 }); } var note = new NoteOn { ChannelNumber = Channel.PercussionChannelNumber, NoteNumber = percussionType, Volume = (byte)Calc.Clamp((int)(volume + 0.5), 0, 127), AbsoluteTime = (uint)(timeMillis / frameRateMillis + 0.5), Length = (uint)(4800 / frameRateMillis), AbsoluteRealTime = TimeSpan.FromMilliseconds(timeMillis), End = TimeSpan.FromMilliseconds(timeMillis + 4800), RealTimeLength = TimeSpan.FromMilliseconds(4800) }; track.Channels[Channel.PercussionChannelNumber].Events.Add(note); actualPercussion[percussionType] = note; break; } case EventType.PercussionOffEvent: { var percussionType = (byte)(fileBytes[i + 1] + Percussion.MinNoteNumber); var percussion = actualPercussion[percussionType]; if (percussion == null) //throw new Exception("neni na co navazovat"); { continue; } TimeSpan end; if (timeMillis < percussion.AbsoluteRealTime.TotalMilliseconds + 4800) { end = TimeSpan.FromMilliseconds(timeMillis); } else { end = percussion.AbsoluteRealTime + TimeSpan.FromMilliseconds(4800); } percussion.End = end; percussion.RealTimeLength = end - percussion.AbsoluteRealTime; percussion.Length = (uint)(percussion.RealTimeLength.TotalMilliseconds / frameRateMillis); track.Channels[percussion.ChannelNumber].Events.Add(new NoteOff { ChannelNumber = percussion.ChannelNumber, AbsoluteRealTime = percussion.End, AbsoluteTime = (uint)(timeMillis / frameRateMillis + 0.5), NoteNumber = percussion.NoteNumber, Velocity = 64 }); actualPercussion[percussionType] = null; break; } case EventType.SmallSpaceEvent: { var tempo = fileBytes[i + 1] | fileBytes[i + 2] << 8; var chord = fileBytes[i + 3]; if (timeMillis % beatLength == 0 && chord != 24) { var beat = new BeatEvent { AbsoluteTime = (uint)(timeMillis / frameRateMillis + 0.5 + beatLength), AbsoluteRealTime = TimeSpan.FromMilliseconds(timeMillis + beatLength), Length = TimeSpan.FromMilliseconds(beatLength), Chord = new Key(chord), Level = 2 }; track.MetaEvents.Add(beat); } timeMillis += frameRateMillis /** tempo / 600.0*/; break; } case EventType.BigSpaceEvent: { var tempo = fileBytes[i + 1] | fileBytes[i + 2] << 8; var chord = fileBytes[i + 3]; if (timeMillis % beatLength == 0 && chord != 24) { var beat = new BeatEvent { AbsoluteTime = (uint)(timeMillis / frameRateMillis + 0.5 + beatLength), AbsoluteRealTime = TimeSpan.FromMilliseconds(timeMillis + beatLength), Length = TimeSpan.FromMilliseconds(beatLength), Chord = new Key(chord), Level = 2 }; track.MetaEvents.Add(beat); } timeMillis += frameRateMillis * 6 /** tempo / 600.0*/; break; } case EventType.EndEvent: { timeMillis += frameRateMillis * 200; break; } } } track.MetaEvents.Add(new EndOfTrack { AbsoluteRealTime = TimeSpan.FromMilliseconds(timeMillis + 1200) }); { var collector = new VolumeChangeCollector(midi); collector.DetermineVolumes(); } { var collector = new InstrumentChangeCollector(midi); collector.DetermineInstruments(); } if (showBeats) { Normalizer.AddBeats(midi, false, 32); } if (showChords) { var analyzer = new ChordAnalyzer(midi); analyzer.AddChordNotesToModel(48); } if (randomize) { foreach (var note in midi.EventsOfType <NoteOn>()) { var startOffset = random.Next(10); var lengthChange = 0.1 * random.NextDouble() * note.RealTimeLength.TotalMilliseconds; note.AbsoluteRealTime += TimeSpan.FromMilliseconds(startOffset); note.RealTimeLength -= TimeSpan.FromMilliseconds(lengthChange); note.End -= TimeSpan.FromMilliseconds(startOffset + lengthChange); } } ChannelPlayabilityChecker.Check(midi); midi.Length = midi.EventsOfType <EndOfTrack>().Max(e => e.AbsoluteRealTime); return(midi); }