Continuous sound synthesizer

I am starting to write a soft synthesizer with a peculiar characteristic: oscillators will have a “continuous wave” knob, which will allow users to consistently choose sinusoidal, square and saw waves. That is, if the handle is completely to the left, the output will be a sine wave, if in the middle it will be a saw blade wave, if all this is to the right, it will be a square wave and then intermediate positions will output waves that are “interpolated” versions of classical waves. - Handle positions and wave types can be changed, but a continuous way to change the waveform is required -

I thought of several ways to implement an oscillator:

  • Invent a function that takes the position of the handle and calculates the spectrum of the actual signal (an array of amplitudes and frequencies), and then uses a bunch of sinusoidal functions and a sum unit to implement the output signal.

  • Similar to 1. but apply the inverse Fourier transform instead of sines and sums (OK, at this point I’m not sure if they are actually the same.)

  • Create a waveform table for each possible pen position and use the wave table synthesis method to generate the output signal.

  • Start with two waves of saw teeth (they contain both even and odd harmonics), invert one and sum them up and control the amplitude of each of them with the handle. Waveform will not

I have a few questions:

but. I read that technique number 1 works very intensively with the processor and is not entirely feasible. Is this true for ARM processors such as iPad to iPad?

Q. Whatever technique I choose, is it possible to solve the smoothing problem by simply connecting a low-pass filter to the output of the generator?

C. Any other suggestion on how to implement such a generator?

Any suggestions on using C ++ toolkit? I watched STK from CCRMA, but I don't know if there are other more suitable libraries.

Wish me good luck!;)

Edit: Someone pointed me to din last night. Bezier curves are another consideration.

+7
source share
4 answers

I'm not sure you are not over complicating this. If I understand correctly, everything you do with a continuous wave knob efficiently mixes different amounts of three waveforms. Thus, simply generate all 3 waveforms all the time, and then sum them together with different amplification factors in accordance with the combination of the described waveforms.

To synthesize a limited waveform to avoid smoothing, you are likely to find most of what you need here .

Hope this helps.

+5
source

Here is the answer for B (Is it possible to solve the smoothing problem by simply connecting a low-pass filter to the output?), Which affects some other points.

Unfortunately, the answer is no. Aliasing is caused by the presence of harmonic frequencies above the Nyquist frequency (i.e., half the sampling frequency). If these harmonics are present in your oscillator shape, filtering cannot help. (Appropriate aggressive filtering will destroy the nature of the waves you generate.) Oversampling (another answer mentions this) may, but it is expensive.

To avoid this, you must generate forms with a limited frequency band. That is, waveforms that do not have harmonics above some selected <Nyquist value. Doing this is non-trivial. This article is worth reading here . There are two established practical approaches to solving this problem: BLIT (Band Limited Impulse Train) and MinBLEP. Both approaches try to smooth out harmonically generating gaps by inserting “material” at the corresponding points on the waveform.

With this in mind, your options begin to decline. Probably the best compromise between lightness and sound will be to generate a series of limited frequency bands. You still need to research some form of smoothing to handle the interpolated waves.

iDevice ARM is quite capable of performing DSP in real time. General tip: write hard code, use the built-in functions, and avoid division. Your rendering cycle will be called 44,100 times per second, so if your code is completed within 1/44100 s (0.023 ms), you will have no problem. In practice, you should be able to run multiple oscillators at the same time without any problems. The presence of all these music apps in the app store testifies to this.

STK is a great built-in library. (The Perry Cook book, “Real-time Sound Sync for Interactive Applications,” is also a good ground and deserves attention.) The STK was not intentionally optimized, although I'm not sure how well it will generate your “continuous” signals, kvraudio.com and musicdsp .org should be on your reading list.

+2
source

