After having Tonfall released, I think it might be a good idea to go a bit deeper into some audio-dsp subjects. The easiest way to create a sound is by creating a wave out of an algorithm. You usually take a normalized variable between zero and one as the phase and pass it to a function. The phase itself must be incremented every sample by the following expression.
phase += frequency / samplingRate;
phase -= int( phase ); // [0,1]
amplitude = waveshaper( phase ); // [-1,+1]
Tonfall provides wave-shaping function like sinus, triangle, sawtooth and pulse (rectangle). The last one is well known by me from the C64 sound-chip and provided setting the pulse width. A normal pulse wave is 1.0 for all phase value lower than 0.5 and -1.0 for the rest of the phases. If you modulate the center (0.5) back and forth, the sound gets more wide and living. This is called Pulse-modulation but also reflects to phase-modulation. The effect on this simple waveform is the same.
For Audiotools Pulverisateur we wanted to implement such modulations for all kinds of waveshapes, even curves. So I needed to find a good and fast way to translate the phase value into a modulated value that could be passed into the wave-function.
amplitude = waveshaper( modulate( phase ) ); // [-1,+1]
These were the requirements
- Receive a value between zero and one and return a value between zero and one
- Ability to bend the value in both directions (symmetric)
- Be able to remain the input
Lets see what I came up with
The best part is, that there a parameter t to shape the curve. The upper curve (t>0) extends the output value and it compresses it later. The lower(t<0) is exactly doing the opposite. It is symmetric to y=x. Lets compare some values of t.
t: +/- 2
t: +/- 1
t: 0
That is another benefit. When you pass t=0, you get a straight line.
Meaning: output = input
t: +/-64
For really high values for t towards INFINITY you get in the end a right angle.
Costs
Curves like that are usually very expensive. I stumbled upon Super Ellipse, which distracted me for a couple of hours. It uses exponential functions, which I cannot run on every sample at 44100 Hz. I thought about taking a quadric bezier curve, but transforming the function to x leads to a sqrt-root. This solution presented here costs just one division and some simple algebra, which is okay for audio-dsp. I don’t know, if I invented this thing. If you know, what it is, let me know!
Phase modulated sinus-wave
Function (for positive t)
Function (for negative t)
Actionscript
private function bend( x: Number, t: Number ): Number
{
if( t < 0.0 )
{
return x / ( t * x - t + 1.0 );
}
var tx: Number = t * x;
return ( tx + x ) / ( tx + 1.0 );
}
If you want to listen to the implementation, check out Audiotool, launch the application and create a Pulverisateur. Make sure to init the default patch and start with a single oscillator. Hope you like it!
Hey Andre! Great post, would you be able to create a demo in Audiotool showing Pulverisateur in action? Couldn’t find it anywhere in the modules in the right drawer.
Done the same time while you typed. Check out last link.
I’m not sure if a name for what you’ve described already exists, but it is very cool. Thanks for posting your insights. Looking forward to reading more DSP related articles!
Thanks for sharing, Andre!
I have two questions about tonfall:
1) how to use BiQuadFilter? I need to implement processor for it or no?
2) how to deal with 2 sounds, if I want to use different processors on them?
thanks!
@Irek
1) You can pass a Signal of the SignalBuffer and it runs the filter over the next pointers.
2) Check out the ToneMatrix in Tonfall. It runs a polyphonic synthesizer. Different processors are only useful when generating or processing different stuff.
Well done to Petter Solberg for coming a thrilling 2nd in the Wales Rally GB 2010 – bit slidey though!
There is discontinuity in first derivative… :/
hi, nice work!
like @Itek, =Id like to use the BiQuad to manage a LowPass, but it stays very obscure to me
could u be a bit more explicit on it please ?
at least, explain parameters u pass to the public function and how I inject this in the mixerUnit ?
cheers
e.
how can ı do that ı dont know can you help me about it if you want to help me pls send me e mail
we can do everything from kayseri kayseri is so pretty city in anatolia u can visit kayseri