Home > Back-end >  Implementing a digital delay line in C
Implementing a digital delay line in C

Time:12-07

I'm trying to implement a digital delay line in C, which delays the time sequence by an integer number. The background is audio signal processing and I want to add some delay as about 10 ms which is 441 samples when sampling rate is 44100 Hz. The input audio stream is send to me block by block, so I'm expected to output the same size of signal. The block size is genenrally 1024 samples or something like that.

I have a pointer *data which is the time sequence of length blockSize, and a pointer *buffer of length N that is used to save the delayed N samples for the usage of the next block. Here we can assume that blockSize > N.

I know how to realize it if data has the length of blockSize N: first copy the last N samples to the beginning of data, and then write samples from data N:

memcpy(data, data   blockSize, N * sizeof(*data));
write_data(data   N, blockSize);
read_data(data   N, blockSize);

But I have no idea how to do it with data and buffer, two pointers without consecutive memory addresses.

If I have data of length blockSize and buffer of length 2 * N, I can write something like:

void delayline(int *data, int *buffer, unsigned blockSize, unsigned N)
{
memcpy(buffer   N, data   blockSize - N, N * sizeof(*data)); // copy the last N samples of data to the second half of buffer
memmove(data   N, data, (blockSize - N) * sizeof(*data)); // delay the remaining blockSize - N samples by N
memcpy(data, buffer, N * sizeof(*data));  // copy the first half of buffer to data, these samples are from the previous block
memcpy(buffer, buffer   N, N * sizeof(*data));  // copy the second half of buffer to the first half for the use of next block
}

But I don't know how to do it if buffer only has a length of N. Is it possible? Thank you in advance!

CodePudding user response:

Here is my initial idea about how to make a delay line.

#include <stdio.h>

#define DELAY_SIZE 5
int delay_data[DELAY_SIZE];
int delay_data_index = 0;

// The output of this function is equal to the input
// that was passed to it 5 iterations ago.
// (The first five outputs are fixed to 0.)
int delay(int x)
{
  int r = delay_data[delay_data_index];
  delay_data[delay_data_index] = x;
  delay_data_index  ;
  if (delay_data_index >= DELAY_SIZE) { delay_data_index = 0; }
  return r;
}

void out(int x) {
  printf("%d\n", x);
}

int main() {
  out(delay(1));   // 0
  out(delay(2));   // 0
  out(delay(3));   // 0
  out(delay(4));   // 0
  out(delay(5));   // 0
  out(delay(6));   // 1
  out(delay(7));   // 2
  out(delay(8));   // 3
  out(delay(9));   // 4
  out(delay(10));  // 5
  out(delay(11));  // 6
  out(delay(12));  // 7
}

It certainly won't be the most efficient thing ever because it moves data one int at a time, but you should be able to use it as a starting point and then optimize it later if needed.

  •  Tags:  
  • c
  • Related