@@ -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; | |||
} | |||
@@ -209,28 +209,27 @@ void CableWidget::fromJson(json_t *rootJ, const std::map<int, ModuleWidget*> &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(); | |||
@@ -38,16 +38,11 @@ void PortWidget::step() { | |||
return; | |||
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); | |||
} | |||
@@ -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]; | |||
} | |||
} | |||
@@ -61,12 +61,12 @@ struct Barrier { | |||
return; | |||
std::unique_lock<std::mutex> 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) { | |||