Audio Library

Status
Not open for further replies.
I haven't tested everything I've done to my copy of Audio.cpp & Audio.h yet, and I haven't written a decent set of examples either, so I am not rushing to make a pull request but if anybody wants to take a peek at my initial additions/mods for the library they can look at my (albeit, I expect, temporary) fork at https://github.com/robsoles/Audio

Only testing by listening to headphones with an appropriate source on Line-in, the following sketch (compiled against my copy of the library) appears to meet my expectations - I am about to be dragged, kicking and screaming, roughly 1600 kilometres from anything I could use to more thoroughly test (and write sketches to test) my stuff for about three days so I figure I'll let anyone interested try this stuff sooner rather than later.
Code:
// filterCalc test sketch..

#include <Audio.h>
#include <Wire.h>
#include <SD.h>


//For Filter Type: 0 = LPF, 1 = HPF, 2 = BPF, 3 = NOTCH, 4 = PeakingEQ, 5 = LowShelf, 6 = HighShelf
  #define FILTER_LOPASS 0
  #define FILTER_HIPASS 1
  #define FILTER_BANDPASS 2
  #define FILTER_NOTCH 3
  #define FILTER_PARAEQ 4
  #define FILTER_LOSHELF 5
  #define FILTER_HISHELF 6

 
/*
typedef union
{
  // uint32_t uint1;
  unsigned long uint1;
  // int32_t int1;
  long int1;
} transInt;
*/

const int myInput = AUDIO_INPUT_LINEIN;
// const int myInput = AUDIO_INPUT_MIC;

// each filter requires a set up parameters
int BassFilterParameters[] = {  // notch, Fc=2175 Hz
  896456695, -1707514503, 896456695, 1707514503, -719171567, 0, 0, 0};
int TrebFilterParameters[]={0,0,0,0,0};

int updateFilter[5];

// Create the Audio components.  These should be created in the
// order data flows, inputs/sources -> processing -> outputs
//

AudioInputI2S       audioInput;         // audio shield: mic or line-in
AudioFilterBiquad   BassFilter(BassFilterParameters);
AudioOutputI2S      audioOutput;        // audio shield: headphones & line-out



// Create Audio connections between the components
//
AudioConnection c1(audioInput, 0, audioOutput, 0);
AudioConnection c2(audioInput, 0, BassFilter, 0);
AudioConnection c3(BassFilter, 0, audioOutput, 1);

// Create an object to control the audio shield.
// 
AudioControlSGTL5000 audioShield;



