Forums

phase distorsion (music dsp)

Started by Robert Frunzke 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'.


Thanks in advance,
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'. > > > Thanks in advance, > 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. �����������������������������������������������������������������������
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'. > > > Thanks in advance, > 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. Does this help you? 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'. >> >> >>Thanks in advance, >>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. > > Does this help you? >
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