Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 10 of 10

Thread: Audio library without Audio adapter - ADC to RMS

  1. #1
    Junior Member
    Join Date
    Jun 2016
    Posts
    1

    Audio library without Audio adapter - ADC to RMS

    I'm not much of an audio expert and I'm looking for a little advice on an issue. I've connected an ADMP401 MEMS mic to the Teensy 3.2 ADC pin A9 and I'm using the audio library to connect and calculate the RMS value of the incoming signal. The setup works, though the RMS output sits at 0.37 in quiet environments and max output is around 0.80. I expected the min and max values of 0-1 and I'm wondering why this is and how to resolve it.

    I see in the Audio System Design documentation that the input signal range is 0 - 1.2v and since the mic specs indicate that the output signal sits at half of the VCC - 1.65v, I'm guessing this is the issue. Is this the case? And why is the input range 0-1.2v when I thought ADC input range is 0-3.3v?

    Also, I'm still a bit perplexed on the sample rate and bit depth when using the ADC and/or the audio library. The audio library by default captures at 16bit/44.1k? I've come across the ADC library which enables various settings but I'm wondering if that applies and how to control sample rate and bit depth when using the Audio Library.

    Thanks so much for the help!

  2. #2
    Senior Member Ben's Avatar
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    401
    Hi,

    the Audio Library switches the reference voltage to an internal reference which is more precise and less noisy that the 3.3V generated by Teensys voltage regulator. This enhances ADC performance but limits the input voltage to 0...1.2V.
    The mic has an offset voltage of 0.8 volts (datasheet), not ideal since it's not exactly half the ADC voltage range, but it's ok. But with loud signals you will possibly overdrive the ADC because the signal will get larger than 1.2V, and you won't be able to use the full 0...1.2V range without overdriving the ADC (clipping).

    To my knowledge the Audio Library is fixed at 44.1/16. The ADC is technically capable of sampling with 16 bit, but the lower bits are noisy, the effectively usable resolution is about 12 bits.

  3. #3
    Senior Member duff's Avatar
    Join Date
    Jan 2013
    Location
    Las Vegas
    Posts
    955

    Red face

    Quote Originally Posted by nejohnson2 View Post
    I see in the Audio System Design documentation that the input signal range is 0 - 1.2v and since the mic specs indicate that the output signal sits at half of the VCC - 1.65v, I'm guessing this is the issue. Is this the case? And why is the input range 0-1.2v when I thought ADC input range is 0-3.3v?

    I'm using the same microphone just use this circuit:
    Name:  adccircuit.png