void filterCalc(uint8_t filtertype, float fC, float dB_Gain, float Q, uint32_t quantization_unit, uint32_t fS, int *coef)
{

// I used resources like http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
// to make this routine, I tested most of the filter types and they worked. Such filters have limits and
// before calling this routine with varying values the end user should check that those values are limited
// to valid results.

  float A;
  if(filtertype<FILTER_PARAEQ) A=pow(10,dB_Gain/20); else A=pow(10,dB_Gain/40);
  float W0 = 2*3.14159265358979323846*fC/fS; 
  float cosw=cos(W0);
  float sinw=sin(W0);
  //float alpha = sinw*sinh((log(2)/2)*BW*W0/sinw);
  //float beta = sqrt(2*A);
  float alpha = sinw / (2 * Q); 
  float beta = sqrt(A)/Q;
  float b0,b1,b2,a0,a1,a2;

  switch(filtertype) {
  case FILTER_LOPASS:
    b0 = (1.0F - cosw) * 0.5F; // =(1-COS($H$2))/2
    b1 = 1.0F - cosw;
    b2 = (1.0F - cosw) * 0.5F;
    a0 = 1.0F + alpha;
    a1 = 2.0F * cosw;
    a2 = alpha - 1.0F;
  break;
  case FILTER_HIPASS:
    b0 = (1.0F + cosw) * 0.5F;
    b1 = -(cosw + 1.0F);
    b2 = (1.0F + cosw) * 0.5F;
    a0 = 1.0F + alpha;
    a1 = 2.0F * cosw;
    a2 = alpha - 1.0F;
  break;
  case FILTER_BANDPASS:
    b0 = alpha;
    b1 = 0.0F;
    b2 = -alpha;
    a0 = 1.0F + alpha;
    a1 = 2.0F * cosw;
    a2 = alpha - 1.0F;
   break;
  case FILTER_NOTCH:
    b0=1;
    b1=-2*cosw;
    b2=1;
    a0=1+alpha;
    a1=2*cosw;
    a2=-(1-alpha);
  break;
  case FILTER_PARAEQ:
    b0 = 1 + (alpha*A);
    b1 =-2 * cosw;
    b2 = 1 - (alpha*A);
    a0 = 1 + (alpha/A);
    a1 = 2 * cosw;
    a2 =-(1-(alpha/A));
  break;
  case FILTER_LOSHELF:
    b0 = A * ((A+1.0F) - ((A-1.0F)*cosw) + (beta*sinw));
    b1 = 2.0F * A * ((A-1.0F) - ((A+1.0F)*cosw));
    b2 = A * ((A+1.0F) - ((A-1.0F)*cosw) - (beta*sinw));
    a0 = (A+1.0F) + ((A-1.0F)*cosw) + (beta*sinw);
    a1 = 2.0F * ((A-1.0F) + ((A+1.0F)*cosw));
    a2 = -((A+1.0F) + ((A-1.0F)*cosw) - (beta*sinw));
  break;
  case FILTER_HISHELF:
    b0 = A * ((A+1.0F) + ((A-1.0F)*cosw) + (beta*sinw));
    b1 = -2.0F * A * ((A-1.0F) + ((A+1.0F)*cosw));
    b2 = A * ((A+1.0F) + ((A-1.0F)*cosw) - (beta*sinw));
    a0 = (A+1.0F) - ((A-1.0F)*cosw) + (beta*sinw);
    a1 = -2.0F * ((A-1.0F) - ((A+1.0F)*cosw));
    a2 = -((A+1.0F) - ((A-1.0F)*cosw) - (beta*sinw));
  }

  a0=(a0*2)/(float)quantization_unit; // once here instead of five times there...
  b0/=a0;
  *coef++=(int)(b0+0.499);
  b1/=a0;
  *coef++=(int)(b1+0.499);
  b2/=a0;
  *coef++=(int)(b2+0.499);
  a1/=a0;
  *coef++=(int)(a1+0.499);
  a2/=a0;
  *coef++=(int)(a2+0.499);
}


void setup() {
  // Audio connections require memory to work.  For more
  // detailed information, see the MemoryAndCpuUsage example
  AudioMemory(12);
  // Enable the audio shield and set the output volume.
  audioShield.enable();
  audioShield.inputSelect(myInput);
  audioShield.route(1,1); // using I2S, using DAP
  audioShield.dap_audio_eq(1); // using Biquad filters
  audioShield.dap_peqs(1); // only using one of the filters.
  filterCalc(FILTER_PARAEQ, 3300, 0, 0.2, 524288, 44100,TrebFilterParameters);
  audioShield.load_peq(0,TrebFilterParameters);
  audioShield.volume(60);
}

elapsedMillis chgMsec=0;
float lastbass=0;
float lastvol=0;

void loop() {
  // every 10 ms, check for adjustment the tone & vol
  if (chgMsec > 10) { // more regular updates for actual changes seems better.
    float bass1 = analogRead(16);
    bass1=((bass1-512)/512)*60;
    bass1=(int)bass1;
    bass1=bass1/10;  // only changing for 0.1dB steps
    if(lastbass!=bass1)
    {
      filterCalc(FILTER_PARAEQ, 220, bass1, 0.2, 2147483648, 44100, updateFilter);
      filterCalc(FILTER_PARAEQ, 3300, -bass1, 0.2, 524288, 44100, TrebFilterParameters);
      BassFilter.updateCoefs(updateFilter); // load for AudioBiquadFilter
      audioShield.load_peq(0,TrebFilterParameters); // load for SGTL5000 PEQ.
      lastbass=bass1;
    }

    float vol1=analogRead(15)/1.024;
    vol1=(int)vol1;
    vol1=vol1/10;
    if(lastvol!=vol1)
    {
      audioShield.volume(vol1);
      lastvol=vol1;
    }
    chgMsec = 0;
  }
}
Anything I've added to my copy of the library that isn't used in that sketch should be considered untested.

