audio record, processing and play with teensy 3.1

Status
Not open for further replies.

saxen

Active member
Hello everybody,
I'm going to start a project soon, and after searching around about the hardware to use (arduino, rpy, etc.), I found out about teensy 3.1. It seems very interesting, but I want to be sure that the board meets the requirements of my project.
In few words, I will need to use a mic and speaker to record sound and play sound. I found this mic, and I'm looking for something similar (in size/cost) for the speaker. I guess I will also need an amplifier for the audio output.

Here are a couple of questions:
1) Can I record and play sound at 44.1KHz sampling rate using the ADC and DAC available in Teensy? I know that the available memory might be a limitation, but I do not need to store the recorded audio, just some DSP with it and discarded.

2) About the output amplifier, I found this Op Amp, or this audio amp. I know they are two different things, but which one do you think might fit better between the teensy internal DAC and a small speaker?

Thanks for your time, and I hope you can help me with these questions.

Enrico
 
Here are a couple of questions:
1) Can I record and play sound at 44.1KHz sampling rate using the ADC and DAC available in Teensy?

Play, yes.

Record, maybe, but no such code exists yet, so it's not even 100% certain whether this is possible. If it is, your choices will involve some combination of waiting for the audio library to develop, or writing the code yourself.

2) About the output amplifier, I found this Op Amp, or this audio amp. I know they are two different things, but which one do you think might fit better between the teensy internal DAC and a small speaker?

The 3.7W amp is designed to drive a speaker. That little opamp probably isn't capable of powering a speaker.
 
Hi Paul,
thank you for your answers.
About recording, maybe this was not the right word to use, sorry. What I meant was getting 44100 samples per second from the ADC (analogRead?) and do some processing with them. Basically, something in this direction but with 44.1k sampling rate. So, is this possible? :)

Thanks,
Enrico
 
Last edited:
It is possbile to get the output what you want easily . Please refer to below calculations:
You require a sampling rate of 44100 samples per second that means a conversion time of 1/44100 = 22.67 Usec.
But the conversion rate that teensy3.1 controller offers is much fast almost 11 times faster.
You Just need to choose the configuration carefuly.
For details please refer to the datasheet of the teensy3.1 microcontroller.
I have pasted a screenshot of the same below :
conversion time.PNG
 
What I meant was getting 44100 samples per second from the ADC (analogRead?) and do some processing with them.

Yes. In fact, the audio library already has an object for the ADC input. So far, it's a little light on the "do some processing" part. There's a FFT object that sort-of works. You can certainly feed the audio through the mixer with other sources and output it. Eventually the library will get many more objects that do analysis on the sound.
 
So far, it's a little light on the "do some processing" part. There's a FFT object that sort-of works. You can certainly feed the audio through the mixer with other sources and output it. Eventually the library will get many more objects that do analysis on the sound.

Until here, I thought I understood everything. :)

I want to build a guitar effects pedal with the Teensy (something like the pedalshield http://www.electrosmash.com/pedalshield or the stompshield http://www.openmusiclabs.com/projects/stomp-shield/). And my assumption was/is that I could use their arduino sketches already because the teensy is fully compatible. Can you point me to the error in my theory? Thanks a lot! :)
 
Hi Eggsperde,
Stomppedal code for the arduino wont work straightaway on Teensy3.0/3.1.. it is not the same kind of chip, and many registers are hard coded to get stuff like freerunning adc's and more going on the small AVR chips
.. But my guess is, that the Teensy3.1 will quickly be adapted by the stompbox freaks.. you dont even need the audioshield for fullspeed 12-bit playback! Just use a timer to get a stable samplefrequency, read 1 or more adc's (you can use standard calls to start with, they are fast enough on Teensy 3.
I've measured standard analogRead() performance yesterday, and calculated performance for it, I switchd resolution easily with analogReadRes();
Conversion times with analogRead()
16bit 11.8 uS
10bit 8,6 us
8bit 4.2 uS

So if you were to sample with 60khz ( which could also be 2 channels of 30 khz ofcourse..)
16bit: 60k*11,8us= 708mS -> ~30% free for processing
10bit: 60k*8,6us= 516mS -> ~50% free for processing
8bit: 60k*4,2= 258mS -> ~75% free for processing

So, actually it is a piece of cake to make a (multichannel in, mono out) stompbox with 10 or 8 bit with pure a teensy3.1, for real 16 stereo bit i'd advise to go for the audioshield plus audio library. nobody has build a stompbox with it sofar as far as I know, but hey.. maybe you are the first..




Until here, I thought I understood everything. :)

I want to build a guitar effects pedal with the Teensy (something like the pedalshield http://www.electrosmash.com/pedalshield or the stompshield http://www.openmusiclabs.com/projects/stomp-shield/). And my assumption was/is that I could use their arduino sketches already because the teensy is fully compatible. Can you point me to the error in my theory? Thanks a lot! :)
 
Hi Paul,

I read very positive things about the Teensy project in general and your communication in special. Great to see you live and in action! :)

