Skip to content

Commit e89040c

Browse files
committed
examples/Audio_Playback: Update example code.
- Switch to WavReader. - Fix the handling of multi-channels. - Simplify the example code. Signed-off-by: iabdalkader <[email protected]>
1 parent e9b6a0c commit e89040c

File tree

1 file changed

+43
-113
lines changed

1 file changed

+43
-113
lines changed

examples/Beginner/Audio_Playback/Audio_Playback.ino

+43-113
Original file line numberDiff line numberDiff line change
@@ -6,154 +6,84 @@
66
*/
77

88
#include <Arduino_AdvancedAnalog.h>
9-
109
#include <Arduino_USBHostMbed5.h>
11-
1210
#include <DigitalOut.h>
1311
#include <FATFileSystem.h>
1412

15-
AdvancedDAC dac1(A12);
16-
1713
USBHostMSD msd;
1814
mbed::FATFileSystem usb("USB_DRIVE");
1915

20-
FILE * file = nullptr;
21-
int sample_size = 0;
22-
int samples_count = 0;
16+
WavReader wavreader;
17+
AdvancedDAC dac1(A12);
2318

19+
#define N_SAMPLES (512)
20+
int16_t sample_buf[N_SAMPLES];
2421

25-
void setup()
26-
{
22+
void setup() {
2723
Serial.begin(115200);
28-
while (!Serial);
24+
while (!Serial) {
25+
}
2926

30-
/* Enable power for HOST USB connector. */
27+
// Enable power for HOST USB connector.
3128
pinMode(PA_15, OUTPUT);
3229
digitalWrite(PA_15, HIGH);
3330

34-
Serial.println("Please connect a USB stick to the GIGA's USB port ...");
35-
while (!msd.connect()) delay(100);
31+
Serial.println("Please connect a USB stick to the USB host port ...");
32+
while (!msd.connect()) {
33+
delay(100);
34+
}
3635

3736
Serial.println("Mounting USB device ...");
3837
int const rc_mount = usb.mount(&msd);
39-
if (rc_mount)
40-
{
38+
if (rc_mount) {
4139
Serial.print("Error mounting USB device ");
4240
Serial.println(rc_mount);
43-
return;
41+
while (1);
4442
}
4543

4644
Serial.println("Opening audio file ...");
47-
48-
/* 16-bit PCM Mono 16kHz realigned noise reduction */
49-
file = fopen("/USB_DRIVE/AUDIO_SAMPLE.wav", "rb");
50-
if (file == nullptr)
51-
{
52-
Serial.print("Error opening audio file: ");
53-
Serial.println(strerror(errno));
54-
return;
45+
if (!wavreader.open("/USB_DRIVE/AUDIO_SAMPLE.wav")) {
46+
Serial.print("Error opening audio file: ");
47+
while (1);
5548
}
5649

57-
Serial.println("Reading audio header ...");
58-
struct wav_header_t
59-
{
60-
char chunkID[4]; //"RIFF" = 0x46464952
61-
unsigned long chunkSize; //28 [+ sizeof(wExtraFormatBytes) + wExtraFormatBytes] + sum(sizeof(chunk.id) + sizeof(chunk.size) + chunk.size)
62-
char format[4]; //"WAVE" = 0x45564157
63-
char subchunk1ID[4]; //"fmt " = 0x20746D66
64-
unsigned long subchunk1Size; //16 [+ sizeof(wExtraFormatBytes) + wExtraFormatBytes]
65-
unsigned short audioFormat;
66-
unsigned short numChannels;
67-
unsigned long sampleRate;
68-
unsigned long byteRate;
69-
unsigned short blockAlign;
70-
unsigned short bitsPerSample;
71-
};
72-
73-
wav_header_t header;
74-
fread(&header, sizeof(header), 1, file);
75-
76-
Serial.println("WAV File Header read:");
7750
char msg[64] = {0};
78-
snprintf(msg, sizeof(msg), "File Type: %s", header.chunkID);
79-
Serial.println(msg);
80-
snprintf(msg, sizeof(msg), "File Size: %ld", header.chunkSize);
81-
Serial.println(msg);
82-
snprintf(msg, sizeof(msg), "WAV Marker: %s", header.format);
83-
Serial.println(msg);
84-
snprintf(msg, sizeof(msg), "Format Name: %s", header.subchunk1ID);
85-
Serial.println(msg);
86-
snprintf(msg, sizeof(msg), "Format Length: %ld", header.subchunk1Size);
87-
Serial.println(msg);
88-
snprintf(msg, sizeof(msg), "Format Type: %hd", header.audioFormat);
89-
Serial.println(msg);
90-
snprintf(msg, sizeof(msg), "Number of Channels: %hd", header.numChannels);
91-
Serial.println(msg);
92-
snprintf(msg, sizeof(msg), "Sample Rate: %ld", header.sampleRate);
93-
Serial.println(msg);
94-
snprintf(msg, sizeof(msg), "Sample Rate * Bits/Sample * Channels / 8: %ld", header.byteRate);
95-
Serial.println(msg);
96-
snprintf(msg, sizeof(msg), "Bits per Sample * Channels / 8: %hd", header.blockAlign);
97-
Serial.println(msg);
98-
snprintf(msg, sizeof(msg), "Bits per Sample: %hd", header.bitsPerSample);
99-
Serial.println(msg);
100-
101-
/* Find the data section of the WAV file. */
102-
struct chunk_t
103-
{
104-
char ID[4];
105-
unsigned long size;
106-
};
107-
108-
chunk_t chunk;
109-
snprintf(msg, sizeof(msg), "id\t" "size");
110-
Serial.println(msg);
111-
/* Find data chunk. */
112-
while (true)
113-
{
114-
fread(&chunk, sizeof(chunk), 1, file);
115-
snprintf(msg, sizeof(msg), "%c%c%c%c\t" "%li", chunk.ID[0], chunk.ID[1], chunk.ID[2], chunk.ID[3], chunk.size);
116-
Serial.println(msg);
117-
if (*(unsigned int *) &chunk.ID == 0x61746164)
118-
break;
119-
/* Skip chunk data bytes. */
120-
fseek(file, chunk.size, SEEK_CUR);
121-
}
51+
snprintf(msg, sizeof(msg), "Number of Channels: %hd", wavreader.channels()); Serial.println(msg);
52+
snprintf(msg, sizeof(msg), "Sample Rate: %ld", wavreader.sample_rate()); Serial.println(msg);
53+
snprintf(msg, sizeof(msg), "Bits per Sample: %hd", wavreader.sample_size()); Serial.println(msg);
54+
snprintf(msg, sizeof(msg), "Number of Samples = %i", wavreader.sample_count()); Serial.println(msg);
12255

123-
/* Determine number of samples. */
124-
sample_size = header.bitsPerSample / 8;
125-
samples_count = chunk.size * 8 / header.bitsPerSample;
126-
snprintf(msg, sizeof(msg), "Sample size = %i", sample_size); Serial.println(msg);
127-
snprintf(msg, sizeof(msg), "Samples count = %i", samples_count); Serial.println(msg);
56+
// Round the total number of samples to a multiple of the DAC's buffer size
57+
wavreader.set_max_samples((wavreader.sample_count() / N_SAMPLES) * N_SAMPLES);
12858

129-
/* Configure the advanced DAC. */
130-
if (!dac1.begin(AN_RESOLUTION_12, header.sampleRate, 256, 16))
131-
{
59+
// Configure and start the DAC. Note that the DAC is single-channel. If the file has two channels,
60+
// the buffer size is set to half the number of samples, as the two channels will be averaged.
61+
if (!dac1.begin(AN_RESOLUTION_12, wavreader.sample_rate(), N_SAMPLES / wavreader.channels(), 32)) {
13262
Serial.println("Failed to start DAC1 !");
133-
return;
63+
while (1);
13464
}
13565
}
13666

137-
void loop()
138-
{
139-
if (dac1.available() && !feof(file))
140-
{
141-
/* Read data from file. */
142-
uint16_t sample_data[256] = {0};
143-
fread(sample_data, sample_size, 256, file);
144-
145-
/* Get a free buffer for writing. */
67+
void loop() {
68+
if (dac1.available()) {
69+
// Get a free buffer for writing.
14670
SampleBuffer buf = dac1.dequeue();
14771

148-
/* Write data to buffer. */
149-
for (size_t i = 0; i < buf.size(); i++)
150-
{
151-
/* Scale down to 12 bit. */
152-
uint16_t const dac_val = ((static_cast<unsigned int>(sample_data[i])+32768)>>4) & 0x0fff;
153-
buf[i] = dac_val;
72+
// Read samples in a loop.
73+
wavreader.read(sample_buf, N_SAMPLES, true);
74+
75+
// Write samples to buffer.
76+
for (size_t i=0; i<N_SAMPLES; i+=wavreader.channels()) {
77+
// Map the samples to positive range and down scale to 12-bit.
78+
if (wavreader.channels() == 1) {
79+
buf[i] = ((unsigned int)(sample_buf[i] + 32768)) >> 4;
80+
} else {
81+
// Average the two channels, if the file has two channels
82+
buf[i / 2] = ((unsigned int)((sample_buf[i] + sample_buf[i+1] / 2) + 32768)) >> 4;
83+
}
15484
}
15585

156-
/* Write the buffer to DAC. */
86+
// Write the buffer to DAC.
15787
dac1.write(buf);
15888
}
15989
}

0 commit comments

Comments
 (0)