If you try the above sketch I want your feedback please. If you try any of the 'untested' stuff in my fork I want your feedback twice as much ;)

I will write tests/examples for the other bits and pieces as soon as practical for me. When opportunity allows I am going to use some audio sweeping equipment at my work to more thoroughly test filters and other details.
 
oh (facepalm) I have 3 pots connected to my teensy 3.1, am on a train atm, later I will borrow a desktop and post replacement loop() for single pot tone only test, sorry.
 
hi,
i have a stupid question.....
can someone tell me what the basic wirering is to use the onboar dac with a small headphone speaker?
thank you!
ps:
i'm so happy to find this thread !!
 
The DAC isn't capable of driving a speaker by itself. If you try, you may damage the chip. You need to connect an amplifier to it.

To connect an amplifier, one wire on your input to the amplifier goes to ground, and the other goes to the DAC. Preferably through a small resistor (390 ohm will bring maximum mA you can draw from pin below 9mA reccomended maximum) to avoid any potential for damage. You will also want to call dac.analogReference(INTERNAL); to set the DAC to use the 1.2v internal reference (instead of the 3.3v reference it typically uses), which is close enough to the typical .894v spec for line level that you don't need to worry about sticking a voltage divider on there to get it down further.

A 1uf capacitor in series with the resistor might also be prudent but I don't think it would be necessary with the resistor on there protecting the pin, and the amplifier would have caps on it's own input.

I guess with the resistor on there you could drive a tiny speaker quietly directly from the DAC pin. You'd want to leave the analog reference at 3.3v. But it would be so quiet it's hardly worth it. I guess a piezo might be loud-ish but the audio quality would be terrible.
 
The DAC isn't capable of driving a speaker by itself. If you try, you may damage the chip. You need to connect an amplifier to it.

This is true, it's meant to only drive an amplifier. It's meant to output less than 1 mA current.

However, I did try connecting it to a speaker here, with a 10 uF capacitor in series. That Teensy 3.1 still works great. I wouldn't recommend anyone rely on this, but the DAC output does appear to be current limited. A tiny but audible amount of sound did come out the speaker.


I've been neglecting the audio library for the last few days while working on wrapping up a 1.18 release and a few other general PJRC business things. I'm going to get back onto the audio library development this weekend.
 
Paul:
I thought any pin of the Teensy could source up to 9mA? (actually I think the absolute max is quite a bit higher, but 9mA max seems to be the recommended max from the datasheet) Is the DAC pin different?

I intend to make a shield soon for my own use which uses the DAC for audio output, and I want to be sure the design will be reliable. I chose a 390 ohm resistor in series because that would limit the current below 9mA but if the limit is actually 1mA then I would need to increase that. (I can't rely in it being current limited if the datasheet doesn't say it is.)
 
Last edited:
Just in case there is somebody with an Audio Adapter and only one pot who is actually interested, here is a replacement loop() which does the 'tone test' and doesn't influence the volume control. It may be worthwhile to change the volume to 80 in the setup() routine to make it easier to hear.
Code:
void loop() {
  // every 10 ms, check for adjustment the tone & vol
  if (chgMsec > 10) { // more regular updates for actual changes seems better.
    float bass1 = analogRead(15);
    bass1=((bass1-512)/512)*60;
    bass1=(int)bass1;
    bass1=bass1/10;  // only changing for 0.1dB steps
    if(lastbass!=bass1)
    {
      filterCalc(FILTER_PARAEQ, 220, bass1, 0.2, 2147483648, 44100, updateFilter);
      filterCalc(FILTER_PARAEQ, 3300, -bass1, 0.2, 524288, 44100, TrebFilterParameters);
      BassFilter.updateCoefs(updateFilter); // load for AudioBiquadFilter
      audioShield.load_peq(0,TrebFilterParameters); // load for SGTL5000 PEQ.
      lastbass=bass1;
    }

    /*float vol1=analogRead(15)/1.024;
    vol1=(int)vol1;
    vol1=vol1/10;
    if(lastvol!=vol1)
    {
      audioShield.volume(vol1);
      lastvol=vol1;
    } */
    chgMsec = 0;
  }
}
 