Since I am a rather new citizen in the microcontroller world, I will just order a Teensy for playing around with buttons and LEDs and wait for the
stompbox freaks
to make the
piece of cake
slightly easier to digest. You calculations definitely give hope to well-sounding results. Thank you very much for your reply; I will come back in due time.

All the best!!!
 
Eggsperde, don't mix the great Paul Stoffregen up with humble me! I'm PaulD, and I will post a working stompbox code this weekend for Teensy3.1, it is testproject for me, so it is no extra work.
Wishing you also the best, nevertheless! ")
 
Oh no, how embarrassing... and on the internet.... forever... .plus being officially guilty of thread-hijacking. Sorry for the confusion, Paul!

Do you plan publishing your efforts with the Guitar-Teensy? I am absolutely interested in seeing your ideas materialize in the very first implementation.

Cheers,
Frank
 
haha Eggsperde,
I've got the code running, with synchronized background adc function, using Pedvides adc library: https://github.com/pedvide/ADC
You can choose resolution and sampleRate you want, lowering sampleRate will give you more cpu time, ofcourse..
I havent tested it with actual guitar yet, but hey, it runs, gives vital information about performance over serial, so you can tweak it fast.
Have fun!
-You'll have to connect your guitar to A0 via C and dividernetwork. protective Diodes strongly recommended!
-output A14 via C

Code:
/*
---------------------------------------------------------------
 C r u d e   S t o m p b o x   w i t h   T e e n s y   3 . 1 
---------------------------------------------------------------
Version 0.1  "Fuzzzzyy.."
Paul Driessen - 27 March 2014
ADC library used https://github.com/pedvide/ADC

This code represents the shortes way a sample can travel through a Teensy 3.1.
It uses Pedvide's ADC lib, for the benefit of adc usage in the background, the standard Arduino calls dont support that ( why not? )
Once setup correctly, the audiolatency of this code is 2 samples.

Features:
-low latency 2 sample latency throughput, output 12 bits via internal ADC
-A serial performance indicator will show you how much CPU you have left for coding cool stuff.
-An example fuzz routine with simple LP filter

Connections needed:
Input circuitry:
[TODO] ** OWN RISK **

Output circuitry:
-A condensator on pin A14

*/

#include <ADC.h>

ADC adc; // adc object

int rawAudioIn; 
int dcAudio;
int audioIn;
int audioOut;
int sampleRate;
int microsPerSample;
elapsedMicros microCount;
elapsedMillis updateDisplay;
int accu=0;

void setup()
{                
  Serial.begin(38400);
  delay(1000);
  adc.setAveraging(1);                   // where not into astrophysics here, no averaging required
  adc.setResolution(16);                 // valid resolutions for singelended adc like this are 8, 10, 12 or 16 bit.
                                         // each resolution comes with it own max speed.  
                                         // Note: 16 bit will distort the output easy, I've added no conversion between bit depth buildin ( but it's easy: code it yourself!)
  sampleRate=50000 ;                    // requested samplerate, will result however in 1 uS steppable frequencies!
  microsPerSample= 1000000/sampleRate;   // thats how we keep pace
  
  analogWriteResolution(12);             // max resolution on the output
  
  for(int t=0; t<40000; t++)
  {
    accu  += adc.analogRead(A0);          // get the dc level.. 
  }
  dcAudio = accu / 40000;
  
  adc.enableInterrupts();
  adc.startSingleRead(A0);                //get the systems started,
  //adc.startContinuous (A0);
  while(!adc.isComplete()) {};   //gets the first rawAudio..
  microCount=0;
}

