| @@ -99,7 +99,7 @@ struct CarlaInternalPluginModule : Module, Thread { | |||||
| float dataOut[NUM_OUTPUTS][BUFFER_SIZE]; | float dataOut[NUM_OUTPUTS][BUFFER_SIZE]; | ||||
| float* dataOutPtr[NUM_OUTPUTS]; | float* dataOutPtr[NUM_OUTPUTS]; | ||||
| unsigned audioDataFill = 0; | unsigned audioDataFill = 0; | ||||
| int64_t lastBlockFrame = -1; | |||||
| uint32_t lastProcessCounter = 0; | |||||
| bool fileChanged = false; | bool fileChanged = false; | ||||
| std::string currentFile; | std::string currentFile; | ||||
| @@ -300,12 +300,12 @@ struct CarlaInternalPluginModule : Module, Thread { | |||||
| if (audioDataFill == BUFFER_SIZE) | if (audioDataFill == BUFFER_SIZE) | ||||
| { | { | ||||
| const int64_t blockFrame = pcontext->engine->getBlockFrame(); | |||||
| const uint32_t processCounter = pcontext->processCounter; | |||||
| // Update time position if running a new audio block | // Update time position if running a new audio block | ||||
| if (lastBlockFrame != blockFrame) | |||||
| if (lastProcessCounter != processCounter) | |||||
| { | { | ||||
| lastBlockFrame = blockFrame; | |||||
| lastProcessCounter = processCounter; | |||||
| fCarlaTimeInfo.playing = pcontext->playing; | fCarlaTimeInfo.playing = pcontext->playing; | ||||
| fCarlaTimeInfo.frame = pcontext->frame; | fCarlaTimeInfo.frame = pcontext->frame; | ||||
| } | } | ||||
| @@ -95,7 +95,7 @@ struct CarlaModule : Module { | |||||
| float* dataInPtr[NUM_INPUTS]; | float* dataInPtr[NUM_INPUTS]; | ||||
| float* dataOutPtr[NUM_OUTPUTS]; | float* dataOutPtr[NUM_OUTPUTS]; | ||||
| unsigned audioDataFill = 0; | unsigned audioDataFill = 0; | ||||
| int64_t lastBlockFrame = -1; | |||||
| uint32_t lastProcessCounter = 0; | |||||
| CardinalExpanderFromCarlaMIDIToCV* midiOutExpander = nullptr; | CardinalExpanderFromCarlaMIDIToCV* midiOutExpander = nullptr; | ||||
| std::string patchStorage; | std::string patchStorage; | ||||
| @@ -327,12 +327,12 @@ struct CarlaModule : Module { | |||||
| if (audioDataFill == BUFFER_SIZE) | if (audioDataFill == BUFFER_SIZE) | ||||
| { | { | ||||
| const int64_t blockFrame = pcontext->engine->getBlockFrame(); | |||||
| const uint32_t processCounter = pcontext->processCounter; | |||||
| // Update time position if running a new audio block | // Update time position if running a new audio block | ||||
| if (lastBlockFrame != blockFrame) | |||||
| if (lastProcessCounter != processCounter) | |||||
| { | { | ||||
| lastBlockFrame = blockFrame; | |||||
| lastProcessCounter = processCounter; | |||||
| fCarlaTimeInfo.playing = pcontext->playing; | fCarlaTimeInfo.playing = pcontext->playing; | ||||
| fCarlaTimeInfo.frame = pcontext->frame; | fCarlaTimeInfo.frame = pcontext->frame; | ||||
| fCarlaTimeInfo.bbt.valid = pcontext->bbtValid; | fCarlaTimeInfo.bbt.valid = pcontext->bbtValid; | ||||
| @@ -30,9 +30,10 @@ struct HostAudio : TerminalModule { | |||||
| const int numInputs; | const int numInputs; | ||||
| const int numOutputs; | const int numOutputs; | ||||
| bool bypassed = false; | bool bypassed = false; | ||||
| bool in1connected = false; | |||||
| bool in2connected = false; | bool in2connected = false; | ||||
| int dataFrame = 0; | |||||
| int64_t lastBlockFrame = -1; | |||||
| uint32_t dataFrame = 0; | |||||
| uint32_t lastProcessCounter = 0; | |||||
| // for rack core audio module compatibility | // for rack core audio module compatibility | ||||
| dsp::RCFilter dcFilters[numIO]; | dsp::RCFilter dcFilters[numIO]; | ||||
| @@ -70,23 +71,26 @@ struct HostAudio : TerminalModule { | |||||
| void processTerminalInput(const ProcessArgs&) override | void processTerminalInput(const ProcessArgs&) override | ||||
| { | { | ||||
| const int blockFrames = pcontext->engine->getBlockFrames(); | |||||
| const int64_t blockFrame = pcontext->engine->getBlockFrame(); | |||||
| const uint32_t bufferSize = pcontext->bufferSize; | |||||
| const uint32_t processCounter = pcontext->processCounter; | |||||
| // only checked on input | // only checked on input | ||||
| if (lastBlockFrame != blockFrame) | |||||
| if (lastProcessCounter != processCounter) | |||||
| { | { | ||||
| bypassed = isBypassed(); | bypassed = isBypassed(); | ||||
| dataFrame = 0; | dataFrame = 0; | ||||
| lastBlockFrame = blockFrame; | |||||
| lastProcessCounter = processCounter; | |||||
| if (numIO == 2) | if (numIO == 2) | ||||
| { | |||||
| in1connected = inputs[0].isConnected(); | |||||
| in2connected = inputs[1].isConnected(); | in2connected = inputs[1].isConnected(); | ||||
| } | |||||
| } | } | ||||
| // only incremented on output | // only incremented on output | ||||
| const int k = dataFrame; | |||||
| DISTRHO_SAFE_ASSERT_INT2_RETURN(k < blockFrames, k, blockFrames,); | |||||
| const uint32_t k = dataFrame; | |||||
| DISTRHO_SAFE_ASSERT_INT2_RETURN(k < bufferSize, k, bufferSize,); | |||||
| // from host into cardinal, shows as output plug | // from host into cardinal, shows as output plug | ||||
| if (bypassed) | if (bypassed) | ||||
| @@ -122,7 +126,7 @@ struct HostAudio : TerminalModule { | |||||
| struct HostAudio2 : HostAudio<2> { | struct HostAudio2 : HostAudio<2> { | ||||
| #ifndef HEADLESS | #ifndef HEADLESS | ||||
| // for stereo meter | // for stereo meter | ||||
| int internalDataFrame = 0; | |||||
| uint32_t internalDataFrame = 0; | |||||
| float internalDataBuffer[2][128]; | float internalDataBuffer[2][128]; | ||||
| volatile bool resetMeters = true; | volatile bool resetMeters = true; | ||||
| float gainMeterL = 0.0f; | float gainMeterL = 0.0f; | ||||
| @@ -153,11 +157,14 @@ struct HostAudio2 : HostAudio<2> { | |||||
| void processTerminalOutput(const ProcessArgs&) override | void processTerminalOutput(const ProcessArgs&) override | ||||
| { | { | ||||
| const int blockFrames = pcontext->engine->getBlockFrames(); | |||||
| if (!in1connected && !in2connected) | |||||
| return; | |||||
| const uint32_t bufferSize = pcontext->bufferSize; | |||||
| // only incremented on output | // only incremented on output | ||||
| const int k = dataFrame++; | |||||
| DISTRHO_SAFE_ASSERT_INT2_RETURN(k < blockFrames, k, blockFrames,); | |||||
| const uint32_t k = dataFrame++; | |||||
| DISTRHO_SAFE_ASSERT_INT2_RETURN(k < bufferSize, k, bufferSize,); | |||||
| if (bypassed) | if (bypassed) | ||||
| return; | return; | ||||
| @@ -168,21 +175,30 @@ struct HostAudio2 : HostAudio<2> { | |||||
| const float gain = std::pow(params[0].getValue(), 2.f); | const float gain = std::pow(params[0].getValue(), 2.f); | ||||
| // read stereo values | // read stereo values | ||||
| float valueL = inputs[0].getVoltageSum() * 0.1f; | |||||
| float valueR = inputs[1].getVoltageSum() * 0.1f; | |||||
| float valueL, valueR; | |||||
| // Apply DC filter | |||||
| if (dcFilterEnabled) | |||||
| if (in1connected) | |||||
| { | { | ||||
| dcFilters[0].process(valueL); | |||||
| valueL = dcFilters[0].highpass(); | |||||
| } | |||||
| valueL = inputs[0].getVoltageSum() * 0.1f; | |||||
| valueL = clamp(valueL * gain, -1.0f, 1.0f); | |||||
| dataOuts[0][k] += valueL; | |||||
| if (dcFilterEnabled) | |||||
| { | |||||
| dcFilters[0].process(valueL); | |||||
| valueL = dcFilters[0].highpass(); | |||||
| } | |||||
| valueL = clamp(valueL * gain, -1.0f, 1.0f); | |||||
| dataOuts[0][k] += valueL; | |||||
| } | |||||
| else | |||||
| { | |||||
| valueL = 0.0f; | |||||
| } | |||||
| if (in2connected) | if (in2connected) | ||||
| { | { | ||||
| valueR = inputs[1].getVoltageSum() * 0.1f; | |||||
| if (dcFilterEnabled) | if (dcFilterEnabled) | ||||
| { | { | ||||
| dcFilters[1].process(valueR); | dcFilters[1].process(valueR); | ||||
| @@ -192,14 +208,18 @@ struct HostAudio2 : HostAudio<2> { | |||||
| valueR = clamp(valueR * gain, -1.0f, 1.0f); | valueR = clamp(valueR * gain, -1.0f, 1.0f); | ||||
| dataOuts[1][k] += valueR; | dataOuts[1][k] += valueR; | ||||
| } | } | ||||
| else | |||||
| else if (in1connected) | |||||
| { | { | ||||
| valueR = valueL; | valueR = valueL; | ||||
| dataOuts[1][k] += valueL; | dataOuts[1][k] += valueL; | ||||
| } | } | ||||
| #ifndef HEADLESS | #ifndef HEADLESS | ||||
| const int j = internalDataFrame++; | |||||
| else | |||||
| { | |||||
| valueR = 0.0f; | |||||
| } | |||||
| const uint32_t j = internalDataFrame++; | |||||
| internalDataBuffer[0][j] = valueL; | internalDataBuffer[0][j] = valueL; | ||||
| internalDataBuffer[1][j] = valueR; | internalDataBuffer[1][j] = valueR; | ||||
| @@ -228,11 +248,11 @@ struct HostAudio8 : HostAudio<8> { | |||||
| void processTerminalOutput(const ProcessArgs&) override | void processTerminalOutput(const ProcessArgs&) override | ||||
| { | { | ||||
| const int blockFrames = pcontext->engine->getBlockFrames(); | |||||
| const uint32_t bufferSize = pcontext->bufferSize; | |||||
| // only incremented on output | // only incremented on output | ||||
| const int k = dataFrame++; | |||||
| DISTRHO_SAFE_ASSERT_INT2_RETURN(k < blockFrames, k, blockFrames,); | |||||
| const uint32_t k = dataFrame++; | |||||
| DISTRHO_SAFE_ASSERT_INT2_RETURN(k < bufferSize, k, bufferSize,); | |||||
| if (bypassed) | if (bypassed) | ||||
| return; | return; | ||||
| @@ -27,7 +27,7 @@ USE_NAMESPACE_DISTRHO; | |||||
| struct HostCV : TerminalModule { | struct HostCV : TerminalModule { | ||||
| CardinalPluginContext* const pcontext; | CardinalPluginContext* const pcontext; | ||||
| int dataFrame = 0; | int dataFrame = 0; | ||||
| int64_t lastBlockFrame = -1; | |||||
| uint32_t lastProcessCounter = 0; | |||||
| enum ParamIds { | enum ParamIds { | ||||
| BIPOLAR_INPUTS_1_5, | BIPOLAR_INPUTS_1_5, | ||||
| @@ -64,18 +64,19 @@ struct HostCV : TerminalModule { | |||||
| if (pcontext->variant != kCardinalVariantMain) | if (pcontext->variant != kCardinalVariantMain) | ||||
| return; | return; | ||||
| const int64_t blockFrame = pcontext->engine->getBlockFrame(); | |||||
| const uint32_t bufferSize = pcontext->bufferSize; | |||||
| const uint32_t processCounter = pcontext->processCounter; | |||||
| // only checked on input | // only checked on input | ||||
| if (lastBlockFrame != blockFrame) | |||||
| if (lastProcessCounter != processCounter) | |||||
| { | { | ||||
| dataFrame = 0; | dataFrame = 0; | ||||
| lastBlockFrame = blockFrame; | |||||
| lastProcessCounter = processCounter; | |||||
| } | } | ||||
| // only incremented on output | // only incremented on output | ||||
| const int k = dataFrame; | |||||
| DISTRHO_SAFE_ASSERT_RETURN(k < pcontext->engine->getBlockFrames(),); | |||||
| const uint32_t k = dataFrame; | |||||
| DISTRHO_SAFE_ASSERT_RETURN(k < bufferSize,); | |||||
| if (isBypassed()) | if (isBypassed()) | ||||
| { | { | ||||
| @@ -102,9 +103,11 @@ struct HostCV : TerminalModule { | |||||
| if (pcontext->variant != kCardinalVariantMain) | if (pcontext->variant != kCardinalVariantMain) | ||||
| return; | return; | ||||
| const uint32_t bufferSize = pcontext->bufferSize; | |||||
| // only incremented on output | // only incremented on output | ||||
| const int k = dataFrame++; | |||||
| DISTRHO_SAFE_ASSERT_RETURN(k < pcontext->engine->getBlockFrames(),); | |||||
| const uint32_t k = dataFrame++; | |||||
| DISTRHO_SAFE_ASSERT_RETURN(k < bufferSize,); | |||||
| if (isBypassed()) | if (isBypassed()) | ||||
| return; | return; | ||||
| @@ -62,7 +62,7 @@ struct HostMIDICC : TerminalModule { | |||||
| const MidiEvent* midiEvents; | const MidiEvent* midiEvents; | ||||
| uint32_t midiEventsLeft; | uint32_t midiEventsLeft; | ||||
| uint32_t midiEventFrame; | uint32_t midiEventFrame; | ||||
| int64_t lastBlockFrame; | |||||
| uint32_t lastProcessCounter; | |||||
| uint8_t channel; | uint8_t channel; | ||||
| uint8_t chPressure[16]; | uint8_t chPressure[16]; | ||||
| @@ -99,7 +99,7 @@ struct HostMIDICC : TerminalModule { | |||||
| midiEvents = nullptr; | midiEvents = nullptr; | ||||
| midiEventsLeft = 0; | midiEventsLeft = 0; | ||||
| midiEventFrame = 0; | midiEventFrame = 0; | ||||
| lastBlockFrame = -1; | |||||
| lastProcessCounter = 0; | |||||
| channel = 0; | channel = 0; | ||||
| // adapted from Rack | // adapted from Rack | ||||
| @@ -120,13 +120,12 @@ struct HostMIDICC : TerminalModule { | |||||
| const bool isBypassed) | const bool isBypassed) | ||||
| { | { | ||||
| // Cardinal specific | // Cardinal specific | ||||
| const int64_t blockFrame = pcontext->engine->getBlockFrame(); | |||||
| const bool blockFrameChanged = lastBlockFrame != blockFrame; | |||||
| const uint32_t processCounter = pcontext->processCounter; | |||||
| const bool processCounterChanged = lastProcessCounter != processCounter; | |||||
| if (blockFrameChanged) | |||||
| if (processCounterChanged) | |||||
| { | { | ||||
| lastBlockFrame = blockFrame; | |||||
| lastProcessCounter = processCounter; | |||||
| midiEvents = pcontext->midiEvents; | midiEvents = pcontext->midiEvents; | ||||
| midiEventsLeft = pcontext->midiEventCount; | midiEventsLeft = pcontext->midiEventCount; | ||||
| midiEventFrame = 0; | midiEventFrame = 0; | ||||
| @@ -306,7 +305,7 @@ struct HostMIDICC : TerminalModule { | |||||
| } | } | ||||
| } | } | ||||
| return blockFrameChanged; | |||||
| return processCounterChanged; | |||||
| } | } | ||||
| } midiInput; | } midiInput; | ||||
| @@ -58,7 +58,7 @@ struct HostMIDIGate : TerminalModule { | |||||
| const MidiEvent* midiEvents; | const MidiEvent* midiEvents; | ||||
| uint32_t midiEventsLeft; | uint32_t midiEventsLeft; | ||||
| uint32_t midiEventFrame; | uint32_t midiEventFrame; | ||||
| int64_t lastBlockFrame; | |||||
| uint32_t lastProcessCounter; | |||||
| uint8_t channel; | uint8_t channel; | ||||
| // stuff from Rack | // stuff from Rack | ||||
| @@ -84,7 +84,7 @@ struct HostMIDIGate : TerminalModule { | |||||
| midiEvents = nullptr; | midiEvents = nullptr; | ||||
| midiEventsLeft = 0; | midiEventsLeft = 0; | ||||
| midiEventFrame = 0; | midiEventFrame = 0; | ||||
| lastBlockFrame = -1; | |||||
| lastProcessCounter = 0; | |||||
| channel = 0; | channel = 0; | ||||
| learningId = -1; | learningId = -1; | ||||
| mpeMode = false; | mpeMode = false; | ||||
| @@ -107,13 +107,12 @@ struct HostMIDIGate : TerminalModule { | |||||
| const bool velocityMode, int8_t learnedNotes[18], const bool isBypassed) | const bool velocityMode, int8_t learnedNotes[18], const bool isBypassed) | ||||
| { | { | ||||
| // Cardinal specific | // Cardinal specific | ||||
| const int64_t blockFrame = pcontext->engine->getBlockFrame(); | |||||
| const bool blockFrameChanged = lastBlockFrame != blockFrame; | |||||
| const uint32_t processCounter = pcontext->processCounter; | |||||
| const bool processCounterChanged = lastProcessCounter != processCounter; | |||||
| if (blockFrameChanged) | |||||
| if (processCounterChanged) | |||||
| { | { | ||||
| lastBlockFrame = blockFrame; | |||||
| lastProcessCounter = processCounter; | |||||
| midiEvents = pcontext->midiEvents; | midiEvents = pcontext->midiEvents; | ||||
| midiEventsLeft = pcontext->midiEventCount; | midiEventsLeft = pcontext->midiEventCount; | ||||
| midiEventFrame = 0; | midiEventFrame = 0; | ||||
| @@ -122,7 +121,7 @@ struct HostMIDIGate : TerminalModule { | |||||
| if (isBypassed) | if (isBypassed) | ||||
| { | { | ||||
| ++midiEventFrame; | ++midiEventFrame; | ||||
| return blockFrameChanged; | |||||
| return processCounterChanged; | |||||
| } | } | ||||
| while (midiEventsLeft != 0) | while (midiEventsLeft != 0) | ||||
| @@ -220,7 +219,7 @@ struct HostMIDIGate : TerminalModule { | |||||
| } | } | ||||
| } | } | ||||
| return blockFrameChanged; | |||||
| return processCounterChanged; | |||||
| } | } | ||||
| } midiInput; | } midiInput; | ||||
| @@ -55,7 +55,7 @@ struct HostMIDIMap : TerminalModule { | |||||
| const MidiEvent* midiEvents; | const MidiEvent* midiEvents; | ||||
| uint32_t midiEventsLeft; | uint32_t midiEventsLeft; | ||||
| uint32_t midiEventFrame; | uint32_t midiEventFrame; | ||||
| int64_t lastBlockFrame; | |||||
| uint32_t lastProcessCounter; | |||||
| int nextLearningId; | int nextLearningId; | ||||
| uint8_t channel; | uint8_t channel; | ||||
| @@ -117,7 +117,7 @@ struct HostMIDIMap : TerminalModule { | |||||
| midiEvents = nullptr; | midiEvents = nullptr; | ||||
| midiEventsLeft = 0; | midiEventsLeft = 0; | ||||
| midiEventFrame = 0; | midiEventFrame = 0; | ||||
| lastBlockFrame = -1; | |||||
| lastProcessCounter = 0; | |||||
| nextLearningId = -1; | nextLearningId = -1; | ||||
| channel = 0; | channel = 0; | ||||
| @@ -134,13 +134,12 @@ struct HostMIDIMap : TerminalModule { | |||||
| void processTerminalInput(const ProcessArgs& args) override | void processTerminalInput(const ProcessArgs& args) override | ||||
| { | { | ||||
| // Cardinal specific | // Cardinal specific | ||||
| const int64_t blockFrame = pcontext->engine->getBlockFrame(); | |||||
| const bool blockFrameChanged = lastBlockFrame != blockFrame; | |||||
| const uint32_t processCounter = pcontext->processCounter; | |||||
| const bool processCounterChanged = lastProcessCounter != processCounter; | |||||
| if (blockFrameChanged) | |||||
| if (processCounterChanged) | |||||
| { | { | ||||
| lastBlockFrame = blockFrame; | |||||
| lastProcessCounter = processCounter; | |||||
| midiEvents = pcontext->midiEvents; | midiEvents = pcontext->midiEvents; | ||||
| midiEventsLeft = pcontext->midiEventCount; | midiEventsLeft = pcontext->midiEventCount; | ||||
| midiEventFrame = 0; | midiEventFrame = 0; | ||||
| @@ -81,7 +81,7 @@ struct HostMIDI : TerminalModule { | |||||
| const MidiEvent* midiEvents; | const MidiEvent* midiEvents; | ||||
| uint32_t midiEventsLeft; | uint32_t midiEventsLeft; | ||||
| uint32_t midiEventFrame; | uint32_t midiEventFrame; | ||||
| int64_t lastBlockFrame; | |||||
| uint32_t lastProcessCounter; | |||||
| bool wasPlaying; | bool wasPlaying; | ||||
| uint8_t channel; | uint8_t channel; | ||||
| @@ -140,7 +140,7 @@ struct HostMIDI : TerminalModule { | |||||
| midiEvents = nullptr; | midiEvents = nullptr; | ||||
| midiEventsLeft = 0; | midiEventsLeft = 0; | ||||
| midiEventFrame = 0; | midiEventFrame = 0; | ||||
| lastBlockFrame = -1; | |||||
| lastProcessCounter = 0; | |||||
| wasPlaying = false; | wasPlaying = false; | ||||
| channel = 0; | channel = 0; | ||||
| smooth = true; | smooth = true; | ||||
| @@ -171,12 +171,12 @@ struct HostMIDI : TerminalModule { | |||||
| bool process(const ProcessArgs& args, std::vector<rack::engine::Output>& outputs, const bool isBypassed) | bool process(const ProcessArgs& args, std::vector<rack::engine::Output>& outputs, const bool isBypassed) | ||||
| { | { | ||||
| // Cardinal specific | // Cardinal specific | ||||
| const int64_t blockFrame = pcontext->engine->getBlockFrame(); | |||||
| const bool blockFrameChanged = lastBlockFrame != blockFrame; | |||||
| const uint32_t processCounter = pcontext->processCounter; | |||||
| const bool processCounterChanged = lastProcessCounter != processCounter; | |||||
| if (blockFrameChanged) | |||||
| if (processCounterChanged) | |||||
| { | { | ||||
| lastBlockFrame = blockFrame; | |||||
| lastProcessCounter = processCounter; | |||||
| midiEvents = pcontext->midiEvents; | midiEvents = pcontext->midiEvents; | ||||
| midiEventsLeft = pcontext->midiEventCount; | midiEventsLeft = pcontext->midiEventCount; | ||||
| @@ -292,7 +292,7 @@ struct HostMIDI : TerminalModule { | |||||
| outputs[STOP_OUTPUT].setVoltage(stopPulse.process(args.sampleTime) ? 10.f : 0.f); | outputs[STOP_OUTPUT].setVoltage(stopPulse.process(args.sampleTime) ? 10.f : 0.f); | ||||
| outputs[CONTINUE_OUTPUT].setVoltage(continuePulse.process(args.sampleTime) ? 10.f : 0.f); | outputs[CONTINUE_OUTPUT].setVoltage(continuePulse.process(args.sampleTime) ? 10.f : 0.f); | ||||
| return blockFrameChanged; | |||||
| return processCounterChanged; | |||||
| } | } | ||||
| void processMessage(const midi::Message& msg) | void processMessage(const midi::Message& msg) | ||||
| @@ -541,6 +541,18 @@ struct HostMIDI : TerminalModule { | |||||
| CardinalPluginContext* const pcontext; | CardinalPluginContext* const pcontext; | ||||
| uint8_t channel = 0; | uint8_t channel = 0; | ||||
| // caching | |||||
| struct { | |||||
| bool gate = false; | |||||
| bool velocity = false; | |||||
| bool aftertouch = false; | |||||
| bool pitchbend = false; | |||||
| bool modwheel = false; | |||||
| bool start = false; | |||||
| bool stop = false; | |||||
| bool cont = false; | |||||
| } connected; | |||||
| MidiOutput(CardinalPluginContext* const pc) | MidiOutput(CardinalPluginContext* const pc) | ||||
| : pcontext(pc) {} | : pcontext(pc) {} | ||||
| @@ -595,9 +607,21 @@ struct HostMIDI : TerminalModule { | |||||
| void processTerminalInput(const ProcessArgs& args) override | void processTerminalInput(const ProcessArgs& args) override | ||||
| { | { | ||||
| if (midiInput.process(args, outputs, isBypassed())) | if (midiInput.process(args, outputs, isBypassed())) | ||||
| { | |||||
| midiOutput.frame = 0; | midiOutput.frame = 0; | ||||
| midiOutput.connected.gate = inputs[GATE_INPUT].isConnected(); | |||||
| midiOutput.connected.velocity = inputs[VELOCITY_INPUT].isConnected(); | |||||
| midiOutput.connected.aftertouch = inputs[AFTERTOUCH_INPUT].isConnected(); | |||||
| midiOutput.connected.pitchbend = inputs[PITCHBEND_INPUT].isConnected(); | |||||
| midiOutput.connected.modwheel = inputs[MODWHEEL_INPUT].isConnected(); | |||||
| midiOutput.connected.start = inputs[START_INPUT].isConnected(); | |||||
| midiOutput.connected.stop = inputs[STOP_INPUT].isConnected(); | |||||
| midiOutput.connected.cont = inputs[CONTINUE_INPUT].isConnected(); | |||||
| } | |||||
| else | else | ||||
| { | |||||
| ++midiOutput.frame; | ++midiOutput.frame; | ||||
| } | |||||
| } | } | ||||
| void processTerminalOutput(const ProcessArgs&) override | void processTerminalOutput(const ProcessArgs&) override | ||||
| @@ -605,37 +629,67 @@ struct HostMIDI : TerminalModule { | |||||
| if (isBypassed()) | if (isBypassed()) | ||||
| return; | return; | ||||
| auto connected = midiOutput.connected; | |||||
| for (int c = 0; c < inputs[PITCH_INPUT].getChannels(); ++c) | for (int c = 0; c < inputs[PITCH_INPUT].getChannels(); ++c) | ||||
| { | { | ||||
| int vel = (int) std::round(inputs[VELOCITY_INPUT].getNormalPolyVoltage(10.f * 100 / 127, c) / 10.f * 127); | |||||
| vel = clamp(vel, 0, 127); | |||||
| midiOutput.setVelocity(vel, c); | |||||
| if (connected.velocity) | |||||
| { | |||||
| const constexpr float n = 10.f * 100.f / 127.f; | |||||
| const int vel = clamp( | |||||
| static_cast<int>(inputs[VELOCITY_INPUT].getNormalPolyVoltage(n, c) / 10.f * 127.f + 0.5f), 0, 127); | |||||
| midiOutput.setVelocity(vel, c); | |||||
| } | |||||
| else | |||||
| { | |||||
| midiOutput.setVelocity(100, c); | |||||
| } | |||||
| int note = (int) std::round(inputs[PITCH_INPUT].getVoltage(c) * 12.f + 60.f); | |||||
| note = clamp(note, 0, 127); | |||||
| bool gate = inputs[GATE_INPUT].getPolyVoltage(c) >= 1.f; | |||||
| const int note = clamp(static_cast<int>(inputs[PITCH_INPUT].getVoltage(c) * 12.f + 60.5f), 0, 127); | |||||
| const bool gate = connected.gate ? inputs[GATE_INPUT].getPolyVoltage(c) >= 1.f : false; | |||||
| midiOutput.setNoteGate(note, gate, c); | midiOutput.setNoteGate(note, gate, c); | ||||
| int aft = (int) std::round(inputs[AFTERTOUCH_INPUT].getPolyVoltage(c) / 10.f * 127); | |||||
| aft = clamp(aft, 0, 127); | |||||
| midiOutput.setKeyPressure(aft, c); | |||||
| if (connected.aftertouch) | |||||
| { | |||||
| const int aft = clamp( | |||||
| static_cast<int>(inputs[AFTERTOUCH_INPUT].getPolyVoltage(c) / 10.f * 127.f + 0.5f), 0, 127); | |||||
| midiOutput.setKeyPressure(aft, c); | |||||
| } | |||||
| else | |||||
| { | |||||
| midiOutput.setKeyPressure(0, c); | |||||
| } | |||||
| } | } | ||||
| int pw = (int) std::round((inputs[PITCHBEND_INPUT].getVoltage() + 5.f) / 10.f * 16383); | |||||
| pw = clamp(pw, 0, 16383); | |||||
| midiOutput.setPitchWheel(pw); | |||||
| if (connected.pitchbend) | |||||
| { | |||||
| const int pw = clamp( | |||||
| static_cast<int>((inputs[PITCHBEND_INPUT].getVoltage() + 5.f) / 10.f * 16383.f + 0.5f), 0, 16383); | |||||
| midiOutput.setPitchWheel(pw); | |||||
| } | |||||
| else | |||||
| { | |||||
| midiOutput.setPitchWheel(0); | |||||
| } | |||||
| int mw = (int) std::round(inputs[MODWHEEL_INPUT].getVoltage() / 10.f * 127); | |||||
| mw = clamp(mw, 0, 127); | |||||
| midiOutput.setModWheel(mw); | |||||
| if (connected.modwheel) | |||||
| { | |||||
| const int mw = clamp( | |||||
| static_cast<int>(inputs[MODWHEEL_INPUT].getVoltage() / 10.f * 127.f + 0.5f), 0, 127); | |||||
| midiOutput.setModWheel(mw); | |||||
| } | |||||
| else | |||||
| { | |||||
| midiOutput.setModWheel(0); | |||||
| } | |||||
| bool start = inputs[START_INPUT].getVoltage() >= 1.f; | |||||
| const bool start = connected.start ? inputs[START_INPUT].getVoltage() >= 1.f : false; | |||||
| midiOutput.setStart(start); | midiOutput.setStart(start); | ||||
| bool stop = inputs[STOP_INPUT].getVoltage() >= 1.f; | |||||
| const bool stop = connected.stop ? inputs[STOP_INPUT].getVoltage() >= 1.f : false; | |||||
| midiOutput.setStop(stop); | midiOutput.setStop(stop); | ||||
| bool cont = inputs[CONTINUE_INPUT].getVoltage() >= 1.f; | |||||
| const bool cont = connected.cont ? inputs[CONTINUE_INPUT].getVoltage() >= 1.f : false; | |||||
| midiOutput.setContinue(cont); | midiOutput.setContinue(cont); | ||||
| } | } | ||||
| @@ -41,7 +41,7 @@ struct HostTime : TerminalModule { | |||||
| rack::dsp::PulseGenerator pulseReset, pulseBar, pulseBeat, pulseClock; | rack::dsp::PulseGenerator pulseReset, pulseBar, pulseBeat, pulseClock; | ||||
| float sampleTime = 0.0f; | float sampleTime = 0.0f; | ||||
| int64_t lastBlockFrame = -1; | |||||
| uint32_t lastProcessCounter = 0; | |||||
| // cached time values | // cached time values | ||||
| struct { | struct { | ||||
| bool reset = true; | bool reset = true; | ||||
| @@ -63,15 +63,15 @@ struct HostTime : TerminalModule { | |||||
| void processTerminalInput(const ProcessArgs& args) override | void processTerminalInput(const ProcessArgs& args) override | ||||
| { | { | ||||
| const int64_t blockFrame = pcontext->engine->getBlockFrame(); | |||||
| const uint32_t processCounter = pcontext->processCounter; | |||||
| // local variables for faster access | // local variables for faster access | ||||
| double tick, tickClock; | double tick, tickClock; | ||||
| // Update time position if running a new audio block | // Update time position if running a new audio block | ||||
| if (lastBlockFrame != blockFrame) | |||||
| if (lastProcessCounter != processCounter) | |||||
| { | { | ||||
| lastBlockFrame = blockFrame; | |||||
| lastProcessCounter = processCounter; | |||||
| timeInfo.reset = pcontext->reset; | timeInfo.reset = pcontext->reset; | ||||
| timeInfo.bar = pcontext->bar; | timeInfo.bar = pcontext->bar; | ||||
| timeInfo.beat = pcontext->beat; | timeInfo.beat = pcontext->beat; | ||||
| @@ -129,6 +129,13 @@ struct HostTime : TerminalModule { | |||||
| } | } | ||||
| } | } | ||||
| // store back the local values | |||||
| timeInfo.tick = tick; | |||||
| timeInfo.tickClock = tickClock; | |||||
| if (isBypassed()) | |||||
| return; | |||||
| const bool hasReset = pulseReset.process(args.sampleTime); | const bool hasReset = pulseReset.process(args.sampleTime); | ||||
| const bool hasBar = pulseBar.process(args.sampleTime); | const bool hasBar = pulseBar.process(args.sampleTime); | ||||
| const bool hasBeat = pulseBeat.process(args.sampleTime); | const bool hasBeat = pulseBeat.process(args.sampleTime); | ||||
| @@ -140,13 +147,6 @@ struct HostTime : TerminalModule { | |||||
| ? ((float) (timeInfo.beat - 1) + beatPhase) / pcontext->beatsPerBar | ? ((float) (timeInfo.beat - 1) + beatPhase) / pcontext->beatsPerBar | ||||
| : 0.0f; | : 0.0f; | ||||
| // store back the local values | |||||
| timeInfo.tick = tick; | |||||
| timeInfo.tickClock = tickClock; | |||||
| if (isBypassed()) | |||||
| return; | |||||
| lights[kHostTimeRolling].setBrightness(playing ? 1.0f : 0.0f); | lights[kHostTimeRolling].setBrightness(playing ? 1.0f : 0.0f); | ||||
| lights[kHostTimeReset].setBrightnessSmooth(hasReset ? 1.0f : 0.0f, args.sampleTime * 0.5f); | lights[kHostTimeReset].setBrightnessSmooth(hasReset ? 1.0f : 0.0f, args.sampleTime * 0.5f); | ||||
| lights[kHostTimeBar].setBrightnessSmooth(hasBar ? 1.0f : 0.0f, args.sampleTime * 0.5f); | lights[kHostTimeBar].setBrightnessSmooth(hasBar ? 1.0f : 0.0f, args.sampleTime * 0.5f); | ||||
| @@ -148,7 +148,7 @@ struct IldaeilModule : Module { | |||||
| float audioDataOut1[BUFFER_SIZE]; | float audioDataOut1[BUFFER_SIZE]; | ||||
| float audioDataOut2[BUFFER_SIZE]; | float audioDataOut2[BUFFER_SIZE]; | ||||
| unsigned audioDataFill = 0; | unsigned audioDataFill = 0; | ||||
| int64_t lastBlockFrame = -1; | |||||
| uint32_t lastProcessCounter = 0; | |||||
| CardinalExpanderFromCarlaMIDIToCV* midiOutExpander = nullptr; | CardinalExpanderFromCarlaMIDIToCV* midiOutExpander = nullptr; | ||||
| volatile bool resetMeterIn = true; | volatile bool resetMeterIn = true; | ||||
| @@ -359,12 +359,12 @@ struct IldaeilModule : Module { | |||||
| if (audioDataFill == BUFFER_SIZE) | if (audioDataFill == BUFFER_SIZE) | ||||
| { | { | ||||
| const int64_t blockFrame = pcontext->engine->getBlockFrame(); | |||||
| const uint32_t processCounter = pcontext->processCounter; | |||||
| // Update time position if running a new audio block | // Update time position if running a new audio block | ||||
| if (lastBlockFrame != blockFrame) | |||||
| if (lastProcessCounter != processCounter) | |||||
| { | { | ||||
| lastBlockFrame = blockFrame; | |||||
| lastProcessCounter = processCounter; | |||||
| fCarlaTimeInfo.playing = pcontext->playing; | fCarlaTimeInfo.playing = pcontext->playing; | ||||
| fCarlaTimeInfo.frame = pcontext->frame; | fCarlaTimeInfo.frame = pcontext->frame; | ||||
| fCarlaTimeInfo.bbt.valid = pcontext->bbtValid; | fCarlaTimeInfo.bbt.valid = pcontext->bbtValid; | ||||
| @@ -51,7 +51,7 @@ struct MidiEvent { | |||||
| }; | }; | ||||
| struct CardinalPluginContext : rack::Context { | struct CardinalPluginContext : rack::Context { | ||||
| uint32_t bufferSize; | |||||
| uint32_t bufferSize, processCounter; | |||||
| double sampleRate; | double sampleRate; | ||||
| float parameters[kModuleParameters]; | float parameters[kModuleParameters]; | ||||
| CardinalVariant variant; | CardinalVariant variant; | ||||
| @@ -1019,6 +1019,7 @@ protected: | |||||
| context->midiEventCount = midiEventCount; | context->midiEventCount = midiEventCount; | ||||
| } | } | ||||
| ++context->processCounter; | |||||
| context->engine->stepBlock(frames); | context->engine->stepBlock(frames); | ||||
| fWasBypassed = bypassed; | fWasBypassed = bypassed; | ||||
| @@ -48,7 +48,7 @@ enum CardinalVariant { | |||||
| // ----------------------------------------------------------------------------------------------------------- | // ----------------------------------------------------------------------------------------------------------- | ||||
| struct CardinalPluginContext : rack::Context { | struct CardinalPluginContext : rack::Context { | ||||
| uint32_t bufferSize; | |||||
| uint32_t bufferSize, processCounter; | |||||
| double sampleRate; | double sampleRate; | ||||
| float parameters[kModuleParameters]; | float parameters[kModuleParameters]; | ||||
| CardinalVariant variant; | CardinalVariant variant; | ||||
| @@ -69,6 +69,7 @@ struct CardinalPluginContext : rack::Context { | |||||
| CardinalPluginContext(Plugin* const p) | CardinalPluginContext(Plugin* const p) | ||||
| : bufferSize(p->getBufferSize()), | : bufferSize(p->getBufferSize()), | ||||
| processCounter(0), | |||||
| sampleRate(p->getSampleRate()), | sampleRate(p->getSampleRate()), | ||||
| #if CARDINAL_VARIANT_MAIN | #if CARDINAL_VARIANT_MAIN | ||||
| variant(kCardinalVariantMain), | variant(kCardinalVariantMain), | ||||