DanT.Synth Noodles

Yeah, I maintain a circular buffer of 1024 samples, but 512 should be fine as well. I also maintain a running total (5 of them actually, Σx, Σx², Σy, Σy² and Σxy) Each sample I subtract the oldest sample value from the accumulators, then store the new sample in its place, and add that to the accumulators. This avoids adding up all 1024 values over and over again.

There is a small but non-zero possibility of a cumulative error building up in the accumulators due to rounding errors, especially if the signal wavelengths are some multiple of the buffer length, so I also maintain a second set of accumulators without the subtract stage, and every 1024 samples I swap in the values from those and reset them to 0. But I think you’d have to run the device for a long time before such compensation is really necessary.

Edit

I suspect I’m doing the same statistical correlation as you, and it can be formulated just using the running totals:

From wikipedia - Correlation and dependence

1 Like

Ok I took a very quick look at your source, seems like we are doing pretty much the same thing, but you have a better way to accumulate the sums.

I think I may have thought the buffer needed to be cleverer that it does, as I originally started with a ring buffer, but changed to the array when I needed the iterators for the accumulator

I should just keep it simple stupid

Thanks for the help, I think I know how to improve the code now, and good to know that, at least in theory, I am doing the right calculation

2 Likes

If anybody was confused by my term pipeline accumulator.

The circular buffer is used as a fifo pipeline. We are not interested in anything inside the pipe, only in what is at the ends.

As stuff goes into the pipe; we add it to the accumulator. We subtract whatever come out of the other end. Hence the accumulator always reflects the sum of the pipe’s contents.

1 Like

Thanks for the clarification, again, I am a C++ novice, but I think generally a FIFO buffer would typically be called a Queue, whereas a pipeline could be confused with |, or file pipes, or function chaining (similar to fluent type implementations).

Which actually does help me a lot…

I believe I could implement a variable window size for my correlation module by simply keeping a running sum, and then each step either;

continue to remove samples from the queue and the sum until the window is reduced to the correct size

or do not remove the sample from the queue or sum and let them fill up to the correct size.

I don’t know where you saw the recommendation of 512 samples, but presumably it is linked to engine sample rate. So a variable length buffer is useful, and I would implement it as you just suggested. Using the queue means that a longer buffer does not increase the workload.

1 Like

Still haven’t got back to my experimental new modules, but I did create this generative patch that I could listen to (and am listening to) for hours and hours…

Getting excited for V2, also picked up the VCV Drums that I am really enjoying…

Hey @carbon14

Just wanted to say thanks again for the help,

I have finally managed to find some time this evening to get back to this code, and using the queue instead of the array accumulate has reduced the CPU of this new module from approximately 2.0% to 0.3% and the variable sized window works perfectly so far

Should be able to have this new module ready to go for the V2 release :grin:

3 Likes
1 Like

Like what this module does to the sound, so how does it work? It really messes with the sound! Luv it V2 maybe worth getting after all.

The module itself does not actually do anything to the sound.

The patch in the video uses the output as a CV signal to modulate the FM input of the Fundamental VCO-2.

The CV signal the module outputs is generated by the correlation between two signals from the VCO-1 modules.

The correlation (or in other words, the relationship) between the two signals is calculated over a variable amount of time (this is called the window) and can be a few to a couple hundred milliseconds.

If the two signals are both trending in the same direction during the window, the output will be from 0 to 5 volts, if the two signals are trending opposite during the window, the output will be from 0 to -5 volts.

In the patch there is also a small modulation of the attenuator and the offset parameters, this causes the output to multiplied (attenuated) by a value and added (offset) to a value.

Due to the cyclical nature of waveforms, as I slightly change the frequencies of the signals, the output changes from a see-saw type output to fast oscillations. And at certain key frequencies, these oscillations have a relationship either back to the input signals, or to the frequency of the VCO-2 which is generating the sound.

Also, not shown in the video, the patch uses some mid-side processing and some delay, just to make the sounds a bit more interesting.

Thanks Dan, so any oscillator would work with this module?

Well it depends on how you employ the module output really, if you want a similar sound then any oscillator with an FM input should be somewhat similar (although the wave shape of the oscillator will have a big impact on the sound).

But you might also use the output to modulate any other parameter for many other effects, such as the frequency or PWM of an oscillator, or the cut-off or resonance of a filter for example. The possibilities are really endless, the joy of modular synthesis…

Also, the two input signals do not have to be from oscillators either, they could be LFOs or noise for example.

New waveshaper module is taking shape

5 Likes

Does this wave-shaper suppress aliasing?

Not currently, the code simply adjusts the input value per sample based on the parameters, not exactly sure how I would implement anti-aliasing in this.

Although it is a feature I could add I suppose… I don’t know, a filter on this module feels like it would remove some of the character.

I believe that it would only add aliasing when the parameters are being modulated. I guess if the input had aliasing then it potentially could enhance or reveal unwanted inharmonics?

Not knowing exactly what this module does, of course I can’t know if it aliases or not. I can tell you that my waves-shaper (“Shaper”), will alias a ton if you turn off the over-sampling.

Oversampling is the brute force, easy way to mitigate aliasing. It works with anything. Line-6 patented it with the original POD, but I think that patent was probably invalid - oversampling to mitigate aliasing in a wave-shaper was well known before that. In any case that patent is from the 90’s iirc.

Here is a short article I wrote on how to evaluate aliasing using free VCV modules: Demo/aliasing2.md at main · squinkylabs/Demo · GitHub

btw, there are many opinions on “how bad” aliasing sounds, or even if it sounds good. I’ve gone on and on about this, but here is my personal opinion on aliasing:

  • One may decide the like or don’t like aliasing, and then act on that.
  • Very few people would choose to add aliasing - most people don’t like the sound.
  • There are many circumstances where it isn’t audible.
  • Adding oversampling can be a lot of work. One might decide that the module is cool as it is, and the extra work to reduce the aliasing isn’t “worth it”.
  • If a module has a manual, and the module can alias a lot, I would recommend mentioning that (although I have only seen that once myself).

btw, once you develop oversampling code you can re-use it all over the place. I use my one resampler in Shaper, Saws, Kitchen Sink, and the ancient Functional VCO-1,

1 Like

I don’t currently have a frequency analyser built for V2, so I can’t test properly…

But, from this crude listening test, it doesn’t seem super bad to me, what do you think? (The bottom right shows what the waveshaper is doing to the triangle wave).

Clone the Bogaudio repo and build it.