Efficient way of generating sine tones with code?
Hi,
I am trying to generate a lot of sine tones (about 16 000 of them) to generate controlled versions of pseudorandom noise.
I want to do this using some kind of "for loop" to generate a chosen number of sine tones and controlling their frequency and phase algorithmically.
I have sort of managed to do this in gen~ just by adding sines together, but the problem is that this calculation then takes place during each sample and that eats so much CPU so about 120 sines is all that I can manage before the CPU is maxed out!
How can I do this in code so that I just initiate the signal generators ONCE, give them properties in the for loop and then just keep them playing instead of trying to generate them all over again on each sample in gen~?
Additive synthesis of 16k waves is going to be a lot more difficult than subtractive synthesis of white or pink noise.
if you wanted to have that many oscillators at randomized frequencies, amplitudes and phases, you'd need to precalculate a wavetable that, in order to avoid discontinuities, would be so long it would have a latency that would defeat the purpose of the exercise; the only thing you can do is what you're attempting to do now in gen~, or perhaps use oscbank~ if that is suitable
At the risk of revealing my own ignorance, is this a job for fft? I mean, pull a load of sine tones out of a rich sound source, and then manipulated their individual phases etc? Still, 16,000 though ;(
What I do know is that gen~ is 'always on', calculating every sample, so probably unsuited to what you need.
Brendan
Hi,
Thanks for the answers!
I guess I could do some things with FFT, but my application is a little specific and hard to explain, but I have my reasons for wanting to use discrete sines to generate my sound / noise.
16 000 is not an absolute requirement, if I get to around 2000 discrete tones then I would be quite happy.
Is there any way of having part of the gen~ code executing only when a variable have been changed and not on every sample?
Is there a way to use Java script or some of the Java related objects in Max to use code to generate sine waves dynamically?
//Jonatan
Sounds like you have a job for [poly~]. The max number of voices is 1023, so you'll need several [poly~] objects for several thousand sines.
there's no point in reinventing the wheel-- why not use oscbank~, in conjunction with jfc's suggestion to have poly~? gen~ is always 'on'-- it needs to GENerate the audio if you are using it for every sample otherwise you would get silence.
the only way you can "stop" calculations is if you precalculate the audio and then play it back from a buffer-- but then it is no longer dynamic. so the way you've framed the question indicates your needs are contradictory
here's a patch with 500 discrete oscillators which vary freq and amplitude continuously. you can use multisliders to control manually or randomize with metro. you can change 'fundamental" frequency in Hz and range of frequencies in octaves. it only uses 8% cpu on my old laptop, so 2000 or more is easily done-- adapted from ioscbank~ help file
if you dont need to modulate it, why not generate a wavetable offline and write in in a 10000 ms buffer?
If the frequencies are held constant, the suggestion of using the inverse Fourier transform seems spot on. The fourier domain is based on the notion of a signal being made up of a potentially unlimited number of constant sinewaves. A good engineering challenge!
There's also many cheap approximations of sine waves out there, but it's hard to beat a wavetable in practice. And anything over 1000 voices is going to really hammer the audio thread.
Thanks a lot for the help!
ioscbank~seems to be spot on!
But the help file for this object seemed very limited to me.
Can someone explain a little bit more about how it works?
For example if I want to change all 500 oscillator frequencies at the same time, is that possible or is it some sort of shift register where each value is read and executed in order?
Can I also change number of oscillators on the fly and adjust volume individually?
What I mean is that all these things seem possible, I just don't understand how to do it right now...
did you download my patch? you can change the amplitude and frequency of each oscillator individually and simultaneously, as illustrated.
the number of oscillators is fixed at instantiation, but you can always set the amplitude to zero to turn off an oscillator. you just send messages to the object in the correct format, as shown in the help file
Ok, I will dig deeper into this, my new favorite object after some sleep!
Thanks agin for the help!
Floating Point's patch is great!
I tested it with 2000 oscillators, it seems to work quite well. Here is a version with matrices instead of lists to generate the frequency/amplitude pairs.
You don't even need [poly~] to manage CPU usage: the 'clear' object even takes care of reducing the processing power inside [ioscbank~], that's quite nice.
nice, Jean-Francois, and I like the zombie partials moving around in the spectroscope display-- and if you put a jit.bsort just before your jit.multiplex (freq input) the frequency wandering is constrained somewhat. yes, the clear message is a good feature for minimizing cpu
Interesting, indeed, and we can adjust in a way the amount of wandering using the maxiter attribute for [jit.bsort]. Adding sines sounds like a boring exercise, but I still find the sound of this patch quite interesting, and with potential for more refinements!
years ago I made a supercollider patch to use as a class demonstration on audio perception, which explored the three continua between harmonicityinharmonicity, noisinesspurity, and dullnessbrightness, each of which contribute to the sense of pitch and pitch discrimination, which was based on, in part, the arrangement of sine waves and their relation to each other-- this patch reminds me of it-- maybe I should try to reimplement it in max....
(Aaargh, guys yer killin me here; MaxMSP envy = 100%)
Floating Point; it would be very nice to see that patch actually.
I am working on a few different things all on the same topic of multiple sines.
One thing is to do a measurement system with exact sines to reduce the need of windowing in FFT and increase speed and accuracy with reduced side lobes if only one frequency present exactly in the middle of every FFT bin.
Then I have an idea for a "shepards tone" (https://www.youtube.com/watch?v=BzNzgsAE4F0) oscillator and also variants of sort of a "shepards noise" kind of thing.
Also additive synthesis in the extreme seems to have some real potential, and as you write to separate non-harmonic and odd/even harmonics could also make a very nice algorithmic oscillator.