Additive synthesis help


    Oct 17 2016 | 3:42 pm
    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.
    FIRST PATCH:
    SECOND PATCH:

    • Oct 17 2016 | 8:55 pm
      It isn't clicking for me. Something about your audio settings? ...?
    • Oct 17 2016 | 10: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 | 7:55 am
      Sorry, no clicking here either (in the first example). Very nice patch btw
      Brendan
    • Oct 18 2016 | 8:23 am
      Exactly. I like your first patch, and it doesn't click.
    • Oct 19 2016 | 3:33 pm
      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 | 4:44 pm
      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 | 7: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.
    • Oct 20 2016 | 3:41 pm
      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?