6#include <QtCore/qtimer.h>
7#include <QtCore/qendian.h>
56 if (canOpen && enoughDataAvailable())
67 if (canOpen && writeHeader())
78 if (!device->
isOpen() || !writeDataLength())
79 qWarning() <<
"Failed to finalize wav file";
108 int bytesPerSec =
format.bytesPerFrame() *
format.sampleRate();
109 return bytesPerSec ?
size() * 1000 / bytesPerSec : 0;
121 return device->
size();
142 const int bytesPerSample =
format.bytesPerSample();
143 if (!haveFormat || bytesPerSample == 0)
149 while (l < maxlen - 1) {
151 device->
read(tmp, 3);
153 qSwap(tmp[0], tmp[2]);
154#if Q_BYTE_ORDER == Q_BIG_ENDIAN
167 qint64 nSamples = maxlen / bytesPerSample;
168 maxlen = nSamples * bytesPerSample;
171 if (!byteSwap ||
format.bytesPerFrame() == 1)
174 nSamples =
read / bytesPerSample;
175 switch (bytesPerSample) {
177 bswap2(
data, nSamples);
180 bswap4(
data, nSamples);
198bool QWaveDecoder::writeHeader()
200 if (device->
size() != 0)
203#ifndef Q_LITTLE_ENDIAN
210 memset(&
header, 0, HeaderLength);
213 memcpy(
header.riff.descriptor.id,
"RIFF",4);
215 reinterpret_cast<unsigned char*
>(&
header.riff.descriptor.
size));
216 memcpy(
header.riff.type,
"WAVE",4);
219 memcpy(
header.wave.descriptor.id,
"fmt ",4);
220 qToLittleEndian<quint32>(
quint32(16),
221 reinterpret_cast<unsigned char*
>(&
header.wave.descriptor.
size));
222 qToLittleEndian<quint16>(
quint16(1),
223 reinterpret_cast<unsigned char*
>(&
header.wave.audioFormat));
225 reinterpret_cast<unsigned char*
>(&
header.wave.numChannels));
227 reinterpret_cast<unsigned char*
>(&
header.wave.sampleRate));
229 reinterpret_cast<unsigned char*
>(&
header.wave.byteRate));
231 reinterpret_cast<unsigned char*
>(&
header.wave.blockAlign));
232 qToLittleEndian<quint16>(
quint16(
format.bytesPerSample() * 8),
233 reinterpret_cast<unsigned char*
>(&
header.wave.bitsPerSample));
238 reinterpret_cast<unsigned char*
>(&
header.
data.descriptor.size));
240 return device->
write(
reinterpret_cast<const char *
>(&
header), HeaderLength);
243bool QWaveDecoder::writeDataLength()
245#ifndef Q_LITTLE_ENDIAN
254 if (!device->
seek(4)) {
260 if (device->
write(
reinterpret_cast<const char *
>(&
length), 4) != 4)
264 if (!device->
seek(40))
267 return device->
write(
reinterpret_cast<const char *
>(&
dataSize), 4);
270void QWaveDecoder::parsingFailed()
277void QWaveDecoder::handleData()
283 if (junkToSkip > 0) {
284 discardBytes(junkToSkip);
287 if (junkToSkip > 0) {
295 if (state == QWaveDecoder::InitialState) {
300 device->
read(
reinterpret_cast<char *
>(&riff),
sizeof(RIFFHeader));
303 if (((
qstrncmp(riff.descriptor.id,
"RIFF", 4) != 0) && (
qstrncmp(riff.descriptor.id,
"RIFX", 4) != 0))
304 ||
qstrncmp(riff.type,
"WAVE", 4) != 0) {
309 state = QWaveDecoder::WaitingForFormatState;
310 bigEndian = (
qstrncmp(riff.descriptor.id,
"RIFX", 4) == 0);
314 if (state == QWaveDecoder::WaitingForFormatState) {
315 if (findChunk(
"fmt ")) {
317 peekChunk(&descriptor);
319 quint32 rawChunkSize = descriptor.size +
sizeof(chunk);
324 device->
read(
reinterpret_cast<char *
>(&wave),
sizeof(WAVEHeader));
326 if (rawChunkSize >
sizeof(WAVEHeader))
327 discardBytes(rawChunkSize -
sizeof(WAVEHeader));
331 wave.audioFormat = qFromBigEndian<quint16>(wave.audioFormat);
333 wave.audioFormat = qFromLittleEndian<quint16>(wave.audioFormat);
336 if (wave.audioFormat != 0 && wave.audioFormat != 1) {
346 bps = qFromBigEndian<quint16>(wave.bitsPerSample);
347 rate = qFromBigEndian<quint32>(wave.sampleRate);
348 channels = qFromBigEndian<quint16>(wave.numChannels);
350 bps = qFromLittleEndian<quint16>(wave.bitsPerSample);
351 rate = qFromLittleEndian<quint32>(wave.sampleRate);
352 channels = qFromLittleEndian<quint16>(wave.numChannels);
376 format.setSampleRate((wave.sampleRate));
377 format.setChannelCount((wave.numChannels));
379 state = QWaveDecoder::WaitingForDataState;
383 if (state == QWaveDecoder::WaitingForDataState) {
384 if (findChunk(
"data")) {
388 device->
read(
reinterpret_cast<char *
>(&descriptor),
sizeof(chunk));
390 descriptor.size = qFromBigEndian<quint32>(descriptor.size);
392 descriptor.size = qFromLittleEndian<quint32>(descriptor.size);
407 if (device->
atEnd()) {
412bool QWaveDecoder::enoughDataAvailable()
415 if (!peekChunk(&descriptor,
false))
420 if (
qstrncmp(descriptor.id,
"RIFX", 4) == 0)
421 descriptor.size = qFromBigEndian<quint32>(descriptor.size);
422 if (
qstrncmp(descriptor.id,
"RIFF", 4) == 0)
423 descriptor.size = qFromLittleEndian<quint32>(descriptor.size);
431bool QWaveDecoder::findChunk(
const char *chunkId)
436 if (!peekChunk(&descriptor))
439 if (
qstrncmp(descriptor.id, chunkId, 4) == 0)
444 junkToSkip =
qint64(
sizeof(chunk) + descriptor.size);
448 discardBytes(junkToSkip);
460bool QWaveDecoder::peekChunk(chunk *pChunk,
bool handleEndianness)
465 if (!device->
peek(
reinterpret_cast<char *
>(pChunk),
sizeof(chunk)))
468 if (handleEndianness) {
470 pChunk->size = qFromBigEndian<quint32>(pChunk->size);
472 pChunk->size = qFromLittleEndian<quint32>(pChunk->size);
477void QWaveDecoder::discardBytes(
qint64 numBytes)
484 if (
r.size() < numBytes)
485 junkToSkip = numBytes -
r.size();
490 device->
seek(device->
pos() + numBytes);
491 junkToSkip = origPos + numBytes - device->
pos();
497#include "moc_qwavedecoder.cpp"
IOBluetoothDevice * device
\inmodule QtCore \reentrant
virtual bool open(QIODeviceBase::OpenMode mode)
Opens the device and sets its OpenMode to mode.
void readyRead()
This signal is emitted once every time new data is available for reading from the device's current re...
virtual qint64 size() const
For open random-access devices, this function returns the size of the device.
virtual qint64 pos() const
For random-access devices, this function returns the position that data is written to or read from.
virtual bool isSequential() const
Returns true if this device is sequential; otherwise returns false.
bool isOpen() const
Returns true if the device is open; otherwise returns false.
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
QIODeviceBase::OpenMode openMode() const
Returns the mode in which the device has been opened; i.e.
qint64 peek(char *data, qint64 maxlen)
virtual qint64 bytesAvailable() const
Returns the number of bytes that are available for reading.
virtual void close()
First emits aboutToClose(), then closes the device and sets its OpenMode to NotOpen.
virtual bool seek(qint64 pos)
For random-access devices, this function sets the current position to pos, returning true on success,...
virtual bool atEnd() const
Returns true if the current read and write position is at the end of the device (i....
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
qsizetype size() const
Returns the number of characters in this string.
QChar * data()
Returns a pointer to the data stored in the QString.
qint64 bytesAvailable() const override
Returns the number of bytes that are available for reading.
static qint64 headerLength()
qint64 readData(char *data, qint64 maxlen) override
Reads up to maxSize bytes from the device into data, and returns the number of bytes read or -1 if an...
qint64 size() const override
For open random-access devices, this function returns the size of the device.
qint64 pos() const override
For random-access devices, this function returns the position that data is written to or read from.
qint64 writeData(const char *data, qint64 len) override
Writes up to maxSize bytes from data to the device.
QAudioFormat audioFormat() const
bool seek(qint64 pos) override
For random-access devices, this function sets the current position to pos, returning true on success,...
bool open(QIODevice::OpenMode mode) override
bool isSequential() const override
Returns true if this device is sequential; otherwise returns false.
void close() override
First emits aboutToClose(), then closes the device and sets its OpenMode to NotOpen.
QWaveDecoder(QIODevice *device, QObject *parent=nullptr)
Combined button and popup list for selecting options.
void bswap4(char *data, qsizetype count) noexcept
void bswap2(char *data, qsizetype count) noexcept
int qstrncmp(const char *str1, const char *str2, size_t len)
static QString header(const QString &name)
constexpr const T & qMin(const T &a, const T &b)
GLenum GLuint GLenum GLsizei length
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint GLsizei GLsizei GLenum format
unsigned long long quint64
QVideoFrameFormat::PixelFormat fmt
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent