M Makefile +0 -1
@@ 38,4 38,3 @@ THIRD_PARTY_LIBS :=
# no routinely user-modifiable parts
include build/Makefile.inc
-
M build/Makefile.inc +11 -8
@@ 29,10 29,12 @@ src/AudioReadStreamFactory.o: ./bqaudios
src/AudioReadStreamFactory.o: ./bqaudiostream/Exceptions.h
src/AudioReadStreamFactory.o: src/WavFileReadStream.cpp
src/AudioReadStreamFactory.o: src/OggVorbisReadStream.cpp
+src/AudioReadStreamFactory.o: src/MiniMP3ReadStream.cpp
src/AudioReadStreamFactory.o: src/MediaFoundationReadStream.cpp
+src/AudioReadStreamFactory.o: src/SimpleWavFileReadStream.cpp
+src/AudioReadStreamFactory.o: src/SimpleWavFileReadStream.h
src/AudioReadStreamFactory.o: src/CoreAudioReadStream.cpp
src/AudioReadStreamFactory.o: src/OpusReadStream.cpp
-src/AudioReadStreamFactory.o: src/MiniMP3ReadStream.cpp
src/AudioWriteStreamFactory.o: ./bqaudiostream/AudioWriteStreamFactory.h
src/AudioWriteStreamFactory.o: ./bqaudiostream/AudioWriteStream.h
src/AudioWriteStreamFactory.o: ./bqaudiostream/Exceptions.h
@@ 42,13 44,14 @@ src/AudioWriteStreamFactory.o: src/Simpl
src/AudioWriteStreamFactory.o: src/SimpleWavFileWriteStream.h
src/AudioWriteStreamFactory.o: src/CoreAudioWriteStream.cpp
src/AudioWriteStreamFactory.o: src/CoreAudioWriteStream.h
-src/Exceptions.o: ./bqaudiostream/Exceptions.h
+src/AudioStreamExceptions.o: ./bqaudiostream/Exceptions.h
+src/CoreAudioReadStream.o: ./bqaudiostream/AudioReadStream.h
+src/CoreAudioWriteStream.o: ./bqaudiostream/AudioWriteStream.h
src/MediaFoundationReadStream.o: ./bqaudiostream/AudioReadStream.h
-src/WavFileWriteStream.o: ./bqaudiostream/AudioWriteStream.h
+src/MiniMP3ReadStream.o: ./bqaudiostream/AudioReadStream.h
+src/OggVorbisReadStream.o: ./bqaudiostream/AudioReadStream.h
+src/OpusReadStream.o: ./bqaudiostream/AudioReadStream.h
+src/SimpleWavFileReadStream.o: ./bqaudiostream/AudioReadStream.h
src/SimpleWavFileWriteStream.o: ./bqaudiostream/AudioWriteStream.h
src/WavFileReadStream.o: ./bqaudiostream/AudioReadStream.h
-src/CoreAudioWriteStream.o: ./bqaudiostream/AudioWriteStream.h
-src/CoreAudioReadStream.o: ./bqaudiostream/AudioReadStream.h
-src/OggVorbisReadStream.o: ./bqaudiostream/AudioReadStream.h
-src/OpusReadStream.o: ./bqaudiostream/AudioReadStream.h
-src/MiniMP3ReadStream.o: ./bqaudiostream/AudioReadStream.h
+src/WavFileWriteStream.o: ./bqaudiostream/AudioWriteStream.h
M src/SimpleWavFileReadStream.cpp +47 -17
@@ 61,13 61,13 @@ SimpleWavFileReadStream::SimpleWavFileRe
m_bitDepth(0),
m_startPos(0),
m_index(0),
- m_file(nullptr)
+ m_file(0)
{
m_file = new ifstream(filename.c_str(), ios::in | std::ios::binary);
if (!*m_file) {
delete m_file;
- m_file = nullptr;
+ m_file = 0;
throw FileNotFound(m_path);
}
@@ 92,14 92,14 @@ SimpleWavFileReadStream::readHeader()
uint32_t totalSize = readExpectedChunkSize("RIFF");
readExpectedTag("WAVE");
uint32_t fmtSize = readExpectedChunkSize("fmt ");
- if (fmtSize != 16) {
+ if (fmtSize < 16) {
cout << "fmtSize = " << fmtSize << endl;
- throw InvalidFileFormat(m_path, "unexpected format chunk size");
+ throw InvalidFileFormat(m_path, "unexpectedly short format chunk");
}
uint32_t audioFormat = readMandatoryNumber(2);
- if (audioFormat != 1) {
- throw InvalidFileFormat(m_path, "PCM formats only supported by this reader");
+ if (audioFormat != 1 && audioFormat != 3) {
+ throw InvalidFileFormat(m_path, "only PCM and float WAV formats are supported by this reader");
}
uint32_t channels = readMandatoryNumber(2);
@@ 107,23 107,42 @@ SimpleWavFileReadStream::readHeader()
uint32_t byteRate = readMandatoryNumber(4);
uint32_t bytesPerSample = readMandatoryNumber(2);
uint32_t bitsPerSample = readMandatoryNumber(2);
-
+
if (bitsPerSample != 8 &&
bitsPerSample != 16 &&
- bitsPerSample != 24) {
+ bitsPerSample != 24 &&
+ bitsPerSample != 32) {
throw InvalidFileFormat(m_path, "unsupported bit depth");
}
+ if (bitsPerSample == 32) {
+ if (audioFormat == 1) {
+ throw InvalidFileFormat(m_path, "32-bit samples are only supported in float format, not PCM");
+ } else {
+ char *buf = (char *)malloc(sizeof(float));
+ *(float *)buf = -0.f;
+ m_floatSwap = (buf[0] != '\0');
+ }
+ }
+
m_channelCount = channels;
m_sampleRate = sampleRate;
m_bitDepth = bitsPerSample;
- cerr << "bit depth = " << m_bitDepth << endl;
+ // we don't use these
+ (void)totalSize;
+ (void)byteRate;
+ (void)bytesPerSample;
+
+ // and we ignore extended format chunk data
+ if (fmtSize > 16) {
+ m_file->ignore(fmtSize - 16);
+ }
while (true) {
string tag = readTag();
if (tag == "") {
- throw InvalidFileFormat(m_path, "tag expected");
+ throw InvalidFileFormat(m_path, "tag expected after fmt chunk");
}
uint32_t chunkSize = readChunkSizeAfterTag();
if (tag == "data") {
@@ 135,11 154,6 @@ SimpleWavFileReadStream::readHeader()
}
}
}
-
- // we don't use these
- (void)totalSize;
- (void)byteRate;
- (void)bytesPerSample;
}
uint32_t
@@ 203,6 217,7 @@ SimpleWavFileReadStream::getFrames(size_
case 8: frames[got] = convertSample8(buf); break;
case 16: frames[got] = convertSample16(buf); break;
case 24: frames[got] = convertSample24(buf); break;
+ case 32: frames[got] = convertSampleFloat(buf); break;
}
++got;
}
@@ 238,10 253,26 @@ SimpleWavFileReadStream::convertSample24
return float(i) / 2147483647.f;
}
+float
+SimpleWavFileReadStream::convertSampleFloat(const vector<uint8_t> &v)
+{
+ if (!m_floatSwap) {
+ const uint8_t *buf = v.data();
+ return *(const float *)buf;
+ } else {
+ vector<uint8_t> vv(4);
+ for (int i = 0; i < 4; ++i) {
+ vv[i] = v[3-i];
+ }
+ const uint8_t *buf = vv.data();
+ return *(const float *)buf;
+ }
+}
+
int
SimpleWavFileReadStream::getBytes(int n, vector<uint8_t> &v)
{
- if (!m_file) return {};
+ if (!m_file) return 0;
for (int i = 0; i < n; ++i) {
char c;
@@ 271,5 302,4 @@ SimpleWavFileReadStream::le2int(const ve
}
-
#endif
M src/SimpleWavFileReadStream.h +3 -1
@@ 70,6 70,7 @@ private:
int m_channels;
int m_rate;
int m_bitDepth;
+ bool m_floatSwap;
size_t m_startPos;
size_t m_index;
@@ 85,7 86,8 @@ private:
float convertSample8(const vector<uint8_t> &);
float convertSample16(const vector<uint8_t> &);
float convertSample24(const vector<uint8_t> &);
-
+ float convertSampleFloat(const vector<uint8_t> &);
+
int getBytes(int n, std::vector<uint8_t> &);
static uint32_t le2int(const std::vector<uint8_t> &le);
};
M test/TestAudioStreamRead.h +1 -1
@@ 60,7 60,7 @@ private slots:
{
QFETCH(QString, audiofile);
- cerr << "\n\n*** audiofile = " << audiofile.toLocal8Bit().data() << "\n\n" << endl;
+// cerr << "\n\n*** audiofile = " << audiofile.toLocal8Bit().data() << "\n\n" << endl;
try {
M test/TestWavReadWrite.h +9 -9
@@ 18,17 18,17 @@ namespace breakfastquay {
static const float DB_FLOOR = -1000.0;
-static float to_dB(float ratio)
+static float to_dBV(float ratio)
{
if (ratio == 0.0) return DB_FLOOR;
- float dB = 10 * log10f(ratio);
+ float dB = 20 * log10f(ratio);
return dB;
}
-static float from_dB(float dB)
+static float from_dBV(float dB)
{
if (dB == DB_FLOOR) return 0.0;
- float m = powf(10.0, dB / 10.0);
+ float m = powf(10.0, dB / 20.0);
return m;
}
@@ 123,8 123,8 @@ private slots:
QVERIFY(ws);
- float error = from_dB(-10);
- float warning = from_dB(-25);
+ float error = from_dBV(-10);
+ float warning = from_dBV(-25);
float maxdiff = 0.f;
float mda = 0.f, mdb = 0.f;
int maxdiffindex = -1;
@@ 157,14 157,14 @@ private slots:
QString message = QString("Max diff is %1 (%2 dB) at index %3 (a = %4, b = %5) [error threshold %6 (%7 dB), warning threshold %8 (%9 dB)]")
.arg(maxdiff)
- .arg(to_dB(maxdiff))
+ .arg(to_dBV(maxdiff))
.arg(maxdiffindex)
.arg(mda)
.arg(mdb)
.arg(error)
- .arg(to_dB(error))
+ .arg(to_dBV(error))
.arg(warning)
- .arg(to_dB(warning));
+ .arg(to_dBV(warning));
QVERIFY2(maxdiff < error, message.toLocal8Bit().data());