# phase distorsion (music dsp)

Started by May 25, 2004
```Hello,

there is the following function (the base for a phase distorsion algorithm):

f(x) = sin( 2*pi * PD(phase) )

phase is 0..1

How can I choose PD() so that fx(x) results in a triangle wave
(approximation)? PD() should be small (in x86 code size) and preferably
without branches and without any 'memory'.

Robert
```
```Robert Frunzke wrote:

> Hello,
>
> there is the following function (the base for a phase distorsion
> algorithm):
>
> f(x) = sin( 2*pi * PD(phase) )
>
> phase is 0..1
>
> How can I choose PD() so that fx(x) results in a triangle wave
> (approximation)? PD() should be small (in x86 code size) and preferably
> without branches and without any 'memory'.
>
>
> Robert

You haven't been explicit enough to rule out a random number generator.
What are the constraints on PD()?

Jerry
--
Engineering is the art of making what you want from things you can get.
&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;

```
```Robert Frunzke <Robert.no.spam.F@freenet.de> writes:

> there is the following function (the base for a phase distorsion algorithm):
>
> f(x) = sin( 2*pi * PD(phase) )
>
> phase is 0..1

So what relevance does the "x" on the left-hand side of the equation
have for the right-hand side of the equation?

Do you mean something like:

f(x) = sin( 2 * pi * PD( phase(x) ) )

?

Why does phase have to be between zero and one?

> How can I choose PD() so that fx(x) results in a triangle wave
> (approximation)? PD() should be small (in x86 code size) and preferably
> without branches and without any 'memory'.

If x is a counter running fast enough, you could just have:

PD(phase(x)) = x % 1000 / 100000

and you would have a reasonably good sawtooth (though not triangular).

Of course its peak magnitude would only be 2*pi/100. :-)

Ciao,

Peter K.

--
Peter J. Kootsookos

"I will ignore all ideas for new works [..], the invention of which
has reached its limits and for whose improvement I see no further
hope."

- Julius Frontinus, c. AD 84
```
```Robert Frunzke wrote:

> Hello,
>
> there is the following function (the base for a phase distorsion
> algorithm):
>
> f(x) = sin( 2*pi * PD(phase) )
>
> phase is 0..1
>
> How can I choose PD() so that fx(x) results in a triangle wave
> (approximation)? PD() should be small (in x86 code size) and
> preferably without branches and without any 'memory'.
>
>
> Robert

Without bothering too much with your variable naming...

if you want to approximate a triangle, this could be a good starting
point:

f(x) = sin ( asin(x) )
will provide an ascending line f(x) = x  for all x in [ 0..1 ]

f(x) = sin( asin(-x)) provides a descending line.

Now combine both as:

if (x<0.5)
f(x) = sin (asin(x))
else
f(x) = sin(asin(1-x))

There you are with a basic triangle element if you increase x from 0
to 1.

Could be done easier, however, if you're required to do it with a PD
inside a sin() function, asin() might be the optimal solution.

Next step should be the approximation of the asin function,
look-up-table or algorithmic solution - depends on your requirements
- if this approach is acceptable.

Bernhard

```
```Robert Frunzke wrote:
> Hello,
>
> there is the following function (the base for a phase distorsion algorithm):
>
> f(x) = sin( 2*pi * PD(phase) )
>
> phase is 0..1
>
> How can I choose PD() so that fx(x) results in a triangle wave
> (approximation)?

Hi Robert,

you are doing frequency modulation. Phase modulation would have to be
added to the frequency term of the sine:

f_phase(t) = sin(2 pi + PD(t))

Anycase, to solve your problem you have set f(t) = triangle(2 Pi t)
and solve the equation for PD - you'll get a piecewise defined
function as follows

1/(2 Pi) ArcSin[4 t], 0 <= t < 1/4
PD(t) = 1/(2 Pi) ArcSin[-4 t + 2], 1/4 <= t < 3/4
1/(2 Pi) ArcSin[4 t - 4], 3/4 <= t <= 1

for 0 <= t <= 1 (for larger ranges first calculate t modulo 1).

You can break this up into further terms if you take a polynomial
approximation for ArcSin in the range [0,1].

> PD() should be small (in x86 code size) and preferably
> without branches and without any 'memory'.

You can still efficiently code this even if you have branches. The
memory requirement depends on your required accuracy (number of
coefficients in the polynomial approximation). Don't use Taylor series
for approxmiation, rather some minimax polynomial (you'll get less
terms for equal accuracy).

Regards,
Andor
```
```Bernhard Holzmayer wrote:
> Robert Frunzke wrote:
>
>
>>Hello,
>>
>>there is the following function (the base for a phase distorsion
>>algorithm):
>>
>>f(x) = sin( 2*pi * PD(phase) )
>>
>>phase is 0..1
>>
>>How can I choose PD() so that fx(x) results in a triangle wave
>>(approximation)? PD() should be small (in x86 code size) and
>>preferably without branches and without any 'memory'.
>>
>>
>>Robert
>
>
> Without bothering too much with your variable naming...
>

Yes, I messed it up. As you realized x=phase.

> if you want to approximate a triangle, this could be a good starting
> point:
>
> f(x) = sin ( asin(x) )
> will provide an ascending line f(x) = x  for all x in [ 0..1 ]
>
> f(x) = sin( asin(-x)) provides a descending line.
>
> Now combine both as:
>
> if (x<0.5)
>         f(x) = sin (asin(x))
> else
>         f(x) = sin(asin(1-x))
>
>
> There you are with a basic triangle element if you increase x from 0
> to 1.
>
> Could be done easier, however, if you're required to do it with a PD
> inside a sin() function, asin() might be the optimal solution.
>
> Next step should be the approximation of the asin function,
> look-up-table or algorithmic solution - depends on your requirements
> - if this approach is acceptable.
>
>

This is exactly what I was searching for. Thanks a lot :)

BTW: The purpose of all this is a very small synthesizer for a demo.
"Very small" means that I will try to crunch the phase distorsion
algorithm and playback code and data into a 4k executable (just for
fun..). Looks like there will be no more space for initialising
look-up-tables and the like. Execution speed does not matter here anyway.

I found the phase distorion very efficient in code size (you get a nice
sound without any filter code). The complete algorithm is kinda Casio
CZ101 emulation, but not truely..

Robert

```
```Andor wrote:
> Robert Frunzke wrote:
>
>>Hello,
>>
>>there is the following function (the base for a phase distorsion algorithm):
>>
>>f(x) = sin( 2*pi * PD(phase) )
>>
>>phase is 0..1
>>
>>How can I choose PD() so that fx(x) results in a triangle wave
>>(approximation)?
>
>
> Hi Robert,
>
> you are doing frequency modulation. Phase modulation would have to be
> added to the frequency term of the sine:
>
> f_phase(t) = sin(2 pi + PD(t))
>
> Anycase, to solve your problem you have set f(t) = triangle(2 Pi t)
> and solve the equation for PD - you'll get a piecewise defined
> function as follows
>
>         1/(2 Pi) ArcSin[4 t], 0 <= t < 1/4
> PD(t) = 1/(2 Pi) ArcSin[-4 t + 2], 1/4 <= t < 3/4
>         1/(2 Pi) ArcSin[4 t - 4], 3/4 <= t <= 1
>
> for 0 <= t <= 1 (for larger ranges first calculate t modulo 1).
>
> You can break this up into further terms if you take a polynomial
> approximation for ArcSin in the range [0,1].
>

Thanks. I did not mean phase modulation, I really mean phase distorsion
(an uncommon algorithms, e.g. used in the Casio CZ101).

Thank you very much for that complete solution.

Robert

>
>>PD() should be small (in x86 code size) and preferably
>>without branches and without any 'memory'.
>
>
> You can still efficiently code this even if you have branches. The
> memory requirement depends on your required accuracy (number of
> coefficients in the polynomial approximation). Don't use Taylor series
> for approxmiation, rather some minimax polynomial (you'll get less
> terms for equal accuracy).
>
> Regards,
> Andor
```
```Robert Frunzke <Robert.no.spam.F@freenet.de> wrote in message news:<c90imp\$42r\$05\$1@news.t-online.com>...
> Hello,
>
> there is the following function (the base for a phase distorsion algorithm):
>
> f(x) = sin( 2*pi * PD(phase) )
>
> phase is 0..1
>
> How can I choose PD() so that fx(x) results in a triangle wave

Eh... I there are a few things missing here. What's the relation between
x and the phase? Are you sure you can do with sines of unit amplitude,
or should there be an amplitude term included? Why do you include only
one sine and not an integral over frequency? Or are you interested in
a nonlinear function that distorts the monochromatic sine into a
triangle wave of equal period?

Rune
```
```You can (very coarsely) approximate a triangular wave by the
expression y = sin(x+0.5sin(x)). You can also approximate a
I-trapeziodal wave by the expression y = sin(x+0.5sin(2x)) and a
square wave by y = sin(x+sin(2x)). I don't remember a closer
approximation off the top of my head but that should get you
started...

--smb
```