Vibe Coding Log - Sharing Journey - Demo of Smaller Spinoff (Unique Time Based Synth - Grossbeat Like)

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS

Post

Touch The Universe wrote: Tue Jun 09, 2026 7:59 am What could be causing this weird release behavior? Sounds like gating?
Not having seen that video, not knowing what the code looks like, I'm confident that automated tests could have caught that. Then you can fix problems as they surface, and be assured the whole big bowl of mud still behaves as expected with every small change.
Automated testing is a good industry-standard software engineering practice. It takes an investment to implement, an investment that will pay itself back. Just saying...
We are the KVR collective. Resistance is futile. You will be assimilated. Image
My MusicCalc is served over https!!

Post

BertKoor wrote: Tue Jun 09, 2026 11:06 am
Touch The Universe wrote: Tue Jun 09, 2026 7:59 am What could be causing this weird release behavior? Sounds like gating?
Not having seen that video, not knowing what the code looks like, I'm confident that automated tests could have caught that. Then you can fix problems as they surface, and be assured the whole big bowl of mud still behaves as expected with every small change.
Automated testing is a good industry-standard software engineering practice. It takes an investment to implement, an investment that will pay itself back. Just saying...
Not even sure what you are refering to. Im still on this little bug after more passes then I care to share. I'm here atm. I'll look up what you are refering to.




Ran 27 commands
Now I have the complete picture. Let me synthesize everything I found:


Ran 4 commands
Ran 4 commands
Now I have everything needed. Here is the complete analysis:

Root cause found
The choke/gate is caused by three independent problems stacking in the shared Filter 1 path. None of them exists in Vital's self-contained per-voice SVF path.

Problem 1 — The audio entering Filter 1 is already amplitude-gated by selectedAmpGain
Signal chain with Shared mode + Filter 1:

vitalL (raw oscillator)
→ voiceL += vitalL [no amp yet — line 15003]
→ voiceL *= finalVoiceAmpGain [= selectedAmpGain = Amp1/4 envelope × velocity]
→ mixedL
→ left = mixedL * masterGain
→ filter rawL = left [Filter 1 reads this]
→ f1L = processFilter(rawL)
→ finalL = f1L * outputGain
The amplitude envelope selectedAmpGain is multiplied in before Filter 1 processes the audio. When the amp envelope releases (decays to zero), the signal feeding Filter 1 goes to zero — even if the filter cutoff is still open. This is amplitude gating masquerading as a filter gate.

With Self Amp + Filter1 mode:

vitalL
→ voiceL += vitalL * vitalSelfAmpGain [VA envelope gates here instead]
→ voiceL *= 1.0f [finalVoiceAmpGain bypassed — line 16785]
→ passes through Filter 1
finalVoiceAmpGain is forced to 1.0f because vitalSelfAmpOwnsTail = true. So the VA envelope gates the signal cleanly per-voice, and Amp 1/4 can't choke it after the fact.

Problem 2 — sharedFilterEnvBlock uses jmax accumulation, making it track the "loudest" voice's envelope
cpp
sharedFilterEnvBlock = juce::jmax(sharedFilterEnvBlock, filterEnvForSharedBridge);
This is a shared single-voice accumulator for a polyphonic instrument. When you play two notes and release one, the surviving note's filter envelope keeps Filter 1 open. When the last voice releases, the envelope falls from some non-neutral level toward 0, passing through applyFilterEnvRange which interprets envLevel=0.0 as maximum negative mod relative to the 0.5 center.

In applyFilterEnvRange:

cpp
const float bipolarEnv = (envLevel - 0.5f) * 2.0f; // 0.0 → bipolarEnv = -1.0
So sharedFilterEnv = 0.0 → bipolarEnv = -1.0 → cutoff modulation is maximum negative — the filter closes as hard as the env amount and range allow. With high env amount and positive polarity, a decaying env approaching 0 pulls the cutoff sharply downward during release, acting like an amplitude gate.

In the Vital per-voice SVF path, the envelope is unipolar [0..1] applied multiplicatively to octave offset. envLevel = 0.0 simply means 0 octaves of modulation — it returns to baseCutoff. The filter cannot be closed below base cutoff by a decaying envelope. There is no such symmetry break.

