22 * GIGA R1 - Audio Playback
33 * Simple wav format audio playback via 12-Bit DAC output by reading from a USB drive.
44 * In order for this sketch to work you need to rename 'USB_DRIVE' to the name of your USB stick drive.
5+ * Furthermore you need to store the provided audio file AUDIO_SAMPLE.wav on it.
56*/
67
78#include < Arduino_AdvancedAnalog.h>
89#include < DigitalOut.h>
910#include < USBHostMbed5.h>
1011#include < FATFileSystem.h>
1112
12- #include " wav_seeker.h"
13-
1413AdvancedDAC dac1 (A12);
1514
1615USBHostMSD msd;
1716mbed::FATFileSystem usb (" USB_DRIVE" );
1817
18+ FILE * file = nullptr ;
19+ int sample_size = 0 ;
20+ int samples_count = 0 ;
21+
22+
1923void setup ()
2024{
2125 Serial.begin (115200 );
@@ -38,28 +42,116 @@ void setup()
3842 }
3943
4044 Serial.println (" Opening audio file ..." );
41-
42- // 16-bit PCM Mono 16kHz realigned noise reduction
43- FILE * f = fopen (" /USB_DRIVE/AUDIO_SAMPLE.wav" , " r " );
44- if (f == nullptr )
45+
46+ /* 16-bit PCM Mono 16kHz realigned noise reduction */
47+ file = fopen (" /USB_DRIVE/AUDIO_SAMPLE.wav" , " rb " );
48+ if (file == nullptr )
4549 {
4650 Serial.print (" Error opening audio file: " );
4751 Serial.println (strerror (errno));
4852 return ;
4953 }
5054
51- Serial.println (" Playing audio file ..." );
52- wav_play_rl (f, dac1, false );
53-
54- Serial.println (" Cleaning up ..." );
55- fclose (f);
56- int const rc_umount = usb.unmount ();
57- if (rc_umount < 0 )
55+ Serial.println (" Reading audio header ..." );
56+ struct wav_header_t
5857 {
59- Serial.print (" Error unmounting USB drive: " );
60- Serial.println (rc_umount);
58+ char chunkID[4 ]; // "RIFF" = 0x46464952
59+ unsigned long chunkSize; // 28 [+ sizeof(wExtraFormatBytes) + wExtraFormatBytes] + sum(sizeof(chunk.id) + sizeof(chunk.size) + chunk.size)
60+ char format[4 ]; // "WAVE" = 0x45564157
61+ char subchunk1ID[4 ]; // "fmt " = 0x20746D66
62+ unsigned long subchunk1Size; // 16 [+ sizeof(wExtraFormatBytes) + wExtraFormatBytes]
63+ unsigned short audioFormat;
64+ unsigned short numChannels;
65+ unsigned long sampleRate;
66+ unsigned long byteRate;
67+ unsigned short blockAlign;
68+ unsigned short bitsPerSample;
69+ };
70+
71+ wav_header_t header;
72+ fread (&header, sizeof (header), 1 , file);
73+
74+ Serial.println (" WAV File Header read:" );
75+ char msg[64 ] = {0 };
76+ snprintf (msg, sizeof (msg), " File Type: %s" , header.chunkID );
77+ Serial.println (msg);
78+ snprintf (msg, sizeof (msg), " File Size: %ld" , header.chunkSize );
79+ Serial.println (msg);
80+ snprintf (msg, sizeof (msg), " WAV Marker: %s" , header.format );
81+ Serial.println (msg);
82+ snprintf (msg, sizeof (msg), " Format Name: %s" , header.subchunk1ID );
83+ Serial.println (msg);
84+ snprintf (msg, sizeof (msg), " Format Length: %ld" , header.subchunk1Size );
85+ Serial.println (msg);
86+ snprintf (msg, sizeof (msg), " Format Type: %hd" , header.audioFormat );
87+ Serial.println (msg);
88+ snprintf (msg, sizeof (msg), " Number of Channels: %hd" , header.numChannels );
89+ Serial.println (msg);
90+ snprintf (msg, sizeof (msg), " Sample Rate: %ld" , header.sampleRate );
91+ Serial.println (msg);
92+ snprintf (msg, sizeof (msg), " Sample Rate * Bits/Sample * Channels / 8: %ld" , header.byteRate );
93+ Serial.println (msg);
94+ snprintf (msg, sizeof (msg), " Bits per Sample * Channels / 8: %hd" , header.blockAlign );
95+ Serial.println (msg);
96+ snprintf (msg, sizeof (msg), " Bits per Sample: %hd" , header.bitsPerSample );
97+ Serial.println (msg);
98+
99+ /* Find the data section of the WAV file. */
100+ struct chunk_t
101+ {
102+ char ID[4 ];
103+ unsigned long size;
104+ };
105+
106+ chunk_t chunk;
107+ snprintf (msg, sizeof (msg), " id\t " " size" );
108+ Serial.println (msg);
109+ /* Find data chunk. */
110+ while (true )
111+ {
112+ fread (&chunk, sizeof (chunk), 1 , file);
113+ snprintf (msg, sizeof (msg), " %c%c%c%c\t " " %li" , chunk.ID [0 ], chunk.ID [1 ], chunk.ID [2 ], chunk.ID [3 ], chunk.size );
114+ Serial.println (msg);
115+ if (*(unsigned int *) &chunk.ID == 0x61746164 )
116+ break ;
117+ /* Skip chunk data bytes. */
118+ fseek (file, chunk.size , SEEK_CUR);
119+ }
120+
121+ /* Determine number of samples. */
122+ sample_size = header.bitsPerSample / 8 ;
123+ samples_count = chunk.size * 8 / header.bitsPerSample ;
124+ snprintf (msg, sizeof (msg), " Sample size = %i" , sample_size); Serial.println (msg);
125+ snprintf (msg, sizeof (msg), " Samples count = %i" , samples_count); Serial.println (msg);
126+
127+ /* Configure the advanced DAC. */
128+ if (!dac1.begin (AN_RESOLUTION_12, header.sampleRate , 256 , 16 ))
129+ {
130+ Serial.println (" Failed to start DAC1 !" );
61131 return ;
62132 }
63133}
64134
65- void loop () {}
135+ void loop ()
136+ {
137+ if (dac1.available () && !feof (file))
138+ {
139+ /* Read data from file. */
140+ uint16_t sample_data[256 ] = {0 };
141+ fread (sample_data, sample_size, 256 , file);
142+
143+ /* Get a free buffer for writing. */
144+ SampleBuffer buf = dac1.dequeue ();
145+
146+ /* Write data to buffer. */
147+ for (size_t i = 0 ; i < buf.size (); i++)
148+ {
149+ /* Scale down to 12 bit. */
150+ uint16_t const dac_val = ((static_cast <unsigned int >(sample_data[i])+32768 )>>4 ) & 0x0fff ;
151+ buf[i] = dac_val;
152+ }
153+
154+ /* Write the buffer to DAC. */
155+ dac1.write (buf);
156+ }
157+ }
0 commit comments