Go Down

Topic: Re: Arduino Realtime Audio Processing (Read 3679 times) previous topic - next topic

alex5678

Because I cannot find Teensys on my local store, is there any other solution hardware?

alex5678

I am following this schematic here:

arduino-realtime-audio-processing

and I try the reverb code:

Code: [Select]
/* Arduino Audio Loopback Test
 *
 * Arduino Realtime Audio Processing
 * 2 ADC 8-Bit Mode
 * ana\u0161og input 1 is used to sample the audio signal
 * analog input 0 is used to control an audio effect
 * PWM DAC with Timer2 as analog output
 
 
 
 * KHM 2008 /  Martin Nawrath
 * Kunsthochschule fuer Medien Koeln
 * Academy of Media Arts Cologne
 
 */


#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))


//#include "WProgram.h"
void setup();
void loop();
void fill_sinewave();
int ledPin = 13;                 // LED connected to digital pin 13
int testPin = 7;


boolean div32;
boolean div16;
// interrupt variables accessed globally
volatile boolean f_sample;
volatile byte badc0;
volatile byte badc1;
volatile byte ibb;



int cnta;
int icnt;

int cnt2;
int iw1;

int iw;
byte bb;

byte dd[512];  // Audio Memory Array 8-Bit


void setup()
{
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output
  pinMode(testPin, OUTPUT);
  Serial.begin(57600);        // connect to the serial port
  Serial.println("Arduino Audio Reverb");


  fill_sinewave();        // reload wave after 1 second


  // set adc prescaler  to 64 for 19kHz sampling frequency
  cbi(ADCSRA, ADPS2);
  sbi(ADCSRA, ADPS1);
  sbi(ADCSRA, ADPS0);




  sbi(ADMUX,ADLAR);  // 8-Bit ADC in ADCH Register
  pwmsbi(ADMUX,REFS0);  // VCC Reference
  cbi(ADMUX,REFS1);
  cbi(ADMUX,MUX0);   // Set Input Multiplexer to Channel 0
  cbi(ADMUX,MUX1);
  cbi(ADMUX,MUX2);
  cbi(ADMUX,MUX3);


  // Timer2 PWM Mode set to fast PWM
  cbi (TCCR2A, COM2A0);
  sbi (TCCR2A, COM2A1);
  sbi (TCCR2A, WGM20);
  sbi (TCCR2A, WGM21);

  cbi (TCCR2B, WGM22);




  // Timer2 Clock Prescaler to : 1
  sbi (TCCR2B, CS20);
  cbi (TCCR2B, CS21);
  cbi (TCCR2B, CS22);

  // Timer2 PWM Port Enable
  sbi(DDRB,3);                    // set digital pin 11 to output

  //cli();                         // disable interrupts to avoid distortion
  cbi (TIMSK0,TOIE0);              // disable Timer0 !!! delay is off now
  sbi (TIMSK2,TOIE2);              // enable Timer2 Interrupt


  Serial.print("ADC offset=");     // trim to 127
  iw1=badc1; 
  Serial.println(iw1);
}



void loop()
{
  while (!f_sample) {     // wait for Sample Value from ADC
  }                       // Cycle 15625 KHz = 64uSec

  PORTD = PORTD  | 128;   // Test Output on pin 7
  f_sample=false;

  bb=dd[icnt] ;              // read the delay buffer
  iw = 127-bb ;              // substract offset
  iw = iw * badc0 / 255;     // scale delayed sample with potentiometer

  iw1 = 127 - badc1;          // substract offset from new sample
  iw1=iw1+iw;                 // add delayed sample and new sample
  if (iw1 < -127) iw1=-127;   // Audio limiter
  if (iw1 > 127) iw1=127;     // Audio limiter

  bb= 127+iw1;                // add offset
  dd[icnt]=bb;                // store sample in audio buffer

  icnt++;
  icnt = icnt & 511;         // limit bufferindex 0..511

  cnt2++;               // let the led blink about every second
  if (cnt2 >= 15360){
    cnt2=0;
    PORTB = PORTB ^ 32;   // Toggle LED on Pin 11
  }

  OCR2A=bb;            // Sample Value to PWM Output

  PORTD = PORTD  ^ 128;   // Test Output on pin 7


} // loop
//******************************************************************
void fill_sinewave(){
  float pi = 3.141592;
  float dx ;
  float fd ;
  float fcnt;
  dx=2 * pi / 512;                    // fill the 512 byte bufferarry
  for (iw = 0; iw <= 511; iw++){      // with  50 periods sinewawe
    fd= 127*sin(fcnt);                // fundamental tone
    fcnt=fcnt+dx;                     // in the range of 0 to 2xpi  and 1/512 increments
    bb=127+fd;                        // add dc offset to sinewawe
    dd[iw]=bb;                        // write value into array

  }
}


