Audio Code Library: Delay


This delay is implemented with a simple circular buffer, a very common structure. The algorithm is simple. First, allocate enough memory to hold the necessary number of samples (sampling rate time delay time). Set a pointer to the start of the delayline. For each sample, read the value in the delayline to pass to the output, and then write the current input sample, along with the delayline output to allow feedback. Then increment the pointer to the next location in the delayline. If the pointer reaches the end of the allocated space, set it to the first memory location.

The code allows for the delay time, feedback multiplier, and mix levels for the input and delayed signal to be specified in the constructor.

See also:

Please do not redistribute this code. In the event that it contains a bug, this will ensure that it can be fixed without the buggy copies floating around indefinitely.

Last Modified: 6/28/98

Delay.h

/*********************************************************

Delay.h - A delay unit

Copyright (c) 1998, Scott Lehman, slehman@harmony-central.com
This code may be used and modified freely provided that credit
is given to the author in any public release. Any derivative
programs must be distributed freely and/or the modified source
code made publicly available.  All code is provided AS IS and
without warranty of any kind.
*********************************************************/

#ifndef DELAY_H
#define DELAY_H

#include "Processor.h"

class Delay : public Processor {
public:
  Delay(float time, float feedback, float wetMix, float dryMix);
  void Initialize(void);
  void Process(void);
  void Cleanup(void);
  ~Delay(){;}

private:
  float delayTime, feedbackGain;  // delayTime is in milliseconds
  float wetLevel, dryLevel, * outputSignal, * inputSignal;
  float * buffer, delayLineOutput;
  float * delayLineStart, * delayLineEnd, * readPtr;
  int  i;
  Delay(void){};
  Delay(Delay&){};
};

#endif

Delay.cpp

/*********************************************************

Delay.cpp - A delay unit

Copyright (c) 1998, Scott Lehman, slehman@harmony-central.com
This code may be used and modified freely provided that credit
is given to the author in any public release. Any derivative
programs must be distributed freely and/or the modified source
code made publicly available.  All code is provided AS IS and
without warranty of any kind.
*********************************************************/


#include "Delay.h"


// ************  Delay(float, float, float, float)  ***********

// time - delay time, in milliseconds
// feedback - feedback gain, from 0 to 1 (or .9999...)
// wetMix - level of delayed signal, from 0 to 1
// dryMix - level of input signal, from 0 to 1

Delay :: Delay (float time, float feedback, float wetMix, float dryMix) {

  SetNumInputs(1);
  SetNumOutputs(1);

  delayTime = time;
  feedbackGain = feedback;
  wetLevel = wetMix;
  dryLevel = dryMix;


  return;
}


// ******************  Initialize(void)  *******************

void Delay :: Initialize(void)
{
	//Double check that input/output buffers are there
  if (inputs[0] == NULL)
    ModuleError("Buffer in Delay input not assigned");
  if (outputs[0] == NULL)
    ModuleError("Buffer in Delay output not assigned");

  //compute required buffer size for desired delay and allocate for it
  int bufferLength = (int)(delayTime*samplingRate/1000);
  if(bufferLength <= 0)
    ModuleError("Delay buffer length in non-positive");
  delayLineStart = new float[bufferLength];
  if (delayLineStart == NULL)
    ModuleError("Couldn't allocate buffer in Delay");

  //set up pointers for delay line
  delayLineEnd = delayLineStart + bufferLength;
  readPtr = delayLineStart;

  //zero out the buffer (silence)
  do {
    *readPtr = (float)0.0;
  }
  while (++readPtr < delayLineEnd);

  //reset read pointer to start of delayline
  readPtr = delayLineStart;

  //only one in and out.  Assign to new pointers for simplicity
  outputSignal = outputs[0];
  inputSignal = inputs[0];

  return;
}

// ********************  Process(void)  ******************

void Delay:: Process()
{

  for (i=0; i<frameLength; i++) { //for each sample...

    //get delayed sample
    delayLineOutput = *readPtr;

    //weight the delayed sample and the current input to create the output
    outputSignal[i] = dryLevel * inputSignal[i] + 
		                  wetLevel * delayLineOutput;

    //write the input sample and any feedback to delayline
    *readPtr = inputSignal[i] + 
			         feedbackGain * delayLineOutput;
	
    //increment buffer index and wrap if necesary
    if (++readPtr >= delayLineEnd)
      readPtr = delayLineStart;

  }

  return;
}


// **********************  Cleanup(void)  *******************

void Delay :: Cleanup(void)
{
  //Free memory allocated during initialization
  delete [] delayLineStart;
}


Back to the Audio Programming Page

Back to Harmony Central® Home Page

Email: webmaster@harmony-central.com
Copyright © 1995-98 Harmony Central, Inc. All rights reserved.