Kevin Chen / Mbed 2 deprecated drue

Dependencies:   mbed SDFileSystem

Committer:
kchen7
Date:
Sat Apr 27 21:47:02 2019 +0000
Revision:
7:af45a10fdfb6
baseline demo version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kchen7 7:af45a10fdfb6 1 #include <mbed.h>
kchen7 7:af45a10fdfb6 2 #include <sd_card_player.h>
kchen7 7:af45a10fdfb6 3
kchen7 7:af45a10fdfb6 4 // must pass p18 on mbed (only one w/ AnalogOut)
kchen7 7:af45a10fdfb6 5 sd_card_player::sd_card_player(AnalogOut *_dac) {
kchen7 7:af45a10fdfb6 6 wave_DAC=_dac;
kchen7 7:af45a10fdfb6 7 wave_DAC->write_u16(32768); //DAC is 0-3.3V, so idles at ~1.6V
kchen7 7:af45a10fdfb6 8 }
kchen7 7:af45a10fdfb6 9
kchen7 7:af45a10fdfb6 10 //-----------------------------------------------------------------------------
kchen7 7:af45a10fdfb6 11 // player function. Takes a pointer to an opened wave file. The file needs
kchen7 7:af45a10fdfb6 12 // to be stored in a filesystem with enough bandwidth to feed the wave data.
kchen7 7:af45a10fdfb6 13 // LocalFileSystem isn't, but the SDcard is, at least for 22kHz files. The
kchen7 7:af45a10fdfb6 14 // SDcard filesystem can be hotrodded by increasing the SPI frequency it uses
kchen7 7:af45a10fdfb6 15 // internally.
kchen7 7:af45a10fdfb6 16 //-----------------------------------------------------------------------------
kchen7 7:af45a10fdfb6 17 void sd_card_player::play(FILE *wavefile)
kchen7 7:af45a10fdfb6 18 {
kchen7 7:af45a10fdfb6 19 unsigned chunk_id,chunk_size,channel;
kchen7 7:af45a10fdfb6 20 unsigned data,samp_int,i;
kchen7 7:af45a10fdfb6 21 short unsigned dac_data;
kchen7 7:af45a10fdfb6 22 long long slice_value;
kchen7 7:af45a10fdfb6 23 char *slice_buf;
kchen7 7:af45a10fdfb6 24 short *data_sptr;
kchen7 7:af45a10fdfb6 25 unsigned char *data_bptr;
kchen7 7:af45a10fdfb6 26 int *data_wptr;
kchen7 7:af45a10fdfb6 27 FMT_STRUCT wav_format;
kchen7 7:af45a10fdfb6 28 long slice,num_slices;
kchen7 7:af45a10fdfb6 29 DAC_wptr=0;
kchen7 7:af45a10fdfb6 30 DAC_rptr=0;
kchen7 7:af45a10fdfb6 31 for (i=0;i<256;i+=2) {
kchen7 7:af45a10fdfb6 32 DAC_fifo[i]=0;
kchen7 7:af45a10fdfb6 33 DAC_fifo[i+1]=3000;
kchen7 7:af45a10fdfb6 34 }
kchen7 7:af45a10fdfb6 35 DAC_wptr=4;
kchen7 7:af45a10fdfb6 36 DAC_on=0;
kchen7 7:af45a10fdfb6 37
kchen7 7:af45a10fdfb6 38 fread(&chunk_id,4,1,wavefile);
kchen7 7:af45a10fdfb6 39 fread(&chunk_size,4,1,wavefile);
kchen7 7:af45a10fdfb6 40 while (!feof(wavefile)) {
kchen7 7:af45a10fdfb6 41 switch (chunk_id) {
kchen7 7:af45a10fdfb6 42 case 0x46464952:
kchen7 7:af45a10fdfb6 43 fread(&data,4,1,wavefile);
kchen7 7:af45a10fdfb6 44 break;
kchen7 7:af45a10fdfb6 45 case 0x20746d66:
kchen7 7:af45a10fdfb6 46 fread(&wav_format,sizeof(wav_format),1,wavefile);
kchen7 7:af45a10fdfb6 47 if (chunk_size > sizeof(wav_format))
kchen7 7:af45a10fdfb6 48 fseek(wavefile,chunk_size-sizeof(wav_format),SEEK_CUR);
kchen7 7:af45a10fdfb6 49 break;
kchen7 7:af45a10fdfb6 50 case 0x61746164:
kchen7 7:af45a10fdfb6 51 // allocate a buffer big enough to hold a slice
kchen7 7:af45a10fdfb6 52 slice_buf=(char *)malloc(wav_format.block_align);
kchen7 7:af45a10fdfb6 53 if (!slice_buf) {
kchen7 7:af45a10fdfb6 54 printf("Unable to malloc slice buffer");
kchen7 7:af45a10fdfb6 55 exit(1);
kchen7 7:af45a10fdfb6 56 }
kchen7 7:af45a10fdfb6 57 num_slices=chunk_size/wav_format.block_align;
kchen7 7:af45a10fdfb6 58 samp_int=1000000/(wav_format.sample_rate);
kchen7 7:af45a10fdfb6 59
kchen7 7:af45a10fdfb6 60 // starting up ticker to write samples out -- no printfs until tick.detach is called
kchen7 7:af45a10fdfb6 61 tick.attach_us(this,&sd_card_player::dac_out, samp_int);
kchen7 7:af45a10fdfb6 62 DAC_on=1;
kchen7 7:af45a10fdfb6 63
kchen7 7:af45a10fdfb6 64 // start reading slices, which contain one sample each for however many channels
kchen7 7:af45a10fdfb6 65 // are in the wave file. one channel=mono, two channels=stereo, etc. Since
kchen7 7:af45a10fdfb6 66 // mbed only has a single AnalogOut, all of the channels present are averaged
kchen7 7:af45a10fdfb6 67 // to produce a single sample value. This summing and averaging happens in
kchen7 7:af45a10fdfb6 68 // a variable of type signed long long, to make sure that the data doesn't
kchen7 7:af45a10fdfb6 69 // overflow regardless of sample size (8 bits, 16 bits, 32 bits).
kchen7 7:af45a10fdfb6 70 //
kchen7 7:af45a10fdfb6 71 // note that from what I can find that 8 bit wave files use unsigned data,
kchen7 7:af45a10fdfb6 72 // while 16 and 32 bit wave files use signed data
kchen7 7:af45a10fdfb6 73 //
kchen7 7:af45a10fdfb6 74 for (slice=0;slice<num_slices;slice+=1) {
kchen7 7:af45a10fdfb6 75 fread(slice_buf,wav_format.block_align,1,wavefile);
kchen7 7:af45a10fdfb6 76 if (feof(wavefile)) {
kchen7 7:af45a10fdfb6 77 printf("Oops -- not enough slices in the wave file\n");
kchen7 7:af45a10fdfb6 78 exit(1);
kchen7 7:af45a10fdfb6 79 }
kchen7 7:af45a10fdfb6 80 data_sptr=(short *)slice_buf; // 16 bit samples
kchen7 7:af45a10fdfb6 81 data_bptr=(unsigned char *)slice_buf; // 8 bit samples
kchen7 7:af45a10fdfb6 82 data_wptr=(int *)slice_buf; // 32 bit samples
kchen7 7:af45a10fdfb6 83 slice_value=0;
kchen7 7:af45a10fdfb6 84 for (channel=0;channel<wav_format.num_channels;channel++) {
kchen7 7:af45a10fdfb6 85 switch (wav_format.sig_bps) {
kchen7 7:af45a10fdfb6 86 case 16:
kchen7 7:af45a10fdfb6 87 slice_value+=data_sptr[channel];
kchen7 7:af45a10fdfb6 88 break;
kchen7 7:af45a10fdfb6 89 case 32:
kchen7 7:af45a10fdfb6 90 slice_value+=data_wptr[channel];
kchen7 7:af45a10fdfb6 91 break;
kchen7 7:af45a10fdfb6 92 case 8:
kchen7 7:af45a10fdfb6 93 slice_value+=data_bptr[channel];
kchen7 7:af45a10fdfb6 94 break;
kchen7 7:af45a10fdfb6 95 }
kchen7 7:af45a10fdfb6 96 }
kchen7 7:af45a10fdfb6 97 slice_value/=wav_format.num_channels;
kchen7 7:af45a10fdfb6 98
kchen7 7:af45a10fdfb6 99 // slice_value is now averaged. Next it needs to be scaled to an unsigned 16 bit value
kchen7 7:af45a10fdfb6 100 // with DC offset so it can be written to the DAC.
kchen7 7:af45a10fdfb6 101 switch (wav_format.sig_bps) {
kchen7 7:af45a10fdfb6 102 case 8: slice_value<<=8;
kchen7 7:af45a10fdfb6 103 break;
kchen7 7:af45a10fdfb6 104 case 16: slice_value+=32768;
kchen7 7:af45a10fdfb6 105 break;
kchen7 7:af45a10fdfb6 106 case 32: slice_value>>=16;
kchen7 7:af45a10fdfb6 107 slice_value+=32768;
kchen7 7:af45a10fdfb6 108 break;
kchen7 7:af45a10fdfb6 109 }
kchen7 7:af45a10fdfb6 110 dac_data=(short unsigned)slice_value;
kchen7 7:af45a10fdfb6 111 DAC_fifo[DAC_wptr]=dac_data;
kchen7 7:af45a10fdfb6 112 DAC_wptr=(DAC_wptr+1) & 0xff;
kchen7 7:af45a10fdfb6 113 while (DAC_wptr==DAC_rptr) {
kchen7 7:af45a10fdfb6 114 }
kchen7 7:af45a10fdfb6 115 }
kchen7 7:af45a10fdfb6 116 DAC_on=0;
kchen7 7:af45a10fdfb6 117 tick.detach();
kchen7 7:af45a10fdfb6 118 free(slice_buf);
kchen7 7:af45a10fdfb6 119 break;
kchen7 7:af45a10fdfb6 120 case 0x5453494c:
kchen7 7:af45a10fdfb6 121 fseek(wavefile,chunk_size,SEEK_CUR);
kchen7 7:af45a10fdfb6 122 break;
kchen7 7:af45a10fdfb6 123 default:
kchen7 7:af45a10fdfb6 124 printf("unknown chunk type 0x%x, size %d\n",chunk_id,chunk_size);
kchen7 7:af45a10fdfb6 125 data=fseek(wavefile,chunk_size,SEEK_CUR);
kchen7 7:af45a10fdfb6 126 break;
kchen7 7:af45a10fdfb6 127 }
kchen7 7:af45a10fdfb6 128 fread(&chunk_id,4,1,wavefile);
kchen7 7:af45a10fdfb6 129 fread(&chunk_size,4,1,wavefile);
kchen7 7:af45a10fdfb6 130 }
kchen7 7:af45a10fdfb6 131 }
kchen7 7:af45a10fdfb6 132
kchen7 7:af45a10fdfb6 133
kchen7 7:af45a10fdfb6 134 void sd_card_player::dac_out()
kchen7 7:af45a10fdfb6 135 {
kchen7 7:af45a10fdfb6 136 if (DAC_on) {
kchen7 7:af45a10fdfb6 137 wave_DAC->write_u16(DAC_fifo[DAC_rptr]);
kchen7 7:af45a10fdfb6 138 DAC_rptr=(DAC_rptr+1) & 0xff;
kchen7 7:af45a10fdfb6 139 }
kchen7 7:af45a10fdfb6 140 }
kchen7 7:af45a10fdfb6 141