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
)
21QWaveDecoder::QWaveDecoder(QIODevice *device, QObject *parent)
27QWaveDecoder::QWaveDecoder(QIODevice *device,
const QAudioFormat &format, QObject *parent)
34QWaveDecoder::~QWaveDecoder()
39bool QWaveDecoder::open(QIODevice::OpenMode mode)
42 if (mode & QIODevice::ReadOnly && mode & ~QIODevice::WriteOnly) {
43 canOpen = QIODevice::open(mode | QIODevice::Unbuffered);
45 m_headerBuf = std::make_unique<QByteArray>();
46 connect(device, &QIODevice::readyRead,
this, &QWaveDecoder::handleData);
48 if (device->bytesAvailable() > 0)
54 if (mode & QIODevice::WriteOnly) {
55 if (format.sampleFormat() != QAudioFormat::Int16)
57 canOpen = QIODevice::open(mode);
58 if (canOpen && writeHeader())
62 return QIODevice::open(mode);
65void QWaveDecoder::close()
67 if (isOpen() && (openMode() & QIODevice::WriteOnly)) {
68 Q_ASSERT(dataSize < INT_MAX);
69 if (!device->isOpen() || !writeDataLength())
70 qWarning() <<
"Failed to finalize wav file";
78bool QWaveDecoder::seek(qint64 pos)
80 return device->seek(pos);
83qint64 QWaveDecoder::pos()
const
88void QWaveDecoder::setIODevice(QIODevice * )
92QAudioFormat QWaveDecoder::audioFormat()
const
97QIODevice* QWaveDecoder::getDevice()
102int QWaveDecoder::duration()
const
104 if (openMode() & QIODevice::WriteOnly)
106 int bytesPerSec = format.bytesPerFrame() * format.sampleRate();
107 return bytesPerSec ? size() * 1000 / bytesPerSec : 0;
110qint64 QWaveDecoder::size()
const
112 if (openMode() & QIODevice::ReadOnly) {
117 return device->size();
121bool QWaveDecoder::isSequential()
const
123 return device->isSequential();
126qint64 QWaveDecoder::bytesAvailable()
const
128 return haveFormat ? device->bytesAvailable() : 0;
131qint64 QWaveDecoder::headerLength()
136qint64 QWaveDecoder::readData(
char *data, qint64 maxlen)
138 const int bytesPerSample = format.bytesPerSample();
139 if (!haveFormat || bytesPerSample == 0)
143 maxlen = (maxlen / bytesPerSample) * bytesPerSample;
147 qint64 totalRead = 0;
152 if (m_headerBuf && !m_headerBuf->isEmpty()) {
153 qint64 fromBuf = qMin(maxlen, qint64(m_headerBuf->size()));
155 fromBuf = (fromBuf / bytesPerSample) * bytesPerSample;
157 memcpy(dst, m_headerBuf->constData(), size_t(fromBuf));
158 m_headerBuf->remove(0,
static_cast<qsizetype>(fromBuf));
159 totalRead += fromBuf;
163 if (m_headerBuf->isEmpty())
169 qint64 read = device->read(dst, maxlen);
175 if (m_byteSwap && format.bytesPerFrame() > 1 && totalRead > 0) {
176 qint64 nSamples = totalRead / bytesPerSample;
177 switch (bytesPerSample) {
178 case 2: qbswap<2>(data, qsizetype(nSamples), data);
break;
179 case 4: qbswap<4>(data, qsizetype(nSamples), data);
break;
180 default: Q_UNREACHABLE();
187qint64 QWaveDecoder::writeData(
const char *data, qint64 len)
191 qint64 written = device->write(data, len);
196bool QWaveDecoder::writeHeader()
198 if (device->size() != 0)
201#ifndef Q_LITTLE_ENDIAN
205 CombinedHeader header;
206 memset(&header, 0, HeaderLength);
208 memcpy(header.riff.descriptor.id,
"RIFF", 4);
209 qToLittleEndian<quint32>(quint32(dataSize + HeaderLength - 8),
210 reinterpret_cast<
unsigned char*>(&header.riff.descriptor.size));
211 memcpy(header.riff.type,
"WAVE", 4);
213 memcpy(header.wave.descriptor.id,
"fmt ", 4);
214 qToLittleEndian<quint32>(quint32(16),
215 reinterpret_cast<
unsigned char*>(&header.wave.descriptor.size));
216 qToLittleEndian<quint16>(quint16(1),
217 reinterpret_cast<
unsigned char*>(&header.wave.audioFormat));
218 qToLittleEndian<quint16>(quint16(format.channelCount()),
219 reinterpret_cast<
unsigned char*>(&header.wave.numChannels));
220 qToLittleEndian<quint32>(quint32(format.sampleRate()),
221 reinterpret_cast<
unsigned char*>(&header.wave.sampleRate));
222 qToLittleEndian<quint32>(quint32(format.sampleRate() * format.bytesPerFrame()),
223 reinterpret_cast<
unsigned char*>(&header.wave.byteRate));
224 qToLittleEndian<quint16>(quint16(format.channelCount() * format.bytesPerSample()),
225 reinterpret_cast<
unsigned char*>(&header.wave.blockAlign));
226 qToLittleEndian<quint16>(quint16(format.bytesPerSample() * 8),
227 reinterpret_cast<
unsigned char*>(&header.wave.bitsPerSample));
229 memcpy(header.data.descriptor.id,
"data", 4);
230 qToLittleEndian<quint32>(quint32(dataSize),
231 reinterpret_cast<
unsigned char*>(&header.data.descriptor.size));
233 return device->write(
reinterpret_cast<
const char *>(&header), HeaderLength);
236bool QWaveDecoder::writeDataLength()
238#ifndef Q_LITTLE_ENDIAN
244 if (!device->seek(4)) {
245 qDebug() <<
"can't seek";
249 quint32 length = quint32(dataSize + HeaderLength - 8);
250 if (device->write(
reinterpret_cast<
const char *>(&length), 4) != 4)
253 if (!device->seek(40))
256 return device->write(
reinterpret_cast<
const char *>(&dataSize), 4);
259void QWaveDecoder::parsingFailed()
264 disconnect(device, &QIODevice::readyRead,
this, &QWaveDecoder::handleData);
268void QWaveDecoder::handleData()
270 using namespace QtPrivate;
272 if (openMode() == QIODevice::WriteOnly)
277 disconnect(device, &QIODevice::readyRead,
this, &QWaveDecoder::handleData);
278 connect(device, &QIODevice::readyRead,
this, &QIODevice::readyRead);
286 QByteArray incoming = device->readAll();
287 if (!incoming.isEmpty())
288 m_headerBuf->append(incoming);
291 if (m_headerBuf->size() <
int(
sizeof(RIFFHeader)) +
int(
sizeof(chunk)))
296 if (!drwav_init_memory(&wav, m_headerBuf->constData(), size_t(m_headerBuf->size()),
nullptr)) {
305 drwav_uint16 audioFormat = drwav_fmt_get_format(&wav.fmt);
307 if (audioFormat != 0 && audioFormat != 1) {
314 int bitsPerSample = wav.bitsPerSample;
315 int sampleRate =
int(wav.sampleRate);
316 int channels =
int(wav.channels);
319 QAudioFormat::SampleFormat fmt = QAudioFormat::Unknown;
320 switch (bitsPerSample) {
321 case 8: fmt = QAudioFormat::UInt8;
break;
322 case 16: fmt = QAudioFormat::Int16;
break;
326 if (fmt == QAudioFormat::Unknown || sampleRate == 0 || channels == 0) {
333 bool bigEndian = (wav.container == drwav_container_rifx);
334 m_byteSwap = (bigEndian != (QSysInfo::ByteOrder == QSysInfo::BigEndian));
336 qint64 dataChunkDataPos = qint64(wav.dataChunkDataPos);
337 dataSize = qint64(wav.dataChunkDataSize);
342 if (!device->isSequential()) {
343 if (!device->seek(dataChunkDataPos)) {
354 if (dataChunkDataPos < m_headerBuf->size()) {
355 *m_headerBuf = m_headerBuf->mid(qsizetype(dataChunkDataPos));
357 m_headerBuf->clear();
361 format.setSampleFormat(fmt);
362 format.setSampleRate(sampleRate);
363 format.setChannelCount(channels);
366 dataSize = device->size() - dataChunkDataPos;
369 disconnect(device, &QIODevice::readyRead,
this, &QWaveDecoder::handleData);
370 connect(device, &QIODevice::readyRead,
this, &QIODevice::readyRead);
378#include "moc_qwavedecoder.cpp"