@@ -11,7 +11,7 @@ static const int PORT_MAX_CHANNELS = 16; | |||||
struct Port { | struct Port { | ||||
/** Voltage of the port */ | |||||
/** Voltage of the port. */ | |||||
union { | union { | ||||
/** Unstable API. Use set/getVoltage() instead. */ | /** Unstable API. Use set/getVoltage() instead. */ | ||||
float voltages[PORT_MAX_CHANNELS] = {}; | float voltages[PORT_MAX_CHANNELS] = {}; | ||||
@@ -25,7 +25,7 @@ struct Port { | |||||
uint8_t channels = 1; | uint8_t channels = 1; | ||||
/** Unstable API. Use isConnected() instead. */ | /** Unstable API. Use isConnected() instead. */ | ||||
bool active; | bool active; | ||||
/** For rendering plug lights on cables | |||||
/** For rendering plug lights on cables. | |||||
Green for positive, red for negative, and blue for polyphonic | Green for positive, red for negative, and blue for polyphonic | ||||
*/ | */ | ||||
Light plugLights[3]; | Light plugLights[3]; | ||||
@@ -34,16 +34,19 @@ struct Port { | |||||
voltages[channel] = voltage; | 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) { | float getVoltage(int channel = 0) { | ||||
return voltages[channel]; | 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) { | 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) { | float getNormalVoltage(float normalVoltage, int channel = 0) { | ||||
return isConnected() ? getVoltage(channel) : normalVoltage; | return isConnected() ? getVoltage(channel) : normalVoltage; | ||||
} | } | ||||
@@ -209,28 +209,27 @@ void CableWidget::fromJson(json_t *rootJ, const std::map<int, ModuleWidget*> &mo | |||||
void CableWidget::draw(const widget::DrawContext &ctx) { | void CableWidget::draw(const widget::DrawContext &ctx) { | ||||
float opacity = settings::cableOpacity; | float opacity = settings::cableOpacity; | ||||
float tension = settings::cableTension; | 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; | float thickness = 5; | ||||
if (isComplete()) { | 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; | 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(); | math::Vec outputPos = getOutputPos(); | ||||
@@ -38,16 +38,11 @@ void PortWidget::step() { | |||||
return; | return; | ||||
std::vector<float> values(3); | std::vector<float> 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); | plugLight->setBrightnesses(values); | ||||
} | } | ||||
@@ -10,8 +10,8 @@ void Cable::step() { | |||||
Input *input = &inputModule->inputs[inputId]; | Input *input = &inputModule->inputs[inputId]; | ||||
// Match number of polyphonic channels to output port | // Match number of polyphonic channels to output port | ||||
input->channels = output->channels; | 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]; | input->voltages[i] = output->voltages[i]; | ||||
} | } | ||||
} | } | ||||
@@ -61,12 +61,12 @@ struct Barrier { | |||||
return; | return; | ||||
std::unique_lock<std::mutex> lock(mutex); | std::unique_lock<std::mutex> lock(mutex); | ||||
count++; | count++; | ||||
if (count >= total) { | |||||
count = 0; | |||||
cv.notify_all(); | |||||
if (count < total) { | |||||
cv.wait(lock); | |||||
} | } | ||||
else { | else { | ||||
cv.wait(lock); | |||||
count = 0; | |||||
cv.notify_all(); | |||||
} | } | ||||
} | } | ||||
}; | }; | ||||
@@ -82,11 +82,11 @@ struct SpinBarrier { | |||||
void wait() { | void wait() { | ||||
count++; | count++; | ||||
if (count >= total) { | |||||
count = 0; | |||||
if (count < total) { | |||||
while (count > 0) {} | |||||
} | } | ||||
else { | else { | ||||
while (count > 0) {} | |||||
count = 0; | |||||
} | } | ||||
} | } | ||||
}; | }; | ||||
@@ -159,6 +159,9 @@ Engine::Engine() { | |||||
internal->sampleRate = sampleRate; | internal->sampleRate = sampleRate; | ||||
internal->sampleTime = 1 / sampleRate; | internal->sampleTime = 1 / sampleRate; | ||||
internal->sampleRateRequested = sampleRate; | internal->sampleRateRequested = sampleRate; | ||||
internal->engineBarrier.total = 1; | |||||
internal->workerBarrier.total = 1; | |||||
} | } | ||||
Engine::~Engine() { | Engine::~Engine() { | ||||
@@ -209,6 +212,11 @@ static void Engine_stepModules(Engine *engine, int id) { | |||||
for (int i = id; i < modulesLen; i += threadCount) { | for (int i = id; i < modulesLen; i += threadCount) { | ||||
Module *module = internal->modules[i]; | Module *module = internal->modules[i]; | ||||
if (!module->bypass) { | if (!module->bypass) { | ||||
for (Output &output : module->outputs) { | |||||
// Reset output channels without clearing channel voltages | |||||
output.channels = 1; | |||||
} | |||||
// Step module | // Step module | ||||
if (settings::powerMeter) { | if (settings::powerMeter) { | ||||
auto startTime = std::chrono::high_resolution_clock::now(); | auto startTime = std::chrono::high_resolution_clock::now(); | ||||
@@ -225,6 +233,11 @@ static void Engine_stepModules(Engine *engine, int id) { | |||||
module->step(); | module->step(); | ||||
} | } | ||||
} | } | ||||
else { | |||||
for (Output &output : module->outputs) { | |||||
output.setChannels(0); | |||||
} | |||||
} | |||||
// Iterate ports and step plug lights | // Iterate ports and step plug lights | ||||
for (Input &input : module->inputs) { | for (Input &input : module->inputs) { | ||||