You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Most VCOs in VCV will produce bothersome clicks and pops when modulating the pulse width because they used the Fundemental VCO as a reference. The developer of Slime Child Audio found the solution to this issue:
From Slime Child Audio:
VCV VCO’s MinBLEP implementation will sometimes insert a second discontinuity immediately after the first, which results in a pop. Many developers–myself included–have used that implementation as reference, and have inadvertently duplicated the bug, which is why you’re seeing it in other modules too.
The fix is pretty simple: only insert discontinuities for the single sample where the pre-antialiased value has changed (e.g. the exact sample where the value jumps from -1 → +1 or +1 → -1).
Sample SIMD implementation:
// ...
// Calculate waveform
value = rack::simd::ifelse(_phase < _width, 1.0f, -1.0f);
// Check for discontinuity
int change_mask = rack::simd::movemask(value != _last);
_last = value;
if (change_mask != 0) {
// Insert discontinuity where phase crosses 0
rack::simd::float_4 zero_cross = (delta_phase - _phase) / delta_phase;
int zero_mask = change_mask & rack::simd::movemask((0.0f < zero_cross) & (zero_cross <= 1.0f));
if (zero_mask) {
for (int i = 0; i < channels; i++) {
if (zero_mask & (1 << i)) {
rack::simd::float_4 mask = rack::simd::movemaskInverserack::simd::float_4(1 << i);
float p = zero_cross[i] - 1.0f;
rack::simd::float_4 x = mask & static_castrack::simd::float_4(2.0f);
_minblep_generator.insertDiscontinuity(p, x);
}
}
}
// Insert discontinuity where phase crosses pulse width
rack::simd::float_4 pulse_cross = (_width - (_phase - delta_phase)) / delta_phase;
int pulse_mask = change_mask & rack::simd::movemask((0.0f < pulse_cross) & (pulse_cross <= 1.0f));
pulse_mask = pulse_mask & ~zero_mask; // Don't double-insert! This is probably overkill but it's cheap
if (pulse_mask) {
for (int i = 0; i < channels; i++) {
if (pulse_mask & (1 << i)) {
rack::simd::float_4 mask = rack::simd::movemaskInverse<rack::simd::float_4>(1 << i);
float p = pulse_cross[i] - 1.0f;
rack::simd::float_4 x = mask & static_cast<rack::simd::float_4>(-2.0f);
_minblep_generator.insertDiscontinuity(p, x);
}
}
}
}
// Add MinBLEP result
value += _minblep_generator.process();
Most VCOs in VCV will produce bothersome clicks and pops when modulating the pulse width because they used the Fundemental VCO as a reference. The developer of Slime Child Audio found the solution to this issue:
https://community.vcvrack.com/t/clicks-and-pops-from-pwm/15824/5
From Slime Child Audio:
VCV VCO’s MinBLEP implementation will sometimes insert a second discontinuity immediately after the first, which results in a pop. Many developers–myself included–have used that implementation as reference, and have inadvertently duplicated the bug, which is why you’re seeing it in other modules too.
The fix is pretty simple: only insert discontinuities for the single sample where the pre-antialiased value has changed (e.g. the exact sample where the value jumps from -1 → +1 or +1 → -1).
Sample SIMD implementation:
// ...
// Calculate waveform
value = rack::simd::ifelse(_phase < _width, 1.0f, -1.0f);
// Check for discontinuity
int change_mask = rack::simd::movemask(value != _last);
_last = value;
if (change_mask != 0) {
// Insert discontinuity where phase crosses 0
rack::simd::float_4 zero_cross = (delta_phase - _phase) / delta_phase;
int zero_mask = change_mask & rack::simd::movemask((0.0f < zero_cross) & (zero_cross <= 1.0f));
if (zero_mask) {
for (int i = 0; i < channels; i++) {
if (zero_mask & (1 << i)) {
rack::simd::float_4 mask = rack::simd::movemaskInverserack::simd::float_4(1 << i);
float p = zero_cross[i] - 1.0f;
rack::simd::float_4 x = mask & static_castrack::simd::float_4(2.0f);
_minblep_generator.insertDiscontinuity(p, x);
}
}
}
}
// Add MinBLEP result
value += _minblep_generator.process();
// ...
See attachment:
minblep_diff.txt
The text was updated successfully, but these errors were encountered: