DSPRelated.com
Forums

time variable delay

Started by Ralph Harry September 2, 2004
Hi to all,

I need to implement a time variable delay on dsp in order to simulate
the doppler effect of a sound source coming nearer and moving away.
If I just pick the from the buffer the sample with delay corresponding
to (distance of source)/(speed of sound), I get clicks when moving
from one position to an other.
What's the proper way (preferably not too expensive) to implement such
a filter?
Thanks!

Ralph
Ralph Harry wrote:
> Hi to all, > > I need to implement a time variable delay on dsp in order to simulate > the doppler effect of a sound source coming nearer and moving away. > If I just pick the from the buffer the sample with delay corresponding > to (distance of source)/(speed of sound), I get clicks when moving > from one position to an other. > What's the proper way (preferably not too expensive) to implement such > a filter? > Thanks! > > Ralph
You could use an ADC with built-in sample rate conversion and drive one of its sample clocks with a VCO, and the other sample clock with a fixed freq oscillator. Buffer the samples into a fifo and output them to a DAC whose sample clock is driven by the fixed oscillator. This could also be done in software, but arbitrary sample rate conversion is a big job. Just an idea. -- Jim Thomas Principal Applications Engineer Bittware, Inc jthomas@bittware.com http://www.bittware.com (603) 226-0404 x536 Things could be a lot better around here, but worse is more likely - Calvin
"Ralph Harry" <rharry@hotmail.com> wrote in message
news:9e232c45.0409020024.34e08a4b@posting.google.com...
> Hi to all, > > I need to implement a time variable delay on dsp in order to simulate > the doppler effect of a sound source coming nearer and moving away. > If I just pick the from the buffer the sample with delay corresponding > to (distance of source)/(speed of sound), I get clicks when moving > from one position to an other. > What's the proper way (preferably not too expensive) to implement such > a filter?
Ralph, Your description of the implementation you're having trouble with isn't too clear. I really don't know what you mean by "the sample with delay corresponding to (distance of source)/(speed of sound)" and "moving from one position to another". If I understand the situation, you have a model of a sound source and want to superimpose motion on it. You also mention a "buffer". So, if you have one buffer filled with data that is never refreshed or updated, then no matter what rate you extract data from the buffer you will go past the "end" of the data and have a click - unless the buffer contents are very carefully designed so that there is no end transient. That's hard to do and maybe impossible in some cases. Forgetting about Doppler for the moment, if indeed you have but a single buffer worth of data of NT seconds (where N is the number of samples and T is the sample interval) then that data will be periodic at 1/NT. If F is the frequency resolution of the receiver then F>2/NT is a good rule of thumb. Otherwise the spectrum will appear to be discrete and probably not a good simulation. Back to Doppler: Are you sure that it's really a "time-variable delay" that you need? I should think what's needed is time compression / expansion. So, ideally you want to extract samples at variable spatial distances. I presume you are starting with samples at discrete intervals of time and distance corresponding to zero Doppler and that the output sample rate is constant, right? One of the classical methods is to put the data in a buffer and sample the data out at veriable rates. But, if the output sample rate is fixed, then you need to take "samples" that lie in between what's in the buffer - implying interpolation. If the sample rate is high enough, linear interpolation may suffice. Or, if the sample rate is really high then picking the nearest sample may suffice. Either method adds some noise - which may overcome some of the discrete spectrum concern above. A little more information would help a lot. Fred
Harmony Central has some sample code for a variable length delay.  It uses
linear interpolation to get the value between the samples.  It's for a chorus
or flanger so it uses an oscillator to control the delay length.

http://www.harmony-central.com/Computer/Programming/

http://www.harmony-central.com/Effects/Articles/Flanging/
http://www.harmony-central.com/Effects/Articles/Chorus/

Jeff

>I need to implement a time variable delay on dsp in >order to simulate the doppler effect of a sound >source coming nearer and moving away.
Hi Ralph,

You need to interpolate your data, as Fred mentioned, so that you can pick 
delayed samples more precisely.

Google in comp.dsp for fractional delay FIR filters for a survey of 
appropriate techniques:

http://groups.google.ca/groups?hl=en&lr=&ie=UTF-8&q=fractional+delay++FIR+group%3Acomp.dsp&meta=group%3Dcomp.dsp

Also, to produce correctly sampled output, you also have to generate output 
samples at a rate higher than twice the maximum frequency that could be 
generated by Doppler shifting the input.  Then you decimate to get back to 
the sampling frequency you want.

Note that this means you cannot move instantaneously from one place to 
another, as that would generate infinitely high frequencies.  If you try it, 
you'll make a click.  Note that if you did it in the real world, you'd make 
a pretty loud click, too.

--

Matt 


Hi!

First of all, thanks to everybody who posted some ideas!

Jim: I'm looking for a 100% software implementation because the
hardware is finalized.

Jeff: I've already had a look at Harmony's code. It's indeed great if
you implement a chorus or a flanger with low frequency oscillator -
but I think it is restricted to the case where you interpolate between
adjacent samples. The trouble with the doppler effect is that the
transition is typically larger than just one sample.