//******************************************************************
// Timer2 Interrupt Service at 62.5 KHz
// here the audio and pot signal is sampled in a rate of:  16Mhz / 256 / 2 / 2 = 15625 Hz
// runtime : xxxx microseconds
ISR(TIMER2_OVF_vect) {

  PORTB = PORTB  | 1 ;

  div32=!div32;                            // divide timer2 frequency / 2 to 31.25kHz
  if (div32){
    div16=!div16;  //
    if (div16) {                       // sample channel 0 and 1 alternately so each channel is sampled with 15.6kHz
      badc0=ADCH;                    // get ADC channel 0
      sbi(ADMUX,MUX0);               // set multiplexer to channel 1
    }
    else
    {
      badc1=ADCH;                    // get ADC channel 1
      cbi(ADMUX,MUX0);               // set multiplexer to channel 0
      f_sample=true;
    }
    ibb++;
    ibb--;
    ibb++;
    ibb--;    // short delay before start conversion
    sbi(ADCSRA,ADSC);              // start next conversion
  }

}

int main(void)
{
  init();

  setup();
   
  for (;;)
    loop();
       
  return 0;
}


on Arduino MEGA 2560 R3 using the pins that the image has. However, I don't get something on ouput. Is this point a connection? Has anyone make this circuit work? Is there any other reliable circuit for input from a microphone + reverberation + output on earphones?

Thank you...

PieterP

The code you posted was written for the ATmega168. The timer configuration etc. is different for the ATmega2560.

PieterP

Because I cannot find Teensys on my local store, is there any other solution hardware?
You can order Teensy online.

What other Arduino-compatible boards do they have in your local store?

alex5678

I don't want to migrate to other platform, but Arduino. Is there a reliable circuit that will let me use microphone and earphones for real time processing on Arduino DUE (preferably)?

Grumpy_Mike

#35
Aug 02, 2019, 06:08 am Last Edit: Aug 02, 2019, 06:14 am by Grumpy_Mike
Quote
Is there a reliable circuit that will let me use microphone and earphones for real time processing on Arduino
Yes you posted it in reply #31.

Quote
However, I don't get something on ouput. Is this point a connection?
No. The convention that author is using is to only have a contact if there is a dot, and there is no dot. I don't like that convention for exactly that reason, it confuses people.

If you are using a Due then you can use the analogue output on it, DAC 0 and DAC 1. However be careful as these outputs are very weak and can only stand a source current of 3mA and a sink current of 6mA, like the majority of pins on the Due. It would seem DAC 0 is particularly vulnerable with people reporting they have burned it out. I would recommend that you connect this pin straight to an op amp in the voltage follower buffer mode. That is the pin direct to the +ve input and the -ve input connected to the output. I would also couple it to the line output via a capacitor like the input is.

Also where it says 5V use 3V3 as you can't put 5V signals into a Due. Also you can't get enough current from a Due pin to light an LED directly unless it is one of the high current pins.

However you face the same problem as you do with the Mega in that software designed to run on the timers of a Uno will not work because the timers are different. On the Due they are very different so you need to read the data sheet.

With a Due you can also use the I2S drivers.

For other options try searching on the words:-
Arduino audio experimenters board

However you reluctance / inability to use mail order is a big restriction.

alex5678

#36
Aug 02, 2019, 06:12 pm Last Edit: Aug 02, 2019, 07:09 pm by alex5678
I will follow this example and will try to make it work:

https://www.arduino.cc/en/Tutorial/SimpleAudioPlayer