Apologies if I should have put this in a new thread but thought it might be relevant enough to put here.

I am currently writing my entire audio program within one class copied from the existing ones. Would it be more or less beneficial in terms of memory or cpu to have separate classes for, for example, oscillator, filter, adsr, etc?

Thanks!
 
That would be a whole new library. Maybe some of the existing code might help you get a start. I do not know if the DMA channels will help. You'll probably need to use the I2S interrupts. Processing individual samples will not be nearly as efficient, but the ARM chip is pretty fast, so you still might manage to get it to do something useful.

But do not fool yourself into thinking this might be possible in the context of this audio library, which is fundamentally based on block processing.

Maybe my jabbering was a bit unclear, but what i meant is more like an audio connection/special audio stream. Of course, to be able to do what I described(audio signal direct passthrough) I understand that within the bounds of this lib, it could be only achieveble (if achieveble at all) without those direct forwarded samples could be modified. As I said, i'm a beginner in MCU programming, i'm viewing this from the point of an audio-guy, and i know this functionallity is very very handy in a lot of situations.

As far as i understand the audio "engine" does this in every 2,9ms:
While the new 128 samples are gathered, the previously gathered samples are being processed, AND the previously processed samples are being sent to output. Correct me if this is wrong, but this should introduce 5,8ms IO RTL, and that could mean a drawback for a number of applications.

For example, a recording application: In some cases (Eg. a musician would like to record him/herself playing) this amount of latency can confuse the player if he/she is listening to him/herself via the teensys output while playing (this is called direct monitoring). By the way, around 6ms is tolerable for most of the people, but still doesn't feel natural, and is uncomfortable, also, anything else in the signal chain will introduce extra latency, and if this adds up higher than 10ms, then direct monitoring is unusable.
So, the only thing the musician can do, is plugging the instrument in a D.I box (wich basically just for splitting the signal in this scenario) , and listens to himself via the D.I output 1, and connects the DI-s other output to the teensy, wich records the performance,

Another advantage could be taken of this in time based effects like reverbs, delays, modulation(flanger etc)). And still without the necessarrity of modifying the "direct through" sample, only by processing the audio block in "the next round".

And yes, with the power of the ARM chip, per-sample processing would make possible a number type zero-latency effects (1 sample to be axact, so not zero, but only a fraction of a millisec) wich is very enticing. But from here we get out of the scope of the current audio library, i know. Also, a lot of DSP methods are unusable per-sample , so the usage of audio blocks would be still required. and processing audio blocks need time, so this gets complicated here.

If I had the kowledge to write an audio library, i would make a similar approach described above. The audio engine would be forwarding samples to the output in the sample rate, but also would populate an user adjustable size ring buffer with samples. From then, every audio object could decide how many the samples is necessarry, and could decide it's own audio block size, what would of course equal to latency, and time to process the block.

Don't get me wrong Paul, I admire all the work You've done. I just thought that what i'm talking about is achievable within the bounds of the current lib.
I've only done some basic arduino projects in the last years, and have basic C knowledge. AlthroughIi'm an IT guy, my field is networking, and i'm a professional musician, and I work a lot with digital audio. But I don't even understand about 80% of the code in the audio library, and You've wrote all of it (besides creating the Teensy) so if You say that this kind of behaviour is not achievable, i believe it :) I just felt that maybe You didn't get what i was talking about exactly.

EDIT: As i can see on the datasheet of the SGTL5000, it has capabilities to create this kind of direct through, visible on the Simplified Application Diagram on the first page. I believe maybe this is what they call "Stereo LINEIN - Codec bypass for low power" among the features. As i found out, this should be supported only for the line in, and it also by-passes the DAC. So not exactly what i'm after, but definately could do the trick, but sadly only between the line-in and the HP out.


