Phase Modulation

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

Get Adobe Flash player

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!

Or just open a template I made on Audiotool.com

11 thoughts on “Phase Modulation”

  1. 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.

  2. 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!

  3. 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!

  4. @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.

  5. 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.

Comments are closed.