Audio lib hanging

Status
Not open for further replies.

swarfrat

Active member
I'm hesitant to say it's the audio library hanging, but on my Teensy 3.0, I have a couple problems with this simple program (below). I've got an Adafruit MAX4466 board wired up to pin 9, running off 3.3v. If I read raw analog values, I see more or less what I'd expect. But with the peak meter in the loop - if the mic ever clips (thump it) then the peak never goes below "10" (0 - 30) after that point. Trying to rule out that its not something actually holding a charge on the pin, I stuck an analog read in there, and it SOMETIMES prints the analogread value but other times prints it and then hangs the processor. It's not trying to print a float - it's a %d and cast to an int. And once in a while it actually lets another value escape to the serial console. If I completely remove the audio library and just print the raw value the pin goes to 1023 on clipping and then immediately falls back to around 510 (the 1/3 scale offset does not occur when reading the pin.)

Running Arduino 1.6.9 and Teensyduino v1.29-beta3

Code:
#include <Audio.h>
#include <Wire.h>

// GUItool: begin automatically generated code
AudioInputAnalog         adc1(A9);           //xy=164,95
AudioAnalyzePeak         peak1;          //xy=317,123
AudioConnection          patchCord1(adc1, peak1);
// GUItool: end automatically generated code


void setup() {
  AudioMemory(4);
  Serial.begin(9600);
}

// for best effect make your terminal/monitor a minimum of 31 chars wide and as high as you can.

elapsedMillis fps;

void loop() {
  if (fps > 24) {
    if (peak1.available()) {
      fps = 0;
      int monoPeak = peak1.read() * 30.0;
      Serial.printf("%d\r\n", monoPeak);

      if (monoPeak >9) 
      {
        Serial.printf("Raw: %d\r\n", (int)analogRead(A9));
      }
    }
  }
}
 
You definitely can not use analogRead while AudioInputAnalog is running. If analogRead tries to access the ADC hardware at the wrong moment, it'll get confused by the simultaneous access from AudioInputAnalog (using DMA) and it'll wait forever for the ADC to finish, because AudioInputAnalog interfered.
 
Thanks for clarifying that it makes sense - I was just trying to independently verify what was going on. AudioAnalyzePeak however still seems to get stuck with a non-clearing peak value of 10 in the example if the mic clips, which does not seem to happen if I do my own analogRead & peak detection. Since I'm just doing simple peak detection, I just ripped it out and read the pin directly, and my SPL meter stoplight works now.

The program works, though the stoplight had the opposite effect of what I intended - my 3yo now has a stoplight he can make turn red when he's loud. Instead of being a reminder that we need to wear hearing protection when we play drums, it's a game to make it turn red. :rolleyes: Shoulda seen that one coming.
 
AudioAnalyzePeak however still seems to get stuck with a non-clearing peak value of 10 in the example if the mic clips

Can you be a little more specific about how to reproduce this problem? None of the published examples use the mic by default. The signal range is supposed to be 0 to 1.0.

I'm sure what you're saying makes sense in the context of specific code, perhaps one of the examples with only slight modification? If there's a bug in the library that causes lockup, I've never stumbled across it. Can you please post the complete program to reproduce the problem. I'll test where with a mic and some loud sounds.
 
The source in the first post will do it - removing the analogread for clarity will result in the app running as expected, but never going below 10 once the mic clipped.

Code:
#include <Audio.h>
#include <Wire.h>

// GUItool: begin automatically generated code
AudioInputAnalog         adc1(A9);           //xy=164,95
AudioAnalyzePeak         peak1;          //xy=317,123
AudioConnection          patchCord1(adc1, peak1);
// GUItool: end automatically generated code


void setup() {
  AudioMemory(4);
  Serial.begin(9600);
}

// for best effect make your terminal/monitor a minimum of 31 chars wide and as high as you can.

elapsedMillis fps;

void loop() {
  if (fps > 24) {
    if (peak1.available()) {
      fps = 0;
      int monoPeak = peak1.read() * 30.0;
      Serial.printf("%d\r\n", monoPeak);

      // if (monoPeak >9) 
      //{
      //  Serial.printf("Raw: %d\r\n", (int)analogRead(A9));
      //}
    }
  }
}
 
Oh, I see now you're using an Adafruit mic and the ADC object. The library should not crash no matter when you connect, but I do need to know how you've connected things if I'm going to try to reproduce the problem.

I have the Adafruit mic here. I powered mine from 3.3V. It has 1.65 volt DC offset, so it's output certainly isn't directly compatible with the 0 to 1.2V range of the ADC input.

Do you have the recommended circuit between this Adafruit board and the A9 pin? Or if something else, can you give me a photo or diagram of how it's actually connected? I'll try the same here. If this were the audio shield mic, I could just run it with a board. But with a product like this Adafruit board, the connection details matter.
 
I hooked it up to pins AGND, 3.3V, and A9. Yes it's biased to 1/2 VCC but A9 reads that range anyway - it can't read negative. Raw reading shows bias reads 512 over time, as I'd expect it to. The Audio Librarie's AudioInputAnalog doc says "signal range is 0 to 1.2v" which looks about right for a 0-3.3V input and a 1.65v bias. I saw the circuitry but it wasn't clear what that was for - I can see it does DC blocking, but the rest of the circuit wasn't immediately clear what it did, beyond a little LPF as well. Since I've got a simple board that handles powering and buffering of the electret mic, I assumed I probably didn't need anything special as I already had a somewhat conditioned signal source.

Reading A9 directly gives me the results I expected to see.
Code:
int g_peak = 0;

void scanpeaks(void)
{
  int peak =0;
  for (int i=0; i < WINDOWSIZE; i++)
  {
      int val = analogRead(A9);
      peak = (val > peak) ? val :  peak;
  }

  noInterrupts();
  g_peak = peak - 512;
  interrupts();
}

Timer t1;

void setup() {
    t1.begin(scanpeaks, 100000);
}
...

It's just a volume meter, so I can miss short events. When the timer fires, it reads a bunch of samples, decides peaks based on that. Repeat. I left out the business logic of what to do with the signals for now. (The volume meter BTW did NOT have the intended effect. Rather than inform my 3yo that we need to wear hearing protection while playing drums. It just became a game to make the red light turn on. So... I might turn it into a build status indicator at work or something.)
 
Last edited:
The Audio Librarie's AudioInputAnalog doc says "signal range is 0 to 1.2v" which looks about right for a 0-3.3V input and a 1.65v bias.

No, you need a 0.6 volt DC bias, because the signal range is from 0 to 1.2V.


but the rest of the circuit wasn't immediately clear what it did,

Those extra parts create a low-noise 0.6V DC bias. At least it's supposed to be low noise, but it's just a low-pass filtering of the 3.3V power.



Reading A9 directly gives me the results I expected to see.

The audio lib uses the internal reference. To get the same results with analogRead(), you must use analogReference(INTERNAL).
 
Status
Not open for further replies.
Back
Top