I have tried it in the past without achieving anything. What I want basically is to make it real time, so nothing to store in the SDcard, just doing DSP to the input sound ( https://www.adafruit.com/product/1063) and take an output on the speaker/earphones.

I bought a speaker 0.5Watt, 8 Ohms. Can Arduino handle it? Or I will have problem...

Also, what is your opinion on this: https://create.arduino.cc/projecthub/msb4180/speech-recognition-and-synthesis-with-arduino-2f0363?f=1

??

Thank you...

Grumpy_Mike

Quote
What I want basically is to make it real time, so nothing to store in the SDcard, just doing DSP to the input sound
OK start off with a simple loop function. Just read the analogue input and write that value to the output.

In the case of your processor having one, this is the analogue output. If not then the input needs cutting down to an 8 bit sample with a shift to the right by two places ( in the case of a 10 bit A/D ) and then written to the PWM register to change the duty cycle.

alex5678

#38
Aug 02, 2019, 11:45 pm Last Edit: Aug 02, 2019, 11:46 pm by alex5678
I use  this code in order to hear on the speaker, what I say on the microphone, but I get noise, and the microphone reads too high values...Any suggestion?

Thank you...

Code: [Select]
void setup() {
  // open a serial connection
  Serial.begin(9600);
}

void loop() {
  // read the input on A0 at default resolution (12 bits)
  // and send it out the serial connection

  // change the resolution to 12 bits and read A0
  analogReadResolution(12);
  Serial.print(", 12-bit : ");
  Serial.println(analogRead(A0));

  analogWriteResolution(12);
  analogWrite(DAC1, analogRead(A0) );

  // a little delay to not hog Serial Monitor
  delay(100);
}


Code: [Select]

00:43:08.370 -> , 12-bit : 4079
00:43:08.473 -> , 12-bit : 4089
00:43:08.542 -> , 12-bit : 4095
00:43:08.646 -> , 12-bit : 4095
00:43:08.749 -> , 12-bit : 3845
00:43:08.852 -> , 12-bit : 4095
00:43:08.956 -> , 12-bit : 4095
00:43:09.058 -> , 12-bit : 4095
00:43:09.159 -> , 12-bit : 4045
00:43:09.260 -> , 12-bit : 4095
00:43:09.362 -> , 12-bit : 4021
00:43:09.465 -> , 12-bit : 4095
00:43:09.565 -> , 12-bit : 3714
00:43:09.666 -> , 12-bit : 3864
00:43:09.768 -> , 12-bit : 3887
00:43:09.869 -> , 12-bit : 3838
00:43:09.970 -> , 12-bit : 4095
00:43:10.070 -> , 12-bit : 3254
00:43:10.170 -> , 12-bit : 4095
00:43:10.272 -> , 12-bit : 4095
00:43:10.371 -> , 12-bit : 3992
00:43:10.439 -> , 12-bit : 3988
00:43:10.573 -> , 12-bit : 4095




Grumpy_Mike

#39
Aug 03, 2019, 12:46 am Last Edit: Aug 03, 2019, 12:47 am by Grumpy_Mike
You are doing two analogue reads for one output. It is the analog read that takes the time. So you are only outputting at half the true sample rate. Just read it once into a variable and use that.

Your readings are right near the top of 4095 which corresponds to the maximum voltage the A/D will take.
Adjust the bias on the input side until you get a reading of about 2048 with no sound. This will allow you to see the maximum change when you apply sound to the microphone.

analogWriteResolution( 12 ) ; should be done only once in the setup function.

Yes you can use serial print for testing but you will never get any sound out of the system while you use it, because it acts like a huge delay. So once you have the readings showing up and down movement comment out all print statements in the loop along with any delay calls.

alex5678

#40
Aug 03, 2019, 10:46 am Last Edit: Aug 03, 2019, 10:46 am by alex5678
I am trying this code:

Code: [Select]

void setup()
{
    // open a serial connection
    analogWriteResolution(12);
    analogReadResolution(12);
    //Serial.begin(9600);
}

void loop()
{
    int value_;
    Serial.print(", 12-bit : ");
    value_ = analogRead(A1);
    //Serial.println(value_);
    analogWrite(DAC0, value_);
    // a little delay to not hog Serial Monitor
    //delay(100);
}


I hear nothing...

Thank you...

Grumpy_Mike

You have still got a serial print in that loop.

alex5678

You are right. I will check it again...

Thank you...

alex5678

#43
Aug 03, 2019, 08:46 pm Last Edit: Aug 03, 2019, 08:46 pm by alex5678
I run this code:

Code: [Select]

void setup()
{
    // open a serial connection
    analogWriteResolution(12);
    analogReadResolution(12);
    //Serial.begin(9600);
}

void loop()
{
    int value_;
    //Serial.print(", 12-bit : ");
    value_ = analogRead(A1);
    //Serial.println(value_);
    analogWrite(DAC0, value_);
    // a little delay to not hog Serial Monitor
    //delay(100);
}


Nothing... Does it matter that I use 220uF instaed of 250uF that the schematic shows??

https://www.arduino.cc/en/Tutorial/SimpleAudioPlayer

Thank you...

Grumpy_Mike

Quote
Does it matter that I use 220uF instaed of 250uF that the schematic shows??
No.

Not at all sure what you are doing wrong now, it should work.

Let me try this myself. I should be able to have a try sometime before the morning, I am in the UK, but not at home at the moment.

Go Up