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 <stdio.h> 00016 #include <wave_player.h> 00017 00018 00019 //----------------------------------------------------------------------------- 00020 // constructor -- accepts an mbed pin to use for AnalogOut. Only p18 will work 00021 wave_player::wave_player(AnalogOut *_dac) 00022 { 00023 wave_DAC=_dac; 00024 wave_DAC->write_u16(32768); //DAC is 0-3.3V, so idles at ~1.6V 00025 verbosity=0; 00026 } 00027 00028 //----------------------------------------------------------------------------- 00029 // if verbosity is set then wave player enters a mode where the wave file 00030 // is decoded and displayed to the screen, including sample values put into 00031 // the DAC FIFO, and values read out of the DAC FIFO by the ISR. The DAC output 00032 // itself is so slow as to be unusable, but this might be handy for debugging 00033 // wave files that don't play 00034 //----------------------------------------------------------------------------- 00035 void wave_player::set_verbosity(int v) 00036 { 00037 verbosity=v; 00038 } 00039 00040 //----------------------------------------------------------------------------- 00041 // player function. Takes a pointer to an opened wave file. The file needs 00042 // to be stored in a filesystem with enough bandwidth to feed the wave data. 00043 // LocalFileSystem isn't, but the SDcard is, at least for 22kHz files. The 00044 // SDcard filesystem can be hotrodded by increasing the SPI frequency it uses 00045 // internally. 00046 //----------------------------------------------------------------------------- 00047 void wave_player::play(FILE *wavefile, bool *playpoint) 00048 { 00049 unsigned chunk_id,chunk_size,channel; 00050 unsigned data,samp_int,i; 00051 short unsigned dac_data; 00052 long long slice_value; 00053 char *slice_buf; 00054 short *data_sptr; 00055 unsigned char *data_bptr; 00056 int *data_wptr; 00057 00058 FMT_STRUCT wav_format; 00059 long slice,num_slices; 00060 DAC_wptr=0; 00061 DAC_rptr=0; 00062 for (i=0;i<256;i+=2) { 00063 DAC_fifo[i]=0; 00064 DAC_fifo[i+1]=3000; 00065 } 00066 DAC_wptr=4; 00067 DAC_on=0; 00068 00069 fread(&chunk_id,4,1,wavefile); 00070 fread(&chunk_size,4,1,wavefile); 00071 while (!feof(wavefile)) { 00072 if (verbosity) 00073 printf("Read chunk ID 0x%x, size 0x%x\n",chunk_id,chunk_size); 00074 switch (chunk_id) { 00075 case 0x46464952: 00076 fread(&data,4,1,wavefile); 00077 if (verbosity) { 00078 printf("RIFF chunk\n"); 00079 printf(" chunk size %d (0x%x)\n",chunk_size,chunk_size); 00080 printf(" RIFF type 0x%x\n",data); 00081 } 00082 break; 00083 case 0x20746d66: 00084 fread(&wav_format,sizeof(wav_format),1,wavefile); 00085 if (verbosity) { 00086 printf("FORMAT chunk\n"); 00087 printf(" chunk size %d (0x%x)\n",chunk_size,chunk_size); 00088 printf(" compression code %d\n",wav_format.comp_code); 00089 printf(" %d channels\n",wav_format.num_channels); 00090 printf(" %d samples/sec\n",wav_format.sample_rate); 00091 printf(" %d bytes/sec\n",wav_format.avg_Bps); 00092 printf(" block align %d\n",wav_format.block_align); 00093 printf(" %d bits per sample\n",wav_format.sig_bps); 00094 } 00095 if (chunk_size > sizeof(wav_format)) 00096 fseek(wavefile,chunk_size-sizeof(wav_format),SEEK_CUR); 00097 break; 00098 case 0x61746164: 00099 // allocate a buffer big enough to hold a slice 00100 slice_buf=(char *)malloc(wav_format.block_align); 00101 if (!slice_buf) { 00102 printf("Unable to malloc slice buffer"); 00103 exit(1); 00104 } 00105 num_slices=chunk_size/wav_format.block_align; 00106 samp_int=1000000/(wav_format.sample_rate); 00107 if (verbosity) { 00108 printf("DATA chunk\n"); 00109 printf(" chunk size %d (0x%x)\n",chunk_size,chunk_size); 00110 printf(" %d slices\n",num_slices); 00111 printf(" Ideal sample interval=%d\n",(unsigned)(1000000.0/wav_format.sample_rate)); 00112 printf(" programmed interrupt tick interval=%d\n",samp_int); 00113 } 00114 00115 // starting up ticker to write samples out -- no printfs until tick.detach is called 00116 if (verbosity) 00117 tick.attach_us(this,&wave_player::dac_out, 500000); 00118 else 00119 tick.attach_us(this,&wave_player::dac_out, samp_int); 00120 DAC_on=1; 00121 00122 // start reading slices, which contain one sample each for however many channels 00123 // are in the wave file. one channel=mono, two channels=stereo, etc. Since 00124 // mbed only has a single AnalogOut, all of the channels present are averaged 00125 // to produce a single sample value. This summing and averaging happens in 00126 // a variable of type signed long long, to make sure that the data doesn't 00127 // overflow regardless of sample size (8 bits, 16 bits, 32 bits). 00128 // 00129 // note that from what I can find that 8 bit wave files use unsigned data, 00130 // while 16 and 32 bit wave files use signed data 00131 // 00132 for (slice=0;slice<num_slices;slice+=1) { 00133 if (*playpoint == false) 00134 { 00135 break; 00136 } 00137 fread(slice_buf,wav_format.block_align,1,wavefile); 00138 if (feof(wavefile)) { 00139 printf("Oops -- not enough slices in the wave file\n"); 00140 exit(1); 00141 } 00142 data_sptr=(short *)slice_buf; // 16 bit samples 00143 data_bptr=(unsigned char *)slice_buf; // 8 bit samples 00144 data_wptr=(int *)slice_buf; // 32 bit samples 00145 slice_value=0; 00146 for (channel=0;channel<wav_format.num_channels;channel++) { 00147 switch (wav_format.sig_bps) { 00148 case 16: 00149 if (verbosity) 00150 printf("16 bit channel %d data=%d ",channel,data_sptr[channel]); 00151 slice_value+=data_sptr[channel]; 00152 break; 00153 case 32: 00154 if (verbosity) 00155 printf("32 bit channel %d data=%d ",channel,data_wptr[channel]); 00156 slice_value+=data_wptr[channel]; 00157 break; 00158 case 8: 00159 if (verbosity) 00160 printf("8 bit channel %d data=%d ",channel,(int)data_bptr[channel]); 00161 slice_value+=data_bptr[channel]; 00162 break; 00163 } 00164 } 00165 slice_value/=wav_format.num_channels; 00166 00167 // slice_value is now averaged. Next it needs to be scaled to an unsigned 16 bit value 00168 // with DC offset so it can be written to the DAC. 00169 switch (wav_format.sig_bps) { 00170 case 8: slice_value<<=8; 00171 break; 00172 case 16: slice_value+=32768; 00173 break; 00174 case 32: slice_value>>=16; 00175 slice_value+=32768; 00176 break; 00177 } 00178 dac_data=(short unsigned)slice_value; 00179 if (verbosity) 00180 printf("sample %d wptr %d slice_value %d dac_data %u\n",slice,DAC_wptr,(int)slice_value,dac_data); 00181 DAC_fifo[DAC_wptr]=dac_data; 00182 DAC_wptr=(DAC_wptr+1) & 0xff; 00183 while (DAC_wptr==DAC_rptr) { 00184 } 00185 } 00186 DAC_on=0; 00187 tick.detach(); 00188 free(slice_buf); 00189 break; 00190 case 0x5453494c: 00191 if (verbosity) 00192 printf("INFO chunk, size %d\n",chunk_size); 00193 fseek(wavefile,chunk_size,SEEK_CUR); 00194 break; 00195 default: 00196 printf("unknown chunk type 0x%x, size %d\n",chunk_id,chunk_size); 00197 data=fseek(wavefile,chunk_size,SEEK_CUR); 00198 break; 00199 } 00200 fread(&chunk_id,4,1,wavefile); 00201 fread(&chunk_size,4,1,wavefile); 00202 } 00203 } 00204 00205 00206 void wave_player::dac_out() 00207 { 00208 if (DAC_on) { 00209 #ifdef VERBOSE 00210 printf("ISR rdptr %d got %u\n",DAC_rptr,DAC_fifo[DAC_rptr]); 00211 #endif 00212 wave_DAC->write_u16(((DAC_fifo[DAC_rptr]) * (vol-16)) >> 4); 00213 DAC_rptr=(DAC_rptr+1) & 0xff; 00214 } 00215 } 00216 00217 int* wave_player:: volu() 00218 { 00219 return &vol; 00220 } 00221
Generated on Mon Jul 18 2022 21:58:59 by
1.7.2