Also here is a simple bit crusher, and downsampler audio effect I've created. Could anybody point out how this could be optimized for the ARM chip? Because the majority of objects like the audio mixer, I don't really get the logic, because the ARM optimization I think. Also, can anybody point out how does the mixer "mix" two samples? What formula is used?
 
Last edited:
I was looking at the processor's datasheet to try to understand I2S, and it looks like there are two TX and two RX lines. That makes me think that it would be possible to talk to two audio boards at once, to get four channel audio. If I'm all wrong about this, please dissuade me before I dive in and try to get this working!
 
@Kondi:
A few comments on your "crusher".
There are a lot of syntax errors - undefined variables etc. (e.g. "data" is not defined)
The declarations of res and crushed_sample should be outside the while loop and crushed_sample doesn't need to be initialized to zero.
Declaring res as uint8_t won't work because if bit_depth is less than 10, res will be greater than a uint8_t can hold.
Your calculation of crushed_sample doesn't make sense. If data is an integer multiple of res you use data as the output. But if it isn't, you use data/res. This is really going to mess up the output signal.
Your simulated downsampling leaves the signal at the 44100Hz sampling rate which is in effect a downsample followed by upsampling. The way that a signal is upsampled in DSP is to insert zero samples and then lowpass filter the resulting signal. The lowpass filter is essential to avoid aliasing and it will be the place where optimization is needed, probably by using the fir filter code in the ARM CMSIS DSP library.

For the mixer code, see AudioMixer4 in Audio.cpp

Pete
 
Thanks for pointing out those all those errors, I've made some corrections. I don't want to flood the thread with my code so You can view it here.

Regarding the bulls*it logic that can be found in the crusher object:

What I am trying to create, is a very simple audio effect, that only simulates, the lower bitdepth, and sample rate. The results are the same resolution (44.1/16)on purpose. This effect has a very specific sound, and is often used as a creative effect.

Your calculation of crushed_sample doesn't make sense. If data is an integer multiple of res you use data as the output. But if it isn't, you use data/res. This is really going to mess up the output signal.


EDIT2: I've looked over on that error for first, and corrected. (The paste is refreshed too)Now it should behave like intended, but i thought that there should be a much simpler solution to this "round to integer with desired resolution".

Your simulated downsampling leaves the signal at the 44100Hz sampling rate which is in effect a downsample followed by upsampling. The way that a signal is upsampled in DSP is to insert zero samples and then lowpass filter the resulting signal. The lowpass filter is essential to avoid aliasing and it will be the place where optimization is needed, probably by using the fir filter code in the ARM CMSIS DSP library.

Like I've mentioned, that's on purpose. The aliasing, and artifacts are a part of the effect. It approaches the sample rate conversion like "sample and hold" . It takes a sample and holds it for however many steps it needs to.

