Microcontroller › Arduino › Reading wave files from RAM
- This topic has 3 replies, 2 voices, and was last updated 8 years, 7 months ago by
Sachin.
-
AuthorPosts
-
June 28, 2016 at 10:45 am #4501
Sachin
ParticipantHii,
I am working on project on sound generation in electric vehicle. I have stored short audio samples (ranges from 1-5 sec) in SD card and successfully able to read and play the wave files from SD card.
1) I am not able to play the wave samples continously instead it just plays once and stops.
2) Now I want to read the samples from SD card into RAM and play it from RAM. I know the RAM of Arduino Due is 96KB which is enough for my project.Thanks in advance…..
Please find the code below
#include <SD.h>
#include <SPI.h>#include "sampler1.h"Sampler sampler1;int x=0;void setup() {// debug output at 9600 baudSerial.begin(9600);// setup SD-cardSerial.print("Initializing SD card…");if (!SD.begin(4)) {Serial.println(" failed!");while(true);}Serial.println(" done.");sampler1.init();//turn on the timer clock in the power management controllerpmc_set_writeprotect(false);pmc_enable_periph_clk(ID_TC4);//we want wavesel 01 with RCTC_Configure(TC1, 1, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK2);TC_SetRC(TC1, 1, 238); // sets <> 44.1 Khz interrupt rateTC_Start(TC1, 1);// enable timer interrupts on the timerTC1->TC_CHANNEL[1].TC_IER=TC_IER_CPCS;TC1->TC_CHANNEL[1].TC_IDR=~TC_IER_CPCS;//Enable the interrupt in the nested vector interrupt controller//TC4_IRQn where 4 is the timer number * timer channels (3) + the channel//number (=(1*3)+1) for timer1 channel1NVIC_EnableIRQ(TC4_IRQn);analogWrite(DAC1,0);}void loop() {if(x<1){sampler1.load("1.wav");sampler1.splay(10);}sampler1.buffill();x++;}void TC4_Handler() //Interrupt at 44.1KHz rate (every 22.6us){TC_GetStatus(TC1, 1);// 2048 is the 0 value of audio out.int16_t ulOutput=2048;//modification of volumesampler1.next();ulOutput += sampler1.output(); //2048+(0-1)if(ulOutput>4095) ulOutput=4095;dacc_write_conversion_data(DACC_INTERFACE, ulOutput);// analogWrite(DAC1,ulOutput);}Sampler.h#include <arduino.h>const int chipSelect = 4; // For Due, the SS of SD Card is on pin 4.const int bufsize = 1024; // buffer size in bytes. You can change this data.// Put here the filenames of your samples on SD cardconst char* samplefile[]= {"1.wav","2.wav","3.wav","4.wav","5.wav","6.wav","7.wav"};// Header of a wave file.// Num_channels will tell us if we are in stereo (2) or mono (1)typedef struct {char RIFF[4];int32_t chunk_size;char WAVE[4];char fmt_[4];int32_t subchunk1_size;int16_t audio_format;int16_t num_channels;int32_t sample_rate;int32_t byte_rate;int16_t block_align;int16_t bits_per_sample;char DATA[4];int32_t subchunk2_size;} wave_header;// Here is our sampler classclass Sampler{public:uint32_t volglobal; // volume max of the sample (when sustain)boolean play; // is the sample playing or not ?int indbuf; // buffer numberuint16_t bufread; // buffer being read numberuint16_t lastbuf; // last buffer read numberint16_t buf[2][bufsize]; // bufferuint32_t possample; // sample positionuint32_t endofsample; // end of sampleuint32_t decrease; // decrease speed//uint16_t samplenote; // sample noteFile myFile; // The wave filewave_header header; // The wave headerboolean openfile ; // Are we opening file ?boolean closefile ; // Are we closing file ?const char* samplen; // Storing the sample nameint16_t patternplaying; // The pattern which is currently playing the sample// Init of the sampler object. Here you can put your default values.void init(){indbuf =0;bufread = 0;lastbuf = 0;play = false;volglobal = 800;openfile = false;closefile = false;patternplaying = -1;}// Play the sample, giving volumevoid splay(uint32_t vol){play=true;volglobal = vol;}// load the wave header in the header data, and the beginning of the wave file in the buffer.void load(const char* samplename){bufread = 0;lastbuf = 0;possample = 0;samplen = samplename;closefile = false;openfile = true;}//Stop playing the samplevoid sstop(){if(play){closefile = true;// Serial.println("sstop");}}// Set the volume of the samplevoid setVol(uint32_t vol){volglobal = vol;}//Set the end of the samplevoid setEnd(uint32_t theEnd){endofsample = (endofsample*theEnd)>>7;//Serial.println("End");}// Fill the buffer if it has to be.// This method must not be called in the main program loop.// The return of the method indicates that it is reading a sound fileboolean buffill(){boolean ret = false;if(play){// The buffer must be filled only if the previous buffer was finished to be readif(bufread==lastbuf){ret = true;// If we the sample read has arrived to the end of the file, we must stop the sample readingif(possample>=(endofsample-bufsize))closefile=true;// OPEN FILEif(openfile){myFile= SD.open(samplen, FILE_READ);myFile.read(&header, sizeof(header));// Serial.println(sizeof(header)); //44endofsample = header.chunk_size-bufsize;// Serial.println(bufsize); //1024// Serial.println(endofsample); //792846= 793878-8=793870-1024=792846myFile.read(buf[0], sizeof(buf[0]));Serial.println(sizeof(buf[0])); //2048??possample = sizeof(buf[0]) + sizeof(header);// Serial.println(possample); //2092 =2048+44openfile = false;// Serial.println(openfile);}else{// CLOSE FILEif(closefile){myFile.close();play = false;// Serial.println("CloseFile");}//READ FILE awapping between buf 0 and 1 takes placeelse{if(lastbuf==0) lastbuf = 1;elselastbuf = 0;int me = myFile.read(buf[lastbuf], sizeof(buf[lastbuf]));// Serial.println(me);//2048// Serial.println(sizeof(buf[lastbuf])); //2048possample += sizeof(buf[lastbuf]);// Serial.println(possample); //4140=2048+2092// If there is an error while reading sample file, we stop the reading and close the fileif(me<=0){play = false;myFile.close();}}}}}Serial.println(lastbuf);return ret;}// Compute the position of the next sample. Must be called in the sound generating loop, before the method "output()"void next(){if(play){// If the wave file is stereo, we take only one side (left).indbuf += header.num_channels;// The reading of the file must stop at the end of file.if(possample>=(endofsample-bufsize)){closefile = true;}// If a buffer is finished to be read, we read the other buffer.if(indbuf>=bufsize) //indbuf 0-1023{if(bufread==0) bufread = 1;else bufread = 0;indbuf=0;}}}// Read the wave file at a position. Returns the volume (12 bits)int16_t output(){int16_t ret=0;if(play){ret = ((buf[bufread][indbuf]>>4)*volglobal)>>7; //ret value ranges from 0 to 1 bcoz buf[][]=2}return ret;}};June 28, 2016 at 12:33 pm #14027Prabakaran P M
Participantvoid loop() {if(x<1){sampler1.load("1.wav");sampler1.splay(10);}sampler1.buffill();x++;}The if loop in the above code is making it to run only onceJune 28, 2016 at 1:32 pm #14032Sachin
ParticipantSorry I forget to tell you, I also tried as (x>100) then I get continous sound but not the original sound but wierd sound.
June 29, 2016 at 11:58 am #14035Sachin
ParticipantHiii,
I am able to perform sucessfully the contionus sound. Now, my problem is how to read the samples from RAM?
-
AuthorPosts
- You must be logged in to reply to this topic.