diff --git a/include/engine/Port.hpp b/include/engine/Port.hpp index d7f924f6..9f8004cd 100644 --- a/include/engine/Port.hpp +++ b/include/engine/Port.hpp @@ -11,7 +11,7 @@ static const int PORT_MAX_CHANNELS = 16; struct Port { - /** Voltage of the port */ + /** Voltage of the port. */ union { /** Unstable API. Use set/getVoltage() instead. */ float voltages[PORT_MAX_CHANNELS] = {}; @@ -25,7 +25,7 @@ struct Port { uint8_t channels = 1; /** Unstable API. Use isConnected() instead. */ bool active; - /** For rendering plug lights on cables + /** For rendering plug lights on cables. Green for positive, red for negative, and blue for polyphonic */ Light plugLights[3]; @@ -34,16 +34,19 @@ struct Port { voltages[channel] = voltage; } + /** Returns the voltage of the given channel. + Because of proper bookkeeping, all channels higher than the input port's number of channels should be 0V. + */ float getVoltage(int channel = 0) { return voltages[channel]; } - /** Returns the voltage if `channel` is a valid channel, otherwise returns the first voltage (channel 0) */ + /** Returns the given channel's voltage if the port is polyphonic, otherwise returns the first voltage (channel 0). */ float getPolyVoltage(int channel) { - return (channel < channels) ? getVoltage(channel) : getVoltage(0); + return (channels == 1) ? getVoltage(channel) : getVoltage(0); } - /** Returns the voltage if a cable is connected, otherwise returns the given normal voltage */ + /** Returns the voltage if a cable is connected, otherwise returns the given normal voltage. */ float getNormalVoltage(float normalVoltage, int channel = 0) { return isConnected() ? getVoltage(channel) : normalVoltage; } diff --git a/src/app/CableWidget.cpp b/src/app/CableWidget.cpp index abece7f7..30b96e01 100644 --- a/src/app/CableWidget.cpp +++ b/src/app/CableWidget.cpp @@ -209,28 +209,27 @@ void CableWidget::fromJson(json_t *rootJ, const std::map &mo void CableWidget::draw(const widget::DrawContext &ctx) { float opacity = settings::cableOpacity; float tension = settings::cableTension; - - if (!isComplete()) { - // Draw opaque if the cable is incomplete - opacity = 1.0; - } - else { - // Draw opaque if mouse is hovering over a connected port - if (outputPort->hovered || inputPort->hovered) - opacity = 1.0; - } - float thickness = 5; + if (isComplete()) { - Output *output = &cable->outputModule->outputs[cable->outputId]; - if (output->channels > 1) { - // Increase thickness if output port is polyphonic + Input *input = &cable->inputModule->inputs[cable->inputId]; + // Draw opaque if mouse is hovering over a connected port + if (input->channels > 1) { + // Increase thickness if input port is polyphonic thickness = 8; } - // else if (output->channels == 0) { - // // Draw translucent cable if not active (i.e. 0 channels) - // opacity *= 0.5; - // } + + if (outputPort->hovered || inputPort->hovered) { + opacity = 1.0; + } + else if (input->channels == 0) { + // Draw translucent cable if not active (i.e. 0 channels) + opacity *= 0.25; + } + } + else { + // Draw opaque if the cable is incomplete + opacity = 1.0; } math::Vec outputPos = getOutputPos(); diff --git a/src/app/PortWidget.cpp b/src/app/PortWidget.cpp index 68b6a30a..684e56af 100644 --- a/src/app/PortWidget.cpp +++ b/src/app/PortWidget.cpp @@ -38,16 +38,11 @@ void PortWidget::step() { return; std::vector values(3); - // Input and Outputs are not virtual, so we can't cast to Port to make this less redundant. - if (type == OUTPUT) { - values[0] = module->outputs[portId].plugLights[0].getBrightness(); - values[1] = module->outputs[portId].plugLights[1].getBrightness(); - values[2] = module->outputs[portId].plugLights[2].getBrightness(); - } - else { - values[0] = module->inputs[portId].plugLights[0].getBrightness(); - values[1] = module->inputs[portId].plugLights[1].getBrightness(); - values[2] = module->inputs[portId].plugLights[2].getBrightness(); + for (int i = 0; i < 3; i++) { + if (type == OUTPUT) + values[i] = module->outputs[portId].plugLights[i].getBrightness(); + else + values[i] = module->inputs[portId].plugLights[i].getBrightness(); } plugLight->setBrightnesses(values); } diff --git a/src/engine/Cable.cpp b/src/engine/Cable.cpp index af82b50d..1427597a 100644 --- a/src/engine/Cable.cpp +++ b/src/engine/Cable.cpp @@ -10,8 +10,8 @@ void Cable::step() { Input *input = &inputModule->inputs[inputId]; // Match number of polyphonic channels to output port input->channels = output->channels; - // Copy voltages from output to input - for (int i = 0; i < output->channels; i++) { + // Copy all voltages from output to input + for (int i = 0; i < PORT_MAX_CHANNELS; i++) { input->voltages[i] = output->voltages[i]; } } diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp index f6f2791a..e255ed73 100644 --- a/src/engine/Engine.cpp +++ b/src/engine/Engine.cpp @@ -61,12 +61,12 @@ struct Barrier { return; std::unique_lock lock(mutex); count++; - if (count >= total) { - count = 0; - cv.notify_all(); + if (count < total) { + cv.wait(lock); } else { - cv.wait(lock); + count = 0; + cv.notify_all(); } } }; @@ -82,11 +82,11 @@ struct SpinBarrier { void wait() { count++; - if (count >= total) { - count = 0; + if (count < total) { + while (count > 0) {} } else { - while (count > 0) {} + count = 0; } } }; @@ -159,6 +159,9 @@ Engine::Engine() { internal->sampleRate = sampleRate; internal->sampleTime = 1 / sampleRate; internal->sampleRateRequested = sampleRate; + + internal->engineBarrier.total = 1; + internal->workerBarrier.total = 1; } Engine::~Engine() { @@ -209,6 +212,11 @@ static void Engine_stepModules(Engine *engine, int id) { for (int i = id; i < modulesLen; i += threadCount) { Module *module = internal->modules[i]; if (!module->bypass) { + for (Output &output : module->outputs) { + // Reset output channels without clearing channel voltages + output.channels = 1; + } + // Step module if (settings::powerMeter) { auto startTime = std::chrono::high_resolution_clock::now(); @@ -225,6 +233,11 @@ static void Engine_stepModules(Engine *engine, int id) { module->step(); } } + else { + for (Output &output : module->outputs) { + output.setChannels(0); + } + } // Iterate ports and step plug lights for (Input &input : module->inputs) {