public void Execute(ref ExecuteContext <Parameters, Providers> context) { if (context.Outputs.Count != 3) { return; } SampleBuffer gatesOutput = context.Outputs.GetSampleBuffer(0); var gatesOutputBuffer = gatesOutput.Buffer; SampleBuffer notesOutput = context.Outputs.GetSampleBuffer(1); var notesOutputBuffer = notesOutput.Buffer; SampleBuffer triggerOutput = context.Outputs.GetSampleBuffer(2); var triggerOutputBuffer = triggerOutput.Buffer; while (true) { ulong data = DequeueIncomingData(); if (data == 0) { break; } MidiJack.MidiMessage message = new MidiJack.MidiMessage(data); ProcessMessage(message); } float sampleDuration = 1.0f / context.SampleRate; int samplesCount = gatesOutput.Samples; for (int s = 0; s < samplesCount; ++s) { for (int c = 0; c < math.min(16, gatesOutput.Channels); ++c) { gatesOutputBuffer[s * gatesOutput.Channels + c] = _Gates[c] ? 1.0f : 0.0f; } for (int c = 0; c < math.min(16, notesOutput.Channels); ++c) { notesOutputBuffer[s * notesOutput.Channels + c] = (_Notes[c] - 60f) / 12f; } for (int c = 0; c < math.min(16, triggerOutput.Channels); ++c) { unsafe { PulseGenerator *retrigger = (PulseGenerator *)((byte *)_Retrigger.GetUnsafePtr() + UnsafeUtility.SizeOf <PulseGenerator>() * c); triggerOutputBuffer[s * triggerOutput.Channels + c] = retrigger->Process(sampleDuration) ? 1.0f : 0.0f; } } } }
void ProcessMessage(MidiJack.MidiMessage message) { var midiStatusCode = message.status >> 4; var midiChannelNumber = message.status & 0xf; switch (midiStatusCode) { case 0x8: ReleaseNote(message.data1); break; case 0x9: if (message.data2 > 0) { int channel = AssignChannel(message.data1); PressNote(message.data1, channel); } else { ReleaseNote(message.data1); } break; case 0xA: // aftertouch break; case 0xB: // CC (knobs) break; case 0xC: // program change break; case 0xD: // aftertouch break; case 0xE: // pitch wheel break; } }