To get the example code to play a WAV file from the built-in SD card on a Teensy 3.5, I had to make two changes:

1. A short delay was needed between the __disable_irq() and calls in AudioPlaySdWav::play(). This prevented the Teensy from getting stuck indefinitely waiting for the DMA to complete in SDHC_CardReadBlock().

2. The audio buffer in AudioPlaySdWav needed to be 4-byte aligned, otherwise the alignment check at the top of SDHC_CardReadBlock() would fail.

Detailed Description:

I wanted to try out playing a WAV file from the built-in SD card on my Teensy 3.5 so I started with the example code and made the necessary changes for DAC output as per the comments.

My only other change was to add a delay to the start of setup() to give the serial monitor time to start capturing data being transmitted by the Teensy. Here's the code I used:

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

AudioPlaySdWav     playWav1;
AudioOutputAnalog  audioOutput;
AudioConnection    patchCord1(playWav1, 0, audioOutput, 0);
AudioConnection    patchCord2(playWav1, 1, audioOutput, 1);

// Use these with the Teensy 3.5 & 3.6 SD card
#define SDCARD_MOSI_PIN  11  // not actually used
#define SDCARD_SCK_PIN   13  // not actually used

void setup() {

  // Audio connections require memory to work.  For more
  // detailed information, see the MemoryAndCpuUsage example

  if (!(SD.begin(SDCARD_CS_PIN))) {
    // stop here, but print a message repetitively
    while (1) {
      Serial.println("Unable to access the SD card");

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

  // Start playing the file.  This sketch continues to
  // run while the file plays.;

  // A brief delay for the library read WAV info

  // Simply wait for the file to finish playing.
  while (playWav1.isPlaying()) {

void loop() {
  playFile("SDTEST1.WAV");  // filenames are always uppercase 8.3 format
I copied the the SDTEST1.WAV file to the SD card, inserted it into the Teensy, then built and ran the example. Nothing happened. After adding some Serial logging to see what was going on, I saw that the code never returned from the call to

I added Serial messages to the implementation of AudioPlaySdWav::play() and in doing so, inadvertently discovered that it no longer got stuck if a Serial message was printed between the __disable_irq() and calls. It turns out that a simple delay(1) call in this position is also enough to fix the issue.

I then worked down through the call stack to find out where the problem first occurs without the delay. It turned out to be the while loop that waits for DMA to complete in SDHC_CardReadBlock():

SdFile::read(uint8_t*, 1)
So it appears that there is some kind of timing issue to do with how soon the DMA is issued after the __disable_irq() call. I don't know how DMA and interrupts work on this chip in anything like enough detail to be able to debug this further unfortunately.

Anyway, with the delay(1) call in place, I found that the AudioPlaySdWav::play() call returned but AudioPlaySdWav::isPlaying() was immediately returning false. Digging into the code I found that the AudioPlaySdWav class was reading a buffer full of zeros from the file. If I added code to simply read the file myself instead of trying to play it, I was able to get a hexdump of valid data. This worked even though I was using the same code to do the reading as the AudioPlaySdWav class was.

I traced the read calls to find out what was going on when AudioPlaySdWav was doing the reading. It turned out that the buffer declared in the AudioPlaySdWav class as uint8_t buffer[512] was not 4-byte aligned. This may be due to me compiling with -Os but I wouldn't have thought I'd be alone in doing that? Anyway, there's a check at the top of the SDHC_CardReadBlock() function that fails and returns -1 if the buffer is misaligned. The AudioPlaySdWav code implicitly casts this -1 value into the uint16_t buffer_length member variable and treats it as a successful read of 65535 bytes. It then tries to process the buffer and fails to find a valid header in the buffer full of zeroes.

The fix is to 4-byte align the buffer with a C++11 alignas(4):

alignas(4) uint8_t buffer[512];
With the two fixes in place, I can now run the example code and see audio waveforms generated on the DAC pin! I'm a bit surprised that playing WAV files from an SD card seems to just work for everyone else. At first I thought it might be my toolchain setup as I'm developing from Makefiles, but running the code in a simple Arduino sketch showed all the same issues.

Anyway, I hope this bug report is of some use. I'm really loving playing with Teensy and extremely grateful for PJRC and the community's contributions so I wanted to give back what little I could here.