Fred: I'll try to be more precise now about the implementation - but I
think you already got most of it. Imagine a sound source and a
listener, both motionless and 'd' meters apart. Then there is a fix
delay equal to d/c between the moment the source emits and the moment
the listener hears the source ('c': speed of sound). If the source is
close to the listener, the delay is nearly 0 - and if you have an
amount of memory corresponding to t seconds, then you can model the
situation with distance source-listener up to c*t.

Now I quote what you wrote:

"Back to Doppler:
Are you sure that it's really a "time-variable delay" that you need? 
I
should think what's needed is time compression / expansion."

Not sure. There's a pitch change when the source moves, but time
remains unchanged.

"So, ideally you want to extract samples at variable spatial
distances.  I presume you are starting with samples at discrete
intervals of time and distance
corresponding to zero Doppler and that the output sample rate is
constant,
right?"

Absolutely!

"One of the classical methods is to put the data in a buffer and
sample the
data out at veriable rates."

Technically impossible (with my hardware).

"But, if the output sample rate is fixed, then
you need to take "samples" that lie in between what's in the buffer -
implying interpolation.  If the sample rate is high enough, linear
interpolation may suffice.   Or, if the sample rate is really high
then
picking the nearest sample may suffice.  Either method adds some noise
-
which may overcome some of the discrete spectrum concern above."

I have designed a user interface which enables to virtually move the
source or the listener. The distance source-listener can be updated
roughly 10 times per second - This means that if the source moves with
high speed, the output pointer in the delay line may jump over, say,
100 samples. So simple linear interpolation will not suffice (The
system sample rate is 48 kHz).

Ralph
Ralph Harry wrote:

> Hi! > > First of all, thanks to everybody who posted some ideas! > > Jim: I'm looking for a 100% software implementation because the > hardware is finalized. > > Jeff: I've already had a look at Harmony's code. It's indeed great if > you implement a chorus or a flanger with low frequency oscillator - > but I think it is restricted to the case where you interpolate between > adjacent samples. The trouble with the doppler effect is that the > transition is typically larger than just one sample.
Why is that a problem? The instant you want, whatever it may be, is either between two samples you have or exactly one of them. You don't have to interpolate between the last value you used and the next one you will want, but between adjacent table entries. ... Jerry -- Engineering is the art of making what you want from things you can get. &#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;
"Ralph Harry" <rharry@hotmail.com> wrote in message
news:9e232c45.0409030118.11cbddcb@posting.google.com...

> > I have designed a user interface which enables to virtually move the > source or the listener. The distance source-listener can be updated > roughly 10 times per second - This means that if the source moves with > high speed, the output pointer in the delay line may jump over, say, > 100 samples. So simple linear interpolation will not suffice (The > system sample rate is 48 kHz).
Ah! I think you need to consider the relationship between the sample rate and the distance update rate. The distance update rate needs to be the same as the sample rate methinks. The way you're doing it, the distance changes in giant steps and the sound record skips or repeats great sections. That's definitely not what you want! That's what creates the clicks. If you update at every output sample then you won't skip anything - you will simply choose a sample location to interpolate that is slightly closer or slightly further away from the sample location had you not had a change in velocity. Note that I say "velocity" and not "distance". This could be important in how you view this. Are you really sure you need to operate in distance and not radial distance rate / radial velocity? Distance really only equates to latency and velocity to Doppler shift. Once you have a distance or time "reference" then you can generate the correct sample distances from the velocity and the distance is, of course, the integral of velocity - integration being a fairly robust process if you need to do it. Anyway, here's what I recommend: Determine the output sample interval in time that is based on the Doppler frequency in relation to the input sample rate. Do this at every output sample. Just as observed frequency for acoustics is: fr = ft*[c/(c+v)] where ft is the "transmitted" frequency and fr is the received frequency, c is the speed of sound and v is radial velocity (positive with up-shift or the transmitter and receiver moving toward one another). In order for output samples to appear to be at a higher frequency, they need to sample the input stream at intervals that are further apart relative to the input. Let's say that there is a system with 10 samples per cycle at the input and an up shift of around 10%. In order for the output to have a relative up shift, we need to have fewer samples per cycle - let's say 9 samples per cycle. If the input sample interval is 1/10 then the output sample interval is 1/9. I do believe this leads to To = Ti*[(c+v)/c] where Ti is the input sample interval and To is the output sample interval which is longer for up Doppler. So the output sample interval (relative to the input sequence) increases as the radial velocity increases - thus increasing the output frequencies. Of course, the output sample interval or sample rate is going to be the same as the input sample interval or sample rate - and it's the data we're changing here. Now, using the same ratio, if Ti is 1msec then To would be 1.11111msec. So, if you start at ti0=0 then to0=0, ti1=0.001 and to1=0.001111, etc. So, you might interpolate between ti1 and ti2 to a point that is 0.001 - 0.001111 = 0.000111msec beyond the data taken at ti1 ... and so forth. However, if you wait for 0.1 seconds before "updating" we immediately see two potential problems. 1) it appears that you aren't interpolating, rather you are jumping to a new spot in the input sequence. This introduces no Doppler shift - only a distance shift. In air at 1000fps, this amounts to an instantaneous jump of 100 feet. In water at 5000fps, this amounts to an instantaneoous jump of 500 feet. At 1kHz: In air, 1kHz has 1000 cycles in 1000 feet or a wavelength of 1 foot In water, the wavelength is 5 feet. So a jump of 100 feet in air or 500 feet in water is a jump of 100 cycles in the waveform - which is not a good thing at all. You really need to generate the samples one at a time. 2) Also, what happens after you jump? You would still need to interpolate with the proper (new) interval. This means you need to be interpolating all the time anyway. So, why not simply update the sample interval each time before doing the interpolation? Fred
I had a little different problem.  I had to generate a group of narrowband 
lines with Gaussian random frequency distribution about a varying center 
frequency.  Clicks were a problem as well since the output was played into a 
speaker system.  I ignored the change in distance since it was not significant 
in my case and focused on the Doppler effect with frequencies on a one 
milli-Hertz grid.  I was updating a tenth Hertz wide signal every eighth of a 
second.  Fred Harris has a couple of papers in conference proceedings from the 
70s on this subject

