A library which allows the playing of Wav files using the TLV320

Dependents:   RSALB_hbridge_helloworld RSALB_lobster WavPlayer_test AudioCODEC_HelloWorld

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers WavPlayer.cpp Source File

WavPlayer.cpp

00001 // TODO: Add licence and stop start remembering and fill buffer functions
00002 
00003 
00004 
00005 #include "WavPlayer.h"
00006 
00007 #define DEBUG 0
00008 #define debug_printf(args ...) if (DEBUG) printf(args)
00009 
00010 #define WAVPLAYER_PLAYER_BUF 1000
00011 
00012 #define WAVPLAYER_OUTPUT_RATE 48000
00013 
00014 #define WAVPLAYER_READ_MARGIN 0.9
00015 
00016 #define WAVLPAYER_SLOW_MARGIN 5
00017 
00018 #define WAVPLAYER_GEN_TEST 0
00019 
00020 #define WAVPLAYER_GEN_FREQ 440
00021 
00022 #if WAVPLAYER_GEN_TEST == 1
00023 #include "sinelookup.h"
00024 #else
00025 #define SINE16LENGTH 2
00026 #define SINE32LENGTH 2
00027 const int16_t sine16lookup[] = {0,10000};
00028 #endif
00029 
00030 WavPlayer* WavPlayer::instance;
00031 //void WavPlayer::i2sisr();
00032 
00033 WavPlayer::WavPlayer() :
00034         flag_play(true), i2s(I2S_TRANSMIT, p5, p6, p7), codec(p9, p10)//, ext_flag(p22), //run_flag(p23)
00035 {
00036     instance = this;
00037     codec.power(true);                  //power up TLV apart from analogue input
00038     codec.stop();
00039     codec.frequency(WAVPLAYER_OUTPUT_RATE);            //set sample frequency
00040     codec.wordsize(16);  //set transfer protocol
00041     codec.master(false);
00042     codec.headphone_volume(0.6);
00043     //interrupt come from the I2STXFIFO only
00044 
00045     i2s.masterslave(I2S_MASTER);
00046     i2s.attach(&WavPlayer::i2sisr);
00047 
00048     i2s.wordsize(16);
00049     i2s.stereomono(I2S_MONO);
00050 
00051     i2s.frequency(WAVPLAYER_OUTPUT_RATE);
00052 
00053     //ext_flag = false;
00054 
00055     flag_vol = false;
00056     volume = 1;
00057 }
00058 
00059 WavPlayer::WavPlayer(FILE **fpp):flag_play(true), i2s(I2S_TRANSMIT, p5, p6, p7), codec(p9, p10)//, ext_flag(p22), //run_flag(p23)
00060 {
00061     instance = this;
00062     codec.power(true);                  //power up TLV apart from analogue input
00063     codec.stop();
00064     codec.frequency(WAVPLAYER_OUTPUT_RATE);            //set sample frequency
00065     codec.wordsize(16);  //set transfer protocol
00066     codec.master(false);
00067     codec.headphone_volume(0.6);
00068     //interrupt come from the I2STXFIFO only
00069 
00070     i2s.masterslave(I2S_MASTER);
00071     i2s.attach(&WavPlayer::i2sisr);
00072 
00073     i2s.wordsize(16);
00074     i2s.stereomono(I2S_MONO);
00075 
00076     i2s.frequency(WAVPLAYER_OUTPUT_RATE);
00077 
00078     //ext_flag = false;
00079 
00080     flag_vol = false;
00081     volume = 1;
00082     open(fpp);
00083 }
00084 
00085 void WavPlayer::i2sisr()
00086 {
00087     instance->i2sisr_();
00088 }
00089 
00090 void WavPlayer::i2sisr_()
00091 {
00092     int to_write = i2s.max_fifo_points() - i2s.fifo_points();
00093     int temp[32];
00094     /*for(int i = 0; i < 32; i++)
00095      {
00096      temp[i] = 0;
00097      }*/
00098     int destore[2];
00099     if (rbuf.numberStored() > to_write + 8 && flag_play)
00100     {
00101         for (int i = 0; i < to_write; i += 2)
00102         {
00103             rbuf.readFirst(destore);
00104             rbuf.usedFirst();
00105             temp[i]   = destore[0];
00106             temp[i+1] = destore[1];
00107         }
00108 
00109         i2s.write(temp, to_write);
00110     }
00111     else
00112     {
00113         for (int i = 0; i < to_write; i++)
00114         {
00115             temp[i] = 0;
00116         }
00117         i2s.write(temp, to_write);
00118         isr_underrun++;
00119         
00120     }
00121 
00122 }
00123 
00124 void WavPlayer::open(FILE **fpp)
00125 {
00126     filepp = fpp;
00127     if (*filepp == NULL)
00128         printf(
00129                 "Please open a file before passing the file pointer pointer...\n\r");
00130     char temp[4];
00131     fgets_m(temp, 4, *filepp);
00132     debug_printf("%s\n\r", temp);
00133     if (strcmp(temp, "RIFF") != 0)
00134         printf("This is not a RIFF file\n\r");
00135     fseekread(*filepp, temp, 8, 4);
00136     if (strcmp(temp, "WAVE") != 0)
00137         printf("This is not a WAVE file\n\r");
00138     
00139     current_time = 0;
00140     
00141     getConfig();
00142 }
00143 
00144 int WavPlayer::getConfig()
00145 {
00146     char temp[4];
00147     clear(temp, 4);
00148     fseekread(*filepp, temp, 4, 4);
00149     config.file_size = getu32(temp, 4);
00150     debug_printf("FileSize = %i\n\r", config.file_size);
00151 
00152     int chunkstart = findChunk(*filepp, "fmt ", 4, config.file_size, 12);
00153 
00154     if (chunkstart != -1)
00155     {
00156 
00157         config.format_tag = fsru16(*filepp, chunkstart + 8);
00158         debug_printf("Format_tag:            %i\n\r", config.format_tag);
00159 
00160         config.channels = fsru16(*filepp, chunkstart + 10);
00161         debug_printf("nChannels:            %i\n\r", config.channels);
00162 
00163         config.samples_per_sec = fsru32(*filepp, chunkstart + 12);
00164         debug_printf("nSamplesPerSec:        %i\n\r", config.samples_per_sec);
00165 
00166         config.avg_bytes_per_sec = fsru32(*filepp, chunkstart + 16);
00167         debug_printf("avg_bytes_per_sec:    %i\n\r", config.avg_bytes_per_sec);
00168 
00169         config.block_align = fsru16(*filepp, chunkstart + 20);
00170         debug_printf("block_align:            %i\n\r", config.block_align);
00171 
00172         config.bits_per_sample = fsru16(*filepp, chunkstart + 22);
00173         debug_printf(
00174                 "bits per sample:            %i\n\r", config.bits_per_sample);
00175 
00176     }
00177 
00178     chunkstart = findChunk(*filepp, "data", 4, config.file_size, 12);
00179 
00180     if (chunkstart != -1)
00181     {
00182         config.data_length = fsru32(*filepp, chunkstart + 4);
00183         debug_printf("Data Length:            %i\n\r", config.data_length);
00184     }
00185     return 0;
00186 
00187 }
00188 
00189 float WavPlayer::play()
00190 {
00191     return play(float(config.data_length) / float(config.samples_per_sec));
00192 
00193 }
00194 
00195 float WavPlayer::play(float time)
00196 {
00197     return play(current_time, time);
00198 }
00199 
00200 float WavPlayer::play(float start, float timefor)
00201 {
00202 
00203     #if WAVPLAYER_GEN_TEST == 1
00204     config.channels = 1;    
00205     config.samples_per_sec = 48000;
00206     #endif
00207     
00208     float timeElapsed = 0;
00209     int endPoint = int((start + timefor) * float(config.samples_per_sec));
00210     if (endPoint * config.block_align >= config.data_length)
00211         endPoint = config.data_length / config.block_align;
00212     //printf("Will end after: %i samples \n\r", endPoint);
00213     int point = int(start * float(config.samples_per_sec));
00214     bool valid = true;
00215     flag_play = false;
00216     int dataOffset = findChunk(*filepp, "data", 4, config.file_size, 12) + 8 + (point * config.block_align);
00217 
00218     double timeComp = 0;
00219 
00220     double out_rate_t_p = 1 / double(WAVPLAYER_OUTPUT_RATE);
00221     //printf("out_rate_t_p = %f\n\r", out_rate_t_p);
00222     double out_rate_t_n = -1 / double(WAVPLAYER_OUTPUT_RATE);
00223     double in_rate = 1 / double(config.samples_per_sec); //0.0000125
00224     //printf("in_rate = %f\n\r", in_rate);
00225     
00226     float phase = 0;
00227 
00228     if (dataOffset != -1)
00229     {
00230         fseek(*filepp, dataOffset, SEEK_SET);
00231 
00232         int16_t buffer[WAVPLAYER_PLAYER_BUF];
00233 
00234         codec.start();
00235         //debug_printf("Expecting isr\n\r");
00236 
00237         i2s.frequency(WAVPLAYER_OUTPUT_RATE);
00238 
00239 
00240         if (config.channels == 1)
00241         {
00242             stereo = false;
00243             i2s.stereomono(I2S_MONO);
00244         }
00245         else
00246         {
00247             stereo =true;
00248             i2s.stereomono(I2S_STEREO);
00249         }
00250 
00251         i2s.attach(&WavPlayer::i2sisr);
00252         i2s.start();
00253         flag_play = true;
00254 
00255         while (valid && point < endPoint)
00256         {
00257             if (rbuf.numberStored() < RBLENGTH - 10)
00258             {
00259 
00260                 //timer.reset();
00261                 //timer.start();
00262                 int numToread = WAVPLAYER_PLAYER_BUF;
00263                 if (numToread > (RBLENGTH - 10) - rbuf.numberStored())
00264                 {
00265                     numToread = (RBLENGTH - 10) - rbuf.numberStored();
00266                 }
00267                 if (numToread + (point * (config.block_align/config.channels)) > config.data_length)
00268                 {
00269                     numToread = config.data_length - point * config.block_align;
00270                     valid = false;
00271                     debug_printf("EOF detected\n\r");
00272                 }
00273                 if(numToread % 2 == 1) numToread--;
00274                 //printf("Generating\n\r");
00275                 //run_flag = true;
00276                 //phase = sine_gen(buffer,numToread,float(config.samples_per_sec)/120,phase);
00277                 timer.reset();
00278                 timer.start();
00279                 //fread(buffer, config.block_align/config.channels, numToread, *filepp);
00280                  #if WAVPLAYER_GEN_TEST == 1
00281                     phase = sine_gen(buffer,numToread,float(config.samples_per_sec)/WAVPLAYER_GEN_FREQ,phase);  
00282                 #else
00283                     fread(buffer, config.block_align/config.channels, numToread, *filepp);
00284                 #endif
00285                 timer.stop();
00286                 //printf("numToread:%f\n\r",float(numToread));
00287                 if(numToread>=10)
00288                 {
00289                     read_time += (timer.read()/float(numToread));
00290                     read_time_div += 1;
00291                 }
00292                 
00293                 
00294                 if(read_time/float(read_time_div) >= WAVPLAYER_READ_MARGIN / float(config.samples_per_sec*config.channels))
00295                 {
00296                     slow_count++;
00297                     if(slow_count > WAVLPAYER_SLOW_MARGIN)
00298                     {
00299                         printf("Data rates not high enough to sustain read...%f seconds per read\n\r", read_time/float(read_time_div));
00300                         valid = false;
00301                         break;
00302                     }
00303 
00304                 }
00305                 
00306                 //run_flag = false;
00307                 int storer[2];
00308                 for (int i = 0; i < numToread; i += 2)
00309                 {
00310 
00311                     //run_flag = true;
00312 
00313                     if (timeComp < out_rate_t_p && timeComp > out_rate_t_n)
00314                     {
00315                         storer[0] = (int) buffer[i];
00316                         storer[1] = (int) buffer[i + 1];
00317 
00318                         //storer[0] = blip;
00319                         //storer[1] = blip;
00320                         timeComp += in_rate;
00321                         while (rbuf.numberStored() > RBLENGTH - 10)
00322                         {
00323                             //run_flag = true;
00324                             //run_flag = false;
00325                         }
00326                         rbuf.addToBuffer(storer);
00327                         timeComp -= out_rate_t_p;
00328                         //printf(",",timeComp);
00329                         point++;
00330                         //printf("straight %f\n\r",timeComp);
00331                     }
00332                     else if (timeComp >= out_rate_t_p)
00333                     {
00334 
00335                         storer[0] = (int) buffer[i];
00336                         storer[1] = (int) buffer[i + 1];
00337 
00338                         //storer[0] = blip;
00339                         //storer[1] = blip;
00340 
00341                         timeComp += in_rate;
00342                         /*const float ct = 5;
00343                          float c = 0;
00344                          float bufi = float(buffer[i]);
00345                          float bufip = float((i+1 >= numToread) ? buffer[i+1] : bufi);*/
00346 
00347                         while (timeComp >= out_rate_t_p)
00348                         {
00349                             //storer[0] = int((((ct-c)/ct)*bufi)+((c/ct)*bufip));
00350                             while (rbuf.numberStored() > RBLENGTH - 10)
00351                             {
00352                                 //run_flag = true;
00353                                 //run_flag = false;
00354                             }
00355                             rbuf.addToBuffer(storer);
00356                             timeComp -= out_rate_t_p;
00357                             //printf(";");
00358                             //if(c < ct) c++;
00359                         }
00360                         point++;
00361 
00362                     }
00363                     else if (timeComp <= out_rate_t_n)
00364                     {
00365                         timeComp += in_rate;
00366                         //printf("-");
00367                     }
00368 
00369                     //storer[1] = 0;
00370                     //if(i%1 == 0) printf("%i\n",int(storer[0]),int(storer[1]));
00371                     //run_flag = false;
00372 
00373                 }
00374                 flag_play = true;
00375                 //timer.stop();
00376                 //printf("point: %i\n\r",isr_underrun);
00377                 //read_time += timer;
00378                 //read_time_div =numToread;
00379 
00380             }
00381         }
00382     }
00383     flag_play = false;
00384     current_time = float(point)/float(config.samples_per_sec);
00385     return current_time;
00386 }
00387 
00388 int WavPlayer::fseekread(FILE *fp, char* str, int offset, int len)
00389 {
00390     fseek(fp, offset, SEEK_SET);
00391     fgets_m(str, len, fp);
00392     return len;
00393 }
00394 
00395 uint32_t WavPlayer::getu32(char str[], int len)
00396 {
00397     uint32_t temp = 0;
00398     for (int i = 0; i < len; i++)
00399     {
00400         temp += str[i] << (i * 8);
00401 
00402     }
00403     return temp;
00404 }
00405 
00406 uint16_t WavPlayer::getu16(char str[], int len)
00407 {
00408     uint16_t temp = 0;
00409     for (int i = 0; i < len; i++)
00410     {
00411         temp += str[i] << (i * 8);
00412     }
00413     return temp;
00414 }
00415 
00416 int32_t WavPlayer::get32(char str[], int len)
00417 {
00418     uint32_t temp = 0;
00419     for (int i = 0; i < len; i++)
00420     {
00421         temp += str[i] << (i * 8);
00422 
00423     }
00424     return temp;
00425 }
00426 
00427 int16_t WavPlayer::get16(char str[], int len)
00428 {
00429     uint16_t temp = 0;
00430     for (int i = 0; i < len; i++)
00431     {
00432         temp += str[i] << (i * 8);
00433     }
00434     return temp;
00435 }
00436 
00437 uint32_t WavPlayer::fsru32(FILE *fp, int offset, int len)
00438 {
00439     char temp[4];
00440     fseekread(fp, temp, offset, len);
00441     return getu32(temp, len);
00442 }
00443 
00444 uint16_t WavPlayer::fsru16(FILE *fp, int offset, int len)
00445 {
00446     char temp[2];
00447     fseekread(fp, temp, offset, len);
00448     return getu16(temp, len);
00449 }
00450 
00451 void WavPlayer::clear(char* str, int len)
00452 {
00453     for (int i = 0; i < len; i++)
00454     {
00455         str[i] = 0;
00456     }
00457 }
00458 
00459 int WavPlayer::findChunk(FILE *fp, char* match, int len, int fileSize,
00460         int startOffset)
00461 {
00462     char temp[5];
00463     int count = startOffset;
00464     while ((count + 8) < fileSize)
00465     {
00466         clear(temp, 5);
00467         fseekread(fp, temp, count, 4);
00468         int chunksize = fsru32(fp, count + 4) + 8;
00469         //debug_printf("@ %i Chunk Name: %s Size: %i\n\r", count, temp, chunksize);
00470 
00471         if (strcmp(temp, match) == 0)
00472         {
00473             return count;
00474         }
00475         count += chunksize;
00476     }
00477     return -1;
00478 }
00479 
00480 int WavPlayer::findChunk(FILE *fp, char* match, int len, int startOffset)
00481 {
00482     return findChunk(fp, match, len, config.file_size, startOffset);
00483 }
00484 
00485 void WavPlayer::fgets_m(char* str, int num, FILE* fp)
00486 {
00487     for (int i = 0; i < num; i++)
00488     {
00489         str[i] = fgetc(fp);
00490         //printf("%c",str[i]);
00491     }
00492 }
00493 
00494 float WavPlayer::sine_gen(int16_t* buf, int len, float div, float phase)
00495 {
00496     #if WAVPLAYER_GEN_TEST == 1
00497     float t = SINE16LENGTH / div;
00498     for (int i = 0; i < len; i++)
00499     {
00500         buf[i] = sine16lookup[int(phase)];
00501         //printf("%i\n\r",buf[i]);
00502         phase += t;
00503         while (phase >= SINE16LENGTH)
00504             phase -= SINE16LENGTH;
00505     }
00506     #endif
00507     return phase;
00508 }