Skip to content

Commit e82aa81

Browse files
authored
Merge pull request #27 from toniebox-reverse-engineering/develop
Develop for Nightly 20220427
2 parents 3a4b078 + a0b9896 commit e82aa81

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+982
-204
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
ConfigStatic.h
22
.vscode/*
3+
build/out/*

AudioCustomLogger.h

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class AudioCustomLogger: public DevNullOut
1818
va_list args;
1919
va_start(args, msg);
2020
Log.printFormat(msg, args);
21+
return 0; //TOOD?
2122
};
2223
};
2324

AudioGeneratorWAVStatic.cpp

+297
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
/*
2+
AudioGeneratorWAVStatic
3+
Audio output generator that reads 8 and 16-bit WAV files
4+
5+
Copyright (C) 2017 Earle F. Philhower, III
6+
7+
This program is free software: you can redistribute it and/or modify
8+
it under the terms of the GNU General Public License as published by
9+
the Free Software Foundation, either version 3 of the License, or
10+
(at your option) any later version.
11+
12+
This program is distributed in the hope that it will be useful,
13+
but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
GNU General Public License for more details.
16+
17+
You should have received a copy of the GNU General Public License
18+
along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
21+
22+
#include "AudioGeneratorWAVStatic.h"
23+
24+
25+
AudioGeneratorWAVStatic::~AudioGeneratorWAVStatic(){}
26+
27+
bool AudioGeneratorWAVStatic::stop()
28+
{
29+
if (!running) return true;
30+
running = false;
31+
output->stop();
32+
return file->close();
33+
}
34+
35+
bool AudioGeneratorWAVStatic::isRunning()
36+
{
37+
return running;
38+
}
39+
40+
41+
// Handle buffered reading, reload each time we run out of data
42+
bool AudioGeneratorWAVStatic::GetBufferedData(int bytes, void *dest)
43+
{
44+
if (!running) return false; // Nothing to do here!
45+
uint8_t *p = reinterpret_cast<uint8_t*>(dest);
46+
while (bytes--) {
47+
// Potentially load next batch of data...
48+
if (buffPtr >= buffLen) {
49+
buffPtr = 0;
50+
uint32_t toRead = availBytes > BUFFER_SIZE ? BUFFER_SIZE : availBytes;
51+
buffLen = file->read( buff, toRead );
52+
availBytes -= buffLen;
53+
}
54+
if (buffPtr >= buffLen)
55+
return false; // No data left!
56+
*(p++) = buff[buffPtr++];
57+
}
58+
return true;
59+
}
60+
61+
bool AudioGeneratorWAVStatic::loop()
62+
{
63+
if (!running) goto done; // Nothing to do here!
64+
65+
// First, try and push in the stored sample. If we can't, then punt and try later
66+
if (!output->ConsumeSample(lastSample)) goto done; // Can't send, but no error detected
67+
68+
// Try and stuff the buffer one sample at a time
69+
do
70+
{
71+
if (bitsPerSample == 8) {
72+
uint8_t l, r;
73+
if (!GetBufferedData(1, &l)) stop();
74+
if (channels == 2) {
75+
if (!GetBufferedData(1, &r)) stop();
76+
} else {
77+
r = 0;
78+
}
79+
lastSample[AudioOutput::LEFTCHANNEL] = l;
80+
lastSample[AudioOutput::RIGHTCHANNEL] = r;
81+
} else if (bitsPerSample == 16) {
82+
if (!GetBufferedData(2, &lastSample[AudioOutput::LEFTCHANNEL])) stop();
83+
if (channels == 2) {
84+
if (!GetBufferedData(2, &lastSample[AudioOutput::RIGHTCHANNEL])) stop();
85+
} else {
86+
lastSample[AudioOutput::RIGHTCHANNEL] = 0;
87+
}
88+
}
89+
} while (running && output->ConsumeSample(lastSample));
90+
91+
done:
92+
file->loop();
93+
output->loop();
94+
95+
return running;
96+
}
97+
98+
99+
bool AudioGeneratorWAVStatic::ReadWAVInfo()
100+
{
101+
uint32_t u32;
102+
uint16_t u16;
103+
int toSkip;
104+
105+
// WAV specification document:
106+
// https://www.aelius.com/njh/wavemetatools/doc/riffmci.pdf
107+
108+
// Header == "RIFF"
109+
if (!ReadU32(&u32)) {
110+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::ReadWAVInfo: failed to read WAV data\n"));
111+
return false;
112+
};
113+
if (u32 != 0x46464952) {
114+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::ReadWAVInfo: cannot read WAV, invalid RIFF header, got: %08X \n"), (uint32_t) u32);
115+
return false;
116+
}
117+
118+
// Skip ChunkSize
119+
if (!ReadU32(&u32)) {
120+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::ReadWAVInfo: failed to read WAV data\n"));
121+
return false;
122+
};
123+
124+
// Format == "WAVE"
125+
if (!ReadU32(&u32)) {
126+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::ReadWAVInfo: failed to read WAV data\n"));
127+
return false;
128+
};
129+
if (u32 != 0x45564157) {
130+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::ReadWAVInfo: cannot read WAV, invalid WAVE header, got: %08X \n"), (uint32_t) u32);
131+
return false;
132+
}
133+
134+
// there might be JUNK or PAD - ignore it by continuing reading until we get to "fmt "
135+
while (1) {
136+
if (!ReadU32(&u32)) {
137+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::ReadWAVInfo: failed to read WAV data\n"));
138+
return false;
139+
};
140+
if (u32 == 0x20746d66) break; // 'fmt '
141+
};
142+
143+
// subchunk size
144+
if (!ReadU32(&u32)) {
145+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::ReadWAVInfo: failed to read WAV data\n"));
146+
return false;
147+
};
148+
if (u32 == 16) { toSkip = 0; }
149+
else if (u32 == 18) { toSkip = 18 - 16; }
150+
else if (u32 == 40) { toSkip = 40 - 16; }
151+
else {
152+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::ReadWAVInfo: cannot read WAV, appears not to be standard PCM \n"));
153+
return false;
154+
} // we only do standard PCM
155+
156+
// AudioFormat
157+
if (!ReadU16(&u16)) {
158+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::ReadWAVInfo: failed to read WAV data\n"));
159+
return false;
160+
};
161+
if (u16 != 1) {
162+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::ReadWAVInfo: cannot read WAV, AudioFormat appears not to be standard PCM \n"));
163+
return false;
164+
} // we only do standard PCM
165+
166+
// NumChannels
167+
if (!ReadU16(&channels)) {
168+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::ReadWAVInfo: failed to read WAV data\n"));
169+
return false;
170+
};
171+
if ((channels<1) || (channels>2)) {
172+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::ReadWAVInfo: cannot read WAV, only mono and stereo are supported \n"));
173+
return false;
174+
} // Mono or stereo support only
175+
176+
// SampleRate
177+
if (!ReadU32(&sampleRate)) {
178+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::ReadWAVInfo: failed to read WAV data\n"));
179+
return false;
180+
};
181+
if (sampleRate < 1) {
182+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::ReadWAVInfo: cannot read WAV, unknown sample rate \n"));
183+
return false;
184+
} // Weird rate, punt. Will need to check w/DAC to see if supported
185+
186+
// Ignore byterate and blockalign
187+
if (!ReadU32(&u32)) {
188+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::ReadWAVInfo: failed to read WAV data\n"));
189+
return false;
190+
};
191+
if (!ReadU16(&u16)) {
192+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::ReadWAVInfo: failed to read WAV data\n"));
193+
return false;
194+
};
195+
196+
// Bits per sample
197+
if (!ReadU16(&bitsPerSample)) {
198+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::ReadWAVInfo: failed to read WAV data\n"));
199+
return false;
200+
};
201+
if ((bitsPerSample!=8) && (bitsPerSample != 16)) {
202+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::ReadWAVInfo: cannot read WAV, only 8 or 16 bits is supported \n"));
203+
return false;
204+
} // Only 8 or 16 bits
205+
206+
// Skip any extra header
207+
while (toSkip) {
208+
uint8_t ign;
209+
if (!ReadU8(&ign)) {
210+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::ReadWAVInfo: failed to read WAV data\n"));
211+
return false;
212+
};
213+
toSkip--;
214+
}
215+
216+
// look for data subchunk
217+
do {
218+
// id == "data"
219+
if (!ReadU32(&u32)) {
220+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::ReadWAVInfo: failed to read WAV data\n"));
221+
return false;
222+
};
223+
if (u32 == 0x61746164) break; // "data"
224+
// Skip size, read until end of chunk
225+
if (!ReadU32(&u32)) {
226+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::ReadWAVInfo: failed to read WAV data\n"));
227+
return false;
228+
};
229+
if(!file->seek(u32, SEEK_CUR)) {
230+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::ReadWAVInfo: failed to read WAV data, seek failed\n"));
231+
return false;
232+
}
233+
} while (1);
234+
if (!file->isOpen()) {
235+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::ReadWAVInfo: cannot read WAV, file is not open\n"));
236+
return false;
237+
};
238+
239+
// Skip size, read until end of file...
240+
if (!ReadU32(&u32)) {
241+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::ReadWAVInfo: failed to read WAV data\n"));
242+
return false;
243+
};
244+
availBytes = u32;
245+
246+
buffPtr = 0;
247+
buffLen = 0;
248+
249+
return true;
250+
}
251+
252+
bool AudioGeneratorWAVStatic::begin(AudioFileSource *source, AudioOutput *output) {
253+
running = false;
254+
buffPtr = 0;
255+
buffLen = 0;
256+
257+
if (!source) {
258+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::begin: failed: invalid source\n"));
259+
return false;
260+
}
261+
file = source;
262+
if (!output) {
263+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::begin: invalid output\n"));
264+
return false;
265+
}
266+
this->output = output;
267+
if (!file->isOpen()) {
268+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::begin: file not open\n"));
269+
return false;
270+
} // Error
271+
272+
if (!ReadWAVInfo()) {
273+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::begin: failed during ReadWAVInfo\n"));
274+
return false;
275+
}
276+
277+
if (!output->SetRate( sampleRate )) {
278+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::begin: failed to SetRate in output\n"));
279+
return false;
280+
}
281+
if (!output->SetBitsPerSample( bitsPerSample )) {
282+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::begin: failed to SetBitsPerSample in output\n"));
283+
return false;
284+
}
285+
if (!output->SetChannels( channels )) {
286+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::begin: failed to SetChannels in output\n"));
287+
return false;
288+
}
289+
if (!output->begin()) {
290+
audioLogger->printf_P(PSTR("AudioGeneratorWAVStatic::begin: output's begin did not return true\n"));
291+
return false;
292+
}
293+
294+
running = true;
295+
296+
return true;
297+
}

AudioGeneratorWAVStatic.h

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
AudioGeneratorWAV
3+
Audio output generator that reads 8 and 16-bit WAV files
4+
5+
Copyright (C) 2017 Earle F. Philhower, III
6+
7+
This program is free software: you can redistribute it and/or modify
8+
it under the terms of the GNU General Public License as published by
9+
the Free Software Foundation, either version 3 of the License, or
10+
(at your option) any later version.
11+
12+
This program is distributed in the hope that it will be useful,
13+
but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
GNU General Public License for more details.
16+
17+
You should have received a copy of the GNU General Public License
18+
along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
21+
#ifndef _AUDIOGENERATORWAVSTATIC_H
22+
#define _AUDIOGENERATORWAVSTATIC_H
23+
24+
#include "AudioGenerator.h"
25+
26+
class AudioGeneratorWAVStatic : public AudioGenerator
27+
{
28+
public:
29+
virtual ~AudioGeneratorWAVStatic() override;
30+
virtual bool begin(AudioFileSource *source, AudioOutput *output) override;
31+
virtual bool loop() override;
32+
virtual bool stop() override;
33+
virtual bool isRunning() override;
34+
35+
private:
36+
bool ReadU32(uint32_t *dest) { return file->read(reinterpret_cast<uint8_t*>(dest), 4); }
37+
bool ReadU16(uint16_t *dest) { return file->read(reinterpret_cast<uint8_t*>(dest), 2); }
38+
bool ReadU8(uint8_t *dest) { return file->read(reinterpret_cast<uint8_t*>(dest), 1); }
39+
bool GetBufferedData(int bytes, void *dest);
40+
bool ReadWAVInfo();
41+
42+
43+
protected:
44+
// WAV info
45+
uint16_t channels;
46+
uint32_t sampleRate;
47+
uint16_t bitsPerSample;
48+
49+
uint32_t availBytes;
50+
51+
// We need to buffer some data in-RAM to avoid doing 1000s of small reads
52+
//uint32_t buffSize;
53+
//uint8_t *buff;
54+
uint16_t buffPtr;
55+
uint16_t buffLen;
56+
57+
static const uint16_t BUFFER_SIZE = 256;
58+
uint8_t buff[BUFFER_SIZE];
59+
};
60+
61+
#endif
62+

AudioOutputCC3200I2S.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ void AudioOutputCC3200I2S::flush() {
113113

114114
bool AudioOutputCC3200I2S::stop() {
115115
flush();
116+
return true;
116117
}
117118
bool AudioOutputCC3200I2S::begin() {
118119
return true;

0 commit comments

Comments
 (0)