The Fourier transform is linear, therefore, taking the FFT, for example, square and saw waves and crossfading each harmonic linearly, and then return it to the time domain, either using iFFT or summing the sines, should give exactly the same result as the direct intersection of signals saws and squares. I'm not sure if this is what you wanted to do, but if there is no need to do FFT or compute intermediate tables.

There are many other ways to smoothly “attenuate” between waveforms, of course - you can use phase distortion, for example, with a distortion curve consisting of linear segments that you move from positions that generate a square, to positions that generate a saw, This It is probably very difficult to implement in a way that is inherently limited by range.

Merging can often be resolved in practice using oversampling and filtering, or simply filtering. Using methods with a limited range is better because overlay always causes some noise, but you can often filter it low enough to be inaudible, which is important for sound synthesis.

+1
source

but. I read that technique number 1 works very intensively with the processor and is not entirely feasible. Is this true for ARM processors like the iPad?

This makes a difficult difficult task (pun intended). Accelerate.framework provides optimized variations of these functions (fwiw), but this still complicates the simple problem. As a general note: floating point calculations on devices are slow. A floating point implementation can significantly reduce the cost of your program. This will likely lead to a compromise of functions, polyphony or quality. Without knowing reqs, it's hard to say if you can handle floating point calculations.

Q. Whatever technique I choose, is it possible to solve the smoothing problem by simply connecting a low-pass filter to the output of the generator?

This will not work for signals generated in the time domain unless you reprogram.

C. Any other suggestion on how to implement such a generator?

see below

Any suggestions on using C ++ toolkit? I watched STK from CCRMA, but I don't know if there are other more suitable libraries.

STK is more like a training tool than a tool kit designed for built-in synthesizers. More suitable implementations exist.

Option 1. Invent a function that occupies the position of the handle and calculates the spectrum of the actual signal (an array of amplitudes and frequencies), and then uses a bunch of sinusoidal functions and a sum unit to implement the output signal.

Option 2. Similar to 1. but apply the inverse Fourier transform instead of sines and sums (OK, at this moment I’m not sure if they are actually the same.)

It is relatively slow on desktops.

Option 4. Start with two waves of tooth teeth (they contain both even and odd harmonics), invert one and sum them up and control the amplitude of each of them with the handle. Waveforms would not be

You can do this efficiently enough (for example, using BLIT) to generate an alias. However, BLIT is limited to several waveforms (you can use it for saw and square). You can look back at the story and ask: "How did they solve this problem in hardware and software synthesizers around 2000." That was one solution. Another was:

Option 3. Create a waveform table for each possible pen position and use the wave table synthesis method to generate the output signal.

Given the capabilities of the device, I would recommend an int implementation of this or BLIT.

The table is easy to disassemble and implement, and also provides good sound and CPU results. It is also highly customizable for CPU / Memory / Quality tradeoffs.

If you want the alias to be free (or closed), go to BLIT (or relative). The reason is that you will need a good piece of memory and a good amount of oversampling to minimize the lack of audio smoothing with wavetables.

Implementation:

There are many BLIT implementations (and families) on the Internet.

Here the table napkin is laid out:

enum { WF_Sine, WF_Saw, WF_Square, WF_COUNT }; enum { TableSize = SomePowerOfTwo }; struct sc_waveform { uint32_t at[TableSize]; }; enum { NPitches = Something }; sc_waveform oscs[WF_COUNT][NPitches]; 

After initialization, use additive synthesis to populate the oscs .

During playback, use either:

  • interpolation and oversampling for reading from tables
  • or a large amount of oversampling the signal, and then downsampling (which is an effective CPU).

For reference: I would appreciate the linear interpolation of the table, which consumed an irresponsible amount of memory (taking into account the available amount) without oversampling, should support your alias frequencies at or below -40 dB if you were not supposed to hear partial sound, and you displayed on frequency 44.1 kHz. This is a naive brute force approach! You can do better with a little extra work.

Finally, you should also find relevant information if you google "Vector Synthesis" - what you are describing is a primitive form.

+1
source

All Articles