Skip to content

Commit a2be6ab

Browse files
committed
Adding audio_playback as provided by FT content.
1 parent 8867dd6 commit a2be6ab

File tree

3 files changed

+307
-0
lines changed

3 files changed

+307
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* GIGA R1 - Audio Playback
3+
* Simple wav format audio playback via 12-Bit DAC output by reading from a USB drive.
4+
*/
5+
6+
#include <USBHostMbed5.h>
7+
#include <DigitalOut.h>
8+
#include <FATFileSystem.h>
9+
10+
// AdvancedDAC library is included inside wav_seeker library
11+
#include "wav_seeker.h"
12+
AdvancedDAC dac1(A12);
13+
14+
USBHostMSD msd;
15+
mbed::FATFileSystem usb("USB_DRIVE_NAME");
16+
17+
void setup() {
18+
Serial.begin(115200);
19+
while (!Serial);
20+
21+
pinMode(PA_15, OUTPUT);
22+
digitalWrite(PA_15, HIGH);
23+
24+
delay(2500);
25+
Serial.println("Starting USB File Read example...");
26+
27+
while (!msd.connect()) {
28+
delay(1000);
29+
}
30+
31+
Serial.println("Mounting USB device...");
32+
int err = usb.mount(&msd);
33+
if (err) {
34+
Serial.print("Error mounting USB device ");
35+
Serial.println(err);
36+
while (1);
37+
}
38+
39+
// Read
40+
Serial.print("read done ");
41+
mbed::fs_file_t file;
42+
struct dirent *ent;
43+
int dirIndex = 0;
44+
int res = 0;
45+
Serial.println("Open file..");
46+
47+
// 16-bit PCM Mono 16kHz realigned noise reduction
48+
FILE *f = fopen("/USB_DRIVE_NAME/AUDIO_SAMPLE.wav", "r+");
49+
50+
// Crucial (from mBed)
51+
wav_play_rl(f, dac1, false);
52+
53+
// Close the file
54+
Serial.println("File closing");
55+
fflush(stdout);
56+
err = fclose(f);
57+
if (err < 0) {
58+
Serial.print("fclose error: ");
59+
Serial.print(strerror(errno));
60+
Serial.print(" (");
61+
Serial.print(-errno);
62+
Serial.print(")");
63+
} else {
64+
Serial.println("File closed!");
65+
}
66+
}
67+
68+
void loop() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
/*
2+
* Based on mBed's repo, algorithm based of the wave_player library by Steve Ravet
3+
* https://os.mbed.com/users/sparkfun/code/wave_player/
4+
* Adapted to GIGA R1
5+
*/
6+
7+
#include "wav_seeker.h"
8+
9+
unsigned short DAC_fifo[256];
10+
short DAC_wptr;
11+
volatile short DAC_rptr;
12+
short DAC_on;
13+
14+
typedef struct uFMT_STRUCT {
15+
short comp_code;
16+
short num_channels;
17+
unsigned sample_rate;
18+
unsigned avg_Bps;
19+
short block_align;
20+
short sig_bps;
21+
} FMT_STRUCT;
22+
23+
void wav_play_rl(FILE *wavefile, AdvancedDAC &dac_out, bool verbosity){
24+
unsigned chunk_id,chunk_size,channel;
25+
unsigned data,samp_int,i;
26+
short unsigned dac_data;
27+
long long slice_value;
28+
char *slice_buf;
29+
short *data_sptr;
30+
unsigned char *data_bptr;
31+
int *data_wptr;
32+
FMT_STRUCT wav_format;
33+
long slice,num_slices;
34+
DAC_wptr=0;
35+
DAC_rptr=0;
36+
37+
for (i=0;i<256;i+=2) {
38+
DAC_fifo[i]=0;
39+
DAC_fifo[i+1]=3000;
40+
}
41+
42+
DAC_wptr=4;
43+
DAC_on=0;
44+
45+
fread(&chunk_id,4,1,wavefile);
46+
fread(&chunk_size,4,1,wavefile);
47+
48+
while (!feof(wavefile)) {
49+
if (verbosity)
50+
Serial.print(F("Read chunk ID ="));
51+
Serial.println(chunk_id);
52+
Serial.print(F("Read chunk size ="));
53+
Serial.println(chunk_size);
54+
55+
switch (chunk_id) {
56+
case 0x46464952:
57+
fread(&data,4,1,wavefile);
58+
if (verbosity) {
59+
Serial.println(F("RIFF chunk"));
60+
Serial.print(F(" chunk size = "));
61+
Serial.println(chunk_size);
62+
Serial.print(F(" RIFF type = "));
63+
Serial.println(data);
64+
}
65+
break;
66+
case 0x20746d66:
67+
fread(&wav_format,sizeof(wav_format),1,wavefile);
68+
if (verbosity) {
69+
Serial.println(F("FORMAT chunk"));
70+
Serial.print(F(" chunk size = "));
71+
Serial.println(chunk_size);
72+
Serial.print(F(" compression code ="));
73+
Serial.println(wav_format.comp_code);
74+
Serial.print(F(" channels ="));
75+
Serial.println(wav_format.num_channels);
76+
Serial.print(F(" samples/sec ="));
77+
Serial.println(wav_format.sample_rate);
78+
Serial.print(F(" bytes/sec ="));
79+
Serial.println(wav_format.avg_Bps);
80+
Serial.print(F(" block align ="));
81+
Serial.println(wav_format.block_align);
82+
Serial.print(F(" bits per sample ="));
83+
Serial.println(wav_format.sig_bps);
84+
}
85+
86+
// Initializing AdvancedAnalogRedux
87+
88+
if (!dac_out.begin(AN_RESOLUTION_12, wav_format.sample_rate, 256, 512)) {
89+
Serial.println("Failed to start DAC1 !");
90+
while (1);
91+
} else{
92+
Serial.println(F("DAC1 Initialized"));
93+
}
94+
95+
if (chunk_size > sizeof(wav_format))
96+
fseek(wavefile,chunk_size-sizeof(wav_format),SEEK_CUR);
97+
break;
98+
case 0x61746164:
99+
slice_buf=(char *)malloc(wav_format.block_align);
100+
if (!slice_buf) {
101+
Serial.println(F("Unable to malloc slice buffer"));
102+
exit(1);
103+
}
104+
num_slices=chunk_size/wav_format.block_align;
105+
samp_int=1000000/(wav_format.sample_rate);
106+
107+
if (verbosity) {
108+
Serial.println(F("DATA chunk"));
109+
Serial.print(F(" chunk size ="));
110+
Serial.println(chunk_size);
111+
Serial.print(F(" slices ="));
112+
Serial.println(num_slices);
113+
Serial.print(F(" Ideal sample interval= "));
114+
Serial.println((unsigned)(1000000.0/wav_format.sample_rate));
115+
Serial.print(F(" programmed interrupt tick interval ="));
116+
Serial.println(samp_int);
117+
}
118+
DAC_on=1;
119+
120+
for (slice=0;slice<num_slices;slice+=1) {
121+
while (dac_out.available()) {
122+
fread(slice_buf,wav_format.block_align,1,wavefile);
123+
if (feof(wavefile)) {
124+
Serial.println(F("Oops -- not enough slices in the wave file\n"));
125+
exit(1);
126+
}
127+
data_sptr=(short *)slice_buf; // 16 bit samples
128+
data_bptr=(unsigned char *)slice_buf; // 8 bit samples
129+
data_wptr=(int *)slice_buf; // 32 bit samples
130+
slice_value=0;
131+
for (channel=0;channel<wav_format.num_channels;channel++) {
132+
switch (wav_format.sig_bps) {
133+
case 16:
134+
if (verbosity)
135+
Serial.print(F("16 bit channel ="));
136+
Serial.println(channel);
137+
Serial.print(F(" data = "));
138+
Serial.println(data_sptr[channel]);
139+
slice_value+=data_sptr[channel];
140+
break;
141+
case 32:
142+
if (verbosity)
143+
Serial.print(F("32 bit channel ="));
144+
Serial.println(channel);
145+
Serial.print(F(" data = "));
146+
Serial.println(data_wptr[channel]);
147+
slice_value+=data_wptr[channel];
148+
break;
149+
case 8:
150+
if (verbosity)
151+
Serial.print(F("8 bit channel ="));
152+
Serial.println(channel);
153+
Serial.print(F(" data = "));
154+
Serial.println((int)data_bptr[channel]);
155+
slice_value+=data_bptr[channel];
156+
break;
157+
}
158+
}
159+
slice_value/=wav_format.num_channels;
160+
161+
switch (wav_format.sig_bps) {
162+
// Working for 8 bit for 12 bit output - acceleartes in the end
163+
case 8: slice_value<<=4;
164+
break;
165+
// WORKING 12 BIT - SCALING DOWN FROM 16 BIT TO 12 BIT (Applied from 16-Bit wav sample files )
166+
case 16: slice_value = (((slice_value+32768)>>4) & 0xfff);
167+
break;
168+
// 32-Bit Case - Won't be used with GIGA as the highest resolution will be 12-Bit
169+
case 32: slice_value>>=16;
170+
slice_value+=32768;
171+
break;
172+
}
173+
dac_data=(short unsigned)slice_value;
174+
if (verbosity)
175+
Serial.print(F("DAC-Data >>>>>>>>>>>>>>"));
176+
Serial.print(F("sample ="));
177+
Serial.println(slice);
178+
Serial.print(F("wptr ="));
179+
Serial.println(DAC_wptr);
180+
Serial.print(F("slice value ="));
181+
Serial.println((int)slice_value);
182+
Serial.print(F("dac_data ="));
183+
Serial.println(dac_data);
184+
DAC_fifo[DAC_wptr]=dac_data;
185+
186+
// Custom_mode begin
187+
188+
DAC_wptr=(DAC_wptr+1) & 0xff;
189+
// Conditional addition to switch between channels - FOR STEREO
190+
if (DAC_wptr >= 255){
191+
static size_t lut_offs = 0;
192+
193+
Serial.println(F("Proceeding DAC ..."));
194+
// Get a free buffer for writing.
195+
SampleBuffer buf = dac_out.dequeue();
196+
// Write data to buffer.
197+
for (size_t i=0; i<buf.size(); i++, lut_offs++) {
198+
buf[i] = DAC_fifo[lut_offs % (sizeof(DAC_fifo)/sizeof(DAC_fifo[0]))];
199+
}
200+
201+
// Writethe buffer to DAC.
202+
Serial.println(F("Writing to DAC ..."));
203+
dac_out.write(buf);
204+
205+
DAC_wptr = 0;
206+
} else {
207+
Serial.println(F("Slicing"));
208+
}
209+
// Custom_mode end
210+
}
211+
}
212+
DAC_on=0;
213+
free(slice_buf);
214+
break;
215+
case 0x5453494c:
216+
if (verbosity)
217+
Serial.print(F("INFO chunk, size"));
218+
Serial.println(chunk_size);
219+
fseek(wavefile,chunk_size,SEEK_CUR);
220+
break;
221+
default:
222+
Serial.print(F("unknown chunk type ="));
223+
Serial.println(chunk_id);
224+
Serial.print(F("chunk size ="));
225+
Serial.println(chunk_size);
226+
data=fseek(wavefile,chunk_size,SEEK_CUR);
227+
break;
228+
}
229+
fread(&chunk_id,4,1,wavefile);
230+
fread(&chunk_size,4,1,wavefile);
231+
}
232+
Serial.println(F("Finished reading file"));
233+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
#include "AdvancedDAC.h"
3+
4+
struct adc_descr_t;
5+
6+
void wav_play_rl(FILE *wavefile, AdvancedDAC &dac_out, bool verbosity);

0 commit comments

Comments
 (0)