7#include <QtCore/qdebug.h>
8#include <QtCore/qendian.h>
9#include <QtCore/qsysinfo.h>
10#include <QtCore/qtimer.h>
11#include <QtCore/qbytearray.h>
19#if QT_DEPRECATED_SINCE(6
, 11
)
21namespace QtMultimediaPrivate {
23class QWaveDecoderOldLayout :
public QIODevice
25 enum State { InitialState, WaitingForFormatState, WaitingForDataState };
28 bool haveFormat =
false;
29 bool haveHeader =
false;
31 QIODevice *device =
nullptr;
33 State state = InitialState;
34 quint32 junkToSkip = 0;
35 bool bigEndian =
false;
36 bool byteSwap =
false;
40static_assert(
sizeof(QWaveDecoder) ==
sizeof(QtMultimediaPrivate::QWaveDecoderOldLayout),
41 "QWaveDecoder ABI size mismatch — adjust fields or QWaveDecoderNewFields");
45QWaveDecoder::QWaveDecoder(QIODevice *device, QObject *parent)
51QWaveDecoder::QWaveDecoder(QIODevice *device,
const QAudioFormat &format, QObject *parent)
58QWaveDecoder::~QWaveDecoder()
63bool QWaveDecoder::open(QIODevice::OpenMode mode)
66 if (mode & QIODevice::ReadOnly && mode & ~QIODevice::WriteOnly) {
67 canOpen = QIODevice::open(mode | QIODevice::Unbuffered);
69 m_headerBuf = std::make_unique<QByteArray>();
70 connect(device, &QIODevice::readyRead,
this, &QWaveDecoder::handleData);
72 if (device->bytesAvailable() > 0)
78 if (mode & QIODevice::WriteOnly) {
79 if (format.sampleFormat() != QAudioFormat::Int16)
81 canOpen = QIODevice::open(mode);
82 if (canOpen && writeHeader())
86 return QIODevice::open(mode);
89void QWaveDecoder::close()
91 if (isOpen() && (openMode() & QIODevice::WriteOnly)) {
92 Q_ASSERT(dataSize < INT_MAX);
93 if (!device->isOpen() || !writeDataLength())
94 qWarning() <<
"Failed to finalize wav file";
102bool QWaveDecoder::seek(qint64 pos)
104 return device->seek(pos);
107qint64 QWaveDecoder::pos()
const
109 return device->pos();
112void QWaveDecoder::setIODevice(QIODevice * )
116QAudioFormat QWaveDecoder::audioFormat()
const
121QIODevice* QWaveDecoder::getDevice()
126int QWaveDecoder::duration()
const
128 if (openMode() & QIODevice::WriteOnly)
130 int bytesPerSec = format.bytesPerFrame() * format.sampleRate();
131 return bytesPerSec ? size() * 1000 / bytesPerSec : 0;
134qint64 QWaveDecoder::size()
const
136 if (openMode() & QIODevice::ReadOnly) {
141 return device->size();
145bool QWaveDecoder::isSequential()
const
147 return device->isSequential();
150qint64 QWaveDecoder::bytesAvailable()
const
152 return haveFormat ? device->bytesAvailable() : 0;
155qint64 QWaveDecoder::headerLength()
160qint64 QWaveDecoder::readData(
char *data, qint64 maxlen)
162 const int bytesPerSample = format.bytesPerSample();
163 if (!haveFormat || bytesPerSample == 0)
167 maxlen = (maxlen / bytesPerSample) * bytesPerSample;
171 qint64 totalRead = 0;
176 if (m_headerBuf && !m_headerBuf->isEmpty()) {
177 qint64 fromBuf = qMin(maxlen, qint64(m_headerBuf->size()));
179 fromBuf = (fromBuf / bytesPerSample) * bytesPerSample;
181 memcpy(dst, m_headerBuf->constData(), size_t(fromBuf));
182 m_headerBuf->remove(0,
static_cast<qsizetype>(fromBuf));
183 totalRead += fromBuf;
187 if (m_headerBuf->isEmpty())
193 qint64 read = device->read(dst, maxlen);
199 if (m_byteSwap && format.bytesPerFrame() > 1 && totalRead > 0) {
200 qint64 nSamples = totalRead / bytesPerSample;
201 switch (bytesPerSample) {
202 case 2: qbswap<2>(data, qsizetype(nSamples), data);
break;
203 case 4: qbswap<4>(data, qsizetype(nSamples), data);
break;
204 default: Q_UNREACHABLE();
211qint64 QWaveDecoder::writeData(
const char *data, qint64 len)
215 qint64 written = device->write(data, len);
220bool QWaveDecoder::writeHeader()
222 if (device->size() != 0)
225#ifndef Q_LITTLE_ENDIAN
229 CombinedHeader header;
230 memset(&header, 0, HeaderLength);
232 memcpy(header.riff.descriptor.id,
"RIFF", 4);
233 qToLittleEndian<quint32>(quint32(dataSize + HeaderLength - 8),
234 reinterpret_cast<
unsigned char*>(&header.riff.descriptor.size));
235 memcpy(header.riff.type,
"WAVE", 4);
237 memcpy(header.wave.descriptor.id,
"fmt ", 4);
238 qToLittleEndian<quint32>(quint32(16),
239 reinterpret_cast<
unsigned char*>(&header.wave.descriptor.size));
240 qToLittleEndian<quint16>(quint16(1),
241 reinterpret_cast<
unsigned char*>(&header.wave.audioFormat));
242 qToLittleEndian<quint16>(quint16(format.channelCount()),
243 reinterpret_cast<
unsigned char*>(&header.wave.numChannels));
244 qToLittleEndian<quint32>(quint32(format.sampleRate()),
245 reinterpret_cast<
unsigned char*>(&header.wave.sampleRate));
246 qToLittleEndian<quint32>(quint32(format.sampleRate() * format.bytesPerFrame()),
247 reinterpret_cast<
unsigned char*>(&header.wave.byteRate));
248 qToLittleEndian<quint16>(quint16(format.channelCount() * format.bytesPerSample()),
249 reinterpret_cast<
unsigned char*>(&header.wave.blockAlign));
250 qToLittleEndian<quint16>(quint16(format.bytesPerSample() * 8),
251 reinterpret_cast<
unsigned char*>(&header.wave.bitsPerSample));
253 memcpy(header.data.descriptor.id,
"data", 4);
254 qToLittleEndian<quint32>(quint32(dataSize),
255 reinterpret_cast<
unsigned char*>(&header.data.descriptor.size));
257 return device->write(
reinterpret_cast<
const char *>(&header), HeaderLength);
260bool QWaveDecoder::writeDataLength()
262#ifndef Q_LITTLE_ENDIAN
268 if (!device->seek(4)) {
269 qDebug() <<
"can't seek";
273 quint32 length = quint32(dataSize + HeaderLength - 8);
274 if (device->write(
reinterpret_cast<
const char *>(&length), 4) != 4)
277 if (!device->seek(40))
280 return device->write(
reinterpret_cast<
const char *>(&dataSize), 4);
283void QWaveDecoder::parsingFailed()
288 disconnect(device, &QIODevice::readyRead,
this, &QWaveDecoder::handleData);
292void QWaveDecoder::handleData()
294 using namespace QtPrivate;
296 if (openMode() == QIODevice::WriteOnly)
301 disconnect(device, &QIODevice::readyRead,
this, &QWaveDecoder::handleData);
302 connect(device, &QIODevice::readyRead,
this, &QIODevice::readyRead);
310 QByteArray incoming = device->readAll();
311 if (!incoming.isEmpty())
312 m_headerBuf->append(incoming);
315 if (m_headerBuf->size() <
int(
sizeof(RIFFHeader)) +
int(
sizeof(chunk)))
320 if (!drwav_init_memory(&wav, m_headerBuf->constData(), size_t(m_headerBuf->size()),
nullptr)) {
329 drwav_uint16 audioFormat = drwav_fmt_get_format(&wav.fmt);
331 if (audioFormat != 0 && audioFormat != 1) {
338 int bitsPerSample = wav.bitsPerSample;
339 int sampleRate =
int(wav.sampleRate);
340 int channels =
int(wav.channels);
343 QAudioFormat::SampleFormat fmt = QAudioFormat::Unknown;
344 switch (bitsPerSample) {
345 case 8: fmt = QAudioFormat::UInt8;
break;
346 case 16: fmt = QAudioFormat::Int16;
break;
350 if (fmt == QAudioFormat::Unknown || sampleRate == 0 || channels == 0) {
357 bool bigEndian = (wav.container == drwav_container_rifx);
358 m_byteSwap = (bigEndian != (QSysInfo::ByteOrder == QSysInfo::BigEndian));
360 qint64 dataChunkDataPos = qint64(wav.dataChunkDataPos);
361 dataSize = qint64(wav.dataChunkDataSize);
366 if (!device->isSequential()) {
367 if (!device->seek(dataChunkDataPos)) {
378 if (dataChunkDataPos < m_headerBuf->size()) {
379 *m_headerBuf = m_headerBuf->mid(qsizetype(dataChunkDataPos));
381 m_headerBuf->clear();
385 format.setSampleFormat(fmt);
386 format.setSampleRate(sampleRate);
387 format.setChannelCount(channels);
390 dataSize = device->size() - dataChunkDataPos;
393 disconnect(device, &QIODevice::readyRead,
this, &QWaveDecoder::handleData);
394 connect(device, &QIODevice::readyRead,
this, &QIODevice::readyRead);
402#include "moc_qwavedecoder.cpp"