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

Thread: Teensy 3.5 Basic Gain using inbuilt ADC and DAC and MAX9814 mic

  1. #1

    Teensy 3.5 Basic Gain using inbuilt ADC and DAC and MAX9814 mic

    Hello all, I am working on project to capture sounds using the mic and perform some processing. I want to implement a digital gain to control the amplification of the sound that it is output through the headphone connected to a 3.5mm jack. I tried with the below code. When I comment out the analogRead line for the potentiometer I can hear the sound from the mic through the inbuilt dac on the teensy via the headphones but when I uncomment I dont hear anything. Any help please. Thank you.

    Code:
    //These are the includes from the Teensy Audio Library
    #include <Audio.h>      //Teensy Audio Library
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    #include <OpenAudio_ArduinoLibrary.h> //for AudioConvert_I16toF32, AudioConvert_F32toI16, and AudioEffectGain_F32
    
    //create audio library objects for handling the audio
    AudioInputAnalog           i2s_in;       
    AudioConvert_I16toF32   int2Float1, int2Float2;    //Converts Int16 to Float.  See class in AudioStream_F32.h
    AudioEffectGain_F32     gain1, gain2;  //Applies digital gain to audio data.  Expected Float data.  
    AudioConvert_F32toI16   float2Int1, float2Int2;    //Converts Float to Int16.  See class in AudioStream_F32.h
    AudioOutputAnalog          i2s_out;       //Digital audio *to* the Teensy Audio Board DAC.  Expects Int16.  Stereo
    
    //Make all of the audio connections
    AudioConnection         patchCord1(i2s_in, 0, int2Float1, 0);    //connect the Left input to the Left Int->Float converter
    AudioConnection         patchCord2(i2s_in, 1, int2Float2, 0);    //connect the Right input to the Right Int->Float converter
    AudioConnection_F32     patchCord10(int2Float1, 0, gain1, 0);    //Left.  makes Float connections between objects
    AudioConnection_F32     patchCord11(int2Float2, 0, gain2, 0);    //Right.  makes Float connections between objects
    AudioConnection_F32     patchCord12(gain1, 0, float2Int1, 0);    //Left.  makes Float connections between objects
    AudioConnection_F32     patchCord13(gain2, 0, float2Int2, 0);    //Right.  makes Float connections between objects
    AudioConnection         patchCord20(float2Int1, 0, i2s_out, 0);  //connect the Left float processor to the Left output
    AudioConnection         patchCord21(float2Int2, 0, i2s_out, 1);  //connect the Right float processor to the Right output
    
    
    #define POT_PIN A3  //potentiometer is tied to this pin
    
    
    void setup() {
      Serial.begin(115200);   //open the USB serial link to enable debugging messages
      delay(500);             //give the computer's USB serial system a moment to catch up.
      Serial.println("OpenAudio_ArduinoLibrary BasicGain_Float...");
      // Audio connections require memory
      AudioMemory(10);      //allocate Int16 audio data blocks
      AudioMemory_F32(10);  //allocate Float32 audio data blocks
      // setup any other other features
      pinMode(POT_PIN, INPUT); //set the potentiometer's input pin as an INPUT
    
    } //end setup()
    
    
    // define the loop() function, the function that is repeated over and over for the life of the device
    unsigned long updatePeriod_millis = 100; //how many milliseconds between updating gain reading?
    unsigned long lastUpdate_millis = 0;
    unsigned long curTime_millis = 0;
    int prev_gain_dB = 0;
    void loop() {
      //choose to sleep ("wait for interrupt") instead of spinning our wheels doing nothing but consuming power
      asm(" WFI");  //ARM-specific.  Will wake on next interrupt.  The audio library issues tons of interrupts, so we wake up often.
      
      //has enough time passed to try updating the GUI?
      curTime_millis = millis(); //what time is it right now
      if (curTime_millis < lastUpdate_millis) lastUpdate_millis = 0; //handle wrap-around of the clock
      if ((curTime_millis - lastUpdate_millis) > updatePeriod_millis) { //is it time to update the user interface?
        
        //read potentiometer
        float val = float(analogRead(POT_PIN)) / 1024.0; //0.0 to 1.0
        val = 0.1*(float)((int)(10.0*val + 0.5));  //quantize so that it doesn't chatter
            
        //compute desired digital gain
        const float min_gain_dB = -20.0, max_gain_dB = 40.0; //set desired gain range
        float gain_dB = min_gain_dB + (max_gain_dB - min_gain_dB)*val; //computed desired gain value in dB
    
        //if the gain is different than before, set the new gain value
        if (abs(gain_dB - prev_gain_dB) > 1.0) { //is it different than before
          gain1.setGain_dB(gain_dB);  //set the gain of the Left-channel gain processor
          gain2.setGain_dB(gain_dB);  //set the gain of the Right-channel gain processor
          Serial.print("Digital Gain dB = "); Serial.println(gain_dB); //print text to Serial port for debugging
          prev_gain_dB = gain_dB;  //we will use this value the next time around
        }
     
        lastUpdate_millis = curTime_millis; //we will use this value the next time around.
      } // end if
    
    } //end loop();
    Last edited by 4bdu1; 01-30-2018 at 10:09 AM.

  2. #2
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,009
    maybe not relevant but for stereo DAC (select DACS in gui) and/or change to AudioOutputAnalogStereo i2s_out;

    or do you want AudioOutputI2S for the audio adaptor headphone jack?

  3. #3
    Quote Originally Posted by manitou View Post
    maybe not relevant but for stereo DAC (select DACS in gui) and/or change to AudioOutputAnalogStereo i2s_out;

    or do you want AudioOutputI2S for the audio adaptor headphone jack?
    Sorry to mention, I'm not using the audio adaptor. I connected a 3.5mm jack to the inbuilt dac and connected headphones. Do I still need to change to AudioOutputAnalogStereo ?

    I changed to AudioOutputAnalogStereo but still the same issue

    I can listen to the signal from the mic when the analogRead line is commented out but not when it is uncommented.

  4. #4
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,442
    There is something highly unlogical: On one side, you write in the title that you are using the built-in ADCs and DACs, but your code you published uses I2S inputs and outputs as if you were using the audio shield plugged onto the Teensy and thus the ADC and DAC from the SGTL5000 instead of the built-in ones.

    In case you are using the audio shield and thus the SGTL5000 ADCs and DACs, there is no reason why analogRead should not work.

    But if you use the Teensy's ADC(s) for audio input (in contradiction to the code which you published), it is normal that trying to use the same ADC for analogRead() will break the audio flow.

  5. #5
    Quote Originally Posted by Theremingenieur View Post
    There is something highly unlogical: On one side, you write in the title that you are using the built-in ADCs and DACs, but your code you published uses I2S inputs and outputs as if you were using the audio shield plugged onto the Teensy and thus the ADC and DAC from the SGTL5000 instead of the built-in ones.

    In case you are using the audio shield and thus the SGTL5000 ADCs and DACs, there is no reason why analogRead should not work.

    But if you use the Teensy's ADC(s) for audio input (in contradiction to the code which you published), it is normal that trying to use the same ADC for analogRead() will break the audio flow.

    Sorry for the variable namings, if you check the type you would realize they are the inbuilt adc and dac I am referring to. I modified some parts of a code from the openaudio arduino library by chip.

    Is there a way to use the Teensy's ADC(s) for audio input and use analog read like when using the audio shield?

  6. #6
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,442
    In case you use both internal ADC(s) for stereo audio, there is no way to do analogRead() for a potentiometer and you would for example have to use a rotary encoder instead. This is documented in the right sidebar of the audio design tool: "analogRead() must not be used, because AudioInputAnalogStereo is regularly accessing the ADC hardware. If both access the hardware at the same moment, analogRead() can end up waiting forever, which effectively crashes your program."

    In case you use only one internal ADC for mono audio, PJRC issued the same warning as above about not using analogRead(), so it is safer to not use it. But basically, by carefully selecting the audio input pin and the potentiometer pin, so that these are internally multiplexed to different ADCs as documented in the MUX chapter of the reference manual, you could have luck and get it perhaps working. But better is again using a rotary encoder instead of a potentiometer.

    To handle one or more rotary encoder knobs, there is a small and resource efficient code to do so: https://forum.pjrc.com/threads/44592...l=1#post145056

  7. #7
    Quote Originally Posted by Theremingenieur View Post
    In case you use both internal ADC(s) for stereo audio, there is no way to do analogRead() for a potentiometer and you would for example have to use a rotary encoder instead. This is documented in the right sidebar of the audio design tool: "analogRead() must not be used, because AudioInputAnalogStereo is regularly accessing the ADC hardware. If both access the hardware at the same moment, analogRead() can end up waiting forever, which effectively crashes your program."

    In case you use only one internal ADC for mono audio, PJRC issued the same warning as above about not using analogRead(), so it is safer to not use it. But basically, by carefully selecting the audio input pin and the potentiometer pin, so that these are internally multiplexed to different ADCs as documented in the MUX chapter of the reference manual, you could have luck and get it perhaps working. But better is again using a rotary encoder instead of a potentiometer.

    To handle one or more rotary encoder knobs, there is a small and resource efficient code to do so: https://forum.pjrc.com/threads/44592...l=1#post145056

    Ok thank you so much. Would definitely try that and also probably try using buttons for an easier alternative maybe.

  8. #8
    Quote Originally Posted by 4bdu1 View Post
    Sorry to mention, I'm not using the audio adaptor. I connected a 3.5mm jack to the inbuilt dac and connected headphones. Do I still need to change to AudioOutputAnalogStereo ?

    I changed to AudioOutputAnalogStereo but still the same issue

    I can listen to the signal from the mic when the analogRead line is commented out but not when it is uncommented.
    a question

    How is you're headphone connected to the teensy? Is there a seperate amp or is it a direct connection and working?

  9. #9
    Quote Originally Posted by AlainD View Post
    a question

    How is you're headphone connected to the teensy? Is there a seperate amp or is it a direct connection and working?
    I connected a 3.5mm jack to the inbuilt dac and just connected the headphones directly and yes it's working

  10. #10
    Quote Originally Posted by 4bdu1 View Post
    I connected a 3.5mm jack to the inbuilt dac and just connected the headphones directly and yes it's working
    Without a 10uF capacitor in series to avoid the DC through the headphone?

  11. #11
    Quote Originally Posted by AlainD View Post
    Without a 10uF capacitor in series to avoid the DC through the headphone?
    There is a 1uF capacitor connected in series to the 3.5mm jack if that's what you are asking.

  12. #12
    Quote Originally Posted by 4bdu1 View Post
    There is a 1uF capacitor connected in series to the 3.5mm jack if that's what you are asking.
    yes, thanks

  13. #13
    Senior Member
    Join Date
    Apr 2014
    Posts
    303
    From 1st post on this thread.......
    "When I comment out the analogRead line for the potentiometer I can hear the sound from the mic through the inbuilt dac on the teensy via the headphones but when I uncomment I dont hear anything. Any help please."

    You dont need either Potentiometers or Encoders to control amplitude, or gain, or Volume......
    You just need numbers........

    Touch a touch pin and let it run a counter up and down to give touch volume control.....
    and ADC pin will get analog audio in to teensy
    and DAC pin will get audio out of teensy, or I2S will get digital audio in and digital audio out of teensy.......nothing else needed..!...!..

  14. #14
    Senior Member
    Join Date
    Apr 2014
    Posts
    303
    I hadn't tried the ADC pin with audio before so I thought I would give it a go......very basic setup.
    I used the PassThroAudio sketch in the examples and commented out the PWM output.
    So Just the audio input on pin A2 and audio output on DAC and powered by USB port.
    Audio in was Lineout from a tablet playing a 440 Hz sinewave tone and output was to LineIn on my PC with Audacity Recording.
    All worked, no crackling or messing about, but for the full sinewave input I was getting only the positive half cycles out. Still a good clean waveform no interference.
    Just wondering does anyone else get this, or is it my too basic a setup, I didn't use the "filter" type network shown in the GUI pages, but I don't think that is the problem..??.
    I need to investigate more....does ADC work for Pos and Neg parts of a waveform..??

    Regards this thread...where you want to input audio, process it, and output audio, watch it and listen to it.....would this simple sketch not be a good place to start and move from there.....the sketch is in the audio library examples under teensy

  15. #15
    Senior Member
    Join Date
    Apr 2014
    Posts
    303
    I have tried out further testing......ADC audio direct on ADC pin......

    The analogue audio sinewave signal Lineout from tablet to pin A2 and output DAC pin to Linein on PC works OK when connected as in the diagram shown in the GUI.
    The RC network is required........
    It adds 0.6 volts bias to signal.......derived by the 10k and 2.2k from the 3.3 volt pin. This lifts the signal so as to be all positive and works with a good sound, no interference that I can see or hear when playing it in Audacity

  16. #16
    Quote Originally Posted by Teenfor3 View Post
    I hadn't tried the ADC pin with audio before so I thought I would give it a go......very basic setup.
    I used the PassThroAudio sketch in the examples and commented out the PWM output.
    So Just the audio input on pin A2 and audio output on DAC and powered by USB port.
    Audio in was Lineout from a tablet playing a 440 Hz sinewave tone and output was to LineIn on my PC with Audacity Recording.
    All worked, no crackling or messing about, but for the full sinewave input I was getting only the positive half cycles out. Still a good clean waveform no interference.
    Just wondering does anyone else get this, or is it my too basic a setup, I didn't use the "filter" type network shown in the GUI pages, but I don't think that is the problem..??.
    I need to investigate more....does ADC work for Pos and Neg parts of a waveform..??

    Regards this thread...where you want to input audio, process it, and output audio, watch it and listen to it.....would this simple sketch not be a good place to start and move from there.....the sketch is in the audio library examples under teensy
    I have been able to implement that already and based on suggestions given here I have also been able to control the volume using buttons. It works well except for some background noise which I'm guessing is from the usb port of my laptop since I'm using that to power for the mean time.

  17. #17
    Quote Originally Posted by Teenfor3 View Post
    I have tried out further testing......ADC audio direct on ADC pin......

    The analogue audio sinewave signal Lineout from tablet to pin A2 and output DAC pin to Linein on PC works OK when connected as in the diagram shown in the GUI.
    The RC network is required........
    It adds 0.6 volts bias to signal.......derived by the 10k and 2.2k from the 3.3 volt pin. This lifts the signal so as to be all positive and works with a good sound, no interference that I can see or hear when playing it in Audacity
    I am using the MAX9814 mic from tindie. It works fine but there's some background sound/noise which I would like to suppress. I tried with little success so I was thinking it's probably noise from the power supply which is the usb port from my laptop. I am trying to get heart signals from the mic that's connected at the tube of a stethoscope chest piece.. so any little background noise is easily noticeable since the heart sounds I'm getting are not that clear enough.

    I went through chip's hearing aid project and tried using a dynamic range compressor to lower the noise frequencies a bit. I got a better response than the former but not as best as I would want it. Increasing the gain or volume still brings the background noise up a bit. I tried using an analog filter with the mic to filter the noise but I was getting unclear sounds. I don't know if they were connection problems or not because I coulde here the noise was reduced but the sound I was listening to wasn't clear and had some stuttering effect sort of.

  18. #18
    Senior Member
    Join Date
    Apr 2014
    Posts
    303
    If you are getting stuttering.....more than likely you have bad connections...??

    There are not many connections needed so should be easy to check...???

    To isolate the source of background noise.....Have you a scope.......where do you see the noise.....

    If you don't have a scope....use Audacity......of download a software scope that uses your sound card as inputs...

    Power the assembly from batteries will eliminate noise from USB....

    Did you try the MIC on its own into PC and watch and listen using Audacity.....

    Did you try teensy on its own with a clean audio in signal......

    You need to be able to state the step you are at....and the result of each step.....

  19. #19
    Senior Member
    Join Date
    Apr 2014
    Posts
    303
    One other suggestion.....

    Is the signal being clipped.....this would give distortion.....you should see this in Audacity....and may hear it as background noise...??.

    Reduce the gain or use a potentiometer as volume control on the input between the MIC and teensy input pin

  20. #20
    Senior Member
    Join Date
    Apr 2014
    Posts
    303
    Another suggestion.....

    I assume you are now not using the code you posted in your initial post for this project.......

    Because it probably would most definitely give all sorts of background noises...?????

    This is the problem of trying to sort problems for users when they don't post the code they are using.....or at least snippets of it to illustrate the problem

  21. #21
    Quote Originally Posted by Teenfor3 View Post
    Another suggestion.....

    I assume you are now not using the code you posted in your initial post for this project.......

    Because it probably would most definitely give all sorts of background noises...?????

    This is the problem of trying to sort problems for users when they don't post the code they are using.....or at least snippets of it to illustrate the problem
    This is my current code

    Code:
    #include <Bounce.h>
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    #include "filters.h"
    
    #include <OpenAudio_ArduinoLibrary.h> //for AudioConvert_I16toF32, AudioConvert_F32toI16, and AudioEffectGain_F32
    
    //Create audio library objects for handling the audio
    AudioConvert_I16toF32   int2Float1;    //Converts Int16 to Float.  See class in AudioStream_F32.h
    AudioEffectGain_F32     gain1;  //Applies digital gain to audio data.  Expected Float data.  
    AudioConvert_F32toI16   float2Int1, float2Int2;    //Converts Float to Int16.  See class in AudioStream_F32.h
    AudioInputAnalog        adc1;  
    AudioOutputAnalog       dac1;
    AudioFilterFIR          firFilter;
    
    AudioEffectCompressor_F32 comp1;
    
    AudioConnection         patchCord1(adc1,int2Float1);    //connect the input to the Int->Float converter 
    AudioConnection_F32     patchCord10(int2Float1, 0, comp1, 0);    //makes Float connections between objects
    AudioConnection_F32     patchCord12(comp1, 0, float2Int1, 0);    //makes Float connections between objects
    AudioConnection         patchCord13(float2Int1,firFilter); //float connection to filter
    AudioConnection         patchCord14(firFilter,dac1); //route output of filter to DAC
    //AudioConnection         patchCord20(float2Int1,dac1);  //connect the float processor to the output
    
    // Bounce objects to easily and reliably read the buttons
    Bounce buttonVolumeUp = Bounce(4, 8);
    Bounce buttonVolumeDown =   Bounce(5, 8);  // 8 = 8 ms debounce time
    
    
    Bounce firstMode = Bounce(0, 8);
    Bounce secondMode = Bounce(1, 8);
    Bounce thirdMode = Bounce(2, 8);
    
    
    void setupMyCompressors(boolean use_HP_filter, float knee_dBFS, float comp_ratio, float attack_sec, float release_sec) {
      comp1.enableHPFilter(use_HP_filter);   
      comp1.setThresh_dBFS(knee_dBFS);      
      comp1.setCompressionRatio(comp_ratio); 
    
      float fs_Hz = AUDIO_SAMPLE_RATE;
      comp1.setAttack_sec(attack_sec, fs_Hz);       
      comp1.setRelease_sec(release_sec, fs_Hz);   
    }
    
    
    struct fir_filter {
      short *coeffs;
      short num_coeffs;  //num_coeffs must be an even number, 4 or higher
    };
    
    //index of current filter. Start with the bell mode
    int fir_index = 0;
    
    struct fir_filter fir_list[] = {
      {f_mode_band_pass, 38},
      {s_mode_band_pass, 38},
      {t_mode_band_pass, 38}
    };
    
    
    void setup() {
      Serial.begin(115200);
      delay(500); 
       // Configure the pushbutton pins
      pinMode(0, INPUT_PULLUP);
      pinMode(1, INPUT_PULLUP);
      pinMode(2, INPUT_PULLUP);
      pinMode(4, INPUT_PULLUP);
      pinMode(5, INPUT_PULLUP);
      
      dac1.analogReference(INTERNAL);
      Serial.println("OpenAudio_ArduinoLibrary BasicGain_Float... Modified"); 
    
      // Audio connections require memory
      AudioMemory(60);      //allocate Int16 audio data blocks
      AudioMemory_F32(60);  //allocate Float32 audio data blocks
    
    
      boolean use_HP_filter = true; //enable the software HP filter to get rid of DC?
      float knee_dBFS, comp_ratio, attack_sec, release_sec;
    
      if (true) {
          Serial.println("Configuring Compressor for fast response for use as a limitter.");
          knee_dBFS = -15.0f; comp_ratio = 5.0f;  attack_sec = 0.005f;  release_sec = 0.200f;
      } else {
          Serial.println("Configuring Compressor for slow response more like an automatic volume control.");
          knee_dBFS = -50.0; comp_ratio = 5.0;  attack_sec = 1.0;  release_sec = 2.0;
      }
    
      setupMyCompressors(use_HP_filter, knee_dBFS, comp_ratio, attack_sec, release_sec);
    
    
      //initialize the filter
      firFilter.begin(fir_list[0].coeffs, fir_list[0].num_coeffs);
      Serial.println("filter initialized... Setup done");
      
    }
    
    int prev_gain_dB = 0;
    float val = 0.50; //set initial volume
    unsigned long last_time = millis();
    
    void loop() {
      asm(" WFI");
    
      buttonVolumeUp.update();
      buttonVolumeDown.update();
      
      firstMode.update();
      secondMode.update();
      thirdMode.update();
    
        // Respond to button presses
      if (buttonVolumeUp.fallingEdge()) {
        Serial.println("VolumeUp Button Press");
        val += 0.25;
        if(val > 1) val = 1;
        Serial.println(val);
      }
      
      if (buttonVolumeDown.fallingEdge()) {
        Serial.println("VolumeDown Button Press");
        val -=  0.25;
        if(val < 0) val = 0;
        Serial.println(val);
      }
    
      if(firstMode.fallingEdge()){
        firFilter.begin(fir_list[0].coeffs, fir_list[0].num_coeffs);
      }
    
      if(secondMode.fallingEdge()){
        firFilter.begin(fir_list[1].coeffs, fir_list[1].num_coeffs);
      }
    
      if(thirdMode.fallingEdge()){
        firFilter.begin(fir_list[2].coeffs, fir_list[2].num_coeffs);
      }
      
      
        
        //read volume val
        val = 0.1*(float)((int)(10.0*val + 0.5));  //quantize so that it doesn't chatter
        Serial.println(val);
            
        //compute desired digital gain
        const float min_gain_dB = -20.0, max_gain_dB = 60.0; //set desired gain range
        float gain_dB = min_gain_dB + (max_gain_dB - min_gain_dB)*val; //computed desired gain value in dB
        Serial.print("gain_dB: ");
        Serial.println(gain_dB);
    
          //if the gain is different than before, set the new gain value
        if (abs(gain_dB - prev_gain_dB) > 1.0) { //is it different than before
          comp1.setPreGain_dB(gain_dB);  //set the gain of the Left-channel gain processor
          Serial.print("Digital Gain dB = ");// Serial.println(gain_dB); //print text to Serial port for debugging
          prev_gain_dB = gain_dB;
        } 
     delay(100);
    
    
    
     // print information about resource usage
      // Proc = 18 (18),  Mem = 4 (5)
      if (millis() - last_time >= 2500) {
        Serial.print("Proc = ");
        Serial.print(AudioProcessorUsage());
        Serial.print(" (");    
        Serial.print(AudioProcessorUsageMax());
        Serial.print("),  Mem = ");
        Serial.print(AudioMemoryUsage());
        Serial.print(" (");    
        Serial.print(AudioMemoryUsageMax());
        Serial.println(")");
        last_time = millis();
      }
    }

  22. #22
    Senior Member
    Join Date
    Apr 2014
    Posts
    303
    You post the code but don't say what bit cause trouble..??

    What is your problem...is it background noice..????

    Is it noise picked up by the mic....OR...is it noise from power rails or earth loops etc.....??

    If I was trying to analyse it I would first remove all the conversions and filters you have added, to bring it to a basic program and see what is happening with the basics.
    Look at the inputs and outputs on Audacity waveforms and listen to it.

    If noise is still there, investigate where it is coming from.....???

Posting Permissions

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