A library which allows the playing of Wav files using the TLV320
Dependents: RSALB_hbridge_helloworld RSALB_lobster WavPlayer_test AudioCODEC_HelloWorld
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 }
Generated on Tue Jul 12 2022 17:42:18 by 1.7.2