Inheritance: NoteEvent
Example #1
0
        /// <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();
        }
Example #3
0
        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;
            }
        }
Example #4
0
        /// <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();
            }
        }
Example #5
0
    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]);
            }
        }
    }
Example #6
0
        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);
        }
Example #7
0
        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);
                            }
                        }
                    }
                }
            }
        }
Example #8
0
        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;
            }
        }
Example #10
0
        /// <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);
        }
Example #11
0
 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);
     }
 }
Example #12
0
 private float Pitch(NoteOn note, PitchBend bend)
 {
     return(note.NoteNumber + bend.RealPitchChange);
 }
Example #13
0
        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;
 }
Example #15
0
 private void HandleNoteOn(int noteNumber)
 {
     currentNoteNumbers.Add(noteNumber);
     NoteOn?.Invoke(noteNumber);
 }
Example #16
0
        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);
 }
Example #18
0
 public NoteWrapper(NoteOn note, float volume)
 {
     Note            = note;
     Volume          = volume;
     EffectiveLength = Math.Min(Math.Max(Length, Rioi), Globals.MaxEffectiveLength);
 }
Example #19
0
 /// <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;
            }
        }
Example #21
0
        /// <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); }
        }
Example #22
0
        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);
        }