Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qwavedecoder.cpp
Go to the documentation of this file.
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/qdebug.h>
8#include <QtCore/qendian.h>
9#include <QtCore/qtimer.h>
10
11#include <limits.h>
12
14
15#if QT_DEPRECATED_SINCE(6, 11)
16
20{
21}
22
27{
28}
29
30QWaveDecoder::~QWaveDecoder() = default;
31
33{
34 bool canOpen = false;
38 handleData();
39 else
41 return canOpen;
42 }
43
44 if (mode & QIODevice::WriteOnly) {
46 return false; // data format is not supported
48 if (canOpen && writeHeader())
49 haveHeader = true;
50 return canOpen;
51 }
52 return QIODevice::open(mode);
53}
54
55void QWaveDecoder::close()
56{
57 if (isOpen() && (openMode() & QIODevice::WriteOnly)) {
59 if (!device->isOpen() || !writeDataLength())
60 qWarning() << "Failed to finalize wav file";
61 }
63}
64
66{
67 return device->seek(pos);
68}
69
70qint64 QWaveDecoder::pos() const
71{
72 return device->pos();
73}
74
75void QWaveDecoder::setIODevice(QIODevice * /* device */)
76{
77}
78
80{
81 return format;
82}
83
85{
86 return device;
87}
88
89int QWaveDecoder::duration() const
90{
92 return 0;
94 return bytesPerSec ? size() * 1000 / bytesPerSec : 0;
95}
96
98{
99 if (openMode() & QIODevice::ReadOnly) {
100 if (!haveFormat)
101 return 0;
102 if (bps == 24)
103 return dataSize*2/3;
104 return dataSize;
105 } else {
106 return device->size();
107 }
108}
109
110bool QWaveDecoder::isSequential() const
111{
112 return device->isSequential();
113}
114
116{
117 return haveFormat ? device->bytesAvailable() : 0;
118}
119
121{
122 return HeaderLength;
123}
124
126{
128 if (!haveFormat || bytesPerSample == 0)
129 return 0;
130
131 if (bps == 24) {
132 // 24 bit WAV, read in as 16 bit
133 qint64 l = 0;
134 while (l < maxlen - 1) {
135 char tmp[3];
136 device->read(tmp, 3);
137 if (byteSwap)
138 qSwap(tmp[0], tmp[2]);
139#if Q_BYTE_ORDER == Q_BIG_ENDIAN
140 data[0] = tmp[0];
141 data[1] = tmp[1];
142#else
143 data[0] = tmp[1];
144 data[1] = tmp[2];
145#endif
146 data += 2;
147 l += 2;
148 }
149 return l;
150 }
151
154 int read = device->read(data, maxlen);
155
156 if (!byteSwap || format.bytesPerFrame() == 1)
157 return read;
158
160 switch (bytesPerSample) {
161 case 2:
162 qbswap<2>(data, nSamples, data);
163 break;
164 case 4:
165 qbswap<4>(data, nSamples, data);
166 break;
167 default:
169 }
170 return read;
171
172}
173
175{
176 if (!haveHeader)
177 return 0;
179 dataSize += written;
180 return written;
181}
182
184{
185 if (device->size() != 0)
186 return false;
187
188#ifndef Q_LITTLE_ENDIAN
189 // only implemented for LITTLE ENDIAN
190 return false;
191#endif
192
194
196
197 // RIFF header
198 memcpy(header.riff.descriptor.id,"RIFF",4);
200 reinterpret_cast<unsigned char*>(&header.riff.descriptor.size));
201 memcpy(header.riff.type, "WAVE",4);
202
203 // WAVE header
204 memcpy(header.wave.descriptor.id,"fmt ",4);
206 reinterpret_cast<unsigned char*>(&header.wave.descriptor.size));
208 reinterpret_cast<unsigned char*>(&header.wave.audioFormat));
210 reinterpret_cast<unsigned char*>(&header.wave.numChannels));
212 reinterpret_cast<unsigned char*>(&header.wave.sampleRate));
214 reinterpret_cast<unsigned char*>(&header.wave.byteRate));
216 reinterpret_cast<unsigned char*>(&header.wave.blockAlign));
218 reinterpret_cast<unsigned char*>(&header.wave.bitsPerSample));
219
220 // DATA header
221 memcpy(header.data.descriptor.id,"data",4);
223 reinterpret_cast<unsigned char*>(&header.data.descriptor.size));
224
225 return device->write(reinterpret_cast<const char *>(&header), HeaderLength);
226}
227
229{
230#ifndef Q_LITTLE_ENDIAN
231 // only implemented for LITTLE ENDIAN
232 return false;
233#endif
234
235 if (isSequential())
236 return false;
237
238 // seek to RIFF header size, see header.riff.descriptor.size above
239 if (!device->seek(4)) {
240 qDebug() << "can't seek";
241 return false;
242 }
243
245 if (device->write(reinterpret_cast<const char *>(&length), 4) != 4)
246 return false;
247
248 // seek to DATA header size, see header.data.descriptor.size above
249 if (!device->seek(40))
250 return false;
251
252 return device->write(reinterpret_cast<const char *>(&dataSize), 4);
253}
254
256{
260}
261
263{
264 if (openMode() == QIODevice::WriteOnly)
265 return;
266
267 // As a special "state", if we have junk to skip, we do
268 if (junkToSkip > 0) {
269 discardBytes(junkToSkip); // this also updates junkToSkip
270
271 // If we couldn't skip all the junk, return
272 if (junkToSkip > 0) {
273 // We might have run out
274 if (device->atEnd())
276 return;
277 }
278 }
279
281 if (device->bytesAvailable() < qint64(sizeof(RIFFHeader)))
282 return;
283
285 device->read(reinterpret_cast<char *>(&riff), sizeof(RIFFHeader));
286
287 // RIFF = little endian RIFF, RIFX = big endian RIFF
288 if (((qstrncmp(riff.descriptor.id, "RIFF", 4) != 0) && (qstrncmp(riff.descriptor.id, "RIFX", 4) != 0))
289 || qstrncmp(riff.type, "WAVE", 4) != 0) {
291 return;
292 }
293
295 bigEndian = (qstrncmp(riff.descriptor.id, "RIFX", 4) == 0);
297 }
298
300 if (findChunk("fmt ")) {
302 const bool peekSuccess = peekChunk(&descriptor);
304
307 return;
308
310 device->read(reinterpret_cast<char *>(&wave), sizeof(WAVEHeader));
311
312 if (rawChunkSize > sizeof(WAVEHeader))
314
315 // Swizzle this
316 if (bigEndian) {
318 } else {
320 }
321
322 if (wave.audioFormat != 0 && wave.audioFormat != 1) {
323 // 32bit wave files have format == 0xFFFE (WAVE_FORMAT_EXTENSIBLE).
324 // but don't support them at the moment.
326 return;
327 }
328
329 int rate;
330 int channels;
331 if (bigEndian) {
335 } else {
339 }
340
342 switch(bps) {
343 case 8:
345 break;
346 case 16:
348 break;
349 case 24:
351 break;
352 case 32:
354 break;
355 }
356 if (fmt == QAudioFormat::Unknown || rate == 0 || channels == 0) {
358 return;
359 }
360
364
366 }
367 }
368
370 if (findChunk("data")) {
372
374 device->read(reinterpret_cast<char *>(&descriptor), sizeof(chunk));
375 if (bigEndian)
377 else
379
380 dataSize = descriptor.size; //means the data size from the data header, not the actual file size
381 if (!dataSize)
383
384 haveFormat = true;
387
388 return;
389 }
390 }
391
392 // If we hit the end without finding data, it's a parsing error
393 if (device->atEnd()) {
395 }
396}
397
399{
401 if (!peekChunk(&descriptor, false))
402 return false;
403
404 // This is only called for the RIFF/RIFX header, before bigEndian is set,
405 // so we have to manually swizzle
406 if (qstrncmp(descriptor.id, "RIFX", 4) == 0)
408 if (qstrncmp(descriptor.id, "RIFF", 4) == 0)
410
411 if (device->bytesAvailable() < qint64(sizeof(chunk)) + descriptor.size)
412 return false;
413
414 return true;
415}
416
417bool QWaveDecoder::findChunk(const char *chunkId)
418{
420
421 do {
422 if (!peekChunk(&descriptor))
423 return false;
424
425 if (qstrncmp(descriptor.id, chunkId, 4) == 0)
426 return true;
427
428 // A program reading a RIFF file can skip over any chunk whose chunk
429 // ID it doesn't recognize; it simply skips the number of bytes specified
430 // by ckSize plus the pad byte, if present. See Multimedia Programming
431 // Interface and Data Specifications 1.0. IBM / Microsoft. August 1991. pp. 10-11.
433
434 // It's possible that bytes->available() is less than the chunk size
435 // if it's corrupt.
436 junkToSkip = qint64(sizeof(chunk) + sizeWithPad);
437
438 // Skip the current amount
439 if (junkToSkip > 0)
441
442 // If we still have stuff left, just exit and try again later
443 // since we can't call peekChunk
444 if (junkToSkip > 0)
445 return false;
446
447 } while (device->bytesAvailable() > 0);
448
449 return false;
450}
451
453{
454 if (device->bytesAvailable() < qint64(sizeof(chunk)))
455 return false;
456
457 if (!device->peek(reinterpret_cast<char *>(pChunk), sizeof(chunk)))
458 return false;
459
460 if (handleEndianness) {
461 if (bigEndian)
463 else
465 }
466 return true;
467}
468
470{
471 // Discards a number of bytes
472 // If the iodevice doesn't have this many bytes in it,
473 // remember how much more junk we have to skip.
474 if (device->isSequential()) {
475 QByteArray r = device->read(qMin(numBytes, qint64(16384))); // uggh, wasted memory, limit to a max of 16k
476 if (r.size() < numBytes)
478 else
479 junkToSkip = 0;
480 } else {
484 }
485}
486
487#endif // QT_DEPRECATED_SINCE(6, 11)
488
490
491#include "moc_qwavedecoder.cpp"
\inmodule QtSql