For the final element of my QT Py Christmas ornament, I'd like to add the ability to play some Christmas music.

 

The SAMD21 has a single DAC output that I'll use to generate tones, but I'll also need to add an audio amplifier to drive a speaker and figure out how to access the external flash memory that I added to store the music files.

 

In this blog I'm going to cover adding the audio amplifier and generating the tones using the DAC.  I'll hopefully be able to get the music playing from the flash memory next time.

 

Audio Amplifier

I recently used a PAM8302A audio amplifier Hat with the M5StickC, so I decided to use an Adafruit PAM8302A breakout board for the audio amplifier.  This is a simple mono class D amplifier, so I'll just need to attach power and ground and the DAC output.  Here is the schematic below:

There is a shutdown pin to save power when not in use, but I'm not going to use it.  I'm also not driving it differentially, so I'll tie the AIN- input to ground.  I'll add a small 8 ohm speaker to the output.

 

The small SMD potentiometer that is used to adjust the input amplitude is very fragile, so if I have to adjust volume much I may end up adjusting the DAC output swing instead of using the pot (I've read reviews of this pot breaking).

 

Audio Library

I found a SamdAudio library that plays WAV files on the SAMD21 DAC using either an SD card or flash memory https://github.com/hydronics2/SamdAudio  .

Since I just used the SD card interface on my Xiao Expansion board, I'll try this library on that first and then move on to trying it with flash memory on the QT Py (the Xiao doesn't have flash memory and the Expansion board is too big to use with the QT Py on the ornament).

 

Christmas Music

The library includes examples using 8 bit WAV files sampled at 22 and 32 kHz.  I had a difficult time finding Christmas music in that format but I found a fair amount of free music in MP3 format.  For the demo I selected "We Wish You a Merry Christmas".  I found an online converter that will convert MP3 to 8 bit WAV format https://audio.online-convert.com/convert-to-wav  .   I've attached the converted file below.

 

Audio player program

Xiao_play_wav_from_SD_card.ino

/*
  Audio player, non blocking.
  read 8bit mono .wav file, up to 4 channels
  use Audacity to convert your audio file

  Author : AloyseTech
  Modified: BriscoeTech
  03/17/19: https://github.com/hydronics2/SamdAudio

  if the sketch compiles, but no sound, check to make sure:
   - '#include <SdFat.h>' is uncommented in SamdAudio.cpp 
   - 'extern SdFat memory;' is ucommented in SamdAudio.cpp
*/

#include <SdFat.h>  //https://github.com/greiman/SdFat
SdFat memory;

#include <SamdAudio.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

SamdAudio AudioPlayer;

#define NUM_AUDIO_CHANNELS 4 //could be 1,2 or 4 for sound

#define AUDIO_BUFFER_SIZE 512 //512 works fine for 22.05kh, 
//set buffer size to 1024 for 32khz and 44.1khz for Adafruit M0 with QUAD Flash

//indicate sample rate here (use audacity to convert your wav)
const unsigned int sampleRate = 22050; //hz

//your wav file
const char *filename0 = "piano8bit_22khz.wav";
const char *filename1 = "sfx1_8bit_22khz.wav";
const char *filename2 = "sfx2_8bit_22khz.wav";
const char *filename3 = "sfx3_8bit_22khz.wav";
const char *filename4 = "sfx4_8bit_22khz.wav";
const char *filename5 = "we-wish-you-a-merry-christmas.wav";

// SD chip select pin (with ethernet shield : 4)
#define YOUR_SD_CS 2

void setup()
{
  pinMode(YOUR_SD_CS, OUTPUT);

if ( !memory.begin(YOUR_SD_CS) )
  {
     //the sd card error was found, exit this function and to not attempt to finish
     Serial.println("can't start card");
  }

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.display();

   // write to display
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE, SSD1306_BLACK);
  display.setCursor(15, 25);
  display.print("We Wish You A");  
  display.setCursor(11, 40);
  display.print("Merry Christmas!");
  display.display();    
  
  Serial.begin(115200);
  while (!Serial); // open the serial to start!

  Serial.print("Initializing Audio Player...");
  if (AudioPlayer.begin(sampleRate, NUM_AUDIO_CHANNELS, AUDIO_BUFFER_SIZE) == -1) 
  {
    Serial.println(" failed!");
    return;
  }
  Serial.println(" done.");

  AudioPlayer.play(filename5, 0); //play 5th file on channel 0

  Serial.println("Playing file.....");
}

void loop()
{  
  if (Serial.available()) 
  {
    char c = Serial.read();
    Serial.println(c); //for debug
    
    if ( c == 'o') 
    {
      AudioPlayer.play(filename5, 0); //playing file on channel 0
      Serial.println("playing audio file on channel 0");
    }
    if ( c == 'p') 
    {
      AudioPlayer.play(filename5, 1); //playing file  on channel 1
      Serial.println("playing audio file on channel 1");
    }
      if ( c == 'k') 
    {
      AudioPlayer.play(filename5, 2); //playing file on channel 2
      Serial.println("playing audio file on channel 2");
    }
      if ( c == 'l') 
    {
      AudioPlayer.play(filename5, 3); //playing file on channel 3
      Serial.println("playing audio file on channel 3");
    }    
  } 
}

 

 

Demo Video

Here is a demo of WAV file playing from the SD card on the Xiao Expansion board.  I'm not getting much volume from the little speaker, so I'll need to look into that.  And certainly not hifi sound .

 

 

The final step will be to get the WAV file to play from the external 2MB flash memory that I added to the QT Py.

 

 

Links to previous blogs

A QT Py Christmas

A QT Py Christmas - add Cap Sense Buttons