The implementation of this effect should be OK imho (I'm not sure the negative numbers are handled well currently), althrough it can be implemented in a much easier way i think.

I can see the mixer object in audio.ccp, but unable to interpret the logic behind, that is why I've asked for it.
 
Last edited:
Just in case there is somebody with an Audio Adapter and only one pot who is actually interested, here is a replacement loop() which does the 'tone test' and doesn't influence the volume control. It may be worthwhile to change the volume to 80 in the setup() routine to make it easier to hear.
Code:
void loop() {
  // every 10 ms, check for adjustment the tone & vol
  if (chgMsec > 10) { // more regular updates for actual changes seems better.
    float bass1 = analogRead(15);
    bass1=((bass1-512)/512)*60;
    bass1=(int)bass1;
    bass1=bass1/10;  // only changing for 0.1dB steps
    if(lastbass!=bass1)
    {
      filterCalc(FILTER_PARAEQ, 220, bass1, 0.2, 2147483648, 44100, updateFilter);
      filterCalc(FILTER_PARAEQ, 3300, -bass1, 0.2, 524288, 44100, TrebFilterParameters);
      BassFilter.updateCoefs(updateFilter); // load for AudioBiquadFilter
      audioShield.load_peq(0,TrebFilterParameters); // load for SGTL5000 PEQ.
      lastbass=bass1;
    }

    /*float vol1=analogRead(15)/1.024;
    vol1=(int)vol1;
    vol1=vol1/10;
    if(lastvol!=vol1)
    {
      audioShield.volume(vol1);
      lastvol=vol1;
    } */
    chgMsec = 0;
  }
}


Bass seems to work with minimum clicks. Can't seem to get the load_peg filter to do anything.
 
Thanks for trying it cartere, I tested it by playing a song with lots of bass kick and high hat (Breathe - The Prodigy). Rolling the 'tone' pot back and forth seemed to influence both to my ear - more 'kick' and less 'hiss' at one end, more 'hiss' and less 'kick' at the other end, fairly 'normal' in the middle.

I brought the teensy with me coz I thought I could show it off to the people we are visiting here, they have a PC (I'm using to post this now) but I don't want to set up stuff on it that they will never use so I'm not reprogramming it here. I found an OK online tone generator and (just now) set it to output 3300Hz - I couldn't hear a difference to that in any position on the 'tone' pot.

I can imagine it is the load_peq(..) routine itself except that if that is applying wrong values it should still have an influence (expect ugly...) so it must be one or more the route selection or dap_enable(1) or dap_peqs(1) that isn't doing as it should.

I am here for another few hours, I will get home so late tonight (~1am my time) that I should just go to bed hoping not to be a zombie at work tomorrow but I should find the failure and fix it by Tuesday afternoon for sure. (lol, so embarrassed I might sit up tonight till I've got it (facepalm)).

The influence I thought I heard it applying to the high hat may be the width of influence the bass filter is setup at.
 
I have done all the bit diddling on paper and can't see why it should not work, but I suspect the "modify" routine is not working right in the library. Must confess I am lost in the C++ world of private vs protected, public makes sense. If modify does not work nothing works................which unfortunately seems to be the case.
 
OH! I just reviewed my copy on github and now I think it is definitely the load_peq(..) routine just missing the simplest thing - it loads the coefficients to the appropriate registers but it doesn't do the following
Code:
  write(DAP_FILTER_COEF_ACCESS,(uint16_t)0x100|filterNum);
  delay(10); // may be unnecessarily long, 1ms or even none is probably OK.
  write(DAP_FILTER_COEF_ACCESS,(uint16_t)filterNum);

So, if you can't wait for me to make the addition you could modify your local copy of Audio.cpp to make load_peq(...) look more like
Code:
// SGTL5000 PEQ Coefficient loader
void AudioControlSGTL5000::load_peq(uint8_t filterNum, int *filterParameters)
{
// 1111 11111111 11111111

  write(DAP_COEF_WR_B0_MSB,(*filterParameters>>4)&65535);
  write(DAP_COEF_WR_B0_LSB,(*filterParameters++)&15);
  write(DAP_COEF_WR_B1_MSB,(*filterParameters>>4)&65535);
  write(DAP_COEF_WR_B1_LSB,(*filterParameters++)&15);
  write(DAP_COEF_WR_B2_MSB,(*filterParameters>>4)&65535);
  write(DAP_COEF_WR_B2_LSB,(*filterParameters++)&15);
  write(DAP_COEF_WR_A1_MSB,(*filterParameters>>4)&65535);
  write(DAP_COEF_WR_A1_LSB,(*filterParameters++)&15);
  write(DAP_COEF_WR_A2_MSB,(*filterParameters>>4)&65535);
  write(DAP_COEF_WR_A2_LSB,(*filterParameters++)&15);

  write(DAP_FILTER_COEF_ACCESS,(uint16_t)0x100|filterNum);
  delay(10); // may be unnecessarily long, 1ms or even none is probably OK.
  write(DAP_FILTER_COEF_ACCESS,(uint16_t)filterNum);
}
So, with that addition we would get to hear whether or not the values are being applied correctly.

I don't want to play with the github editor so in roughly 13 hours I will push this update to my copy on github from my home PC, and then I will go to bed :)

edit:
I have done all the bit diddling on paper and can't see why it should not work, but I suspect the "modify" routine is not working right in the library. Must confess I am lost in the C++ world of private vs protected, public makes sense. If modify does not work nothing works................which unfortunately seems to be the case.
If the modify(..) routine returns expected results of bit diddling then it should (even so much as easily) be applying the value it returns to the selected rergister because it uses a 'known-to-work' (write(..)) method to apply it.

I have to get off this PC but I am checking the thread on my phone fairly regularly.
 
Last edited:
OK I'm bad :) Works much better now, had been trying to get lo_lvl_right to work and not seeing any change, that works as well as the filter now.
 
BTW: write(DAP_FILTER_COEF_ACCESS,(uint16_t)filterNum); should be write(DAP_FILTER_COEF_ACCES,(uint16_t)filterNum);
 
Hi everyone. Just checking in here. I haven't touched the audio library in the last few days. As you can see from other threads across the forum, I'm on a bug fixing rampage... leading up to an official 1.18 release.

Planning to work only on the audio library all next week.
 
BTW: write(DAP_FILTER_COEF_ACCESS,(uint16_t)filterNum); should be write(DAP_FILTER_COEF_ACCES,(uint16_t)filterNum);

I didn't check Paul's defines, sorry about that. I think I will add the second S to them rather than take it off elsewhere.

Glad to hear things seem working now.

@Paul: Was silly of me to decide I would make the pull request without further review, please reject that one and I will make a much better considered one later.
 
Last edited:
Back to the technical stuff ... ;)
Whow can i Input line Level Audio into the Teensy 3.1 direct ? Without any Audio shields ...
I read in the datasheet that it has two adc's with 16bit And could handle 44.1khz...
Soooo what is the wirering side ?
The Outputs will be finished this afternoon ;)
Thank you for this !!
 
Unable to get AudioInputAnalog to work

I'm having issues getting sane data into the main input buffer for a FFT using AudioInputAnalog reading a microphone.
Using the latest Audio lib pushed to github, I've tried Teensyduino 1.18 RC2, and also what changes Paul made in cores as of this posting. Looking at the buffer going into the FFT, something is up with the reads. I've spent a few hours trying to track down what is going wrong in Audio.cpp but haven't been able to get a full buffer of sane data. Using analogRead by itself works perfectly. Attached to this post is a picture of how the hardware is setup.

Code:
#include <Audio.h> // at line ~979, changed to use analogReference(DEFAULT);
#include <Wire.h>
#include <SD.h>

AudioInputAnalog analogPinInput(A9); // analog A9 (pin 23)
AudioAnalyzeFFT256  myFFT(1);
AudioConnection c0(analogPinInput, 0, myFFT, 0);

void setup() {
  AudioMemory(12);  // MemoryAndCpuUsage example, where is it?
}

void loop() {
  if (myFFT.available()) {
    Serial.println("444444"); // resets the xPos in processing
    for (int i=0; i<128; i++) {
       Serial.println(myFFT.output[i]);
    }
  }
}
 

Attachments

  • Teensy3.1 and Mic.jpg
    Teensy3.1 and Mic.jpg
    364.3 KB · Views: 295
@Rossitron
AFAIK, the FFT code is part of the Audio library which won't work unless the Audio shield is present.

Pete
 
AFAIK, the FFT code is part of the Audio library which won't work unless the Audio shield is present.

The Teensy3 Audio Board, available and in stock as of Jan 3, 2014, is the primary hardware intended to be used with this library. It's also possible to use PWM output and ADC input.

The FFT code is from the CMSIS-DSP lib and seems to work fine. AudioInputAnalog almost works for me. About half of the buffer looks good.
 
Looks like the audio library can read from an analog pin but you will have to set up the connections properly.
The PlayMidiTones example has some commented code which sets up pin 16 as an analog input. If you read this and the FFT example you should be able to see how to set up the connections.

Pete
 
Status
Not open for further replies.
Back
Top