[sdiy] help understanding circular buffers for delay line

dan snazelle subjectivity at hotmail.com
Sat Mar 3 04:07:57 CET 2012


If you are using a power of 2 buffer length then just use an "&" of
the length - 1 for starters as this will be much easier to code, worry
about optimisation later:
 
buffer [index & (length - 1)]
 
so for a fixed integer sample delay you would have:
 
inpos = (inpos + 1)  & (length - 1);
buffer [inpos] = input;
output = buffer [(inpos - delay) & ( length - 1)];
 
and make sure delay is less than length - 1
 
Andy

Ok

i just got some time to really study this Andy and I have some questions (surprise)







define length  8000
byte buffer [length]


what is the inpos? is that the same as using a for loop with an i as in matthews example?

and what is delay...is that the J for loop as in matthews example? or is that a delaytime pot?

thanks for your help









> &" of
> the length - 1 for starters as this will be much easier to code, worry
> about optimisation later:
> 
> buffer [index & (length - 1)]
> 
> so for a fixed integer sample delay you would have:
> 
> inpos = (inpos + 1)  & (length - 1);
> buffer [inpos] = input;
> output = buffer [(inpos - delay) & ( length - 1)];
> 
> and make sure delay is less than length - 1
> 
> Andy
> 
> 
> 
> On 2 March 2012 11:53, Matthew Smith <matt at smiffytech.com> wrote:
>> 
>> Quoth Dan Snazelle at 02/03/12 12:27...
>> ...
>> 
>>> So, these two indexes....are they both driven by "for" loops?(one with an offset?)
>> 
>> 
>> This is one of those concepts I'd generally try to explain using diagrams. However, let's see what we can do in plain text.
>> 
>> For starters, if you haven't already done so, I'd suggest you have a look at this Wikipedia article:
>> 
>> http://en.wikipedia.org/wiki/Circular_buffer
>> 
>> ...but possibly stopping when you get to the code, as they are using the dreaded malloc which I have, on more than one occasion, been told to avoid when dealing with small micros.
>> 
>> Here's a very rough example, without using pointers (which I probably would in Real Life) where I am sampling at 48ksps, 8 bits.
>> 
>> # define SIZE_OF_BUFFER 4096
>> 
>> unsigned char mybuffer[SIZE_OF_BUFFER];
>> int i=0; // write index
>> int j=0; // read index
>> for (;;)
>> {
>>  i++;
>>  if (i==SIZE_OF_BUFFER)
>>  {
>>  i=0; // We are indexing from zero, so 4095->0.
>>  }
>> 
>>  j=i+1;
>>  if (j==SIZE_OF_BUFFER)
>>  {
>>  j=0;
>>  }
>> 
>>  mybuffer[i]=read_dac();
>>  write_dac(mybuffer[j]);
>> 
>>  delay(); // wait until it's time for the next sample.
>> }
>> 
>> In real life, to do make this run in time, I'd make this an ISR, rather than an infinite for loop, or use an RTOS.
>> 
>> What's happening here is a simple delay. As I haven't initialised mybuffer[], for the first pass through the loop, write_dac() will be
>> spitting out indeterminate values - something that should be avoided in a real implementation.
>> 
>> After that first pass through though, what will be read from the buffer into the DAC will be the sample that you wrote in there SIZE_OF_BUFFER iterations ago. (Note that the oldest entry in the buffer is the NEXT position, or zero if we've reached the end.)
>> 
>> If we are sampling at 48ksps, this means that the value going to the DAC will be (1/48000) * 4096 = 0.0853 seconds behind what's being read in.
>> 
>> To decrease the delay, we change the relationship between i and j.
>> 
>> To give the effect of an echo, we can scale the value coming out by, say, shifting it 2 places to the right (divide by 4.) Then we can add it to the signal being written, shift the result 1 place to the right (divide by 2, because we could now have a 9 bit number, having added to the 8 bit number) and then send that to the DAC. So the value coming out is half of what's gone in, plus a quarter of what was there 85ms ago.
>> 
>> These are very rough examples (probably with errors!) but I hope they make it a bit more clear.
>> 
>> One thing you may have gathered - any significant delay will need a fair amount of RAM to achieve which, in a microcontroller context, will probably involve the use of external RAM. (It's dirt cheap, but does mean an extra chip.)
>> 
>> Cheers
>> 
>> M
>> 
>> --
>> Matthew Smith
>> 
>> Business: http://www.smiffytech.com
>> Blog:     http://www.smiffysplace.com
>> Linkedin: http://www.linkedin.com/in/smiffy
>> Flickr:   http://www.flickr.com/photos/msmiffy
>> Twitter:  http://twitter.com/smiffy
>> 
>> ABN 16 391 203 815
>> 
>> _______________________________________________
>> Synth-diy mailing list
>> Synth-diy at dropmix.xs4all.nl
>> http://dropmix.xs4all.nl/mailman/listinfo/synth-diy
> _______________________________________________
> Synth-diy mailing list
> Synth-diy at dropmix.xs4all.nl
> http://dropmix.xs4all.nl/mailman/listinfo/synth-diy
> 




More information about the Synth-diy mailing list