Stuart Kent / wave_player

Dependents:   wiimote_audio

Fork of wave_player by Steve Ravet

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers wave_player.cpp Source File

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