Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of wave_player by
wave_player.cpp
00001 //----------------------------------------------------------------------------- 00002 // a sample mbed library to play back wave files. 00003 // 00004 // explanation of wave file format. 00005 // https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ 00006 00007 // if VERBOSE is uncommented then the wave player will enter a verbose 00008 // mode that displays all data values as it reads them from the file 00009 // and writes them to the DAC. Very slow and unusable output on the DAC, 00010 // but useful for debugging wave files that don't work. 00011 //#define VERBOSE 00012 00013 00014 #include <mbed.h> 00015 #include <math.h> 00016 #include <stdio.h> 00017 #include <wave_player.h> 00018 #include <shared.h> 00019 00020 Wiistate wiistate = Nothing; 00021 float vol = 0; //VOLUME FLOAT 00022 Mutex key; 00023 00024 00025 //----------------------------------------------------------------------------- 00026 // constructor -- accepts an mbed pin to use for AnalogOut. Only p18 will work 00027 wave_player::wave_player(AnalogOut *_dac) 00028 { 00029 wave_DAC=_dac; 00030 wave_DAC->write_u16(32768); //DAC is 0-3.3V, so idles at ~1.6V 00031 verbosity=0; 00032 } 00033 00034 //----------------------------------------------------------------------------- 00035 // if verbosity is set then wave player enters a mode where the wave file 00036 // is decoded and displayed to the screen, including sample values put into 00037 // the DAC FIFO, and values read out of the DAC FIFO by the ISR. The DAC output 00038 // itself is so slow as to be unusable, but this might be handy for debugging 00039 // wave files that don't play 00040 //----------------------------------------------------------------------------- 00041 void wave_player::set_verbosity(int v) 00042 { 00043 verbosity=v; 00044 } 00045 00046 int do_vol = 0; 00047 int do_flange = 1; 00048 int do_bit_crush = 0; 00049 int do_delay = 1; 00050 00051 void update_state() { 00052 Wiistate cur_state; 00053 key.lock(); 00054 cur_state = wiistate; 00055 key.unlock(); 00056 00057 if(cur_state == Left) { 00058 do_vol = 1; 00059 do_flange = 1; 00060 do_bit_crush = 0; 00061 do_delay = 0; 00062 } else if(cur_state == Right) { 00063 do_vol = 1; 00064 do_flange = 0; 00065 do_bit_crush = 1; 00066 do_delay = 0; 00067 } else if(cur_state == Up) { 00068 do_vol = 1; 00069 do_flange = 0; 00070 do_bit_crush = 0; 00071 do_delay = 1; 00072 } else if(cur_state == Down) { 00073 do_vol = 1; 00074 do_flange = 1; 00075 do_bit_crush = 0; 00076 do_delay = 1; 00077 } else if(cur_state == Nothing) { 00078 do_vol = 0; 00079 do_flange = 0; 00080 do_bit_crush = 0; 00081 do_delay = 0; 00082 //printf("%d %d %d %d\r\n", do_vol, do_flange, do_bit_crush, do_delay); 00083 //printf("%d %d %d %d %d %d\r\n", cur_state==Nothing, Left, Right,Up,Down, Nothing); 00084 } 00085 00086 //printf("%d %d %d %d\r\n", do_vol, do_flange, do_bit_crush, do_delay); 00087 } 00088 00089 //----------------------------------------------------------------------------- 00090 // player function. Takes a pointer to an opened wave file. The file needs 00091 // to be stored in a filesystem with enough bandwidth to feed the wave data. 00092 // LocalFileSystem isn't, but the SDcard is, at least for 22kHz files. The 00093 // SDcard filesystem can be hotrodded by increasing the SPI frequency it uses 00094 // internally. 00095 //----------------------------------------------------------------------------- 00096 void wave_player::play(FILE *wavefile) 00097 { 00098 unsigned chunk_id,chunk_size,channel; 00099 unsigned data,samp_int,i; 00100 short unsigned dac_data; 00101 long long slice_value; 00102 char *slice_buf; 00103 short *data_sptr; 00104 unsigned char *data_bptr; 00105 int *data_wptr; 00106 FMT_STRUCT wav_format; 00107 long slice,num_slices; 00108 DAC_wptr=0; 00109 DAC_rptr=0; 00110 for (i=0;i<256;i+=2) { 00111 DAC_fifo[i]=0; 00112 DAC_fifo[i+1]=3000; 00113 } 00114 DAC_wptr=4; 00115 DAC_on=0; 00116 00117 fread(&chunk_id,4,1,wavefile); 00118 fread(&chunk_size,4,1,wavefile); 00119 00120 00121 //// 00122 #define SAMPLE_RATE 11025 00123 #define D_SIZE 8000 00124 #define M_PI 3.14159265358979323846 00125 short unsigned delayed[D_SIZE]; 00126 unsigned int d_rptr = 0; 00127 unsigned int d_wptr = D_SIZE-1000;//((float)D_SIZE)/2.0; 00128 unsigned int d_wptr_2 = D_SIZE-3000; 00129 int flange = 0; // CHANG 00130 int flange_amplitude = D_SIZE/4; // /2 00131 //int flange_freq = SAMPLE_RATE; // 2*pi*cur_samp_cnt/11025 00132 float cur_samp_cnt = 0; 00133 int flange_r_ptr = 0; 00134 int flange_dir = 1; 00135 int flip_sec = 0; 00136 00137 //// 00138 for(int di = 0; di < D_SIZE; di++) { 00139 delayed[di] = 0; 00140 } 00141 00142 while (!feof(wavefile)) { 00143 if (verbosity) 00144 printf("Read chunk ID 0x%x, size 0x%x\r\n",chunk_id,chunk_size); 00145 switch (chunk_id) { 00146 case 0x46464952: 00147 fread(&data,4,1,wavefile); 00148 if (verbosity) { 00149 printf("RIFF chunk\r\n"); 00150 printf(" chunk size %d (0x%x)\r\n",chunk_size,chunk_size); 00151 printf(" RIFF type 0x%x\r\n",data); 00152 } 00153 break; 00154 case 0x20746d66: 00155 fread(&wav_format,sizeof(wav_format),1,wavefile); 00156 if (verbosity) { 00157 printf("FORMAT chunk\r\n"); 00158 printf(" chunk size %d (0x%x)\r\n",chunk_size,chunk_size); 00159 printf(" compression code %d\r\n",wav_format.comp_code); 00160 printf(" %d channels\r\n",wav_format.num_channels); 00161 printf(" %d samples/sec\r\n",wav_format.sample_rate); 00162 printf(" %d bytes/sec\r\n",wav_format.avg_Bps); 00163 printf(" block align %d\r\n",wav_format.block_align); 00164 printf(" %d bits per sample\r\n",wav_format.sig_bps); 00165 } 00166 if (chunk_size > sizeof(wav_format)) 00167 fseek(wavefile,chunk_size-sizeof(wav_format),SEEK_CUR); 00168 break; 00169 case 0x61746164: 00170 // allocate a buffer big enough to hold a slice 00171 slice_buf=(char *)malloc(wav_format.block_align); 00172 if (!slice_buf) { 00173 printf("Unable to malloc slice buffer"); 00174 exit(1); 00175 } 00176 num_slices=chunk_size/wav_format.block_align; 00177 samp_int=1000000/(wav_format.sample_rate); 00178 if (verbosity) { 00179 printf("DATA chunk\r\n"); 00180 printf(" chunk size %d (0x%x)\r\n",chunk_size,chunk_size); 00181 printf(" %d slices\r\n",num_slices); 00182 printf(" Ideal sample interval=%d\r\n",(unsigned)(1000000.0/wav_format.sample_rate)); 00183 printf(" programmed interrupt tick interval=%d\r\n",samp_int); 00184 } 00185 00186 // starting up ticker to write samples out -- no printfs until tick.detach is called 00187 if (verbosity) 00188 tick.attach_us(this,&wave_player::dac_out, 500000); 00189 else 00190 tick.attach_us(this,&wave_player::dac_out, samp_int); 00191 DAC_on=1; 00192 00193 // start reading slices, which contain one sample each for however many channels 00194 // are in the wave file. one channel=mono, two channels=stereo, etc. Since 00195 // mbed only has a single AnalogOut, all of the channels present are averaged 00196 // to produce a single sample value. This summing and averaging happens in 00197 // a variable of type signed long long, to make sure that the data doesn't 00198 // overflow regardless of sample size (8 bits, 16 bits, 32 bits). 00199 // 00200 // note that from what I can find that 8 bit wave files use unsigned data, 00201 // while 16 and 32 bit wave files use signed data 00202 // 00203 00204 00205 for (slice=0;slice<num_slices;slice+=1) { 00206 fread(slice_buf,wav_format.block_align,1,wavefile); 00207 if (feof(wavefile)) { 00208 printf("Oops -- not enough slices in the wave file\r\n"); 00209 exit(1); 00210 } 00211 data_sptr=(short *)slice_buf; // 16 bit samples 00212 data_bptr=(unsigned char *)slice_buf; // 8 bit samples 00213 data_wptr=(int *)slice_buf; // 32 bit samples 00214 slice_value=0; 00215 for (channel=0;channel<wav_format.num_channels;channel++) { 00216 switch (wav_format.sig_bps) { 00217 case 16: 00218 if (verbosity) 00219 printf("16 bit channel %d data=%d ",channel,data_sptr[channel]); 00220 slice_value+=data_sptr[channel]; 00221 break; 00222 case 32: 00223 if (verbosity) 00224 printf("32 bit channel %d data=%d ",channel,data_wptr[channel]); 00225 slice_value+=data_wptr[channel]; 00226 break; 00227 case 8: 00228 if (verbosity) 00229 printf("8 bit channel %d data=%d ",channel,(int)data_bptr[channel]); 00230 slice_value+=data_bptr[channel]; 00231 break; 00232 } 00233 } 00234 slice_value/=wav_format.num_channels; 00235 00236 // slice_value is now averaged. Next it needs to be scaled to an unsigned 16 bit value 00237 // with DC offset so it can be written to the DAC. 00238 switch (wav_format.sig_bps) { 00239 case 8: slice_value<<=8; 00240 break; 00241 case 16: slice_value+=32768; 00242 break; 00243 case 32: slice_value>>=16; 00244 slice_value+=32768; 00245 break; 00246 } 00247 dac_data=(short unsigned)slice_value; 00248 if (verbosity) 00249 printf("sample %d wptr %d slice_value %d dac_data %u\r\n",slice,DAC_wptr,(int)slice_value,dac_data); 00250 00251 00252 00253 update_state(); 00254 00255 00256 //// 00257 delayed[d_rptr] = dac_data; 00258 00259 d_rptr = (d_rptr == (D_SIZE-1)) ? 0 : (d_rptr + 1); 00260 d_wptr = (d_wptr == (D_SIZE-1)) ? 0 : (d_wptr + 1); 00261 d_wptr_2 = (d_wptr_2 == (D_SIZE-1)) ? 0 : (d_wptr_2 + 1); 00262 00263 float f_dac_data = (float)dac_data; 00264 float f_delay_data; 00265 float f_delay_data_2; 00266 int flange_dist = 0; 00267 int flange_dist_check; 00268 if(flange) { 00269 flange_dist = flange_amplitude*sin(2*M_PI*cur_samp_cnt/(float)SAMPLE_RATE); 00270 /*if(cur_samp_cnt != 0) { 00271 while(cur_samp_cnt < 4000) { 00272 flange_dist = flange_amplitude*sin(2*M_PI*cur_samp_cnt/(float)SAMPLE_RATE); 00273 printf("%f %f\r\n", flange_dist, 2*M_PI*cur_samp_cnt/(float)SAMPLE_RATE); 00274 cur_samp_cnt++; 00275 } 00276 return; 00277 }*/ 00278 //printf("%d\r\n",flange_dist); 00279 flange_dist_check = d_wptr + flange_dist - D_SIZE; 00280 //d_wptr += flange_dist_check > 0 ? flange_dist_check : (d_wptr + flange_dist) < 0 ? (D_SIZE + d_wptr + flange_dist) : flange_dist; 00281 //d_wptr += flange_dist_check < 0 ? flange_dist : ((d_wptr + flange_dist) < 0) ? 0 : flange_dist; 00282 d_wptr = ((d_wptr + flange_dist) > 0) ? (d_wptr + flange_dist) % D_SIZE : (D_SIZE + flange_dist); //(D_SIZE + flange_dist) WRONG 00283 } 00284 //cur_samp_cnt = (cur_samp_cnt+1) > SAMPLE_RATE ? 0 : (cur_samp_cnt+1); 00285 cur_samp_cnt = (cur_samp_cnt+1) > SAMPLE_RATE ? 0 : (cur_samp_cnt+1); 00286 00287 if(cur_samp_cnt == 0) { 00288 flip_sec = !flip_sec; 00289 } 00290 00291 00292 #define N_SAMPLES_FLANGE_PERIOD 100//((SAMPLE_RATE) >> 2) // WHY IS MZ 100??? 00293 00294 if(do_flange) {// && (flip_sec)) { 00295 if(flange_r_ptr == N_SAMPLES_FLANGE_PERIOD) { 00296 flange_dir = -1; 00297 } else if(flange_r_ptr == -N_SAMPLES_FLANGE_PERIOD) { 00298 flange_dir = 1; 00299 } 00300 flange_r_ptr += flange_dir; 00301 } else { 00302 flange_r_ptr = 0; 00303 } 00304 00305 int total_ptr = (d_wptr + flange_r_ptr); 00306 total_ptr = (total_ptr > D_SIZE) ? (total_ptr - D_SIZE) : total_ptr; 00307 total_ptr = (total_ptr < 0) ? (D_SIZE - total_ptr) : total_ptr; 00308 00309 //f_delay_data = (float) delayed[d_wptr]; 00310 f_delay_data = (float) delayed[total_ptr]; 00311 f_delay_data_2 = (float) delayed[d_wptr_2]; 00312 float f_mix; 00313 00314 00315 if(do_delay || do_flange) { 00316 if(do_flange) { 00317 f_mix = 0.01*f_dac_data + 0.7*f_delay_data; 00318 } else { 00319 f_mix = 0.333*f_dac_data + 0.333*f_delay_data + 0.333*f_delay_data_2; 00320 } 00321 //0.01*f_dac_data + 0.7*f_delay_data; 00322 } else { 00323 f_mix = f_dac_data; 00324 } 00325 //// 00326 00327 float time_in_period = (float)cur_samp_cnt/(float)SAMPLE_RATE; 00328 //float vol = 0.5 + 0.5*sin(2*M_PI*time_in_period); // Full dynamic range 00329 float my_vol = 0.75 + 0.25*sin(2*M_PI*time_in_period); 00330 00331 if(do_vol) f_mix = (my_vol*f_mix); 00332 00333 if(do_bit_crush) { 00334 short unsigned beef = (short unsigned)f_mix; 00335 //beef = (beef>>7) << 7; 00336 //printf("beef %x\r\nbeeeef %x\r\n", beef, beef & 0xFFF0); 00337 DAC_fifo[DAC_wptr]=beef &0xF800; 00338 } else { 00339 DAC_fifo[DAC_wptr]=(short unsigned)(f_mix); 00340 } 00341 DAC_wptr=(DAC_wptr+1) & 0xff; 00342 while (DAC_wptr==DAC_rptr) { 00343 } 00344 } 00345 DAC_on=0; 00346 tick.detach(); 00347 free(slice_buf); 00348 break; 00349 case 0x5453494c: 00350 if (verbosity) 00351 printf("INFO chunk, size %d\r\n",chunk_size); 00352 fseek(wavefile,chunk_size,SEEK_CUR); 00353 break; 00354 default: 00355 printf("unknown chunk type 0x%x, size %d\r\n",chunk_id,chunk_size); 00356 data=fseek(wavefile,chunk_size,SEEK_CUR); 00357 break; 00358 } 00359 fread(&chunk_id,4,1,wavefile); 00360 fread(&chunk_size,4,1,wavefile); 00361 } 00362 } 00363 00364 00365 void wave_player::dac_out() 00366 { 00367 if (DAC_on) { 00368 #ifdef VERBOSE 00369 printf("ISR rdptr %d got %u\r\n",DAC_rptr,DAC_fifo[DAC_rptr]); 00370 #endif 00371 wave_DAC->write_u16(DAC_fifo[DAC_rptr]); 00372 DAC_rptr=(DAC_rptr+1) & 0xff; 00373 } 00374 } 00375
Generated on Wed Jul 20 2022 16:54:25 by
1.7.2