Problem 3 — No per-sample smoothing on Filter 1 cutoff at the shared filter section level
The Vital SVF path has an explicit declick smoother on the envelope modulation signal:

cpp
const float smoothMs = 0.20f + declick * declick * 64.0f;
const float coeff = std::exp(-1.0f / (sampleRateHz * smoothMs * 0.001f));
voice.oscVitalFilterEnvSmoothed += (envShaped - voice.oscVitalFilterEnvSmoothed) * (1.0f - coeff);
The shared Filter 1 section receives sharedFilterEnvBlock and immediately passes it to applyFilterEnvRange with no smoothing. Large envelope drops (end of release) produce instant per-sample cutoff jumps across many octaves. At IIR filter cutoffs that jump discontinuously, this causes output transients that sound like a hard gate click.

Answering your specific questions
1. Where exactly does Filter 1 differ from Vital's self-contained VCF/SVF path?

Vital SVF Shared Filter 1
Amp gate before DSP vitalSelfAmpGain (VA env), OR nothing if Self Amp + Filter1 routes selectedAmpGain (Amp1/4 env) gates audio before filter reads it
Envelope modulation center Unipolar [0..1], env=0 = base cutoff, cannot go below base Bipolar [0.5=center], env=0 = max negative mod, can close far below base
Envelope accumulation Per-voice, voice-owned ADSR instance jmax across all voices into one shared block
Cutoff smoothing Optional declick one-pole per voice None at the shared filter section
Voice lifetime Vital local ADSR owns tail releaseCleanupEnv can kill voice before filter tail finishes
2. Is Filter 1 envelope modulating output gain, not just cutoff?

Yes, indirectly. selectedAmpGain multiplies the audio before Filter 1 receives it (line ~16787–16789 → voiceL *= finalVoiceAmpGain → left → rawL). So the amp envelope is effectively a pre-filter gain gate. When selectedAmpGain reaches zero, Filter 1 receives silence regardless of cutoff.

3. Is Filter 1 output multiplied by Amp 1 / selectedAmpGain after the local Vital amp?

Not directly post-filter — but the pre-filter multiplication achieves the same effect. outputGain at line 17862 (finalL = outL * outputGain) is the FILTER OUTPUT knob, not an ADSR, so it doesn't choke.

4. Is there code that clears, zeros, or kills filter output during release?

Yes — two places:

voiceL *= finalVoiceAmpGain (Amp 1/4 going to zero) starves Filter 1 of input
The releaseCleanup check at line 8909 can kill the voice (voice.active = false) while the filter's internal delay-line state still has energy. The filter state is not cleared, so on the next note the old tail may bleed through briefly
5. Is the Filter 1 envelope bipolar/centered in a way that closes the filter below base cutoff?

Yes. This is the central bug. applyFilterEnvRange converts envLevel to bipolar around 0.5. An envelope decaying toward 0 produces bipolarEnv = -1.0, which with positive amt still results in sign = -1, closing the filter. The Vital SVF env is unipolar and cannot produce this behavior.

6. Does the filter path have smoothing comparable to Vital VCF?

No. Vital SVF has per-voice declick smoothing on the envelope modulation. The shared Filter 1 section applies sharedFilterEnvBlock directly each sample without smoothing.

7. Minimal patch to make Filter 1 behave cleanly without full refactor?

Three targeted changes:

cpp
// PATCH A — In applyFilterEnvRange: treat env=0 as neutral (don't close below base).
// Change the bipolar center so a decaying envelope closes toward base, not below.
// Replace:
const float bipolarEnv = juce::jlimit(-1.0f, 1.0f, (envLevel - 0.5f) * 2.0f);
// With (unipolar: 0=base, 1=max open/close):
const float bipolarEnv = juce::jlimit(-1.0f, 1.0f, (envLevel * 2.0f - 1.0f) * amt >= 0.0f ? envLevel : -(1.0f - envLevel));
// Or more simply: use envLevel directly as a unipolar [0..1] depth, same as Vital SVF:
const float depth = std::abs(envLevel) * std::abs(amt);
const float sign = amt >= 0.0f ? 1.0f : -1.0f;
// (drop the bipolar conversion entirely for the shared bridge)
cpp
// PATCH B — Add a one-pole smoother on sharedFilterEnv before applyFilterEnvRange.
// In the filter section loop, add a per-filterState smoothed value:
const float smoothCoeff = std::exp(-1.0f / (sampleRateHz * 0.005f)); // ~5ms
st.sharedFilterEnvSmoothed = st.sharedFilterEnvSmoothed * smoothCoeff
+ sharedFilterEnv * (1.0f - smoothCoeff);
const float smoothedEnvForFilter = st.sharedFilterEnvSmoothed;
// Use smoothedEnvForFilter in place of sharedFilterEnv in applyFilterEnvRange calls.
cpp
// PATCH C — In Shared mode with oscVitalRouteFilter1, apply finalVoiceAmpGain
// AFTER the filter section rather than before, so the amp envelope cannot
// pre-starve Filter 1. This is effectively what Self Amp + Filter1 already does,
// just with selectedAmpGain instead of vitalSelfAmpGain.
// The cleanest version: when Vital is in Shared mode routed through Filter 1,
// treat it the same as Self Amp + Filter1 — move the amp gate post-filter.
Patch A removes the bipolar behavior that closes the filter past base during release. Patch B removes the cutoff jump clicks. Patch C removes the pre-filter amplitude starvation. Together they make the shared Filter 1 path behave like the Vital per-voice SVF path without touching the polyphony architecture.





EDIT - THIS WAS NOT THE SOLUTION

TRASNFERING THE FILTER 1 MENU INTO A PARELLE FILTER/ENV SYSTEM THAT IS CLEAN
100 High Quality Soundsets: Omnisphere 2, Dune 3, Tone 2 Synths, Pigments, Uhe Synths, Halion, Spire, and others.

TTU Youtube

Post

Touch The Universe wrote: Tue Jun 09, 2026 7:59 am Hoping to get some help. What could be causing this weird release behavior? Sounds like gating? Then I switch to an osc that has its own ADSR and its the normal release behavior.
Asking Urs to fix the monstrosity is not vibe coding :D

Post

at first it's weird or even awkward, then it gets better, then "OMG I LOVE THIS, I'M THE KING OF THE WORLD"
and then things go downward

where else have i seen this sort of pattern

but more seriously
before i could write C++, i found a modular "visual-programming" environment that can make synthesizers and effects called SynthEdit (who doesn't know it)
after i figured out what's going on i began making a "huge MONSTER monosynth" (literally i called it "monster", it didn't have a name chosen yet but this hinted at the goal, it had to have EVERYTHING you might want in a monosynth)

i was similarly euphoric and happy as what you can see in the early pages here
then progress kinda collided with a wall
some things were too complex to be done with normal modules (too much overhead piles up or something) and were much better to be done in a custom module...
other things turned into just dumb ideas that only sounded good as an idea but evil ugly problems come out when you get to the actual details (which you don't do when you're just dreaming and everything looks wonderful, and the path from A to B is a straight line)

i went to the forums and mailing lists where the module developers were "hiding" (actually they were discussing developement).
so i go there with my much-more-broken-than-now engrish and ask for a custom module that does this and this and that but in a certain way (i don't know how but you'll figure it out)... <crickets.wav>
reality struck when i was just told "look dude, no one in here has the free time to make a custom module for you, so download the SDK and write one yourself, like we all do here", and when i told them "but i don't know C++" - "then learn it"

