ZYNQ: Read a WAV File from SD-Card and Play it on the Audio Codec

I thought it would be nice to play audio files as a demonstration. So, let’s read WAV files from an SD-card and send them to the audio codec.

In this tutorial we learn:

  • How to access the SD card slot.
  • How to increase the heap size.
  • How to parse a WAV file.

Open the Main Project

  • Start with the project from this post. Or download the complete project further down.
  • The SD-card IO pins seem to be enabled by default. So, you don’t have to do anything. Here is the relevant configuration of the ZYNQ Processing System anyway (open the block design and double-click the ZYNQ PS):

    I have seen in a different tutorial the signals cd and wp being configured with a pull-up. That does not seem to matter in this case as we don’t use the card-detect or the write-protect functions.

Modify the C-Code

  • If you haven’t done so, launch the SDK.
  • You might want to check if the right UART driver is selected (refer to “SDK Auto Update Bug“).
  • Here is the full modified code (helloworld.c):
  • This code uses the FAT file system and the SD card. Luckily Xilinx has already prepared something for us. Rich-click on the bsp project and select “Board Support Package Settings”. Enable the library like this:
  • The code loads the full WAV file into memory and the plays it from there using DMA. Therefore, we are going to need a lot of heap memory to load a 300MByte WAV file. In order to set up the heap size (and the location), we need to generate a linker script file. Right-click on the project and select “Generate Linker Script” and allocate 400.000.000 bytes for the heap which will reside in the 512MB of DDR RAM:
  • Run the program. You should see this:
  • Insert an SD-card with one or more WAV files (FAT32 file system) and press RETURN. This is a very simple parser, so it won’t be able to handle all the WAV files which exist in the world. The safest bet is a 44.1kHz stereo file. I attached one which works at the bottom of this post. Also note that I didn’t bother to tune the sampling rate to be exactly 44.1kHz. We are running at 39.0625 kHz which means a 44.1kHz file will be substantially slowed down and reduced in pitch. This is what you should see now:
  • If there would be more WAV files, you could select the one you want to play with the arrow up/down keys. Hit RETURN to play the file.
  • Use the left/right arrow keys to change the volume. Note that the volume is implemented by scaling the samples after the file has been loaded. So, you will have to reload the file by hitting RETURN. Very crude, I know.
  • If you want to use another SD card, change it and press SPACE to remount the SD card. This seems to be a little shaky. Maybe I need to shut down the file system library before I re-mount the SD card. Update: It turns out that there is a bug in the xilffs driver which shows up when you switch between SD and SDHC cards. Check out this quick hint.

Playing WAV Files

  • Reading a file from SD card is straight forward once we have the library installed. I kept it simple and loaded the whole “data” chunk of the WAV file into DDR RAM. The program parses the WAV file and extracts the sampling rate from the “ftm ” chunk to work out if we have to decimate the data stream. Have a look at the WAV file format for more details.
  • There is a limit of around 8MBytes each BD can handle. So, I added adau1761_dmaTransmitBLOB() which chops a large block into smaller transfers. For a 300MB WAV file we are looking at around 40BDs. We allocated a pool of 4000.
  • It seems that the codec clips large DAC values. I haven’t looked if that can be solved with the codec’s volume control. But the program can reduce the volume my manipulating the actual samples. Also very crude as this is dropping one or more LSB. But this is not exactly Hifi anyway…
  • To stop the DMA from playing, I am resetting the DMA controller. That seems a little crude since we have to re-initialize the DMA controller afterwards. I am sure there are better ways…

Download the Complete Project

  • Here is a WAV file which I have tested (from the Youtube Audio Library):
    piano.wav
    Piano March by Audionautix is licensed under a Creative Commons Attribution license (https://creativecommons.org/licenses/by/4.0/). Artist: http://audionautix.com/
  • To upload the software to the Zedboard, open the project in Vivado, then click on “Launch SDK”.
  • There seems to be a bug when updating the SDK project which selects a wrong UART driver (refer to “SDK Auto Update Bug” to fix it).
  • Select the project CodecDMADemo and click “Run” (the “play” button at the top of the window).

Boot from SD Card

Follow this quick hint if you want to boot this software from SD card:

Zedboard: Booting Standalone Application from SD-Card

Oscilloscope Music on an Analog HAMEG Scope

ZYNQ: Oscilloscope Music on an Analog HAMEG Scope

Next: Use the Audio Codec with Variable Sampling Rate

ZYNQ: Use the Audio Codec with Variable Sampling Rate

Leave a comment

Your email address will not be published. Required fields are marked *

2 thoughts on “ZYNQ: Read a WAV File from SD-Card and Play it on the Audio Codec”