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 | |
11 | QT_BEGIN_NAMESPACE |
12 | |
13 | namespace { |
14 | |
15 | void 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 | |
24 | void 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 | |
36 | QWaveDecoder::QWaveDecoder(QIODevice *device, QObject *parent) |
37 | : QIODevice(parent), |
38 | device(device) |
39 | { |
40 | } |
41 | |
42 | QWaveDecoder::QWaveDecoder(QIODevice *device, const QAudioFormat &format, QObject *parent) |
43 | : QIODevice(parent), |
44 | device(device), |
45 | format(format) |
46 | { |
47 | } |
48 | |
49 | QWaveDecoder::~QWaveDecoder() = default; |
50 | |
51 | bool 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 | |
74 | void 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 | |
84 | bool QWaveDecoder::seek(qint64 pos) |
85 | { |
86 | return device->seek(pos); |
87 | } |
88 | |
89 | qint64 QWaveDecoder::pos() const |
90 | { |
91 | return device->pos(); |
92 | } |
93 | |
94 | QAudioFormat QWaveDecoder::audioFormat() const |
95 | { |
96 | return format; |
97 | } |
98 | |
99 | QIODevice* QWaveDecoder::getDevice() |
100 | { |
101 | return device; |
102 | } |
103 | |
104 | int 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 | |
112 | qint64 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 | |
125 | bool QWaveDecoder::isSequential() const |
126 | { |
127 | return device->isSequential(); |
128 | } |
129 | |
130 | qint64 QWaveDecoder::bytesAvailable() const |
131 | { |
132 | return haveFormat ? device->bytesAvailable() : 0; |
133 | } |
134 | |
135 | qint64 QWaveDecoder::() |
136 | { |
137 | return HeaderLength; |
138 | } |
139 | |
140 | qint64 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 | |
189 | qint64 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 | |
198 | bool QWaveDecoder::() |
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 ; |
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 | |
243 | bool 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 | |
270 | void QWaveDecoder::parsingFailed() |
271 | { |
272 | Q_ASSERT(device); |
273 | device->disconnect(SIGNAL(readyRead()), receiver: this, SLOT(handleData())); |
274 | emit parsingError(); |
275 | } |
276 | |
277 | void 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 | |
412 | bool 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 | |
431 | bool 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 | |
460 | bool 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 | |
477 | void 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 | |
495 | QT_END_NAMESPACE |
496 | |
497 | #include "moc_qwavedecoder.cpp" |
498 | |