Views: 961
Size:  60.8 KB
    This will bias the signal at .6V DC. This one uses A2 but just connect it to whatever one you want. This mic will overdrive the ADC if is held close and talking loudly using the internal reference. If you have the sparkfun breakout you might be able to lower the gain by some circuit rework also.

    Or you can wait for the update to the Audio library where it will let you change which reference you want i.e..(0->1.2V) or (0->3.3V).

  4. #4
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,068
    Quote Originally Posted by nejohnson2 View Post
    I've come across the ADC library which enables various settings but I'm wondering if that applies and how to control sample rate and bit depth when using the Audio Library.
    The functions to access in Arduino normalize the signal levels to a 1.0 scale with floating point numbers. Likewise, the sample rate isn't supposed to be exposed to Arduino code. Well, not unless you use the queue objects which provide access to raw data. Otherwise, the Arduino functions are meant to always work the same way, regardless of what sample rate and bit depth the library actually uses.

    The sample rate is fixed. So is the bit depth. In theory you could edit the library code to change these, but it's not simple. The sample rate as a #define in AudioStream.h, but there's also device-level code in the input & output objects which is hard-coded for 44.1 kHz. You'd need to change all of that stuff. Likewise, the entire library is designed for 16 bits.

    There is a high res 32 bit sine wave... and someday we'll have a 32 bit I2S output and maybe some other 32 bit stuff, which use a pair of 16 bit connections to move 32 bit data. Creating these takes a lot of programming work, and they run much slower, partly because they have to move twice as much data, but also because the Cortex-M4 DSP extensions are optimized to speed up 16 bit samples.

  5. #5
    Junior Member
    Join Date
    Jul 2016
    Posts
    3

    AudioInputI2S question

    HI,

    I'm trying to read a couple of digital mics using the audio lib. I have the mics connected to the teensy with a i2s to pdm adapter and the i2s signals from the adapter are connected to the proper nets on the teensy.

    When I use the AudioInputI2s class to create an input object I loose the usb serial on the teensy and the teensy is completely unresponsive.
    I'm using Visual Studio 12 with Visual Micro with the Teensyduino load, not sure if that plays into the equation or not.

    Here is the code..

    #include "c:\Teensy 3.1\ICT\common\Audio\Audio.h"
    #include "c:\Teensy 3.1\ICT\common\Audio\analyze_rms.h"

    int s_line_flags;

    AudioInputI2S micIn;
    AudioAnalyzeRMS leftRMS;
    AudioAnalyzePeak leftPeak;

    AudioAnalyzeRMS rightRMS;
    AudioAnalyzePeak rightPeak;


    AudioConnection c1(micIn, 0, leftPeak, 0); //source, sourcePort, destination, destinationPort
    AudioConnection c2(micIn, 1, rightPeak, 1);
    AudioConnection c3(micIn, 0, leftPeak, 0); //source, sourcePort, destination, destinationPort
    AudioConnection c4(micIn, 1, rightPeak, 1);

    void p_main()
    {
    int inVal;

    Serial.begin(115200);
    //turn on LED so I know it's at least got power

    AudioMemory(10); //declare audio blocks; 1 block is about 2.9ms of playback
    micIn.begin();

    while (1)
    {
    digitalWrite(4,!digitalRead(4));
    Serial.printf(".");

    if (leftPeak.available())
    {
    inVal = leftPeak.read();
    Serial.printf(" LeftPeak = %d\r\n", inVal);
    }

    if (rightPeak.available())
    {
    inVal = rightPeak.read();
    Serial.printf(" RightPeak = %d\r\n", inVal);
    }
    delay(50);
    }
    }

  6. #6
    Senior Member
    Join Date
    Jul 2014
    Posts
    2,188
    Quote Originally Posted by t3man View Post
    HI,

    I'm trying to read a couple of digital mics using the audio lib. I have the mics connected to the teensy with a i2s to pdm adapter and the i2s signals from the adapter are connected to the proper nets on the teensy.

    When I use the AudioInputI2s class to create an input object I loose the usb serial on the teensy and the teensy is completely unresponsive.
    I'm using Visual Studio 12 with Visual Micro with the Teensyduino load, not sure if that plays into the equation or not.
    As you seem to have issues with VS, I suggest to try it out first with standard Arduino IDE, which is the official platform supported by PJRC; all others approaches are only useful if you are familiar with their usage. I, myself use plain makefile and NO IDE, but for technical questions on this forum I convert to Arduino IDE, so others can easily reproduce the problem and advice.

  7. #7
    Junior Member
    Join Date
    Jul 2016
    Posts
    3

    AudioinputI2s

    Hi,

    OK , that makes sense.
    I ported the code to Arduino 1.6.7. When I load the code, the USB serial port come up but the code doesn't appear to run.
    At a minimum, it should print out a dot on every loop and DOUT 4 should toggle, but nothing comes out the port and the OUTPUT 4 stays HIGH.

    What am I missing?

    Thanks
    Tim


    Here is the code.

    #include <Audio.h>

    AudioInputI2S micIn;
    AudioAnalyzeRMS leftRMS;
    AudioAnalyzePeak leftPeak;

    AudioAnalyzeRMS rightRMS;
    AudioAnalyzePeak rightPeak;

    //AudioConnection c1(micIn, 0, leftPeak, 0); //source, sourcePort, destination, destinationPort
    //AudioConnection c2(micIn, 1, rightPeak, 1);
    //AudioConnection c3(micIn, 0, leftPeak, 0); //source, sourcePort, destination, destinationPort
    //AudioConnection c4(micIn, 1, rightPeak, 1);

    int s_line_flags;

    void setup() {
    // put your setup code here, to run once:

    Serial.begin(115200);
    Serial.println("Audio test Start UP");

    pinMode(2,OUTPUT);
    pinMode(3,OUTPUT);
    pinMode(4,OUTPUT);

    AudioMemory(10); //declare audio blocks; 1 block is about 2.9ms of playback
    micIn.begin();

    digitalWrite(2, HIGH);
    digitalWrite(3, HIGH);
    digitalWrite(4, HIGH);

    }

    void loop()
    {
    int inVal;

    digitalWrite(4,!digitalRead(4));
    Serial.printf(".");

    if (leftPeak.available())
    {
    inVal = leftPeak.read();
    Serial.printf(" LeftPeak = %d\r\n", inVal);
    }

    if (rightPeak.available())
    {
    inVal = rightPeak.read();
    Serial.printf(" RightPeak = %d\r\n", inVal);
    }
    delay(50);
    }

  8. #8
    Senior Member
    Join Date
    Jul 2014
    Posts
    2,188
    Quote Originally Posted by t3man View Post
    Hi,

    OK , that makes sense.
    I ported the code to Arduino 1.6.7. When I load the code, the USB serial port come up but the code doesn't appear to run.
    At a minimum, it should print out a dot on every loop and DOUT 4 should toggle, but nothing comes out the port and the OUTPUT 4 stays HIGH.

    What am I missing?

    Thanks
    Tim


    Here is the code.

    Code:
    #include <Audio.h>
    
      AudioInputI2S       micIn;
      AudioAnalyzeRMS     leftRMS;
      AudioAnalyzePeak    leftPeak;
    
      AudioAnalyzeRMS     rightRMS;
      AudioAnalyzePeak    rightPeak;
    
      //AudioConnection       c1(micIn, 0, leftPeak, 0);  //source, sourcePort, destination, destinationPort
      //AudioConnection       c2(micIn, 1, rightPeak, 1);
      //AudioConnection       c3(micIn, 0, leftPeak, 0);  //source, sourcePort, destination, destinationPort
      //AudioConnection       c4(micIn, 1, rightPeak, 1);
    
      int s_line_flags;
      
    void setup() {
      // put your setup code here, to run once:
    
      Serial.begin(115200);
      Serial.println("Audio test Start UP");
     
      pinMode(2,OUTPUT);
      pinMode(3,OUTPUT);
      pinMode(4,OUTPUT);
    
      AudioMemory(10);   //declare audio blocks; 1 block is about 2.9ms of playback
      micIn.begin();
    
      digitalWrite(2, HIGH);
      digitalWrite(3, HIGH);
      digitalWrite(4, HIGH);
    
    }
    
    void loop() 
    {
        int inVal;  
      
        digitalWrite(4,!digitalRead(4));
        Serial.printf(".");
    
        if (leftPeak.available())
        {
          inVal = leftPeak.read();  
          Serial.printf(" LeftPeak = %d\r\n", inVal);
        } 
    
        if (rightPeak.available())
        {
          inVal = rightPeak.read(); 
          Serial.printf(" RightPeak = %d\r\n", inVal);
        } 
        delay(50);
    }
    Tim,
    to help the reader, try to wrap code into code tags use
    HTML Code:
    [CODE] ... [/CODE]
    or '#' in advanced.

    As Teensy is too fast to see early prints on terminal I replaced the Serial.begin with
    Code:
      while(!Serial);
      delay(1000);
    //  Serial.begin(115200);
    (note USB serial does not need baudrate setting)
    Then you can see the setup printout and a single dot.
    This means that program hangs early in loop

    to know why
    I simply put an additional print into the first if statement
    Code:
        if (leftPeak.available())
        {
          Serial.printf("L");
          inVal = leftPeak.read();  
          Serial.printf(" LeftPeak = %d\r\n", inVal);
        }
    The letter 'L' is never printed, meaning that leftPeak.available() never returns with true.
    As left/rightPeak.available() never return with 0 (otherwise this part would simply be skipped and dots printed),you can assume that leftPeak.available() crashes.

    This no surprise, as you commented the connection
    Code:
      //AudioConnection       c1(micIn, 0, leftPeak, 0);  //source, sourcePort, destination, destinationPort
      //AudioConnection       c2(micIn, 1, rightPeak, 1);
    Also, if you using I2S on audio card, you have to use SGTL5000 to set the chip (audio examples may help on settings)

    Now, I do not have an Audioboard available, so I cannot go further and determine the reason of the crash

    note that the c3/c4 connections are also going to left/rightPeak but you may have intended left/rightRMS?

  9. #9
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    8,556
    WMXZ: good notes - I learned that html wrap lets this show:
    HTML Code:
    [CODE] ... [/CODE]
    One thing that can cause trouble is infinite : while(!Serial);

    This is a problem when running on battery for blink test or unconnected I like giving a timeout:
    Code:
    while (!Serial && (millis ()  <= 3000));
    That also let me see that a recent TYQT change was not seeing the Teensy start and a borrowed sketch with the infinite while() never started and left me blind . . . I just got Koromix email that says it should be fixed . . .

  10. #10
    Senior Member
    Join Date
    Jul 2014
    Posts
    2,188
    Quote Originally Posted by defragster View Post
    This is a problem when running on battery for blink test or unconnected I like giving a timeout:
    Code:
    while (!Serial && (millis ()  <= 3000));
    Agreed, but I was too lazy to type it in.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •