diff --git a/Examples/Player/LaserFire1.wav b/Examples/Player/LaserFire1.wav deleted file mode 100644 index 44de445..0000000 Binary files a/Examples/Player/LaserFire1.wav and /dev/null differ diff --git a/Examples/Player/LaserFire2.wav b/Examples/Player/LaserFire2.wav deleted file mode 100644 index e0afc58..0000000 Binary files a/Examples/Player/LaserFire2.wav and /dev/null differ diff --git a/Examples/Player/Player.ino b/Examples/Player/Player.ino deleted file mode 100644 index 4f9cdbd..0000000 --- a/Examples/Player/Player.ino +++ /dev/null @@ -1,120 +0,0 @@ -/* - Audio player, non blocking. - read 8bit mono .wav file, up to 4 channels - use Audacity to convert your audio file - - Author : AloyseTech - Modified: BriscoeTech -*/ - -//#include -//SdFat SD; -//#include -#include - -SamdAudio AudioPlayer; - -#define NUM_AUDIO_CHANNELS 4 //could be 1,2 or 4 for sound - -// which Serial you prefer, for information. -#define SERIAL SerialUSB -//#define SERIAL Serial - -// SD chip select pin (with ethernet shield : 4) -#define YOUR_SD_CS 4//10 - -//indicate sample rate here (use audacity to convert your wav) -const unsigned int sampleRate = 22050; - -bool state = true; - -uint32_t timer = 0, updatetimer = 0; - -void setup() -{ - pinMode(2, OUTPUT); - //pinMode(2, INPUT_PULLUP); - //pinMode(3, INPUT_PULLUP); - //pinMode(4, INPUT_PULLUP); - - // debug output at 115200 baud - SERIAL.begin(115200); - while (!SERIAL); - - - // setup SD-card - SERIAL.print("Initializing SD card..."); - if (AudioPlayer.begin(sampleRate, NUM_AUDIO_CHANNELS, YOUR_SD_CS) == -1) - { - SERIAL.println(" failed!"); - return; - } - SERIAL.println(" done."); - - AudioPlayer.play("R2D2.wav", 0); - - SERIAL.println("Playing file....."); -} - -void loop() -{ - /* - if (millis() - timer > 500) - { - //I'm working late at night, full led brightness is dazzling! - //digitalWrite(13,state); - analogWrite(2, state ? 0 : 4); - - state = !state; - timer = millis(); - } - */ - - if (SERIAL.available()) - { - char c = SERIAL.read(); - - if ( c == 'q') - { - AudioPlayer.play("LaserFire1.wav", 0); - } - else if ( c == 'w') - { - AudioPlayer.play("LaserFire1.wav", 1); - } - else if ( c == 'e') - { - AudioPlayer.play("LaserFire2.wav", 2); - } - else if ( c == 'r') - { - AudioPlayer.play("LaserFire2.wav", 3); - } - else if ( c == 't') - { - AudioPlayer.play("R2D2.wav", 3); - } - - else if ( c == '1') - { - AudioPlayer.stopChannel(0); - SERIAL.println("ch0 off!"); - } - else if ( c == '2') - { - AudioPlayer.stopChannel(1); - SERIAL.println("ch1 off!"); - } - else if ( c == '3') - { - AudioPlayer.stopChannel(2); - SERIAL.println("ch2 off!"); - } - else if ( c == '4') - { - AudioPlayer.stopChannel(3); - SERIAL.println("ch3 off!"); - } - } - -} diff --git a/Examples/Player/R2D2.wav b/Examples/Player/R2D2.wav deleted file mode 100644 index b8b011b..0000000 Binary files a/Examples/Player/R2D2.wav and /dev/null differ diff --git a/README.adoc b/README.adoc deleted file mode 100644 index d5ac94e..0000000 --- a/README.adoc +++ /dev/null @@ -1,12 +0,0 @@ -### Audio Library for Arduino SAMD21 - -The SamdAudio library enables an Arduino SAMD21 board to play back 8bit .wav files -from a storage device like an SD card, without blocking program execution. - -This library is based off of ALoyseTech original SamdAudio, but has some minor functionality improvements. - -Library allows the user to setup upto four channels of sound, allowing for up to four sounds to be played simultaneously! - -This library has also been verified to work with FreeRtos https://github.com/BriscoeTech/Arduino-FreeRTOS-SAMD21 - - diff --git a/README.md b/README.md new file mode 100644 index 0000000..3dfd060 --- /dev/null +++ b/README.md @@ -0,0 +1,170 @@ +### Arduino Audio Library for Arduino SAMD21 + + +#### Update... an Adafruit dependency Adafruit_SPIFlash_FatFs.h is not longer available... look to some folks that have forked this repo like [gambalunga](https://github.com/Gambalunga/Audio_FeatherM0) who got it working using the updated Adafruit library. + +This polyphonic library allows you to play WAV files from SPI Flash and SD card to the 10bit DAC of a SAMD21 (Pin A0 on many boards). +Plays up to ~4 WAV files simultaneously. +[![IMAGE ALT TEXT](https://github.com/hydronics2/SamdAudio/blob/master/screen_shot.JPG)](https://youtu.be/A0afENS1ev4 "Playing polyphonic") + +Adafruit has a nice tutorial on how to connect the pin to a 1/8" audio jack. The hookup [instructions are here](https://learn.adafruit.com/circuitpython-essentials/circuitpython-audio-out) (ignore the circiut python example as this library is for an Arduino sketch). +![Adafruit image](https://cdn-learn.adafruit.com/assets/assets/000/057/479/original/circuitpython_ItsyBitsyM0AudioJackButtonPot_bb.jpg?1531328765) + +The 8bit sound quality is medium quality. I was able to get up to 44.1khz using SPI flash on the Adafruit M0 boards. The quality needed to be reduced to ~22khz when playing from the SD card. + +It all sounds fairly marginal at 8bit. Until there is a library with 16bit DMA output, I recommend going with a [Teensy](https://www.pjrc.com/teensy/td_libs_Audio.html) or a peripherial codec to do the heavy lifting of playing quality audio.... but hey this all sounds better than the Arduino UNO. + +The following Adafruit Express boards have onboard FLASH where you can store up to 2MB of sound ~30-60seconds. +This includes: +* [Itsybits M0 Express](https://www.adafruit.com/product/3727) (tested) +* [Adafruit Metro M0 Express](https://www.adafruit.com/product/3505) +* [Trinket M0 Express](https://www.adafruit.com/product/3500) and Gemma Express no SPI Flash so SD card playing only. +* Adafruit M4 Express boards with the SAMD51? should work + + +Read this great description in the Adafruit tutorial for getting the WAV files onto your Adafruit M0 Express board +https://learn.adafruit.com/introducing-itsy-bitsy-m0?view=all#using-spi-flash +Thanks to Tony Dicola and Adafruit for making this so easy! + +For the SD card example, these lines need to be edited in SamdAudio.cpp + +![edits sd](https://github.com/hydronics2/SamdAudio/blob/master/library_modification_SD_card.JPG) + +To revert back to playing WAV files from flash storage example goes like this in SamdAudio.cpp: + +![edits flash](https://github.com/hydronics2/SamdAudio/blob/master/library_modification_flash.JPG) + + +Flash example included in the examples folder. See also SD Card Example: + + /* + + Audio player, non blocking. + read 8bit mono .wav file, up to 4 channels + use Audacity to convert your audio file + Author : AloyseTech + + 03/17/19: https://github.com/hydronics2/SamdAudio + updated to work with Adafruit Qaud Flash memory boards. + This will work with any SAMD21 chip using SPI flash with a little tinkering + - itsyBitsy M0 Express, + - Feather M0 Express, + - probalby M4 of abovev and trinkets + + Read this great description in the Adafruit tutorial for getting the WAV files onto your Adafruit M0 Express board + https://learn.adafruit.com/introducing-itsy-bitsy-m0?view=all#using-spi-flash + Thanks to Tondy Dicola and Adafruit for making this so easy! + + if the sketch compiles and Initializes Audio player, but no sound, look in SamdAudio.cpp and umcomment these! + - #include + - #include + - extern Adafruit_W25Q16BV_FatFs memory; + + */ + + #include + + #include + #include + + #define FLASH_TYPE SPIFLASHTYPE_W25Q16BV // Flash chip type. + // If you change this be + // sure to change the fatfs + // object type below to match. + + #define FLASH_SS SS1 // Flash chip SS pin. + #define FLASH_SPI_PORT SPI1 // What SPI port is Flash on? + + Adafruit_SPIFlash flash(FLASH_SS, &FLASH_SPI_PORT); // Use hardware SPI + + // Finally create an Adafruit_M0_Express_CircuitPython object which gives + // an SD card-like interface to interacting with files stored in CircuitPython's + // flash filesystem. + + Adafruit_W25Q16BV_FatFs memory(flash); + + #include // + SamdAudio AudioPlayer; + + #define NUM_AUDIO_CHANNELS 4 //could be 1,2 or 4 for sound + + #define AUDIO_BUFFER_SIZE 1024 //512 works fine for 22.05kh, use 1024 for 32khz and 44.1khz + + //indicate sample rate here (use audacity to convert your wav) + const unsigned int sampleRate = 32000; //hz + + //your wav file + const char *filename0 = "poem8bit_32khz.wav"; + const char *filename1 = "sfx1_8bit_32khz.wav"; + const char *filename2 = "sfx2_8bit_32khz.wav"; + const char *filename3 = "sfx3_8bit_32khz.wav"; + const char *filename4 = "sfx4_8bit_32khz.wav"; + + void setup() + { + delay(10); + Serial.begin(115200); + while (!Serial); // open the serial to start! + + // Initialize flash library and check its chip ID. + if (!flash.begin(FLASH_TYPE)) + { + Serial.println("Error, failed to initialize flash chip!"); + while(1); + } + Serial.print("Flash chip JEDEC ID: 0x"); Serial.println(flash.GetJEDECID(), HEX); + // First call begin to mount the filesystem. Check that it returns true + // to make sure the filesystem was mounted. + if (!memory.begin()) + { + Serial.println("Error, failed to mount filesystem!"); + while(1); + } + Serial.println("Mounted filesystem!"); + + 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(filename0, 1); + + Serial.println("Playing file....."); + } + + + void loop() + { + if (Serial.available()) + { + char c = Serial.read(); + Serial.println(c); //for debug + + if ( c == 'o') + { + AudioPlayer.play(filename1, 0); //playing file on channel 0 + Serial.println("playing audio file on channel 0"); + } + if ( c == 'p') + { + AudioPlayer.play(filename2, 1); //playing file on channel 1 + Serial.println("playing audio file on channel 1"); + } + if ( c == 'k') + { + AudioPlayer.play(filename3, 2); //playing file on channel 2 + Serial.println("playing audio file on channel 2"); + } + if ( c == 'l') + { + AudioPlayer.play(filename4, 3); //playing file on channel 3 + Serial.println("playing audio file on channel 3"); + } + } + } + + + diff --git a/SamdAudio.cpp b/SamdAudio.cpp index fac7cf2..602f991 100644 --- a/SamdAudio.cpp +++ b/SamdAudio.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2016 Théo Meyer aka AloyseTech. All right reserved. + Copyright (c) 2016 Th�o Meyer aka AloyseTech. All right reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -18,24 +18,33 @@ #include "SamdAudio.h" +//for using flash memory as WAV file storage +#include +#include +extern Adafruit_W25Q16BV_FatFs memory; + +//for using SD card as WAV file storage +//#include +//extern SdFat memory; + //********************************************************************* //Global variables File __audioFile[MAX_N_CHANNELS]; volatile bool __audioPlaying[MAX_N_CHANNELS]={false}; volatile bool __audioFileReady[MAX_N_CHANNELS] = {false}; volatile uint32_t __SampleIndex[MAX_N_CHANNELS]; -uint8_t __WavSamples[MAX_N_CHANNELS][2][AUDIO_BUFFER_SIZE]; +uint8_t __WavSamples[MAX_N_CHANNELS][2][MAX_AUDIO_BUFFER_SIZE]; uint8_t rampDivisor[MAX_N_CHANNELS]={1}; uint8_t whichBuffer[MAX_N_CHANNELS]={0}; volatile bool fillNextBuffer[MAX_N_CHANNELS]={true}; volatile uint16_t __audioData; -SdFat SamdAudioSdFat; int __Volume; bool __criticalSection = false; int __numOfChannelsUsed = 4; +int __audioBufferSize = 1024; // unused declarations, commented out void TC5_Handler (void) __attribute__ ((weak, alias("AudioPlay_Handler"))); @@ -45,15 +54,10 @@ void TC3_Handler (void) __attribute__ ((weak, alias("AudioRead_Handler"))); //********************************************************************* -int SamdAudio::begin(uint32_t sampleRate, uint8_t numOfChannels, uint8_t chipSelect) +int SamdAudio::begin(uint32_t sampleRate, uint8_t numOfChannels, uint16_t audio_buffer_size) { - - // check if sd card is inserted and ready with no errors - if ( !SamdAudioSdFat.begin(chipSelect) ) - { - //the sd card error was found, exit this function and to not attempt to finish - return -1; - } + __audioBufferSize = audio_buffer_size; + if(numOfChannels == 1 || numOfChannels == 2 || numOfChannels == 4) { @@ -65,14 +69,14 @@ int SamdAudio::begin(uint32_t sampleRate, uint8_t numOfChannels, uint8_t chipSel // bad input passed, assume all 4 channels to be safe __numOfChannelsUsed = 4; } - + // initialize arrays for(uint8_t index=0; index=__numOfChannelsUsed)//unsigned, cant be negative if(channel>=__numOfChannelsUsed) return; - + disableReaderTimer(); - - - if(__audioFileReady[channel]) __audioFile[channel].close(); - __audioFile[channel] = SamdAudioSdFat.open(fname); + __audioFile[channel] = memory.open(fname); if(!__audioFile[channel]){ //end(); //SerialUSB.println("Error opening file"); return; } - - + + whichBuffer[channel]=0; fillNextBuffer[channel]=1; - - __audioFile[channel].read(__WavSamples[channel][whichBuffer[channel]], AUDIO_BUFFER_SIZE); - + + __audioFile[channel].read(__WavSamples[channel][whichBuffer[channel]], __audioBufferSize); + __SampleIndex[channel]=0; __audioFileReady[channel] = true; - + rampDivisor[channel]=RAMPIN; - + /*once the buffer is filled for the first time the counter can be started*/ if(alonePlaying(channel)) { enablePlayerTimer(); } __audioPlaying[channel]=true; - + enableReaderTimer(); } @@ -171,7 +171,7 @@ bool __channelsPlaying() void SamdAudio::dacConfigure(void){ analogWriteResolution(10); // analogWrite(A0, 0); - + DAC->CTRLA.bit.ENABLE = 0x01; DAC->DATA.reg = 0; while (DAC->STATUS.bit.SYNCBUSY == 1); @@ -188,26 +188,26 @@ void SamdAudio::configurePlayerTimer(uint32_t sampleRate) // Enable GCLK for TCC2 and TC5 (timer counter input clock) GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_TC4_TC5)) ; while (GCLK->STATUS.bit.SYNCBUSY); - + resetPlayerTimer(); - + // Set Timer counter Mode to 16 bits TC5->COUNT16.CTRLA.reg |= TC_CTRLA_MODE_COUNT16; - + // Set TC5 mode as match frequency TC5->COUNT16.CTRLA.reg |= TC_CTRLA_WAVEGEN_MFRQ; - + TC5->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCALER_DIV1 | TC_CTRLA_ENABLE; - + TC5->COUNT16.CC[0].reg = (uint16_t) (SystemCoreClock / sampleRate - 1); while (syncPlayerTimer()); - + // Configure interrupt request NVIC_DisableIRQ(TC5_IRQn); NVIC_ClearPendingIRQ(TC5_IRQn); NVIC_SetPriority(TC5_IRQn, 0); NVIC_EnableIRQ(TC5_IRQn); - + // Enable the TC5 interrupt request TC5->COUNT16.INTENSET.bit.MC0 = 1; while (syncPlayerTimer()); @@ -257,11 +257,14 @@ void SamdAudio::configureReaderTimer() { // The GCLK clock provider to use // GCLK0, GCLK1 & GCLK3 are used already, see startup.c - const uint8_t GCLK_SRC = 5; - + + //GCLK0 ... freezes serial.. on adafruit M0 + + const uint8_t GCLK_SRC = 1; //1 works for Adafruit M0 express + // Configure the XOSC32K to run in standby //SYSCTRL->XOSC32K.bit.RUNSTDBY = 1; - + // Setup clock provider GCLK_SRC with a /2 source divider // GCLK_GENDIV_ID(X) specifies which GCLK we are configuring // GCLK_GENDIV_DIV(Y) specifies the clock prescalar / divider @@ -272,7 +275,7 @@ void SamdAudio::configureReaderTimer() while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) { /* Wait for synchronization */ } - + // Configure the GCLK module // GCLK_GENCTRL_GENEN, enable the specific GCLK module // GCLK_GENCTRL_SRC_XOSC32K, set the source to the XOSC32K @@ -287,10 +290,10 @@ void SamdAudio::configureReaderTimer() while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) { /* Wait for synchronization */ } - + // Turn the power to the TC3 module on PM->APBCMASK.reg |= PM_APBCMASK_TC3; - + // Set TC3 (shared with TCC2) GCLK source to GCLK_SRC // GCLK_CLKCTRL_CLKEN, enable the generic clock // GCLK_CLKCTRL_GEN(X), specifies the GCLK generator source @@ -301,14 +304,14 @@ void SamdAudio::configureReaderTimer() while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) { /* Wait for synchronization */ } - + // Disable TC3. This is required (if enabled already) // before setting certain registers TC3->COUNT8.CTRLA.reg &= ~TC_CTRLA_ENABLE; while (TC3->COUNT8.STATUS.reg & TC_STATUS_SYNCBUSY) { /* Wait for synchronization */ } - + // Set the mode to 8 bit and set it to run in standby // TC_CTRLA_MODE_COUNT8, specify 8bit mode // TC_CTRLA_RUNSTDBY, keep the module running when in standby @@ -321,22 +324,22 @@ void SamdAudio::configureReaderTimer() while (TC3->COUNT8.STATUS.reg & TC_STATUS_SYNCBUSY) { /* Wait for synchronization */ } - + // Enable the TC3 interrupt vector // Set the priority to second (less important than feeding the DAC NVIC_DisableIRQ(TC3_IRQn); NVIC_ClearPendingIRQ(TC3_IRQn); NVIC_SetPriority(TC3_IRQn, 0xFFFF); NVIC_EnableIRQ(TC3_IRQn); - - + + // Enable interrupt on overflow // TC_INTENSET_OVF, enable an interrupt on overflow TC3->COUNT8.INTENSET.reg = TC_INTENSET_OVF; while (TC3->COUNT8.STATUS.reg & TC_STATUS_SYNCBUSY) { /* Wait for synchronization */ } - + // Enable TC3 TC3->COUNT8.CTRLA.reg |= TC_CTRLA_ENABLE; while (TC3->COUNT8.STATUS.reg & TC_STATUS_SYNCBUSY) { @@ -369,37 +372,37 @@ void SamdAudio::disableReaderTimer() #ifdef __cplusplus extern "C" { #endif - + // TC5 ISR void AudioPlay_Handler (void) { __audioData=0; - + for(uint8_t index=0; index<__numOfChannelsUsed; index++) { if (__audioPlaying[index]) { if(__audioFile[index].available()) { - if (__SampleIndex[index] < AUDIO_BUFFER_SIZE - 1) + if (__SampleIndex[index] < __audioBufferSize - 1) { __audioData+=__WavSamples[index][whichBuffer[index]][__SampleIndex[index]++]/rampDivisor[index]; - + } else //last sample from buffer { __audioData+=__WavSamples[index][whichBuffer[index]][__SampleIndex[index]++]/rampDivisor[index]; - + __SampleIndex[index] = 0; if(!fillNextBuffer[index]) //we have been able to load next buffer : continue; else, loop the buffer... whichBuffer[index]=1-whichBuffer[index]; fillNextBuffer[index]=1; } - + if(rampDivisor[index]>1) rampDivisor[index]--; } - + //end of file, now play ramp out else if (__audioFileReady[index]) { @@ -415,24 +418,24 @@ extern "C" { else { __audioPlaying[index]=false; - + if(!__channelsPlaying()) { //tc disable TC5->COUNT16.CTRLA.reg &= ~TC_CTRLA_ENABLE; while (TC5->COUNT16.STATUS.reg & TC_STATUS_SYNCBUSY); - + TC3->COUNT8.CTRLA.reg &= ~TC_CTRLA_ENABLE; while (TC3->COUNT8.STATUS.reg & TC_STATUS_SYNCBUSY) { /* Wait for synchronization */ } - + } } } } - - + + if(__channelsPlaying()) { if(__numOfChannelsUsed == 4 || __numOfChannelsUsed == 3) @@ -440,7 +443,7 @@ extern "C" { __audioData>>=0; } else if(__numOfChannelsUsed == 2) - { + { __audioData<<=1; } else if(__numOfChannelsUsed == 1) @@ -451,15 +454,15 @@ extern "C" { DAC->DATA.reg = __audioData & 0x3FF; // DAC on 10 bits. while (DAC->STATUS.bit.SYNCBUSY == 1); } - - + + // Clear the interrupt TC5->COUNT16.INTFLAG.bit.MC0 = 1; - + } - - - + + + // TC3 ISR void AudioRead_Handler() { @@ -471,7 +474,7 @@ extern "C" { { if(__audioFile[index].available() && !__criticalSection && fillNextBuffer[index]) { - __audioFile[index].read(__WavSamples[index][1-whichBuffer[index]], AUDIO_BUFFER_SIZE); + __audioFile[index].read(__WavSamples[index][1-whichBuffer[index]], __audioBufferSize); fillNextBuffer[index]=0; } } @@ -480,7 +483,7 @@ extern "C" { TC3->COUNT8.INTFLAG.bit.OVF = 1; } } - + #ifdef __cplusplus } #endif diff --git a/SamdAudio.h b/SamdAudio.h index 58029c4..a2918f2 100644 --- a/SamdAudio.h +++ b/SamdAudio.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2016 Théo Meyer aka AloyseTech. All right reserved. + Copyright (c) 2016 Th�o Meyer aka AloyseTech. All right reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -15,26 +15,23 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - + #ifndef SAMDAUDIO_H #define SAMDAUDIO_H #include "Arduino.h" #include "Print.h" - #include #include //********************************** - - //#define N_CHANNELS 1 //could be 1,2 or 4 - // defines the max number of channels that this device can handle #define MAX_N_CHANNELS 4 - #define AUDIO_BUFFER_SIZE 512 + #define MAX_AUDIO_BUFFER_SIZE 1024 // value can be set in the sketch AUIDO_BUFFER_SIZE + #define RAMPIN 255 //********************************** @@ -43,7 +40,7 @@ public: SamdAudio(){}; - int begin(uint32_t sampleRate, uint8_t numOfChannels, uint8_t chipSelect); + int begin(uint32_t sampleRate, uint8_t numOfChannels, uint16_t audio_buffer_size); void play(const char *fname, uint8_t channel) ; //void play(const char *fname) ; void stopChannel(uint8_t c); @@ -52,8 +49,8 @@ void criticalON(); void criticalOFF(); - private: + void dacConfigure(void); //The first timer is used to feed the DAC with data every 1/sampleRate sec diff --git a/audio/piano8bit_22khz.wav b/audio/piano8bit_22khz.wav new file mode 100644 index 0000000..fb9b5a7 Binary files /dev/null and b/audio/piano8bit_22khz.wav differ diff --git a/audio/poem8bit_32khz.wav b/audio/poem8bit_32khz.wav new file mode 100644 index 0000000..7cee06e Binary files /dev/null and b/audio/poem8bit_32khz.wav differ diff --git a/audio/sfx1_8bit_22khz.wav b/audio/sfx1_8bit_22khz.wav new file mode 100644 index 0000000..69ddeb2 Binary files /dev/null and b/audio/sfx1_8bit_22khz.wav differ diff --git a/audio/sfx1_8bit_32khz.wav b/audio/sfx1_8bit_32khz.wav new file mode 100644 index 0000000..8a20378 Binary files /dev/null and b/audio/sfx1_8bit_32khz.wav differ diff --git a/audio/sfx2_8bit_22khz.wav b/audio/sfx2_8bit_22khz.wav new file mode 100644 index 0000000..6fcc6d8 Binary files /dev/null and b/audio/sfx2_8bit_22khz.wav differ diff --git a/audio/sfx2_8bit_32khz.wav b/audio/sfx2_8bit_32khz.wav new file mode 100644 index 0000000..b5581c3 Binary files /dev/null and b/audio/sfx2_8bit_32khz.wav differ diff --git a/audio/sfx3_8bit_22khz.wav b/audio/sfx3_8bit_22khz.wav new file mode 100644 index 0000000..3d07be5 Binary files /dev/null and b/audio/sfx3_8bit_22khz.wav differ diff --git a/audio/sfx3_8bit_32khz.wav b/audio/sfx3_8bit_32khz.wav new file mode 100644 index 0000000..fa9500e Binary files /dev/null and b/audio/sfx3_8bit_32khz.wav differ diff --git a/audio/sfx4_8bit_22khz.wav b/audio/sfx4_8bit_22khz.wav new file mode 100644 index 0000000..e431efd Binary files /dev/null and b/audio/sfx4_8bit_22khz.wav differ diff --git a/audio/sfx4_8bit_32khz.wav b/audio/sfx4_8bit_32khz.wav new file mode 100644 index 0000000..071ffcb Binary files /dev/null and b/audio/sfx4_8bit_32khz.wav differ diff --git a/examples/play_wav_from_FLASH/play_wav_from_FLASH.ino b/examples/play_wav_from_FLASH/play_wav_from_FLASH.ino new file mode 100644 index 0000000..0b28418 --- /dev/null +++ b/examples/play_wav_from_FLASH/play_wav_from_FLASH.ino @@ -0,0 +1,129 @@ +/* + + Audio player, non blocking. + read 8bit mono .wav file, up to 4 channels + use Audacity to convert your audio file + Author : AloyseTech + + 03/17/19: https://github.com/hydronics2/SamdAudio + updated to work with Adafruit Qaud Flash memory boards. + This will work with any SAMD21 chip using SPI flash with a little tinkering + - itsyBitsy M0 Express, + - Feather M0 Express, + - probalby M4 of abovev and trinkets + + Read this great description in the Adafruit tutorial for getting the WAV files onto your Adafruit M0 Express board + https://learn.adafruit.com/introducing-itsy-bitsy-m0?view=all#using-spi-flash + Thanks to Tondy Dicola and Adafruit for making this so easy! + + if the sketch compiles and Initializes Audio player, but no sound, look in SamdAudio.cpp and umcomment these! + - #include + - #include + - extern Adafruit_W25Q16BV_FatFs memory; + +*/ + +#include + +#include +#include + +#define FLASH_TYPE SPIFLASHTYPE_W25Q16BV // Flash chip type. + // If you change this be + // sure to change the fatfs + // object type below to match. + +#define FLASH_SS SS1 // Flash chip SS pin. +#define FLASH_SPI_PORT SPI1 // What SPI port is Flash on? + +Adafruit_SPIFlash flash(FLASH_SS, &FLASH_SPI_PORT); // Use hardware SPI + +// Finally create an Adafruit_M0_Express_CircuitPython object which gives +// an SD card-like interface to interacting with files stored in CircuitPython's +// flash filesystem. +//Adafruit_M0_Express_CircuitPython pythonfs(flash); +Adafruit_W25Q16BV_FatFs memory(flash); + +#include // +SamdAudio AudioPlayer; + +#define NUM_AUDIO_CHANNELS 4 //could be 1,2 or 4 for sound + +#define AUDIO_BUFFER_SIZE 1024 //512 works fine for 22.05kh, use 1024 for 32khz and 44.1khz + +//indicate sample rate here (use audacity to convert your wav) +const unsigned int sampleRate = 32000; //hz + +//your wav file +const char *filename0 = "poem8bit_32khz.wav"; +const char *filename1 = "sfx1_8bit_32khz.wav"; +const char *filename2 = "sfx2_8bit_32khz.wav"; +const char *filename3 = "sfx3_8bit_32khz.wav"; +const char *filename4 = "sfx4_8bit_32khz.wav"; + +void setup() +{ + delay(10); + Serial.begin(115200); + while (!Serial); // open the serial to start! + + // Initialize flash library and check its chip ID. + if (!flash.begin(FLASH_TYPE)) + { + Serial.println("Error, failed to initialize flash chip!"); + while(1); + } + Serial.print("Flash chip JEDEC ID: 0x"); Serial.println(flash.GetJEDECID(), HEX); + // First call begin to mount the filesystem. Check that it returns true + // to make sure the filesystem was mounted. + if (!memory.begin()) + { + Serial.println("Error, failed to mount filesystem!"); + while(1); + } + Serial.println("Mounted filesystem!"); + + 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(filename0, 1); + + Serial.println("Playing file....."); +} + + +void loop() +{ + if (Serial.available()) + { + char c = Serial.read(); + Serial.println(c); //for debug + + if ( c == 'o') + { + AudioPlayer.play(filename1, 0); //playing file on channel 0 + Serial.println("playing audio file on channel 0"); + } + if ( c == 'p') + { + AudioPlayer.play(filename2, 1); //playing file on channel 1 + Serial.println("playing audio file on channel 1"); + } + if ( c == 'k') + { + AudioPlayer.play(filename3, 2); //playing file on channel 2 + Serial.println("playing audio file on channel 2"); + } + if ( c == 'l') + { + AudioPlayer.play(filename4, 3); //playing file on channel 3 + Serial.println("playing audio file on channel 3"); + } + } +} + diff --git a/examples/play_wav_from_SD_card/play_wav_from_SD_card.ino b/examples/play_wav_from_SD_card/play_wav_from_SD_card.ino new file mode 100644 index 0000000..c9ec7fd --- /dev/null +++ b/examples/play_wav_from_SD_card/play_wav_from_SD_card.ino @@ -0,0 +1,98 @@ +/* + 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 ' is uncommented in SamdAudio.cpp + - 'extern SdFat memory;' is ucommented in SamdAudio.cpp + + +*/ + +#include //https://github.com/greiman/SdFat +SdFat memory; + +#include + +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"; + +// SD chip select pin (with ethernet shield : 4) +#define YOUR_SD_CS 10 + +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"); + } + + 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(filename0, 1); //play 1st 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(filename1, 0); //playing file on channel 0 + Serial.println("playing audio file on channel 0"); + } + if ( c == 'p') + { + AudioPlayer.play(filename2, 1); //playing file on channel 1 + Serial.println("playing audio file on channel 1"); + } + if ( c == 'k') + { + AudioPlayer.play(filename3, 2); //playing file on channel 2 + Serial.println("playing audio file on channel 2"); + } + if ( c == 'l') + { + AudioPlayer.play(filename4, 3); //playing file on channel 3 + Serial.println("playing audio file on channel 3"); + } + } +} diff --git a/library_modification_SD_card.JPG b/library_modification_SD_card.JPG new file mode 100644 index 0000000..a4eb2e2 Binary files /dev/null and b/library_modification_SD_card.JPG differ diff --git a/library_modification_flash.JPG b/library_modification_flash.JPG new file mode 100644 index 0000000..aa80b56 Binary files /dev/null and b/library_modification_flash.JPG differ diff --git a/screen_shot.JPG b/screen_shot.JPG new file mode 100644 index 0000000..129cbd3 Binary files /dev/null and b/screen_shot.JPG differ