Forums > Gen

Additive synthesis help

Oct 17 2016 | 8:42 am

Hello everyone,
I am trying to build a simple additive synthesis oscillator inside gen. My code relies around the presence of a for loop that loops around for the number of the harmonics of the oscillator to output the final result. I am trying to control the amplitude of each partial from outside gen by using a buffer whose length in sample is equal to the number of harmonics . The amplitude values are recorded with a multislider + poke combo. This way I can just access the amplitude of each partial by peeking it inside the for loop. The only problem that I am having right now is that when I move the multislider, and therefore updating the amplitude values, I hear clicks. This happens because I would need some kind of interpolation between successive values of the same amplitude, but I can’t seem to solve this problem inside the for loop. Does anyone know how could I solve this? I attach two patches: the first one is the one with the problem, while the second one is a not so efficient solution using the data object and storing the values of all the partials at any time, regardless the number of harmonics of the oscillator.


— Pasted Max Patch, click to expand. —


-- Pasted Max Patch, click to expand. --

Oct 17 2016 | 1:55 pm

It isn’t clicking for me. Something about your audio settings? …?

Oct 17 2016 | 3:03 pm

Is the first patch not clicking when you move the multisliders, especially when jumping between values? The second patch is not supposed to be clicking, it is a solution that I came up with, but it is quite inefficient.

Oct 18 2016 | 12:55 am

Sorry, no clicking here either (in the first example). Very nice patch btw


Oct 18 2016 | 1:23 am

Exactly. I like your first patch, and it doesn’t click.

Oct 19 2016 | 8:33 am

Couple of other options:
You can also use ioscbank~, which allows you to do interpolation on the gain.

Also, poly~, where each voice is a cycle~ and the fundamental frequency comes in via in~ can also work well. If phase correlation is important, you can send in an unwrapped phasor~-like signal into the right inlet of cycle~ 0. (Driving it with a continuous phase change rather than a frequency)

You’d build that with something like sig~ 440 into !/~ 1. into +=~ into poly~. It’s a more exotic solution, but works well when you need to model something that is synchronous. I use it, for example, to model the driveshaft of a Hammond organ.

Oct 19 2016 | 9:44 am

Hi Peter,
I tried the poly~ approach by using a combination of phasor~ and rate~ to scale the frequency of each partial, but, even is it was sounding correct, I noticed that phases were not correlated when checking it on a scope~.
I need to try the your last suggestion, though.
The only problem that I would have is that I would need to set the number of partials beforehand as instances of the poly~, while I wanted to have a parameter to dynamically control it, as I tried to achieve in the gen~ example. I could maybe set a high number of poly~ instances and just handle the partials that I need by muting the voices that I don’t need inside poly~. I’ll investigate further, thanks a lot for the suggestions.

Oct 19 2016 | 12:49 pm

Hi Francesco,

Yeah, rate~ will probably not work for this, but the unwrapped phasor should. Here’s a couple of tweaks to the code you posted. I’ve added interpolation via vectral~. It’s not perfect, but it eliminates most zipper noise. I also added stretch tuning as an option. I’m not 100% that this is the best way of implementing it–if anything, you’d be better off doing the math inside of a JS object since it’s numbers are 64-bit and this extra precision is helpful when summing up a bunch of numbers. This will make zipper noise when you’re adjusting the stretch factor; you could prevent that by giving each overtone its own phasor, but that adds overhead.

— Pasted Max Patch, click to expand. —
Oct 20 2016 | 8:41 am

Thank you a lot for your solution, Peter.
I have never used the vectral~ object before, but it looks like it could be the solution to my problem. If I understood its use correctly, is it basically doing a filtering (in this case a rampsmooth) entry by entry on an array of values? I see on the help file that it is mostly used for FFT envelope following as a kind of spectral rampsmooth~ , is it correct?

Viewing 9 posts - 1 through 9 (of 9 total)

Forums > Gen