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

Thread: Audio Play SD Card WAV File

  1. #1
    Junior Member
    Join Date
    Sep 2022
    Location
    Secret Evil Lair of Eternal Turpitude
    Posts
    2

    Audio Play SD Card WAV File

    Hi, I'm new to Teensy and this is my first project. I got a Teensy 4.1 and one of the thing I wanted to make is it to play music through a speaker. After spending hours looking online how I could achieve my objective I'm starting to lose hope. I do not know if it is achievable with only the pieces I'm using (Teensy 4.1, SD card, a very simple speaker). Ergo I am asking for help.

    Click image for larger version. 

Name:	IMG_1516.jpg 
Views:	9 
Size:	107.4 KB 
ID:	29283



    On Arduino, I have used the File>Examples>Audio>WavFilePlayer example as my main template. I removed some code that I think did not matter for what I am doing.
    __________________________________________________ __________________________________________________ __________________________________________________
    __________________________________________________ __________________________________________________ __________________________________________________

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

    AudioPlaySdWav playWav1;
    // Use one of these 3 output types: Digital I2S, Digital S/PDIF, or Analog DAC
    //AudioOutputI2S audioOutput;
    //AudioOutputSPDIF audioOutput;
    AudioOutputAnalog audioOutput;
    //On Teensy LC, use this for the Teensy Audio Shield:
    // AudioOutputI2Sslave audioOutput;

    AudioConnection patchCord1(playWav1, 0, audioOutput, 0);
    AudioConnection patchCord2(playWav1, 1, audioOutput, 1);
    AudioControlSGTL5000 sgtl5000_1;

    // Use these with the Teensy 4.1 SD card
    #define SDCARD_CS_PIN BUILTIN_SDCARD
    #define SDCARD_MOSI_PIN 11 // not actually used
    #define SDCARD_SCK_PIN 13 // not actually used

    void setup() {
    Serial.begin(9600);

    // Audio connections require memory to work. For more
    // detailed information, see the MemoryAndCpuUsage example
    AudioMemory(8);
    }

    //Fonction----------------------------------------------------------------------------------

    void playFile(const char *filename)
    {
    Serial.print("Playing file: ");
    Serial.println(filename);

    // Start playing the file. This sketch continues to
    // run while the file plays.
    playWav1.play(filename);

    // A brief delay for the library read WAV info
    delay(25);

    // Simply wait for the file to finish playing.
    while (playWav1.isPlaying()) {
    // uncomment these lines if you audio shield
    // has the optional volume pot soldered
    //float vol = analogRead(15);
    //vol = vol / 1024;
    // sgtl5000_1.volume(vol);
    }
    }

    //------------------------------------------------------------------------------------------

    void loop() {
    playFile("MUSIC.WAV"); // filenames are always uppercase 8.3 format
    delay(500);
    }
    __________________________________________________ __________________________________________________ __________________________________________________
    __________________________________________________ __________________________________________________ __________________________________________________


    My most urgent questions are: Where should I connect the speaker on my Teensy 4.1? How do I call the music in the SD to the speaker and what important commands am I missing?

    Thank you
    Last edited by Dong Clerk; 09-02-2022 at 03:07 AM. Reason: forgor my manners

  2. #2
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    4,275
    Unfortunately you won't be able to do what you want with just what you've bought.

    The 3.1, 3.2, 3.5, and 3.6 Teensies (for which the example was written) have 1 pin (Teensy 3.1 and 3.2) or two pins (Teensy 3.5 or 3.6) that are analog DACs. An Analog DAC is a pin that when you do an AnalogWrite to the pin, it modifies the voltage on the pin to be between 0 and the reference voltage (typically 3.3v). The sound produced by a DAC is decent, but other sound systems (including the audio shield on the Teensy) produce much better sound. Unfortunately the microprocessor used in the Teensy 4.0/4.1/MicroMod no longer provides a DAC.

    For most other pins, if you do AnalogWrite to the pin, it uses what is typically called PWM (pulse width modulation) that turns the pin on/off very fast, so that the average voltage will be what is specified (note some pins don't support PWM). This PWM is useful for making lights dim. It can be used for playing sounds, though it may not be as good as a DAC might be.

    You can then connect this DAC pin and ground to an amplifier, which then connects to a speaker. I don't know what pin AudioOutputAnalog audioOutput uses on the Teensy 4.0, but if it there is a way to set the pin to a pin that does PWM, you can use the new Audio Output function (AudioOutputPWM) that uses a PWM pin for output. You would need to use Teensydunio 1.57 (the current release) to use this. I haven't tried function myself.

    If you aren't connecting up a display that uses SPI (most displays do use SPI), you can use pin 10 and 12 to output sound via MQS (medium quality sound). Unfortunately MQS uses pin 10 and 12, while SPI requires using pin 12 for the MISO function. While I have an example that just uses Tonesweep with MQS, I haven't hooked it up to the SD wav player.

    The main option that people do is to use an extra card that offloads the audio processing. There are at least 3 different cards that you can use:
    • The main approach is to use the official Teensy audio adapter. This is a board made to be mounted on top of or under the Teensy (you will need to solder pins and headers for this),
    • PJRC has a much cheaper board that uses a PT8211 chip. Even though I've bought some of these boards, I haven't actually soldered them up to use.
    • The third option is to get an external I2S device that you hook up to the appropriate pins, and hook speaker(s) to the device. There are typically 2 variants. One variant provides stereo, but you will need amplifiers on the speakers. The other device is a mono device, but it provides the amplifier. Here is one I bought: https://smile.amazon.com/gp/product/...?ie=UTF8&psc=1


    As I mentioned above, that once you produce sound in some fashion, you will need to put an amplifier between the Teensy and the speaker. Otherwise, you likely would only be able to hear a faint echo. You can buy them in various places, but you will need one if you want to continue. Here is one on ebay that looks like it might do the trick (though it looks like you will get 10 parts): https://www.ebay.com/itm/33446129538...item4ddf725b1a.

    Another alternative, that may take more work on your part to set up is to make the Teensy into a USB audio device. You build the Teensy as a Serial + MIDO + Audio (or just Audio device) instead of the normal USB serial device. Once you attach the Teensy, you may need to do something on your system to enable using the device (under Linux I needed to set the Teensy as the default input device, and then issue the 'play -d' command). The advantage is that you won't need any extra parts (assuming your computer has speakers that are turned on).
    Last edited by MichaelMeissner; 09-02-2022 at 07:50 AM.

  3. #3
    Junior Member
    Join Date
    Sep 2022
    Location
    Secret Evil Lair of Eternal Turpitude
    Posts
    2
    Thanks for the quick reply!
    I think I will try the external I2S device. I can't wait to try it.

  4. #4
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    4,275
    Here is an example of ToneSweep for external I2S:

    Code:
    /*
      Demo of the audio sweep function.
      The user specifies the amplitude,
      start and end frequencies (which can sweep up or down)
      and the length of time of the sweep.
    
      Modified to eliminate the audio shield, and use Max98357A mono I2S chip.
      https://smile.amazon.com/gp/product/B07PS653CD/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1
    
      Pins:		Teensy 4.0	Teensy 3.x
    
      LRCLK:	Pin 20/A6	Pin 23/A9
      BCLK:		Pin 21/A7	Pin 9
      DIN:		Pin 7		Pin 22/A8
      Gain:		see below	see below
      Shutdown:	N/C		N/C
      Ground:	Ground		Ground
      VIN:		5v		5v
    
      Other I2S pins not used by the Max98357A device:
    
      MCLK		Pin 23		Pin 11
      DOUT		Pin 8		Pin 13
    
      Gain setting:
    
      15dB	if a 100K resistor is connected between GAIN and GND
      12dB	if GAIN is connected directly to GND
       9dB	if GAIN is not connected to anything (this is the default)
       6dB	if GAIN is conneted directly to Vin
       3dB	if a 100K resistor is connected between GAIN and Vin.
    
      SD setting (documentation from the Adafruit board)
    
      This pin is used for shutdown mode but is also used for setting which channel
      is output. It's a little confusing but essentially:
    
      * If SD is connected to ground directly (voltage is under 0.16V) then the amp
        is shut down
    
      * If the voltage on SD is between 0.16V and 0.77V then the output is (Left +
        Right)/2, that is the stereo average.
    
      * If the voltage on SD is between 0.77V and 1.4V then the output is just the
        Right channel
    
      * If the voltage on SD is higher than 1.4V then the output is the Left
        channel.
    
        This is compounded by an internal 100K pulldown resistor on SD so you need
        to use a pullup resistor on SD to balance out the 100K internal pulldown.
    
      Or alternatively, use the HiLetgo PCM5102 I2S IIS Lossless Digital Audio DAC
      Decoder which provides stereo output:
      https://smile.amazon.com/gp/product/B07Q9K5MT8/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1  */
    
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    // GUItool: begin automatically generated code (edited by meissner afterwards).
    AudioSynthToneSweep	tonesweep;		//xy=99,198
    AudioMixer4		mixer2;			//xy=280,253
    AudioMixer4		mixer1;			//xy=280,175
    AudioOutputI2S		i2s;			//xy=452,189
    
    AudioConnection		patchCord1(tonesweep, 0, mixer1, 0);
    AudioConnection		patchCord2(tonesweep, 0, mixer2, 0);
    AudioConnection		patchCord3(mixer2,    0, i2s,    1);
    AudioConnection		patchCord4(mixer1,    0, i2s,    0);
    // GUItool: end automatically generated code
    
    const float	t_ampx	= 0.8;
    const int	t_lox	= 10;
    const int	t_hix	= 22000;
    const float	t_timex	= 10;		// Length of time for the sweep in seconds
    
    // Do a sweep in both directions, enabling or disabling the left/right speakers
    void do_sweep (int i)
    {
      int do_left  = (i & 1) != 0;
      int do_right = (i & 2) != 0;
      float gain   = (do_left && do_right) ? 0.5f : 1.0f;
    
      Serial.printf ("Sweep up,   left = %c, right = %c\n",
    		 (do_left)  ? 'Y' : 'N',
    		 (do_right) ? 'Y' : 'N');
    
      mixer1.gain (0, do_left  ? gain : 0.0f);
      mixer2.gain (0, do_right ? gain : 0.0f);
    
      if (!tonesweep.play (t_ampx, t_lox, t_hix, t_timex)) {
        Serial.println ("ToneSweep - play failed");
        while (1)
          ;
      }
    
      // wait for the sweep to end
      while (tonesweep.isPlaying ())
        ;
    
      // and now reverse the sweep
      Serial.printf ("Sweep down, left = %c, right = %c\n",
    		 (do_left)  ? 'Y' : 'N',
    		 (do_right) ? 'Y' : 'N');
    
      if (!tonesweep.play (t_ampx, t_hix, t_lox, t_timex)) {
        Serial.println("ToneSweep - play failed");
        while (1)
          ;
      }
    
      // wait for the sweep to end
      while (tonesweep.isPlaying ())
        ;
    
      Serial.println ("Sweep done");
    }
    
    void setup(void)
    {
      // Wait for at least 3 seconds for the USB serial connection
      Serial.begin (9600);
      while (!Serial && millis () < 3000)
        ;
    
      AudioMemory (8);
      Serial.println ("setup done");
    
      for (int i = 1; i <= 3; i++)
        do_sweep (i);
    
      Serial.println ("Done");
    }
    
    void loop (void)
    {
    }
    Obviously for playing songs from the SD card, you would need to replace the bits that do the tone sweep.

Posting Permissions

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