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

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