7#include <QtCore/qtimer.h>
8#include <QtCore/qendian.h>
14#if QT_DEPRECATED_SINCE(6
, 11
)
16QWaveDecoder::QWaveDecoder(QIODevice *device, QObject *parent)
22QWaveDecoder::QWaveDecoder(QIODevice *device,
const QAudioFormat &format, QObject *parent)
29QWaveDecoder::~QWaveDecoder() =
default;
31bool QWaveDecoder::open(QIODevice::OpenMode mode)
34 if (mode & QIODevice::ReadOnly && mode & ~QIODevice::WriteOnly) {
35 canOpen = QIODevice::open(mode | QIODevice::Unbuffered);
36 if (canOpen && enoughDataAvailable())
39 connect(device, &QIODevice::readyRead,
this, &QWaveDecoder::handleData);
43 if (mode & QIODevice::WriteOnly) {
44 if (format.sampleFormat() != QAudioFormat::Int16)
46 canOpen = QIODevice::open(mode);
47 if (canOpen && writeHeader())
51 return QIODevice::open(mode);
54void QWaveDecoder::close()
56 if (isOpen() && (openMode() & QIODevice::WriteOnly)) {
57 Q_ASSERT(dataSize < INT_MAX);
58 if (!device->isOpen() || !writeDataLength())
59 qWarning() <<
"Failed to finalize wav file";
64bool QWaveDecoder::seek(qint64 pos)
66 return device->seek(pos);
69qint64 QWaveDecoder::pos()
const
74void QWaveDecoder::setIODevice(QIODevice * )
78QAudioFormat QWaveDecoder::audioFormat()
const
83QIODevice* QWaveDecoder::getDevice()
88int QWaveDecoder::duration()
const
90 if (openMode() & QIODevice::WriteOnly)
92 int bytesPerSec = format.bytesPerFrame() * format.sampleRate();
93 return bytesPerSec ? size() * 1000 / bytesPerSec : 0;
96qint64 QWaveDecoder::size()
const
98 if (openMode() & QIODevice::ReadOnly) {
105 return device->size();
109bool QWaveDecoder::isSequential()
const
111 return device->isSequential();
114qint64 QWaveDecoder::bytesAvailable()
const
116 return haveFormat ? device->bytesAvailable() : 0;
119qint64 QWaveDecoder::headerLength()
124qint64 QWaveDecoder::readData(
char *data, qint64 maxlen)
126 const int bytesPerSample = format.bytesPerSample();
127 if (!haveFormat || bytesPerSample == 0)
133 while (l < maxlen - 1) {
135 device->read(tmp, 3);
137 qSwap(tmp[0], tmp[2]);
138#if Q_BYTE_ORDER == Q_BIG_ENDIAN
151 qint64 nSamples = maxlen / bytesPerSample;
152 maxlen = nSamples * bytesPerSample;
153 int read = device->read(data, maxlen);
155 if (!byteSwap || format.bytesPerFrame() == 1)
158 nSamples = read / bytesPerSample;
159 switch (bytesPerSample) {
161 qbswap<2>(data, nSamples, data);
164 qbswap<4>(data, nSamples, data);
173qint64 QWaveDecoder::writeData(
const char *data, qint64 len)
177 qint64 written = device->write(data, len);
182bool QWaveDecoder::writeHeader()
184 if (device->size() != 0)
187#ifndef Q_LITTLE_ENDIAN
192 CombinedHeader header;
194 memset(&header, 0, HeaderLength);
197 memcpy(header.riff.descriptor.id,
"RIFF",4);
198 qToLittleEndian<quint32>(quint32(dataSize + HeaderLength - 8),
199 reinterpret_cast<
unsigned char*>(&header.riff.descriptor.size));
200 memcpy(header.riff.type,
"WAVE",4);
203 memcpy(header.wave.descriptor.id,
"fmt ",4);
204 qToLittleEndian<quint32>(quint32(16),
205 reinterpret_cast<
unsigned char*>(&header.wave.descriptor.size));
206 qToLittleEndian<quint16>(quint16(1),
207 reinterpret_cast<
unsigned char*>(&header.wave.audioFormat));
208 qToLittleEndian<quint16>(quint16(format.channelCount()),
209 reinterpret_cast<
unsigned char*>(&header.wave.numChannels));
210 qToLittleEndian<quint32>(quint32(format.sampleRate()),
211 reinterpret_cast<
unsigned char*>(&header.wave.sampleRate));
212 qToLittleEndian<quint32>(quint32(format.sampleRate() * format.bytesPerFrame()),
213 reinterpret_cast<
unsigned char*>(&header.wave.byteRate));
214 qToLittleEndian<quint16>(quint16(format.channelCount() * format.bytesPerSample()),
215 reinterpret_cast<
unsigned char*>(&header.wave.blockAlign));
216 qToLittleEndian<quint16>(quint16(format.bytesPerSample() * 8),
217 reinterpret_cast<
unsigned char*>(&header.wave.bitsPerSample));
220 memcpy(header.data.descriptor.id,
"data",4);
221 qToLittleEndian<quint32>(quint32(dataSize),
222 reinterpret_cast<
unsigned char*>(&header.data.descriptor.size));
224 return device->write(
reinterpret_cast<
const char *>(&header), HeaderLength);
227bool QWaveDecoder::writeDataLength()
229#ifndef Q_LITTLE_ENDIAN
238 if (!device->seek(4)) {
239 qDebug() <<
"can't seek";
243 quint32 length = dataSize + HeaderLength - 8;
244 if (device->write(
reinterpret_cast<
const char *>(&length), 4) != 4)
248 if (!device->seek(40))
251 return device->write(
reinterpret_cast<
const char *>(&dataSize), 4);
254void QWaveDecoder::parsingFailed()
257 disconnect(device, &QIODevice::readyRead,
this, &QWaveDecoder::handleData);
261void QWaveDecoder::handleData()
263 if (openMode() == QIODevice::WriteOnly)
267 if (junkToSkip > 0) {
268 discardBytes(junkToSkip);
271 if (junkToSkip > 0) {
279 if (state == QWaveDecoder::InitialState) {
280 if (device->bytesAvailable() < qint64(
sizeof(RIFFHeader)))
284 device->read(
reinterpret_cast<
char *>(&riff),
sizeof(RIFFHeader));
287 if (((qstrncmp(riff.descriptor.id,
"RIFF", 4) != 0) && (qstrncmp(riff.descriptor.id,
"RIFX", 4) != 0))
288 || qstrncmp(riff.type,
"WAVE", 4) != 0) {
293 state = QWaveDecoder::WaitingForFormatState;
294 bigEndian = (qstrncmp(riff.descriptor.id,
"RIFX", 4) == 0);
295 byteSwap = (bigEndian != (QSysInfo::ByteOrder == QSysInfo::BigEndian));
298 if (state == QWaveDecoder::WaitingForFormatState) {
299 if (findChunk(
"fmt ")) {
301 const bool peekSuccess = peekChunk(&descriptor);
302 Q_ASSERT(peekSuccess);
304 quint32 rawChunkSize = descriptor.size +
sizeof(chunk);
305 if (device->bytesAvailable() < qint64(rawChunkSize))
309 device->read(
reinterpret_cast<
char *>(&wave),
sizeof(WAVEHeader));
311 if (rawChunkSize >
sizeof(WAVEHeader))
312 discardBytes(rawChunkSize -
sizeof(WAVEHeader));
316 wave.audioFormat = qFromBigEndian<quint16>(wave.audioFormat);
318 wave.audioFormat = qFromLittleEndian<quint16>(wave.audioFormat);
321 if (wave.audioFormat != 0 && wave.audioFormat != 1) {
331 bps = qFromBigEndian<quint16>(wave.bitsPerSample);
332 rate = qFromBigEndian<quint32>(wave.sampleRate);
333 channels = qFromBigEndian<quint16>(wave.numChannels);
335 bps = qFromLittleEndian<quint16>(wave.bitsPerSample);
336 rate = qFromLittleEndian<quint32>(wave.sampleRate);
337 channels = qFromLittleEndian<quint16>(wave.numChannels);
340 QAudioFormat::SampleFormat fmt = QAudioFormat::Unknown;
343 fmt = QAudioFormat::UInt8;
346 fmt = QAudioFormat::Int16;
349 fmt = QAudioFormat::Int16;
352 fmt = QAudioFormat::Int32;
355 if (fmt == QAudioFormat::Unknown || rate == 0 || channels == 0) {
360 format.setSampleFormat(fmt);
361 format.setSampleRate(rate);
362 format.setChannelCount(channels);
364 state = QWaveDecoder::WaitingForDataState;
368 if (state == QWaveDecoder::WaitingForDataState) {
369 if (findChunk(
"data")) {
370 disconnect(device, &QIODevice::readyRead,
this, &QWaveDecoder::handleData);
373 device->read(
reinterpret_cast<
char *>(&descriptor),
sizeof(chunk));
375 descriptor.size = qFromBigEndian<quint32>(descriptor.size);
377 descriptor.size = qFromLittleEndian<quint32>(descriptor.size);
379 dataSize = descriptor.size;
381 dataSize = device->size() - headerLength();
384 connect(device, &QIODevice::readyRead,
this, &QIODevice::readyRead);
392 if (device->atEnd()) {
397bool QWaveDecoder::enoughDataAvailable()
400 if (!peekChunk(&descriptor,
false))
405 if (qstrncmp(descriptor.id,
"RIFX", 4) == 0)
406 descriptor.size = qFromBigEndian<quint32>(descriptor.size);
407 if (qstrncmp(descriptor.id,
"RIFF", 4) == 0)
408 descriptor.size = qFromLittleEndian<quint32>(descriptor.size);
410 if (device->bytesAvailable() < qint64(
sizeof(chunk)) + descriptor.size)
416bool QWaveDecoder::findChunk(
const char *chunkId)
421 if (!peekChunk(&descriptor))
424 if (qstrncmp(descriptor.id, chunkId, 4) == 0)
431 const quint32 sizeWithPad = descriptor.size + (descriptor.size & 1);
435 junkToSkip = qint64(
sizeof(chunk) + sizeWithPad);
439 discardBytes(junkToSkip);
446 }
while (device->bytesAvailable() > 0);
451bool QWaveDecoder::peekChunk(chunk *pChunk,
bool handleEndianness)
453 if (device->bytesAvailable() < qint64(
sizeof(chunk)))
456 if (!device->peek(
reinterpret_cast<
char *>(pChunk),
sizeof(chunk)))
459 if (handleEndianness) {
461 pChunk->size = qFromBigEndian<quint32>(pChunk->size);
463 pChunk->size = qFromLittleEndian<quint32>(pChunk->size);
468void QWaveDecoder::discardBytes(qint64 numBytes)
473 if (device->isSequential()) {
474 QByteArray r = device->read(qMin(numBytes, qint64(16384)));
475 if (r.size() < numBytes)
476 junkToSkip = numBytes - r.size();
480 quint64 origPos = device->pos();
481 device->seek(device->pos() + numBytes);
482 junkToSkip = origPos + numBytes - device->pos();
490#include "moc_qwavedecoder.cpp"