public void Test_VstEventCollection_CollectionChanged_Replace() { VstEventCollection target = new VstEventCollection(); target.Add(new VstMidiEvent(0, 100, 0, new byte[] { 100, 110, 120 }, 0, 0)); target.Add(new VstMidiEvent(0, 100, 0, new byte[] { 100, 110, 120 }, 0, 0)); Assert.AreEqual(2, target.Count, "Collection Count is not as expected."); int callCount = 0; target.CollectionChanged += (sender, e) => { Assert.AreEqual(NotifyCollectionChangedAction.Replace, e.Action, "Unexpected collection changed action."); Assert.IsNotNull(e.NewItems, "NewItems collection is null."); Assert.AreEqual(1, e.NewItems.Count, "Not the expected number of items in the NewItems collection."); Assert.IsNotNull(e.NewItems[0], "NewItems[0] is null."); Assert.IsNotNull(e.OldItems, "OldItems collection is null."); Assert.AreEqual(1, e.OldItems.Count, "Not the expected number of items in the OldItems collection."); Assert.IsNotNull(e.OldItems[0], "OldItems[0] is null."); callCount++; }; VstEvent @event = target[0]; target[0] = target[1]; target[1] = @event; Assert.AreEqual(2, callCount, "Call count is not as expected."); }
/// <summary> /// Constructs a new instance. /// </summary> /// <param name="plugin">Must not be null.</param> public MidiProcessor(Plugin plugin) { _plugin = plugin; Events = new VstEventCollection(); NoteOnEvents = new Queue <byte>(); //InitializeParameters(); }
public void Process(VstEventCollection events) { foreach (var midiMessage in events .Where(x => x.EventType == VstEventTypes.MidiEvent) .Select(x => new MidiMessage((VstMidiEvent)x))) { if (midiMessage.HasStatusByte((byte)MidiChannelCommand.NoteOff)) { NoteOff(GetNoteEventArgsFromMessage(midiMessage)); } else if (midiMessage.HasStatusByte((byte)MidiChannelCommand.NoteOn)) { if (midiMessage.Data2 == 0) // Velocity { NoteOff(GetNoteEventArgsFromMessage(midiMessage)); } else { NoteOn(GetNoteEventArgsFromMessage(midiMessage)); } } else if (midiMessage.HasStatusByte((byte)MidiChannelCommand.ControlChange)) { if (midiMessage.Data1 == (byte)MidiControllerType.AllNotesOff || midiMessage.Data1 == (byte)MidiControllerType.AllSoundOff) { var notes = new HashSet <int>(_pressedNotes); foreach (var pressedNote in notes) { NoteOff(new NoteEventArgs(pressedNote, 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) { _plugin.SampleManager.ProcessNoteOffEvent(midiEvent.Data[1]); } if ((midiEvent.Data[0] & 0xF0) == 0x90) { // note on with velocity = 0 is a note off if (midiEvent.Data[2] == 0) { _plugin.SampleManager.ProcessNoteOffEvent(midiEvent.Data[1]); } else { _plugin.SampleManager.ProcessNoteOnEvent(midiEvent.Data[1]); } } } } }
public void Test_VstEventCollection_CollectionChanged_Replace() { var target = new VstEventCollection { new VstMidiEvent(0, 100, 0, new byte[] { 100, 110, 120 }, 0, 0), new VstMidiEvent(0, 100, 0, new byte[] { 100, 110, 120 }, 0, 0) }; target.Should().HaveCount(2); int callCount = 0; target.CollectionChanged += (sender, e) => { e.Action.Should().Be(NotifyCollectionChangedAction.Replace); e.NewItems.Should().NotBeNullOrEmpty(); e.NewItems[0].Should().NotBeNull(); e.OldItems.Should().NotBeNullOrEmpty(); e.OldItems[0].Should().NotBeNull(); callCount++; }; VstEvent @event = target[0]; target[0] = target[1]; target[1] = @event; callCount.Should().Be(2); }
/// <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; // pass note on and note off to the sample manager if ((midiEvent.Data[0] & 0xF0) == 0x80) { _plugin.SampleManager.ProcessNoteOffEvent(midiEvent.Data[1]); } if ((midiEvent.Data[0] & 0xF0) == 0x90) { // note on with velocity = 0 is a note off if (midiEvent.Data[2] == 0) { _plugin.SampleManager.ProcessNoteOffEvent(midiEvent.Data[1]); } else { _plugin.SampleManager.ProcessNoteOnEvent(midiEvent.Data[1]); } } } } }
/// <summary> /// Constructs a new instance. /// </summary> /// <param name="plugin">Must not be null.</param> public MidiProcessor(Plugin plugin) { _plugin = plugin; Events = new VstEventCollection(); NoteOnEvents = new Queue <byte>(); _timeInfo = new VstTimeInfo(); }
/// <summary> /// Midi events are received from the host on this method and are either send to the DryMssEventRelay or /// stored internally. /// </summary> /// <param name="events">A collection with midi events. Never null.</param> /// <remarks> /// Note that some hosts will only receieve midi events during audio processing. /// See also <see cref="IVstPluginAudioProcessor"/>. /// </remarks> public void Process(VstEventCollection vstEvents) { if (vstEvents == null || vstEvents.Count == 0 || this.vstHost == null) { return; } // NOTE: other types of events could be in the collection! foreach (VstEvent evnt in vstEvents) { if (evnt.EventType == VstEventTypes.MidiEvent) { VstMidiEvent midiEvent = (VstMidiEvent)evnt; MssEvent mssEvent = ConvertVstMidiEventToMssEvent(midiEvent, this.SampleTimeAtStartOfProcessingCycle, this.hostInfoOutputPort.SampleRate); if (mssEvent == null) { outEvents.Add(evnt); } else { this.dryMssEventInputPort.ReceiveDryMssEvent(mssEvent); } } else { // non VstMidiEvent outEvents.Add(evnt); } } }
public void Process_NoteOn_SentToRelay() { VstEventCollection vstEvents = new VstEventCollection(); vstEvents.Add(Factory_VstMidiEvent_Basic(0, CreateMidiDataWithDefaultValues(MssMsgType.NoteOn))); Test_Process_VstEventCollection_SentToReplay(vstEvents, 1); }
protected void Test_Process_VstEventCollection_SentToReplay(VstEventCollection vstEvents, int NumMssCompatibleEvents) { MidiHandlerProtectedWrapper midiHandler = Factory_MidiHandler_Basic(); midiHandler.Process(vstEvents); Assert.AreEqual(numDryEventsReceivedByRelay, NumMssCompatibleEvents); }
/// <summary> /// Midi events are received from the host on this method. /// </summary> /// <param name="events">A collection with midi events. Never null.</param> /// <remarks> /// Note that some hosts will only receieve midi events during audio processing. /// See also <see cref="IVstPluginAudioProcessor"/>. /// </remarks> public void Process(VstEventCollection events) { CurrentEvents = events; //_plugin.PluginEditor.Log("Midi Process"); if (!SyncWithAudioProcessor) { ProcessCurrentEvents(); } }
/// <summary> /// Midi events are received from the host on this method. /// </summary> /// <param name="events">A collection with midi events. Never null.</param> /// <remarks> /// Note that some hosts will only receieve midi events during audio processing. /// See also <see cref="IVstPluginAudioProcessor"/>. /// </remarks> public void Process(VstEventCollection events) { CurrentEvents = events; if (!SyncWithAudioProcessor) { ProcessCurrentEvents(); } }
public void Process_SysExEvent_NothingSentToRelay() { VstEventCollection vstEvents = new VstEventCollection(); VstMidiSysExEvent unsupportedEvent = new VstMidiSysExEvent(0, new byte[3]); vstEvents.Add(unsupportedEvent); Test_Process_VstEventCollection_SentToReplay(vstEvents, 0); }
public void Process(VstEventCollection events) { int _transposeSemitones = _plugin.Transpose.Semitones; foreach (VstEvent anyEvent in events) { if (anyEvent.EventType != VstEventTypes.MidiEvent) { continue; } VstMidiEvent midiEvent = (VstMidiEvent)anyEvent; if (((midiEvent.Data[0] & 0xF0) == 0x80 || (midiEvent.Data[0] & 0xF0) == 0x90)) { // these are all the note on and note off events. if (_transposeSemitones != 0) { VstMidiEvent mappedEvent = null; byte[] midiData = new byte[4]; midiData[0] = midiEvent.Data[0]; int _note = midiEvent.Data[1] + _transposeSemitones; if (_note < 0 || _note > 127) { continue; // skip out of range notes. } midiData[1] = (byte)_note; midiData[2] = midiEvent.Data[2]; mappedEvent = new VstMidiEvent(midiEvent.DeltaFrames, midiEvent.NoteLength, midiEvent.NoteOffset, midiData, midiEvent.Detune, midiEvent.NoteOffVelocity); Events.Add(mappedEvent); // add raw note-on note numbers to the queue if ((midiEvent.Data[0] & 0xF0) == 0x90) { lock (((ICollection)NoteOnEvents).SyncRoot) { NoteOnEvents.Enqueue(midiEvent.Data[1]); } } } else { // we're not transposing, so just pass it through. Events.Add(anyEvent); } } else { // not a midi on-off event, so pass it through. Events.Add(anyEvent); } } }
public void Test_VstEventCollection_Constructor() { var target = new VstEventCollection(); target.IsReadOnly.Should().BeFalse(); target.Add(new VstMidiEvent(0, 100, 0, new byte[] { 100, 110, 120 }, 0, 0)); target.Add(new VstMidiEvent(0, 100, 0, new byte[] { 100, 110, 120 }, 0, 0)); target.Should().HaveCount(2); target.Clear(); target.Should().BeEmpty(); }
public void Process_MultipleMsgTypes_SentToRelay() { VstEventCollection vstEvents = new VstEventCollection(); vstEvents.Add(Factory_VstMidiEvent_Basic(0, CreateMidiDataWithDefaultValues(MssMsgType.NoteOn))); vstEvents.Add(Factory_VstMidiEvent_Basic(0, CreateMidiDataWithDefaultValues(MssMsgType.NoteOff))); vstEvents.Add(Factory_VstMidiEvent_Basic(0, CreateMidiDataWithDefaultValues(MssMsgType.CC))); vstEvents.Add(Factory_VstMidiEvent_Basic(0, CreateMidiDataWithDefaultValues(MssMsgType.ChanAftertouch))); vstEvents.Add(Factory_VstMidiEvent_Basic(0, CreateMidiDataWithDefaultValues(MssMsgType.PitchBend))); vstEvents.Add(Factory_VstMidiEvent_Basic(0, CreateMidiDataWithDefaultValues(MssMsgType.PolyAftertouch))); Test_Process_VstEventCollection_SentToReplay(vstEvents, 6); }
public void Process(VstEventCollection events) { foreach (VstEvent evnt in events) { if (evnt.EventType != VstEventTypes.MidiEvent) { continue; } var midiEvent = (VstMidiEvent)evnt; if (((midiEvent.Data[0] & 0xF0) == 0x80 || (midiEvent.Data[0] & 0xF0) == 0x90)) { if (_noteMap.Contains(midiEvent.Data[1])) { byte[] midiData = new byte[4]; midiData[0] = midiEvent.Data[0]; midiData[1] = _noteMap[midiEvent.Data[1]].OutputNoteNumber; midiData[2] = midiEvent.Data[2]; var mappedEvent = new VstMidiEvent(midiEvent.DeltaFrames, midiEvent.NoteLength, midiEvent.NoteOffset, midiData, midiEvent.Detune, midiEvent.NoteOffVelocity); Events.Add(mappedEvent); // add raw note-on note numbers to the queue if ((midiEvent.Data[0] & 0xF0) == 0x90) { lock (((ICollection)NoteOnEvents).SyncRoot) { NoteOnEvents.Enqueue(midiEvent.Data[1]); } } } else if (MidiThru) { // add original note event Events.Add(evnt); } } else if (MidiThru) { // add original (non-note) event Events.Add(evnt); } } }
public void Test_VstEventCollection_ReadOnlyConstructor() { VstEvent[] events = new VstEvent[2]; events[0] = new VstMidiEvent(0, 100, 0, new byte[] { 100, 110, 120 }, 0, 0); events[1] = new VstMidiEvent(0, 100, 0, new byte[] { 100, 110, 120 }, 0, 0); VstEventCollection target = new VstEventCollection(events); Assert.AreEqual(events.Length, target.Count, "Count does not match."); Assert.AreEqual(2, target.Count, "Count is not as expected."); Assert.IsTrue(target.IsReadOnly, "Collection is not read-only."); Assert.AreEqual(events[0], target[0], "First item does not match."); Assert.AreEqual(events[1], target[1], "Second item does not match."); }
public void Test_VstEventCollection_Constructor() { VstEventCollection target = new VstEventCollection(); Assert.IsFalse(target.IsReadOnly, "Collection is read-only."); target.Add(new VstMidiEvent(0, 100, 0, new byte[] { 100, 110, 120 }, 0, 0)); target.Add(new VstMidiEvent(0, 100, 0, new byte[] { 100, 110, 120 }, 0, 0)); Assert.AreEqual(2, target.Count, "Count is not as expected."); target.Clear(); Assert.AreEqual(0, target.Count, "Count is not zero."); }
public void Test_VstEventCollection_ReadOnlyConstructor() { var events = new VstEvent[2]; events[0] = new VstMidiEvent(0, 100, 0, new byte[] { 100, 110, 120 }, 0, 0); events[1] = new VstMidiEvent(0, 100, 0, new byte[] { 100, 110, 120 }, 0, 0); var target = new VstEventCollection(events); target.Should().HaveCount(events.Length); target.IsReadOnly.Should().BeTrue(); target[0].Should().Be(events[0]); target[1].Should().Be(events[1]); }
public void ProcessCurrentEvents() { //_plugin.PluginEditor.Log("ProcessCurrentEvents"); // a plugin must implement IVstPluginMidiSource or this call will throw an exception. var midiHost = _plugin.Host.GetInstance <IVstMidiProcessor>(); // always expect some hosts not to support this. if (midiHost != null) { var outEvents = new VstEventCollection(); var someCommands = _plugin.Host.GetInstance <IVstHostCommands20>(); var timeInfo = someCommands.GetTimeInfo( VstTimeInfoFlags.PpqPositionValid | VstTimeInfoFlags.BarStartPositionValid | VstTimeInfoFlags.TempoValid); if (CurrentEvents != null) { // NOTE: other types of events could be in the collection! foreach (VstEvent evnt in CurrentEvents) { switch (evnt.EventType) { case VstEventTypes.MidiEvent: var midiEvent = (VstMidiEvent)evnt; midiEvent = Cascade.ProcessEvent(midiEvent, timeInfo); //_plugin.PluginEditor.Log("tempo" + x.Tempo); outEvents.Add(midiEvent); break; default: // non VstMidiEvent outEvents.Add(evnt); break; } } } outEvents.AddRange(Cascade.CreateNotes(timeInfo)); midiHost.Process(outEvents); } // Clear the cache, we've processed the events. CurrentEvents = null; }
public void Process_SomeSupportedSomeUnsupporedEvents_SomeSentToRelay() { VstEventCollection vstEvents = new VstEventCollection(); //Supported event type vstEvents.Add(Factory_VstMidiEvent_Basic(0, CreateMidiDataWithDefaultValues(MssMsgType.PitchBend))); //Unsupported event type VstMidiSysExEvent unsupportedEvent = new VstMidiSysExEvent(0, new byte[3]); vstEvents.Add(unsupportedEvent); //Supported event type vstEvents.Add(Factory_VstMidiEvent_Basic(0, CreateMidiDataWithDefaultValues(MssMsgType.PolyAftertouch))); Test_Process_VstEventCollection_SentToReplay(vstEvents, 2); }
public void ProcessCurrentEvents() { if (CurrentEvents == null || CurrentEvents.Count == 0) return; // a plugin must implement IVstPluginMidiSource or this call will throw an exception. IVstMidiProcessor midiHost = _plugin.Host.GetInstance<IVstMidiProcessor>(); // always expect some hosts not to support this. if (midiHost != null) { VstEventCollection outEvents = new VstEventCollection(); // NOTE: other types of events could be in the collection! foreach (VstEvent evnt in CurrentEvents) { if (evnt.EventType == VstEventTypes.MidiEvent) { VstMidiEvent midiEvent = (VstMidiEvent)evnt; if ((midiEvent.Data[0] & 0xF0) == 0x80) { _plugin._synth.ProcessNoteOffEvent(midiEvent.Data[1]); } if ((midiEvent.Data[0] & 0xF0) == 0x90) { // note on with velocity = 0 is a note off if (midiEvent.Data[2] == 0) { _plugin._synth.ProcessNoteOffEvent(midiEvent.Data[1]); } else { //midiEvent = _gain.ProcessEvent(midiEvent); //midiEvent = _transpose.ProcessEvent(midiEvent); _plugin._synth.ProcessNoteOnEvent(midiEvent.Data[1]); } } } else { // non VstMidiEvent outEvents.Add(evnt); } } //midiHost.Process(outEvents); } }
public void Test_VstEventCollection_CollectionChanged_Add() { var target = new VstEventCollection(); int callCount = 0; target.CollectionChanged += (sender, e) => { e.Action.Should().Be(NotifyCollectionChangedAction.Add); e.NewItems.Should().NotBeNullOrEmpty(); e.NewItems[0].Should().NotBeNull(); callCount++; }; target.Add(new VstMidiEvent(0, 100, 0, new byte[] { 100, 110, 120 }, 0, 0)); target.Add(new VstMidiEvent(0, 100, 0, new byte[] { 100, 110, 120 }, 0, 0)); callCount.Should().Be(2); }
public void ProcessCurrentEvents() { if (CurrentEvents == null || CurrentEvents.Count == 0) { return; } // a plugin must implement IVstPluginMidiSource or this call will throw an exception. IVstMidiProcessor midiHost = _plugin.Host.GetInstance <IVstMidiProcessor>(); // always expect some hosts not to support this. if (midiHost != null) { VstEventCollection outEvents = new VstEventCollection(); // NOTE: other types of events could be in the collection! foreach (VstEvent evnt in CurrentEvents) { switch (evnt.EventType) { case VstEventTypes.MidiEvent: VstMidiEvent midiEvent = (VstMidiEvent)evnt; midiEvent = Gain.ProcessEvent(midiEvent); midiEvent = Transpose.ProcessEvent(midiEvent); outEvents.Add(midiEvent); break; default: // non VstMidiEvent outEvents.Add(evnt); break; } } midiHost.Process(outEvents); } // Clear the cache, we've processed the events. CurrentEvents = null; }
public MidiProcessor(Plugin plugin) { _plugin = plugin; Events = new VstEventCollection(); NoteOnNumbers = new Queue <byte>(); NoteOffNumbers = new Queue <byte>(); _noteOnEvents = new List <VstMidiEvent>(); _octavesAddedOrderedNoteOnEvents = new List <VstMidiEvent>(); _rythm = new List <NoteLengthFrames>(); Probability = 100; NoteLengthsArray = new NoteLengths[4]; AccentsArray = new Accents[4]; for (int i = 0; i < 4; i++) { NoteLengthsArray[i] = NoteLengths.quarter; AccentsArray[i] = Accents.none; } CountRythm(); }
/// <summary> /// Removes notes that are expired and generates new notes. /// </summary> /// <param name="events"></param> public void Process(VstEventCollection events) { // remove notes that are expired RemoveNotesThatAreExpired(); // check if time since last tick is larger than the speed of the board if ((DateTime.Now - lastTick).Milliseconds > _plugin.BoardSettings.Speed) { // advance the board to its next state _plugin.BoardSettings.Board.NextState(); // add notes to play based on the active cells AddNotesToPlay(_plugin.BoardSettings); // let the editor know to update the board var _uiEditor = _plugin.GetInstance <PluginEditor>(); _uiEditor.UpdateBoard(); lastTick = DateTime.Now; } }
public void ProcessCurrentEvents() { if (CurrentEvents == null || CurrentEvents.Count == 0) { return; } // always expect some hosts not to support this. if (_midiHost != null) { VstEventCollection outEvents = new VstEventCollection(); // NOTE: other types of events could be in the collection! foreach (VstEvent evnt in CurrentEvents) { switch (evnt.EventType) { case VstEventTypes.MidiEvent: VstMidiEvent midiEvent = (VstMidiEvent)evnt; midiEvent = Gain.ProcessEvent(midiEvent); midiEvent = Transpose.ProcessEvent(midiEvent); outEvents.Add(midiEvent); break; default: // non VstMidiEvent outEvents.Add(evnt); break; } } _midiHost.Process(outEvents); } // Clear the cache, we've processed the events. CurrentEvents = null; }
/// <summary> /// Обработка новых входных данных. /// </summary> /// <param name="events"></param> public void Process(VstEventCollection events) { foreach (var e in events) { if (e.EventType == VstEventTypes.MidiEvent) { var midiEvent = (VstMidiEvent)e; byte firstByte = midiEvent.Data[0]; if (0x80 <= firstByte && firstByte < 0x90) // Note off { pressedNotesCount -= 1; OnNoteOff(midiEvent.Data[1], midiEvent.Data[2]); } else if (0x90 <= firstByte && firstByte < 0xA0) // Note on { pressedNotesCount += 1; OnNoteOn(midiEvent.Data[1], midiEvent.Data[2]); } } } }
/// <summary> /// Passes the <paramref name="events"/> onto the host. /// </summary> /// <param name="events">Must not be null.</param> /// <exception cref="System.ArgumentNullException">Thrown when <paramref name="events"/> is not set to an instance of an object.</exception> public void Process(VstEventCollection events) { Throw.IfArgumentIsNull(events, nameof(events)); _host.HostCommandProxy.Commands.ProcessEvents(events.ToArray()); }
/// <summary> /// Constructs a new instance. /// </summary> /// <param name="plugin">Must not be null.</param> public MidiProcessor(Plugin plugin) { _plugin = plugin; Events = new VstEventCollection(); }
// Process the incoming VST events. *** This is the core of the VST right here. *** public void Process(VstEventCollection inputEvents) { if (_plugin == null) return; _plugin.callCount++; bool thrudone = false; foreach (VstEvent evnt in inputEvents) { _plugin.eventCount++; // Skip non-MIDI Events if (evnt.EventType != VstEventTypes.MidiEvent) { continue; } _plugin.midiCount++; // If set in options, keep the original event as well if (_plugin.Options.MidiThruAll) { Events.Add(evnt); thrudone = true; } // Don't do any more if we aren't running. if (_plugin.CurrentMode != Constants.Modes.RUN) continue; // Construct a MIDI event and act on it VstMidiEvent midiInputEvent = (VstMidiEvent)evnt; byte command = (byte)(midiInputEvent.Data[0] & 0xF0); byte channel = (byte)(midiInputEvent.Data[0] & 0x0F); byte note = midiInputEvent.Data[1]; byte velocity = midiInputEvent.Data[2]; MapNoteItem map = _plugin.NoteMaps[note]; byte[] midiData = null; // Filter out everything except Note On/Note Off and CC events switch (command) { case 0x90: // Note On map.Triggered(Constants.MapTypes.ON); if (map.isDefined(Constants.MapTypes.ON)) { _plugin.hitCount++; midiData = MapNoteItem.StringToBytes(map.OutputBytesStringOn, channel, velocity); } break; case 0x80: // Note Off map.Triggered(Constants.MapTypes.OFF); if (map.isDefined(Constants.MapTypes.OFF)) { _plugin.hitCount++; midiData = MapNoteItem.StringToBytes(map.OutputBytesStringOff, channel, velocity); } break; case 0xB0: // Continuous Controller map.Triggered(Constants.MapTypes.CC); if (map.isDefined(Constants.MapTypes.CC)) { _plugin.hitCount++; midiData = MapNoteItem.StringToBytes(map.OutputBytesStringCC, channel, velocity); } break; default: // Ignore everything else, but keep going below break; } // Check that we got a result. If not - no match. if (midiData == null) { if (_plugin.Options.MidiThru) { // add original event, if not added already. if (!thrudone) { Events.Add(evnt); } } continue; } // In most cases, use VstMidiSysExEvent in place of VstMidiEvent, since this seems to allow arbitary bytes. if (_plugin.Options.AlwaysSysEx) { VstMidiSysExEvent mappedEvent = new VstMidiSysExEvent(midiInputEvent.DeltaFrames, midiData); Events.Add(mappedEvent); } else // Ugly! Split message into three-byte chunks and send them all. { List<byte[]> midichunks = new List<byte[]>(); for (int i = 0; i < midiData.Length; i += 3) { midichunks.Add(midiData.Skip(i).Take(3).ToArray()); } foreach (byte[] midi in midichunks) { VstMidiEvent mappedEvent = new VstMidiEvent(midiInputEvent.DeltaFrames, midiInputEvent.NoteLength, midiInputEvent.NoteOffset, midi, midiInputEvent.Detune, midiInputEvent.NoteOffVelocity); Events.Add(mappedEvent); } } } // foreach }
/// <summary> /// Midi events are received from the host on this method. /// </summary> /// <param name="events">A collection with midi events. Never null.</param> /// <remarks> /// Note that some hosts will only receieve midi events during audio processing. /// See also <see cref="IVstPluginAudioProcessor"/>. /// </remarks> public void Process(VstEventCollection events) { CurrentEvents = events; ProcessCurrentEvents(); }
/// <summary> /// Midi events are received from the host on this method and are either send to the DryMssEventRelay or /// stored internally. /// </summary> /// <param name="events">A collection with midi events. Never null.</param> /// <remarks> /// Note that some hosts will only receieve midi events during audio processing. /// See also <see cref="IVstPluginAudioProcessor"/>. /// </remarks> public void Process(VstEventCollection vstEvents) { if (vstEvents == null || vstEvents.Count == 0 || this.vstHost == null) return; // NOTE: other types of events could be in the collection! foreach (VstEvent evnt in vstEvents) { if (evnt.EventType == VstEventTypes.MidiEvent) { VstMidiEvent midiEvent = (VstMidiEvent)evnt; MssEvent mssEvent = ConvertVstMidiEventToMssEvent(midiEvent, this.SampleTimeAtStartOfProcessingCycle, this.hostInfoOutputPort.SampleRate); if (mssEvent == null) { outEvents.Add(evnt); } else { this.dryMssEventInputPort.ReceiveDryMssEvent(mssEvent); } } else { // non VstMidiEvent outEvents.Add(evnt); } } }
// Process the incoming VST events. This is the core of the app right here. !!!! public void Process(VstEventCollection inputEvents) { _plugin.callCount++; foreach (VstEvent evnt in inputEvents) { _plugin.eventCount++; // Skip non-MIDI Events if (evnt.EventType != VstEventTypes.MidiEvent) { continue; } _plugin.midiCount++; VstMidiEvent midiInputEvent = (VstMidiEvent)evnt; // Filter out everything except Note On/Note Off events byte midiCommand = (byte)(midiInputEvent.Data[0] & 0xF0); if ((midiCommand == 0x90) || (midiCommand == 0x80)) { byte triggerNoteNum = midiInputEvent.Data[1]; if (_plugin.NoteMap.Contains(triggerNoteNum)) { _plugin.hitCount++; byte channel = (byte)(midiInputEvent.Data[0] & 0x0F); byte velocity = midiInputEvent.Data[2]; MapNoteItem item = _plugin.NoteMap[triggerNoteNum]; byte[] midiData = null; if (midiCommand == 0x90) { midiData = MapNoteItem.StringToBytes(item.OutputBytesStringOn, channel, velocity); } else if (midiCommand == 0x80) { midiData = MapNoteItem.StringToBytes(item.OutputBytesStringOff, channel, velocity); } // else midiData remains null, which should never happen // If OutputBytes was empty, ignore this event. Could try sending the event with an empty array (not null) - not sure what would happen. if (midiData == null) { continue; } // Trick: Use VstMidiSysExEvent in place of VstMidiEvent, since this seems to allow arbitary bytes. VstMidiSysExEvent mappedEvent = new VstMidiSysExEvent(midiInputEvent.DeltaFrames, midiData); Events.Add(mappedEvent); } else if (_plugin.midiThru) { // add original event Events.Add(evnt); } // Otherwise ignore silently } } }