Go Down

Topic: AtMega board and simple DSP tasks?? (Read 1 time) previous topic - next topic

khamin00

Can Atmega Arduino board can be used for simple real time DSP applications?
as a n example, receiving an noisy audio signal from a mic and filter such signal and then output a clear audio signal ?

CrossRoads

Only it if is low bandwidth.
10-bit ADC max sample rate is ~10KHz, and you need a DAC to output a clear signal.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

Mr_arduino

#2
Jun 20, 2013, 05:30 pm Last Edit: Jun 20, 2013, 05:44 pm by Mr_arduino Reason: 1
Also please don't use analogRead() if you care about performance.
Here is a simple example to read the A0 and output it using PWM on pin 3.
Code: [Select]

#include <stdint.h>
int speakerPin = 3; // Can be either 3 or 11, two PWM outputs connected to Timer 2
void startPlayback()
{
   pinMode(speakerPin, OUTPUT);

   // Set up Timer 2 to do pulse width modulation on the speaker
   // pin.

   // Use internal clock (datasheet p.160)
   ASSR &= ~(_BV(EXCLK) | _BV(AS2));

   // Set fast PWM mode  (p.157)
   TCCR2A |= _BV(WGM21) | _BV(WGM20);
   TCCR2B &= ~_BV(WGM22);

       // Do non-inverting PWM on pin OC2B (p.155)
       // On the Arduino this is pin 3.
       TCCR2A = (TCCR2A | _BV(COM2B1)) & ~_BV(COM2B0);
       TCCR2A &= ~(_BV(COM2A1) | _BV(COM2A0));
       // No prescaler (p.158)
       TCCR2B = (TCCR2B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);
}


void setup()
{
      pinMode(ledPin, OUTPUT);
  OCR2B=0;
       startPlayback();
   ADMUX = (1<<REFS0)|(1<<ADLAR);
   ADCSRA = (1<<ADEN)|(1<<ADPS2);
}

void loop()
{
 // start single convertion
 // write '1? to ADSC
 ADCSRA |= (1<<ADSC);

 // wait for conversion to complete
 // ADSC becomes '0? again
 // till then, run loop continuously
 while(ADCSRA & (1<<ADSC));
 OCR2B=ADCH;

}

A tip to speed up DSP processing is process the previous byte while waiting for the next one.
Also note that this example ignores the lower 2 bits if you want the lower 2bits to get a total of 10 bits you will need to need to remove |(1<<ADLAR) then read ADCL first do something like this
Code: [Select]

uint8_t temp=ADCL;
uint16_t output=temp|(ADCH<<8);

Notices how I did not just do
Code: [Select]

ADCL|(ADCH<<8)

This is because ADCL must be read first.

g_u_e_s_t

here is project that does 10b/32ksps audio in and out on the arduino:
http://wiki.openmusiclabs.com/wiki/MiniArDSP

very easy things are possible, but not too much more.  i am not sure what you intend by "removing noise", but unless the noise is concentrated in a certain frequency band, it probably wont be possible.

Grumpy_Mike

Quote
receiving an noisy audio signal from a mic and filter such signal and then output a clear audio signal

I am not sure that any computer in the world is capable of doing that, let alone an arduino.
You stand much more of a chance with a Due because you have more memory and more processing power.

Magician

http://interface.khm.de/index.php/lab/experiments/arduino-realtime-audio-processing/
http://coolarduino.wordpress.com/2012/04/09/voice-pitch-shifting-scrambler/

Grumpy_Mike

Yes but non of those links do what the OP was asking for.

Magician

Quote
The first nonlinear technique is used for reducing wideband noise in speech signals. This type of noise includes: magnetic tape hiss, electronic noise in analog circuits, wind blowing by microphones, cheering crowds, etc. Linear filtering is of little use, because the frequencies in the noise completely overlap the frequencies in the voice signal, both covering the range from 200 hertz to 3.2 kHz. How can two signals be separated when they overlap in both the time domain and the frequency domain?

Here's how it is done. In a short segment of speech, the amplitude of the frequency components are greatly unequal. As an example, Fig. 22-10a illustrates the frequency spectrum of a 16 millisecond segment of speech (i.e., 128 samples at an 8 kHz sampling rate). Most of the signal is contained in a few large amplitude frequencies. In contrast, (b) illustrates the spectrum when only random noise is present; it is very irregular, but more uniformly distributed at a low amplitude.

Now the key concept: if both signal and noise are present, the two can be partially separated by looking at the amplitude of each frequency. If the amplitude is large, it is probably mostly signal, and should therefore be retained. If the amplitude is small, it can be attributed to mostly noise, and should therefore be discarded, i.e., set to zero. Mid-size frequency components are adjusted in some smooth manner between the two extremes.

http://www.dspguide.com/ch22/7.htm
Due 'd definitely do this process (of noise reduction) perfectly well , but someone with low budget can get a flavor of DSP with standalone Atmega328p also. Especially when narrow-band interference is an issue, than pitch-shifting example could cut-out such annoyance easily.

jroorda

I did an Arduino DSP project for a course honors project.  What I found was your code has to be very well optimized, because if you can't get near a 20KHz sampling frequency you will get aliasing distortion or you will need to filter out the highs before they get to the Arduino.  I found that I could use an FIR filter to do a basic low pass or bandpass filter, but not much more. 

I used an external SPI controlled DAC to get the audio out, but if I were to do it today I would get the Due, as it has the DAC built in an is fast enough to allow more serious filtering.

Go Up