Go Down

Topic: SOLVED:Arduino Due Delay Effect - Noisy playback *only* with variable delay time (Read 708 times) previous topic - next topic

Grumpy_Mike

Quote
Unfortunately, the running average didn't appear to help.
You could try a real average, take n samples and then create an average, then update your delay value. A running average will always reflect noise, if you are only using a few samples. 

kreiff

You could try a real average, take n samples and then create an average, then update your delay value. A running average will always reflect noise, if you are only using a few samples. 
YES!!!! That was it Mike!! The pot is just mega jittery.

Thank you! I ended up having to take an average of about 2000 samples - I may need to fine tune it more from here - but this works at least when the pot is static

Here is my code:
Code: [Select]

//Setup the ring buffer
#define BSIZE 20000 //Buffer size, sets the maximum delay time.
int ring_buff[BSIZE]; //Ring buffer

const int numReadings = 2000;

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;

void setup() {
 
  //Initialize the buffer contents to all zero
  for (int i=0; i<BSIZE; i++){
    ring_buff[i] = 0;
  }

   for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
   }

  //Enable the ADC and DAC pins
  pinMode(A0, INPUT); // Define A0 as ADC input
  pinMode(A1, INPUT); // Define A1 as a multi-purpose Pot (currently used for testing variable delay times)
  analogReadResolution(12); //Override 10 bit default. We can go to 12 bits because the board used is a Due
  analogWriteResolution(12); //Override default 8 bit since we'll use DAC1 output on Due board

  //Open serial monitor transcript
  Serial.begin(115200);
  }

void loop() {
 
  int analogin; //stores ADC data
  float old_value1; // values read from the tap point
  int analogout; //value to be output and stored into buffer at current_tap
  int analogout_buf; //duplicate of analogue out taken before effect mix attenuation
  int current_tap = 0; //The current tap point - incremented after each sample
  int tap; //Temp variable used in indexing into older tap points
  byte effectMix; // variable for setting the effect vs. input mix
  int delayTime; // sets delay time

  //While loop to improve effect timing
  while (1) {

    total = total - readings[readIndex];
    // read from the sensor:
    readings[readIndex] = analogRead(A1);
    // add the reading to the total:
    total = total + readings[readIndex];
    // advance to the next position in the array:
    readIndex = readIndex + 1;

    // if we're at the end of the array...
    if (readIndex >= numReadings) {
    // ...wrap around to the beginning:
    readIndex = 0;
  }

  // calculate the average:
    average = total / numReadings;
    analogin = analogRead(A0) - 2048; //Making audio values bi-polar

    delayMicroseconds(20);
   
    effectMix = 0; //map(analogRead(2), 0, 4095, 0, 8);
    delayTime = map(average, 0, 4095, 1,20000); //sets delay time, mapped usable values between 900 - 20000

    tap = current_tap - delayTime; // sets temp tap value and grabs values earlier in the ring buffer
    if (tap < 0){                  //if tap is negative number, pushes it back to the top of the ring buffer
      tap += BSIZE;
    }
    old_value1 = ring_buff[tap];   //grabs delayed audio for playback
   
    //Scale values by a specfic divisor to determine feedback amount
    old_value1 /= 2;

    analogout_buf =  analogin + old_value1; //add passthrough audio from ADC to scaled delayed audio

    //Limit the outputs to mimic normal overload distortion
    //avoid digital number wraparound - might not be needed for the buffer?
    if(analogout_buf > 2047){ analogout_buf = 2047;}
    if(analogout_buf < -2047){ analogout_buf = -2047;}
   
    //Effect Level for repeats (i.e. turn down input signal)
    //analogin = analogin >> effectMix; //commented out for testing
   
    analogout = analogin + old_value1; //add passthrough audio from ADC to scaled delayed audio
   
    //Limit the outputs to mimic normal overload distortion
    //avoid digital number wraparound
    if(analogout > 2047){ analogout = 2047;}
    if(analogout < -2047){ analogout = -2047;}
   
    //store duplicated output in buffer for "effect only" playback
    ring_buff[current_tap] = analogout_buf;
   
    //increment (circular) tap-point
    current_tap++;
    if(current_tap > BSIZE-1){ //if tap point goes beyond BSIZE, start back at 0
      current_tap = 0;
    }
   
    //Scale the value back to an unsigned value in preparation for output to DAC
    analogout += 2048;
   
    //Write to DAC1 output pin on Due board
    analogWrite(DAC0, analogout);

   }
}

shawnreeves

[EDITED]
Thanks for posting this thread.
Have you considered a hardware solution:Encoder wheel?
More expensive part but less supporting parts and very fast reads. Besides stability when not touching the wheel, you will be able to carefully control the interval, have very fine control, distinguish between a small change and a large, all sorts of smart possibilities.

Go Up