1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qwavedecoder.h"
5
6#include <QtCore/qtimer.h>
7#include <QtCore/qendian.h>
8#include <limits.h>
9#include <qdebug.h>
10
11QT_BEGIN_NAMESPACE
12
13namespace {
14
15void bswap2(char *data, qsizetype count) noexcept
16{
17 for (qsizetype i = 0; i < count; ++i) {
18 qSwap(value1&: data[0], value2&: data[1]);
19 ++count;
20 data += 2;
21 }
22}
23
24void bswap4(char *data, qsizetype count) noexcept
25{
26 for (qsizetype i = 0; i < count; ++i) {
27 qSwap(value1&: data[0], value2&: data[3]);
28 qSwap(value1&: data[1], value2&: data[2]);
29 ++count;
30 data += 4;
31 }
32}
33
34}
35
36QWaveDecoder::QWaveDecoder(QIODevice *device, QObject *parent)
37 : QIODevice(parent),
38 device(device)
39{
40}
41
42QWaveDecoder::QWaveDecoder(QIODevice *device, const QAudioFormat &format, QObject *parent)
43 : QIODevice(parent),
44 device(device),
45 format(format)
46{
47}
48
49QWaveDecoder::~QWaveDecoder() = default;
50
51bool QWaveDecoder::open(QIODevice::OpenMode mode)
52{
53 bool canOpen = false;
54 if (mode & QIODevice::ReadOnly && mode & ~QIODevice::WriteOnly) {
55 canOpen = QIODevice::open(mode: mode | QIODevice::Unbuffered);
56 if (canOpen && enoughDataAvailable())
57 handleData();
58 else
59 connect(asender: device, SIGNAL(readyRead()), SLOT(handleData()));
60 return canOpen;
61 }
62
63 if (mode & QIODevice::WriteOnly) {
64 if (format.sampleFormat() != QAudioFormat::Int16)
65 return false; // data format is not supported
66 canOpen = QIODevice::open(mode);
67 if (canOpen && writeHeader())
68 haveHeader = true;
69 return canOpen;
70 }
71 return QIODevice::open(mode);
72}
73
74void QWaveDecoder::close()
75{
76 if (isOpen() && (openMode() & QIODevice::WriteOnly)) {
77 Q_ASSERT(dataSize < INT_MAX);
78 if (!device->isOpen() || !writeDataLength())
79 qWarning() << "Failed to finalize wav file";
80 }
81 QIODevice::close();
82}
83
84bool QWaveDecoder::seek(qint64 pos)
85{
86 return device->seek(pos);
87}
88
89qint64 QWaveDecoder::pos() const
90{
91 return device->pos();
92}
93
94QAudioFormat QWaveDecoder::audioFormat() const
95{
96 return format;
97}
98
99QIODevice* QWaveDecoder::getDevice()
100{
101 return device;
102}
103
104int QWaveDecoder::duration() const
105{
106 if (openMode() & QIODevice::WriteOnly)
107 return 0;
108 int bytesPerSec = format.bytesPerFrame() * format.sampleRate();
109 return bytesPerSec ? size() * 1000 / bytesPerSec : 0;
110}
111
112qint64 QWaveDecoder::size() const
113{
114 if (openMode() & QIODevice::ReadOnly) {
115 if (!haveFormat)
116 return 0;
117 if (bps == 24)
118 return dataSize*2/3;
119 return dataSize;
120 } else {
121 return device->size();
122 }
123}
124
125bool QWaveDecoder::isSequential() const
126{
127 return device->isSequential();
128}
129
130qint64 QWaveDecoder::bytesAvailable() const
131{
132 return haveFormat ? device->bytesAvailable() : 0;
133}
134
135qint64 QWaveDecoder::headerLength()
136{
137 return HeaderLength;
138}
139
140qint64 QWaveDecoder::readData(char *data, qint64 maxlen)
141{
142 const int bytesPerSample = format.bytesPerSample();
143 if (!haveFormat || bytesPerSample == 0)
144 return 0;
145
146 if (bps == 24) {
147 // 24 bit WAV, read in as 16 bit
148 qint64 l = 0;
149 while (l < maxlen - 1) {
150 char tmp[3];
151 device->read(data: tmp, maxlen: 3);
152 if (byteSwap)
153 qSwap(value1&: tmp[0], value2&: tmp[2]);
154#if Q_BYTE_ORDER == Q_BIG_ENDIAN
155 data[0] = tmp[0];
156 data[1] = tmp[1];
157#else
158 data[0] = tmp[1];
159 data[1] = tmp[2];
160#endif
161 data += 2;
162 l += 2;
163 }
164 return l;
165 }
166
167 qint64 nSamples = maxlen / bytesPerSample;
168 maxlen = nSamples * bytesPerSample;
169 int read = device->read(data, maxlen);
170
171 if (!byteSwap || format.bytesPerFrame() == 1)
172 return read;
173
174 nSamples = read / bytesPerSample;
175 switch (bytesPerSample) {
176 case 2:
177 bswap2(data, count: nSamples);
178 break;
179 case 4:
180 bswap4(data, count: nSamples);
181 break;
182 default:
183 Q_UNREACHABLE();
184 }
185 return read;
186
187}
188
189qint64 QWaveDecoder::writeData(const char *data, qint64 len)
190{
191 if (!haveHeader)
192 return 0;
193 qint64 written = device->write(data, len);
194 dataSize += written;
195 return written;
196}
197
198bool QWaveDecoder::writeHeader()
199{
200 if (device->size() != 0)
201 return false;
202
203#ifndef Q_LITTLE_ENDIAN
204 // only implemented for LITTLE ENDIAN
205 return false;
206#endif
207
208 CombinedHeader header;
209
210 memset(s: &header, c: 0, n: HeaderLength);
211
212 // RIFF header
213 memcpy(dest: header.riff.descriptor.id,src: "RIFF",n: 4);
214 qToLittleEndian<quint32>(src: quint32(dataSize + HeaderLength - 8),
215 dest: reinterpret_cast<unsigned char*>(&header.riff.descriptor.size));
216 memcpy(dest: header.riff.type, src: "WAVE",n: 4);
217
218 // WAVE header
219 memcpy(dest: header.wave.descriptor.id,src: "fmt ",n: 4);
220 qToLittleEndian<quint32>(src: quint32(16),
221 dest: reinterpret_cast<unsigned char*>(&header.wave.descriptor.size));
222 qToLittleEndian<quint16>(src: quint16(1),
223 dest: reinterpret_cast<unsigned char*>(&header.wave.audioFormat));
224 qToLittleEndian<quint16>(src: quint16(format.channelCount()),
225 dest: reinterpret_cast<unsigned char*>(&header.wave.numChannels));
226 qToLittleEndian<quint32>(src: quint32(format.sampleRate()),
227 dest: reinterpret_cast<unsigned char*>(&header.wave.sampleRate));
228 qToLittleEndian<quint32>(src: quint32(format.sampleRate() * format.bytesPerFrame()),
229 dest: reinterpret_cast<unsigned char*>(&header.wave.byteRate));
230 qToLittleEndian<quint16>(src: quint16(format.channelCount() * format.bytesPerSample()),
231 dest: reinterpret_cast<unsigned char*>(&header.wave.blockAlign));
232 qToLittleEndian<quint16>(src: quint16(format.bytesPerSample() * 8),
233 dest: reinterpret_cast<unsigned char*>(&header.wave.bitsPerSample));
234
235 // DATA header
236 memcpy(dest: header.data.descriptor.id,src: "data",n: 4);
237 qToLittleEndian<quint32>(src: quint32(dataSize),
238 dest: reinterpret_cast<unsigned char*>(&header.data.descriptor.size));
239
240 return device->write(data: reinterpret_cast<const char *>(&header), len: HeaderLength);
241}
242
243bool QWaveDecoder::writeDataLength()
244{
245#ifndef Q_LITTLE_ENDIAN
246 // only implemented for LITTLE ENDIAN
247 return false;
248#endif
249
250 if (isSequential())
251 return false;
252
253 // seek to RIFF header size, see header.riff.descriptor.size above
254 if (!device->seek(pos: 4)) {
255 qDebug() << "can't seek";
256 return false;
257 }
258
259 quint32 length = dataSize + HeaderLength - 8;
260 if (device->write(data: reinterpret_cast<const char *>(&length), len: 4) != 4)
261 return false;
262
263 // seek to DATA header size, see header.data.descriptor.size above
264 if (!device->seek(pos: 40))
265 return false;
266
267 return device->write(data: reinterpret_cast<const char *>(&dataSize), len: 4);
268}
269
270void QWaveDecoder::parsingFailed()
271{
272 Q_ASSERT(device);
273 device->disconnect(SIGNAL(readyRead()), receiver: this, SLOT(handleData()));
274 emit parsingError();
275}
276
277void QWaveDecoder::handleData()
278{
279 if (openMode() == QIODevice::WriteOnly)
280 return;
281
282 // As a special "state", if we have junk to skip, we do
283 if (junkToSkip > 0) {
284 discardBytes(numBytes: junkToSkip); // this also updates junkToSkip
285
286 // If we couldn't skip all the junk, return
287 if (junkToSkip > 0) {
288 // We might have run out
289 if (device->atEnd())
290 parsingFailed();
291 return;
292 }
293 }
294
295 if (state == QWaveDecoder::InitialState) {
296 if (device->bytesAvailable() < qint64(sizeof(RIFFHeader)))
297 return;
298
299 RIFFHeader riff;
300 device->read(data: reinterpret_cast<char *>(&riff), maxlen: sizeof(RIFFHeader));
301
302 // RIFF = little endian RIFF, RIFX = big endian RIFF
303 if (((qstrncmp(str1: riff.descriptor.id, str2: "RIFF", len: 4) != 0) && (qstrncmp(str1: riff.descriptor.id, str2: "RIFX", len: 4) != 0))
304 || qstrncmp(str1: riff.type, str2: "WAVE", len: 4) != 0) {
305 parsingFailed();
306 return;
307 }
308
309 state = QWaveDecoder::WaitingForFormatState;
310 bigEndian = (qstrncmp(str1: riff.descriptor.id, str2: "RIFX", len: 4) == 0);
311 byteSwap = (bigEndian != (QSysInfo::ByteOrder == QSysInfo::BigEndian));
312 }
313
314 if (state == QWaveDecoder::WaitingForFormatState) {
315 if (findChunk(chunkId: "fmt ")) {
316 chunk descriptor;
317 peekChunk(pChunk: &descriptor);
318
319 quint32 rawChunkSize = descriptor.size + sizeof(chunk);
320 if (device->bytesAvailable() < qint64(rawChunkSize))
321 return;
322
323 WAVEHeader wave;
324 device->read(data: reinterpret_cast<char *>(&wave), maxlen: sizeof(WAVEHeader));
325
326 if (rawChunkSize > sizeof(WAVEHeader))
327 discardBytes(numBytes: rawChunkSize - sizeof(WAVEHeader));
328
329 // Swizzle this
330 if (bigEndian) {
331 wave.audioFormat = qFromBigEndian<quint16>(source: wave.audioFormat);
332 } else {
333 wave.audioFormat = qFromLittleEndian<quint16>(source: wave.audioFormat);
334 }
335
336 if (wave.audioFormat != 0 && wave.audioFormat != 1) {
337 // 32bit wave files have format == 0xFFFE (WAVE_FORMAT_EXTENSIBLE).
338 // but don't support them at the moment.
339 parsingFailed();
340 return;
341 }
342
343 int rate;
344 int channels;
345 if (bigEndian) {
346 bps = qFromBigEndian<quint16>(source: wave.bitsPerSample);
347 rate = qFromBigEndian<quint32>(source: wave.sampleRate);
348 channels = qFromBigEndian<quint16>(source: wave.numChannels);
349 } else {
350 bps = qFromLittleEndian<quint16>(source: wave.bitsPerSample);
351 rate = qFromLittleEndian<quint32>(source: wave.sampleRate);
352 channels = qFromLittleEndian<quint16>(source: wave.numChannels);
353 }
354
355 QAudioFormat::SampleFormat fmt = QAudioFormat::Unknown;
356 switch(bps) {
357 case 8:
358 fmt = QAudioFormat::UInt8;
359 break;
360 case 16:
361 fmt = QAudioFormat::Int16;
362 break;
363 case 24:
364 fmt = QAudioFormat::Int16;
365 break;
366 case 32:
367 fmt = QAudioFormat::Int32;
368 break;
369 }
370 if (fmt == QAudioFormat::Unknown || rate == 0 || channels == 0) {
371 parsingFailed();
372 return;
373 }
374
375 format.setSampleFormat(fmt);
376 format.setSampleRate(/*qFromBigEndian<quint32>*/(wave.sampleRate));
377 format.setChannelCount(/*qFromBigEndian<quint16>*/(wave.numChannels));
378
379 state = QWaveDecoder::WaitingForDataState;
380 }
381 }
382
383 if (state == QWaveDecoder::WaitingForDataState) {
384 if (findChunk(chunkId: "data")) {
385 device->disconnect(SIGNAL(readyRead()), receiver: this, SLOT(handleData()));
386
387 chunk descriptor;
388 device->read(data: reinterpret_cast<char *>(&descriptor), maxlen: sizeof(chunk));
389 if (bigEndian)
390 descriptor.size = qFromBigEndian<quint32>(source: descriptor.size);
391 else
392 descriptor.size = qFromLittleEndian<quint32>(source: descriptor.size);
393
394 dataSize = descriptor.size; //means the data size from the data header, not the actual file size
395 if (!dataSize)
396 dataSize = device->size() - headerLength();
397
398 haveFormat = true;
399 connect(asender: device, SIGNAL(readyRead()), SIGNAL(readyRead()));
400 emit formatKnown();
401
402 return;
403 }
404 }
405
406 // If we hit the end without finding data, it's a parsing error
407 if (device->atEnd()) {
408 parsingFailed();
409 }
410}
411
412bool QWaveDecoder::enoughDataAvailable()
413{
414 chunk descriptor;
415 if (!peekChunk(pChunk: &descriptor, handleEndianness: false))
416 return false;
417
418 // This is only called for the RIFF/RIFX header, before bigEndian is set,
419 // so we have to manually swizzle
420 if (qstrncmp(str1: descriptor.id, str2: "RIFX", len: 4) == 0)
421 descriptor.size = qFromBigEndian<quint32>(source: descriptor.size);
422 if (qstrncmp(str1: descriptor.id, str2: "RIFF", len: 4) == 0)
423 descriptor.size = qFromLittleEndian<quint32>(source: descriptor.size);
424
425 if (device->bytesAvailable() < qint64(sizeof(chunk) + descriptor.size))
426 return false;
427
428 return true;
429}
430
431bool QWaveDecoder::findChunk(const char *chunkId)
432{
433 chunk descriptor;
434
435 do {
436 if (!peekChunk(pChunk: &descriptor))
437 return false;
438
439 if (qstrncmp(str1: descriptor.id, str2: chunkId, len: 4) == 0)
440 return true;
441
442 // It's possible that bytes->available() is less than the chunk size
443 // if it's corrupt.
444 junkToSkip = qint64(sizeof(chunk) + descriptor.size);
445
446 // Skip the current amount
447 if (junkToSkip > 0)
448 discardBytes(numBytes: junkToSkip);
449
450 // If we still have stuff left, just exit and try again later
451 // since we can't call peekChunk
452 if (junkToSkip > 0)
453 return false;
454
455 } while (device->bytesAvailable() > 0);
456
457 return false;
458}
459
460bool QWaveDecoder::peekChunk(chunk *pChunk, bool handleEndianness)
461{
462 if (device->bytesAvailable() < qint64(sizeof(chunk)))
463 return false;
464
465 if (!device->peek(data: reinterpret_cast<char *>(pChunk), maxlen: sizeof(chunk)))
466 return false;
467
468 if (handleEndianness) {
469 if (bigEndian)
470 pChunk->size = qFromBigEndian<quint32>(source: pChunk->size);
471 else
472 pChunk->size = qFromLittleEndian<quint32>(source: pChunk->size);
473 }
474 return true;
475}
476
477void QWaveDecoder::discardBytes(qint64 numBytes)
478{
479 // Discards a number of bytes
480 // If the iodevice doesn't have this many bytes in it,
481 // remember how much more junk we have to skip.
482 if (device->isSequential()) {
483 QByteArray r = device->read(maxlen: qMin(a: numBytes, b: qint64(16384))); // uggh, wasted memory, limit to a max of 16k
484 if (r.size() < numBytes)
485 junkToSkip = numBytes - r.size();
486 else
487 junkToSkip = 0;
488 } else {
489 quint64 origPos = device->pos();
490 device->seek(pos: device->pos() + numBytes);
491 junkToSkip = origPos + numBytes - device->pos();
492 }
493}
494
495QT_END_NAMESPACE
496
497#include "moc_qwavedecoder.cpp"
498

source code of qtmultimedia/src/multimedia/audio/qwavedecoder.cpp