In article <yfadnR1QLtIdCKXcRVn-uA@centurytel.net>, "Fred Marshall" 
<fmarshallx@remove_the_x.acm.org> wrote:
> >"Ralph Harry" <rharry@hotmail.com> wrote in message >news:9e232c45.0409030118.11cbddcb@posting.google.com... > >> >> I have designed a user interface which enables to virtually move the >> source or the listener. The distance source-listener can be updated >> roughly 10 times per second - This means that if the source moves with >> high speed, the output pointer in the delay line may jump over, say, >> 100 samples. So simple linear interpolation will not suffice (The >> system sample rate is 48 kHz). > >Ah! I think you need to consider the relationship between the sample rate >and the distance update rate. The distance update rate needs to be the same >as the sample rate methinks. The way you're doing it, the distance changes >in giant steps and the sound record skips or repeats great sections. That's >definitely not what you want! That's what creates the clicks. > >If you update at every output sample then you won't skip anything - you will >simply choose a sample location to interpolate that is slightly closer or >slightly further away from the sample location had you not had a change in >velocity. > >Note that I say "velocity" and not "distance". This could be important in >how you view this. >Are you really sure you need to operate in distance and not radial distance >rate / radial velocity? Distance really only equates to latency and >velocity to Doppler shift. Once you have a distance or time "reference" >then you can generate the correct sample distances from the velocity and the >distance is, of course, the integral of velocity - integration being a >fairly robust process if you need to do it. > >Anyway, here's what I recommend: > >Determine the output sample interval in time that is based on the Doppler >frequency in relation to the input sample rate. Do this at every output >sample. > >Just as observed frequency for acoustics is: > >fr = ft*[c/(c+v)] >where ft is the "transmitted" frequency and fr is the received frequency, c >is the speed of sound and v is radial velocity (positive with up-shift or >the transmitter and receiver moving toward one another). > >In order for output samples to appear to be at a higher frequency, they need >to sample the input stream at intervals that are further apart relative to >the input. Let's say that there is a system with 10 samples per cycle at >the input and an up shift of around 10%. In order for the output to have a >relative up shift, we need to have fewer samples per cycle - let's say 9 >samples per cycle. If the input sample interval is 1/10 then the output >sample interval is 1/9. > >I do believe this leads to >To = Ti*[(c+v)/c] >where Ti is the input sample interval and To is the output sample interval >which is longer for up Doppler. >So the output sample interval (relative to the input sequence) increases as >the radial velocity increases - thus increasing the output frequencies. Of >course, the output sample interval or sample rate is going to be the same as >the input sample interval or sample rate - and it's the data we're changing >here. > >Now, using the same ratio, if Ti is 1msec then To would be 1.11111msec. >So, if you start at ti0=0 then to0=0, ti1=0.001 and to1=0.001111, etc. >So, you might interpolate between ti1 and ti2 to a point that is 0.001 - >0.001111 = 0.000111msec beyond the data taken at ti1 ... and so forth. > >However, if you wait for 0.1 seconds before "updating" we immediately see >two potential problems. >1) it appears that you aren't interpolating, rather you are jumping to a new >spot in the input sequence. This introduces no Doppler shift - only a >distance shift. >In air at 1000fps, this amounts to an instantaneous jump of 100 feet. >In water at 5000fps, this amounts to an instantaneoous jump of 500 feet. >At 1kHz: >In air, 1kHz has 1000 cycles in 1000 feet or a wavelength of 1 foot >In water, the wavelength is 5 feet. >So a jump of 100 feet in air or 500 feet in water is a jump of 100 cycles in >the waveform - which is not a good thing at all. >You really need to generate the samples one at a time. > >2) Also, what happens after you jump? You would still need to interpolate >with the proper (new) interval. This means you need to be interpolating all >the time anyway. So, why not simply update the sample interval each time >before doing the interpolation? > >Fred > >
Thanks to all of you for your inputs.
I have now to sit down and think about how I am going to do the job.
I'll be back to let you know if I've managed something.
Again, thank you!

Ralph