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