2
2
* GIGA R1 - Audio Playback
3
3
* Simple wav format audio playback via 12-Bit DAC output by reading from a USB drive.
4
4
* 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.
5
6
*/
6
7
7
8
#include < Arduino_AdvancedAnalog.h>
8
9
#include < DigitalOut.h>
9
10
#include < USBHostMbed5.h>
10
11
#include < FATFileSystem.h>
11
12
12
- #include " wav_seeker.h"
13
-
14
13
AdvancedDAC dac1 (A12);
15
14
16
15
USBHostMSD msd;
17
16
mbed::FATFileSystem usb (" USB_DRIVE" );
18
17
18
+ FILE * file = nullptr ;
19
+ int sample_size = 0 ;
20
+ int samples_count = 0 ;
21
+
22
+
19
23
void setup ()
20
24
{
21
25
Serial.begin (115200 );
@@ -38,28 +42,116 @@ void setup()
38
42
}
39
43
40
44
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 )
45
49
{
46
50
Serial.print (" Error opening audio file: " );
47
51
Serial.println (strerror (errno));
48
52
return ;
49
53
}
50
54
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
58
57
{
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 !" );
61
131
return ;
62
132
}
63
133
}
64
134
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