volatile byte readySample=0;
int adcUsage=0;
int originalAudio;
void loop()                     
{
  audioIn += (rawAudioIn - dcAudio);             // get rid of DC values the easiest way.. 
  readySample=0; //reset flag
  adc.startSingleRead(A0);                       // prepare the sample for next 
  originalAudio=audioIn;
  //rawAudioIn= adc.analogReadContinuous (); 
  analogWrite(A14, (audioOut+2048));             // 1uS: write the value from previous calculation
  //
  //  
  // S T A R T   O F  C O D I N G   A R E A  ( you'll have about 80% power at your dispo @ 44,1k )
  //
  // Let's try a fuzz to start with..
  int posTreshold=50;      //higher than this will be set to Outlevel
  int negTreshold=-50;     //lower  than this will be set to -1* Outlevel
  int outLevel=1000;       // 
  int IR_filter=8;         // LP: the higher the number, the more the squarewave becomes smooth
  if(audioIn>posTreshold)
  { 
      audioIn=outLevel;    
  }else{
     if(audioIn<negTreshold)
      { 
          audioIn=-1*outLevel; 
      }else{
          audioIn=0; // dead silence below treshold, typicall for fuzz..
      }  
  }  
  // now apply a simple IR filter, to smooth the edges (LP)
  audioIn = audioOut + ( (audioIn - (audioOut)) / IR_filter );
 // Output is ready, copy it to the output.
  audioOut =  audioIn; // 
  
  //  
  // E N D   O F  C O D I N G   A R E A  
  //
  
  // Display Performance in %
  int MC= microCount;
  int Performance= (MC*100)/(microsPerSample);
  int actFramerate =(1000000/microsPerSample);
  if(updateDisplay>1000)
  {
    Serial.println("");
    Serial.print("Time between samples:");
    Serial.println(microsPerSample);
    Serial.print("Real samplerate:");
    Serial.print(actFramerate);    
    Serial.println(" uS"); 
    Serial.print("CPU usage:");
    Serial.print(Performance);
    Serial.println("%"); 
    Serial.print("ADC usage:");
    Serial.print((adcUsage*100)/(microsPerSample));
    Serial.println("% "); 
    Serial.print("originalAudio:");
    Serial.println(originalAudio);
     Serial.print("audioOut:");
    Serial.println(audioOut);
    updateDisplay=0;
  }  
  while(microCount<microsPerSample){}     // fill our timing budget

  microCount-=microsPerSample;            // keep pace 
}

void adc0_isr(void) {
    // Low-level code
    rawAudioIn=ADC0_RA;
    //GPIOC_PTOR = 1<<5; */
    readySample=1;
    adcUsage=microCount;
}
 
Hi Paul, now thats a lot of awesomeness for one post! :)

Thanks a lot for the code and the additional hints! With them the list of ingredients for this project is complete... your support is highly appreciated!

Have a good one,
Frank
 
You certainly can build your own sampling code, but the audio library already has this implemented with very efficient DMA transfers. The DMA engine automatically moves the samples 44100 times per second, so only a single interrupt is generated when a buffer fills. That leaves far more CPU time available for implementing your effects.

The audio library is still very beta status, but the inputs and outputs work quite well. El Supremo contributed a few effect objects, like chorus and flanging, which could be really useful for a guitar peddle.

Of course, you can write your own effect objects. Here's a page with details.

http://www.pjrc.com/teensy/td_libs_AudioNewObjects.html

Basically, you just copy the template and write your own update() function that processes each block of 128 audio samples. Use those functions documented on that page and your effect object will integrate nicely with the rest of the audio library.

The beauty of using the audio library, aside from the already-working efficient input/output, is your effect object will be able to receive input and send output to any other objects. So your effect could run together with chorus and flange, with all 3 running simultaneously, and them perhaps feed those 3 to a mixer object, which then drives the output object.

If you later decide you also need to add a filter before or after your effect, it's extremely easy. Just create another object in your sketch, and different connection objects to route the audio between them. The library lets you very easily build complex audio processing systems, because everything is interoperable with the connection objects to hook the audio streams together between them in any way you need.

The audio library takes care of everything in the background. Your object would also do all its work in the background, every time the library calls its update() function to process another 128 samples.

With all the audio processing happening in the background, your Arduino sketch can do things like adjust your object's parameters or the mixer gains (for more/less chorus, more/less flange, more/less of whatever your custom effect does, etc).

Even though the audio library is still considered beta, and APIs might change before 1.0 release, it already has a lot of excellent infrastructure and interchangeable input and output objects (very easy to upgrade from built-in 12 bit DAC to 16 bit I2S for a higher quality audio DAC) that can really help for a guitar peddle project.
 
Last edited:
Your right! But I just wanted to present a simular "crude" approach as some AVR guitar peddles, I know audiolibrary is better for sound and versatility. The only thing my example does better is latency, and the freedom to choose any samplerate/bitdepth you want, on the fly.. and yes: having no buffer makes it extremely inefficient to make calls to routines, I know..
 
Hi PaulD, the link to the Analog Devices wiki is great - I "wasted" 2h there already today. :)

It throws me a bit back again on the other hand, because now I am not sure which op amp to take. Originally I wanted to buy this amp http://fredsamplifiers.com.au/index.php?main_page=product_info&cPath=3&products_id=83 and use one output for the link to the Teensy and one for headphones (clean sound and no delay). The battery is a bit of a turn-off on the other hand and your suggestion looks somewhat simpler... Guess I have to keep reading. Not the worst thing to do. ;-)
 
Not to hijack, and I have no plans for an audio effects device, but I know MaxMSP can export it's "Gen" level code to a C++ file. I wonder how difficult it would be to prototype effects in MaxMSP->Gen, and then take that code and implement it on a Teensy 3.1. If it could be made relatively painless, it would be a HUGE boon to the Max community.
 
Status
Not open for further replies.
Back
Top