anyway, some of the important lessons i've learned the hard way is...
if something is very big (maybe even if it isn't), you should make a plan, this can even be just a plain-text file
write everything then look for potential problems in the plan (put on your pessimistic critique hat and try to find areas where this optimistic dude will fail)
in this process the plan will probably morph, and if you're lucky you might end up with a very detailed and maybe realistic plan which can actually be used to develope/build something!

and a tip - don't try to put everything in a synth, or at least not in your very very first synth
instead, make something that might have a more limited usage, but it does what it does well
a smaller synth will have less places for bugs to hide, and will be easier to test and debug
It doesn't matter how it sounds..
..as long as it has BASS and it's LOUD!

irc.libera.chat >>> #kvr

Post

Lol, yeah dude, sounds exactly like me, haha, though it seems you gave more effort, and not a full hack.

This journey is as you said, full of highs, going from a to b in ideas, then hitting snags here are there, then jumping for joy that it is solved, only to see that the solution broke things or caused more problems, and even though the solution seemingly worked but took even a day, it turns out that itself was just a short cut and the real solutions is much longer -- and TROUBLESHOOTIN what the issue even is itself takes up most of the time. I gave up on finding it so I'm rebuilding it within the thing. Once a replace is found I can take away the older bit of code. That's the plan atleast.

Planning of course is a good idea, but sometimes you don't know what to plan for, so learning is absolutely required, though it's quite motivating because you can instantly put to use what you are learning. I have no problems spending a whole day learning on reverbs are formed if that means I can put it to use. In the real world, it't take months to apply it.

The monster synth is the only thing that excited me at the moment, so compelled to finish it. It's sounding amazing, whenever i find time to sound design in it, so i have by no means lost interest. Though I'm hesitant to throw larger ideas into it at this point. I have 3 spin off ideas I will try to release on there own. I will have a demo to share with everyone in a bit, just need to learn how make something a "demo".
100 High Quality Soundsets: Omnisphere 2, Dune 3, Tone 2 Synths, Pigments, Uhe Synths, Halion, Spire, and others.

TTU Youtube

Post

BertKoor wrote: Tue Jun 09, 2026 11:06 am
Touch The Universe wrote: Tue Jun 09, 2026 7:59 am What could be causing this weird release behavior? Sounds like gating?
Not having seen that video, not knowing what the code looks like, I'm confident that automated tests could have caught that. Then you can fix problems as they surface, and be assured the whole big bowl of mud still behaves as expected with every small change.
Automated testing is a good industry-standard software engineering practice. It takes an investment to implement, an investment that will pay itself back. Just saying...
This has piqued my interest, but what is it?
100 High Quality Soundsets: Omnisphere 2, Dune 3, Tone 2 Synths, Pigments, Uhe Synths, Halion, Spire, and others.

TTU Youtube

Post

Here is a demo of Focus Time - Mac only for now, can upload a windows version when i create the dll.

https://drive.google.com/file/d/15Pt-v5 ... sp=sharing

Two week trial, 20 minutes cutoff, can save presets.

Screenshot 2026-06-09 at 5.07.01 PM.jpg
You do not have the required permissions to view the files attached to this post.
100 High Quality Soundsets: Omnisphere 2, Dune 3, Tone 2 Synths, Pigments, Uhe Synths, Halion, Spire, and others.

TTU Youtube

Post

From what you said ( "release" ) I understood an envelope generator is misbehaving. You probably already had a working EG / ADSR in the first week.

When I build a component, I write test code as well which asserts the component behaves the way I expect it to behave. These tests also serve as examples how the component should be used by surrounding code. The build script (ci pipeline) writes a report how much of the code is tested. Over 90% is hard, that last 10% is difficult and expensive. And writing good tests is sort of an art of its own.

I have found that by writing tests the quality of my code designs has improved. All sorts of anti-patterns (bad practices) will surface when you try to test pieces of code in isolation. You need to think harder about responsibilities of the code: which part does what, how should it cooperate.

When I find a bug while testing manually, I try to write a test which reproduces the bug. That test initially fails. Then I try to fix the bug: its test should succeed, and all other tests should still succeed as well. This is to stop regression (which is progression in the wrong direction)

If you don't start with test automation at the very beginning, then it's probably too late. Also my experience: nothing wring with throwing all away and starting fresh. But better. You did it before, you can do it again. But better. Because you have learned from mistakes.
We are the KVR collective. Resistance is futile. You will be assimilated. Image
My MusicCalc is served over https!!

Post

Demo? You're actually going to sell it?! Wish I had that kinda hard neck.
.................................
"Hell is other People" J.P.Sartre
.................................

Post

Karbon L. Forms wrote: Tue Jun 09, 2026 9:31 pm Demo? You're actually going to sell it?! Wish I had that kinda hard neck.
one-milliondollars-dr-evil.gif


Im unashamedly willing to for the amount of time and work I'm pooring into this. If you want it free, steal the idea and build it yourself. After a few days, you might think differently, or maybe not.

Won't be crazy, like $9-$19

I might even throw in a soundbank or two to sweeten the deal.

Or maybe, I'll change my mind and insert it into the kvr dev challenge. That's probably more likely. Maybe have it mono, then a paid version for stereo? I'm not sure if the rules allow that, probably not.

By yeah man, if some people are low on luck, I'd be willing to send it there way. For customers I know, good ones, I'd off course be willing to give for free for thanks for previous support.
You do not have the required permissions to view the files attached to this post.
Last edited by Touch The Universe on Tue Jun 09, 2026 9:52 pm, edited 1 time in total.
100 High Quality Soundsets: Omnisphere 2, Dune 3, Tone 2 Synths, Pigments, Uhe Synths, Halion, Spire, and others.

TTU Youtube

Post

Some would argue vibe coding is a bit like punk rock. you didn't need to be a good musician (although many where) you just needed the ideas.

A major dev once said to me "what makes you think you have more ideas then me" my reply "well you have not added it yet". they never did.

If vibe coding (or whatever you want to call it) helps you create the tools you always wanted and ultimately gives you more time to be creative then what's the issue.

peace out.

Post

topaz wrote: Tue Jun 09, 2026 9:43 pm Some would argue vibe coding is a bit like punk rock. you didn't need to be a good musician (although many where) you just needed the ideas.

A major dev once said to me "what makes you think you have more ideas then me" my reply "well you have not added it yet". they never did.

If vibe coding (or whatever you want to call it) helps you create the tools you always wanted and ultimately gives you more time to be creative then what's the issue.

peace out.
It's actually a thing that a founder of a company made up to pump up his valuation and create a media narrative. Hardly punk rock.
REAPER + Davinci Resolve Pro on Manjaro KDE. Neve 88m. Focusrite 18i20 2nd gen. Neumann NDH30 headphones. Mics: Telefunken TF39, AT4050, Miktek C7e, EV RE-15. VSTs: u-he Hive 2, F'em, Renoise Redux, Apisonic Speedrum 2.

Post

I'm still adding to it, the harmonic generator will have these functions.....sample-excited polyphonic harmonic/modal resynthesis with curve based harmonic genesis, lol. i made that last part up.

Here is the simple version with no excitation...




In some ways, I feel ideas themselves, even when implemented aren't as tedious as real coding (while also lacking the joy associated with that too - and the headache), are worth something, if even peanuts. Lots of plugs, but how many creative ones come around that are exciting results. I know that relative, but nonetheless.
100 High Quality Soundsets: Omnisphere 2, Dune 3, Tone 2 Synths, Pigments, Uhe Synths, Halion, Spire, and others.

TTU Youtube

Post

Touch The Universe wrote: Tue Jun 09, 2026 9:36 pm
Karbon L. Forms wrote: Tue Jun 09, 2026 9:31 pm Demo? You're actually going to sell it?! Wish I had that kinda hard neck.
one-milliondollars-dr-evil.gif

Im unashamedly willing to for the amount of time and work I'm pooring into this. If you want it free, steal the idea and build it yourself. After a few days, you might think differently, or maybe not.

Won't be crazy, like $9-$19

I might even throw in a soundbank or two to sweeten the deal.

Or maybe, I'll change my mind and insert it into the kvr dev challenge. That's probably more likely. Maybe have it mono, then a paid version for stereo? I'm not sure if the rules allow that, probably not.

By yeah man, if some people are low on luck, I'd be willing to send it there way. For customers I know, good ones, I'd off course be willing to give for free for thanks for previous support.
Bruh, come on...
REAPER + Davinci Resolve Pro on Manjaro KDE. Neve 88m. Focusrite 18i20 2nd gen. Neumann NDH30 headphones. Mics: Telefunken TF39, AT4050, Miktek C7e, EV RE-15. VSTs: u-he Hive 2, F'em, Renoise Redux, Apisonic Speedrum 2.

Post

"work"
REAPER + Davinci Resolve Pro on Manjaro KDE. Neve 88m. Focusrite 18i20 2nd gen. Neumann NDH30 headphones. Mics: Telefunken TF39, AT4050, Miktek C7e, EV RE-15. VSTs: u-he Hive 2, F'em, Renoise Redux, Apisonic Speedrum 2.

Post Reply

Return to “DSP and Plugin Development”