Skip to content

Commit

Permalink
Big Bugfix Update
Browse files Browse the repository at this point in the history
Ouros - fixed display hairyness. Aligned all buffers to 512.
PressedDuck - fixed, again, issues with polyphonic cable management.
Signals - Fixed poly cable handling.
StepWave - Changed round to roundf, so it doesn't overload on older computers
Syncro - Changed round to roundf
Strings - Changed round to roundf
  • Loading branch information
codygeary committed Nov 12, 2024
1 parent 77dc70a commit 903a25b
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 85 deletions.
53 changes: 15 additions & 38 deletions src/Ouros.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ struct Ouros : Module {
// Global variables for each channel
dsp::PulseGenerator resetPulse[16];
dsp::SchmittTrigger SyncTrigger[16];
CircularBuffer<float, 1024> waveBuffers[4];
CircularBuffer<float, 512> waveBuffers[4];

float oscPhase[16][4] = {{0.0f}};
float prevPhaseResetInput[16] = {0.0f};
Expand Down Expand Up @@ -514,8 +514,8 @@ struct Ouros : Module {

}

int sampleIndex = static_cast<int>(oscPhase[0][2] * 1024);
sampleIndex = clamp(sampleIndex, 0, 1023);
int sampleIndex = static_cast<int>(oscPhase[0][2] * 512);
sampleIndex = clamp(sampleIndex, 0, 511);
waveBuffers[0][sampleIndex] = outputs[L_OUTPUT].getVoltage(0);
waveBuffers[1][sampleIndex] = outputs[R_OUTPUT].getVoltage(0);

Expand All @@ -526,23 +526,16 @@ struct Ouros : Module {
struct PolarXYDisplay : TransparentWidget {
Ouros* module;
float centerX, centerY;
float xScale = 2 * M_PI / 1023;
float radiusScale;

static constexpr float twoPi = 2.0f * M_PI; // Precomputed constant for 2*pi

void draw(const DrawArgs& args) override {
// We do not need to clear the drawing area here if it is handled in drawLayer()
TransparentWidget::draw(args);
}
static constexpr float twoPi = 2.0f * M_PI; // Precomputed constant for 2π

void drawLayer(const DrawArgs& args, int layer) override {
if (!module) return;

if (layer == 1) {
centerX = box.size.x / 2.0f;
centerY = box.size.y / 2.0f;
radiusScale = centerY / 5; // Adjust scale factor for radius
radiusScale = centerY * 0.8f; // Adjust as needed

// Clear the area before drawing the waveform
nvgBeginPath(args.vg);
Expand All @@ -551,36 +544,27 @@ struct PolarXYDisplay : TransparentWidget {
nvgFill(args.vg);

// Draw waveforms
if (!waveBufferEmpty(module->waveBuffers[0])) {
drawWaveform(args, module->waveBuffers[0], nvgRGBAf(1, 0.4, 0, 0.8));
}

if (!waveBufferEmpty(module->waveBuffers[1])) {
drawWaveform(args, module->waveBuffers[1], nvgRGBAf(0, 0.4, 1, 0.8));
}
}

TransparentWidget::drawLayer(args, layer);
}

bool waveBufferEmpty(const CircularBuffer<float, 1024>& waveBuffer) const {
// Check if the buffer has meaningful data; in this case, we'll assume
// that a buffer is "empty" if all values are zero (or some other criteria).
for (size_t i = 0; i < waveBuffer.size(); i++) {
if (waveBuffer[i] != 0.0f) {
return false;
}
}
return true;
}
void drawWaveform(const DrawArgs& args, const CircularBuffer<float, 512>& waveBuffer, NVGcolor color) {

void drawWaveform(const DrawArgs& args, const CircularBuffer<float, 1024>& waveBuffer, NVGcolor color) {
nvgBeginPath(args.vg);
bool firstPoint = true;

for (size_t i = 0; i < waveBuffer.size(); i++) {
float theta = i * xScale; // Compute angle based on index
float radius = waveBuffer[i] * radiusScale + centerY; // Adjust radius based on sample value
const int displaySamples = 512; // Adjust for performance
for (int i = 0; i < displaySamples; i++) {
size_t bufferIndex = i * (waveBuffer.size() - 1) / (displaySamples - 1);

float theta = ((float)i / (displaySamples - 1)) * twoPi; // From 0 to 2π

float amplitude = waveBuffer[bufferIndex] / 5.0f; // Normalize to -1 to +1
float radius = centerY + amplitude * radiusScale;

Vec pos = polarToCartesian(theta, radius);

if (firstPoint) {
Expand All @@ -591,19 +575,12 @@ struct PolarXYDisplay : TransparentWidget {
}
}

// Properly close the path to avoid any unintended lines
nvgClosePath(args.vg);
nvgStrokeColor(args.vg, color); // Set the color for the waveform
nvgStrokeWidth(args.vg, 1.0);
nvgStroke(args.vg);
}

Vec polarToCartesian(float theta, float radius) const {
// Normalize theta to be between -pi and pi
theta = fmod(theta + M_PI, twoPi);
if (theta < 0) theta += twoPi;
theta -= M_PI;

float x = centerX + radius * cos(theta);
float y = centerY + radius * sin(theta);
return Vec(x, y);
Expand Down
16 changes: 8 additions & 8 deletions src/PreeeeeeeeeeessedDuck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -533,10 +533,10 @@ struct PreeeeeeeeeeessedDuck : Module {
int muteChannels[16] = {0}; // Number of polyphonic channels for MUTE inputs

// Arrays to store the current input signals and connectivity status
int activeAudio[16] = {-1}; // Stores the number of the previous active channel for the AUDIO inputs
int activeVcaChannel[16] = {-1}; // Stores the number of the previous active channel for the VCA CV
int activePanChannel[16] = {-1}; // Stores the number of the previous active channel for the PAN CV
int activeMuteChannel[16] = {-1}; // Stores the number of the previous active channel for the MUTE
int activeAudio[16] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; // Stores the number of the previous active channel for the AUDIO inputs
int activeVcaChannel[16] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; // Stores the number of the previous active channel for the VCA CV
int activePanChannel[16] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; // Stores the number of the previous active channel for the PAN CV
int activeMuteChannel[16] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; // Stores the number of the previous active channel for the MUTE
//initialize all active channels with -1, indicating nothing connected.

// Scan all inputs to determine the polyphony
Expand Down Expand Up @@ -641,7 +641,7 @@ struct PreeeeeeeeeeessedDuck : Module {
// Now we compute which channel we need to grab
int diffBetween = i - activeAudio[i];
int currentChannelMax = audioChannels[activeAudio[i]] ;
if (currentChannelMax - diffBetween > 0){ //If we are before the last poly channel
if (diffBetween >= 0 && diffBetween < currentChannelMax){ //If we are before the last poly channel
inputActive = true;
// Handle mono to stereo routing
if (!isConnectedR[ activeAudio[i] ] && isConnectedL[ activeAudio[i] ]) { //Left only
Expand Down Expand Up @@ -684,7 +684,7 @@ struct PreeeeeeeeeeessedDuck : Module {
// Now we compute which channel we need to grab
int diffBetween = i - activeMuteChannel[i];
int currentChannelMax = muteChannels[activeMuteChannel[i]] ;
if (currentChannelMax - diffBetween > 0) { //If we are before the last poly channel
if (diffBetween >= 0 && diffBetween < currentChannelMax) { //If we are before the last poly channel
inputMute = inputs[ MUTE_1_INPUT + activeMuteChannel[i] ].getPolyVoltage(diffBetween) > 0.5f;
}
}
Expand Down Expand Up @@ -746,7 +746,7 @@ struct PreeeeeeeeeeessedDuck : Module {
// Now we compute which channel we need to grab
int diffBetween = i - activeVcaChannel[i];
int currentChannelMax = vcaChannels[activeVcaChannel[i]] ;
if (currentChannelMax - diffBetween > 0) { //If we are before the last poly channel
if (diffBetween >= 0 && diffBetween < currentChannelMax) { //If we are before the last poly channel
inputL[i] *= clamp(inputs[VCA_CV1_INPUT + activeVcaChannel[i]].getPolyVoltage(diffBetween) / 10.f, 0.f, 2.f);
inputR[i] *= clamp(inputs[VCA_CV1_INPUT + activeVcaChannel[i]].getPolyVoltage(diffBetween) / 10.f, 0.f, 2.f);
}
Expand Down Expand Up @@ -780,7 +780,7 @@ struct PreeeeeeeeeeessedDuck : Module {
// Now we compute which channel we need to grab
int diffBetween = i - activePanChannel[i];
int currentChannelMax = panChannels[activePanChannel[i]] ;
if (currentChannelMax - diffBetween > 0) { //If we are before the last poly channel
if (diffBetween >= 0 && diffBetween < currentChannelMax) { //If we are before the last poly channel
pan += inputs[PAN_CV1_INPUT + activePanChannel[i]].getPolyVoltage(diffBetween) / 5.f;
}
}
Expand Down
17 changes: 9 additions & 8 deletions src/PressedDuck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -427,10 +427,10 @@ struct PressedDuck : Module {
int muteChannels[6] = {0}; // Number of polyphonic channels for MUTE inputs

// Arrays to store the current input signals and connectivity status
int activeAudio[6] = {-1}; // Stores the number of the previous active channel for the AUDIO inputs
int activeVcaChannel[6] = {-1}; // Stores the number of the previous active channel for the VCA CV
int activePanChannel[6] = {-1}; // Stores the number of the previous active channel for the PAN CV
int activeMuteChannel[6] = {-1}; // Stores the number of the previous active channel for the MUTE
int activeAudio[6] = {-1, -1, -1, -1, -1, -1}; // Stores the number of the previous active channel for the AUDIO inputs
int activeVcaChannel[6] = {-1, -1, -1, -1, -1, -1}; // Stores the number of the previous active channel for the VCA CV
int activePanChannel[6] = {-1, -1, -1, -1, -1, -1}; // Stores the number of the previous active channel for the PAN CV
int activeMuteChannel[6] = {-1, -1, -1, -1, -1, -1}; // Stores the number of the previous active channel for the MUTE
//initialize all active channels with -1, indicating nothing connected.

// Scan all inputs to determine the polyphony
Expand Down Expand Up @@ -534,7 +534,7 @@ struct PressedDuck : Module {
// Now we compute which channel we need to grab
int diffBetween = i - activeAudio[i];
int currentChannelMax = audioChannels[activeAudio[i]] ;
if (currentChannelMax - diffBetween > 0){ //If we are before the last poly channel
if (diffBetween >= 0 && diffBetween < currentChannelMax){ //If we are before the last poly channel
inputActive = true;
// Handle mono to stereo routing
if (!isConnectedR[ activeAudio[i] ] && isConnectedL[ activeAudio[i] ]) { //Left only
Expand Down Expand Up @@ -571,14 +571,15 @@ struct PressedDuck : Module {
bool buttonMute = params[MUTE1_PARAM + i].getValue() > 0.5f;
bool inputMute = false;


// Check if mute is triggered by the input or previous poly input
if (activeMuteChannel[i] == i) { //if there's an input here
inputMute = inputs[MUTE_1_INPUT + i].getPolyVoltage(0) > 0.5f;
} else if (activeMuteChannel[i] > -1) { //otherwise check the previous channel
// Now we compute which channel we need to grab
int diffBetween = i - activeMuteChannel[i];
int currentChannelMax = muteChannels[activeMuteChannel[i]] ;
if (currentChannelMax - diffBetween > 0) { //If we are before the last poly channel
if (diffBetween >= 0 && diffBetween < currentChannelMax) { //If we are before the last poly channel
inputMute = inputs[ MUTE_1_INPUT + activeMuteChannel[i] ].getPolyVoltage(diffBetween) > 0.5f;
}
}
Expand Down Expand Up @@ -640,7 +641,7 @@ struct PressedDuck : Module {
// Now we compute which channel we need to grab
int diffBetween = i - activeVcaChannel[i];
int currentChannelMax = vcaChannels[activeVcaChannel[i]] ;
if (currentChannelMax - diffBetween > 0) { //If we are before the last poly channel
if (diffBetween >= 0 && diffBetween < currentChannelMax) { //If we are before the last poly channel
inputL[i] *= clamp(inputs[VCA_CV1_INPUT + activeVcaChannel[i]].getPolyVoltage(diffBetween) / 10.f, 0.f, 2.f);
inputR[i] *= clamp(inputs[VCA_CV1_INPUT + activeVcaChannel[i]].getPolyVoltage(diffBetween) / 10.f, 0.f, 2.f);
}
Expand Down Expand Up @@ -674,7 +675,7 @@ struct PressedDuck : Module {
// Now we compute which channel we need to grab
int diffBetween = i - activePanChannel[i];
int currentChannelMax = panChannels[activePanChannel[i]] ;
if (currentChannelMax - diffBetween > 0) { //If we are before the last poly channel
if (diffBetween >= 0 && diffBetween < currentChannelMax) { //If we are before the last poly channel
pan += inputs[PAN_CV1_INPUT + activePanChannel[i]].getPolyVoltage(diffBetween) / 5.f;
}
}
Expand Down
39 changes: 21 additions & 18 deletions src/Signals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ struct Signals : Module {
bool retriggerToggleProcessed = false;
double displayUpdateTime = 0.1;
double timeSinceLastUpdate = 0.0;
float scopeInput[6] = {0.0f};
int scopeChannels[6] = {0}; // Number of polyphonic channels for Scope inputs
int activeScopeChannel[6] = {-1}; // Stores the number of the previous active channel for the Scope
float scopeInput[6] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
int scopeChannels[6] = {0, 0, 0, 0, 0, 0}; // Number of polyphonic channels for Scope inputs
int activeScopeChannel[6] = {-1, -1, -1, -1, -1, -1}; // Stores the number of the previous active channel for the Scope


FramebufferWidget* fbWidget = nullptr;
Expand Down Expand Up @@ -107,16 +107,16 @@ struct Signals : Module {

// Scan all inputs to determine the polyphony
for (int i = 0; i < 6; i++) {
scopeChannels[i] = 0; // Number of polyphonic channels for Scope inputs
activeScopeChannel[i] = -1; // Stores the number of the previous active channel for the Scope
scopeChannels[i] = 0; // Reset number of polyphonic channels
activeScopeChannel[i] = -1; // Reset active channel

// Update the Scope channels
if (inputs[ENV1_INPUT + i].isConnected()) {
scopeChannels[i] = inputs[ENV1_INPUT + i].getChannels();
activeScopeChannel[i] = i;
} else if (i > 0 && activeScopeChannel[i-1] != -1) {
// Use >= to carry over the active polyphonic channel correctly
if (scopeChannels[activeScopeChannel[i-1]] >= (i - activeScopeChannel[i-1])) {
// Ensure that the previous channel has enough poly channels to cover the current index
if (scopeChannels[activeScopeChannel[i-1]] > (i - activeScopeChannel[i-1])) {
activeScopeChannel[i] = activeScopeChannel[i-1]; // Carry over the active channel
} else {
activeScopeChannel[i] = -1; // No valid polyphonic channel to carry over
Expand All @@ -125,7 +125,6 @@ struct Signals : Module {
activeScopeChannel[i] = -1; // Explicitly reset if not connected
}
}

for (int i = 0; i < 6; ++i) { //for the 6 wave inputs


Expand Down Expand Up @@ -178,7 +177,7 @@ struct Signals : Module {
lastInputs[i] = scopeInput[i];
lastTriggerTime[i] = 0.0f;
}

}

if (params[TRIGGER_ON_PARAM].getValue() > 0.5f && !retriggerToggleProcessed) {
Expand Down Expand Up @@ -233,42 +232,46 @@ struct WaveformDisplay : TransparentWidget {

void drawWaveform(const DrawArgs& args) {
if (!module) return;

const auto& buffer = module->envelopeBuffers[channelId];
float range = pow(module->params[Signals::RANGE_PARAM].getValue(),3.0f) / (MAX_TIME / module->currentTimeSetting);

float range = pow(module->params[Signals::RANGE_PARAM].getValue(), 3.0f) / (MAX_TIME / module->currentTimeSetting);
int displaySamples = 1024;
std::vector<Vec> points;

float firstSampleY = box.size.y;
if ((module->activeScopeChannel[channelId] > -1) && !buffer.empty()) {
firstSampleY = box.size.y * (1.0f - (buffer.front() / 15.0f));
}

points.push_back(Vec(0, box.size.y));
points.push_back(Vec(0, firstSampleY));

for (int i = 0; i < displaySamples; ++i) {
// Ensure bufferIndex does not exceed buffer.size() - 1
int bufferIndex = int(i * ((buffer.size() - 1) * range + 1) / (displaySamples - 1));
bufferIndex = clamp(bufferIndex, 0, buffer.size() - 1);

float x = (static_cast<float>(i) / (displaySamples - 1)) * box.size.x;
float y = box.size.y;
if ((module->activeScopeChannel[channelId] > -1 )) {
y = box.size.y * (1.0f - (buffer[bufferIndex] / 15.0f));
}
points.push_back(Vec(x, y));
}

//draw the wave
// Draw the waveform
nvgBeginPath(args.vg);
nvgStrokeWidth(args.vg, 2.0f);
nvgStrokeColor(args.vg, waveformColor);
nvgMoveTo(args.vg, points[0].x, points[0].y);
for (size_t i = 0; i < points.size()-1; ++i) {
for (size_t i = 1; i < points.size(); ++i) { // Start from 1 to avoid duplicating the first point
nvgLineTo(args.vg, points[i].x, points[i].y);
}
nvgStroke(args.vg);
}


void drawLayer(const DrawArgs& args, int layer) override {
if (layer == 1) {
drawWaveform(args);
Expand Down
5 changes: 3 additions & 2 deletions src/StepWave.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "rack.hpp"
#include "plugin.hpp"
using namespace rack;
#include <cmath>

template<typename T, size_t Size>
class CircularBuffer {
Expand Down Expand Up @@ -85,7 +86,7 @@ struct DiscreteRoundBlackKnob : RoundBlackKnob {
float rawValue = paramQuantity->getValue();

// Round the value to the nearest integer
float discreteValue = round(rawValue);
float discreteValue = std::roundf(rawValue);

// Set the snapped value
paramQuantity->setValue(discreteValue);
Expand Down Expand Up @@ -910,7 +911,7 @@ struct StepWave : Module {
}

if (quantizeCVOut){
slewedVoltage[j] = round(slewedVoltage[j]*12.f)/12.f;
slewedVoltage[j] = std::roundf(slewedVoltage[j]*12.f)/12.f;
}

//Main Gate Output
Expand Down
Loading

0 comments on commit 903a25b

Please sign in to comment.