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";
112 int bytesPerSec =
format.bytesPerFrame() *
format.sampleRate();
113 return bytesPerSec ?
size() * 1000 / bytesPerSec : 0;
125 return device->
size();
146 const int bytesPerSample =
format.bytesPerSample();
147 if (!haveFormat || bytesPerSample == 0)
153 while (l < maxlen - 1) {
155 device->
read(tmp, 3);
157 qSwap(tmp[0], tmp[2]);
158#if Q_BYTE_ORDER == Q_BIG_ENDIAN
171 qint64 nSamples = maxlen / bytesPerSample;
172 maxlen = nSamples * bytesPerSample;
175 if (!byteSwap ||
format.bytesPerFrame() == 1)
178 nSamples =
read / bytesPerSample;
179 switch (bytesPerSample) {
181 bswap2(
data, nSamples);
184 bswap4(
data, nSamples);
202bool QWaveDecoder::writeHeader()
204 if (device->
size() != 0)
207#ifndef Q_LITTLE_ENDIAN
214 memset(&
header, 0, HeaderLength);
217 memcpy(
header.riff.descriptor.id,
"RIFF",4);
219 reinterpret_cast<unsigned char*
>(&
header.riff.descriptor.size));
220 memcpy(
header.riff.type,
"WAVE",4);
223 memcpy(
header.wave.descriptor.id,
"fmt ",4);
224 qToLittleEndian<quint32>(
quint32(16),
225 reinterpret_cast<unsigned char*
>(&
header.wave.descriptor.size));
226 qToLittleEndian<quint16>(
quint16(1),
227 reinterpret_cast<unsigned char*
>(&
header.wave.audioFormat));
229 reinterpret_cast<unsigned char*
>(&
header.wave.numChannels));
231 reinterpret_cast<unsigned char*
>(&
header.wave.sampleRate));
233 reinterpret_cast<unsigned char*
>(&
header.wave.byteRate));
235 reinterpret_cast<unsigned char*
>(&
header.wave.blockAlign));
236 qToLittleEndian<quint16>(
quint16(
format.bytesPerSample() * 8),
237 reinterpret_cast<unsigned char*
>(&
header.wave.bitsPerSample));
240 memcpy(
header.data.descriptor.id,
"data",4);
242 reinterpret_cast<unsigned char*
>(&
header.data.descriptor.size));
244 return device->
write(
reinterpret_cast<const char *
>(&
header), HeaderLength);
247bool QWaveDecoder::writeDataLength()
249#ifndef Q_LITTLE_ENDIAN
258 if (!device->
seek(4)) {
264 if (device->
write(
reinterpret_cast<const char *
>(&
length), 4) != 4)
268 if (!device->
seek(40))
271 return device->
write(
reinterpret_cast<const char *
>(&
dataSize), 4);
274void QWaveDecoder::parsingFailed()
281void QWaveDecoder::handleData()
287 if (junkToSkip > 0) {
288 discardBytes(junkToSkip);
291 if (junkToSkip > 0) {
299 if (state == QWaveDecoder::InitialState) {
304 device->
read(
reinterpret_cast<char *
>(&riff),
sizeof(RIFFHeader));
307 if (((
qstrncmp(riff.descriptor.id,
"RIFF", 4) != 0) && (
qstrncmp(riff.descriptor.id,
"RIFX", 4) != 0))
308 ||
qstrncmp(riff.type,
"WAVE", 4) != 0) {
313 state = QWaveDecoder::WaitingForFormatState;
314 bigEndian = (
qstrncmp(riff.descriptor.id,
"RIFX", 4) == 0);
318 if (state == QWaveDecoder::WaitingForFormatState) {
319 if (findChunk(
"fmt ")) {
321 peekChunk(&descriptor);
323 quint32 rawChunkSize = descriptor.size +
sizeof(chunk);
328 device->
read(
reinterpret_cast<char *
>(&wave),
sizeof(WAVEHeader));
330 if (rawChunkSize >
sizeof(WAVEHeader))
331 discardBytes(rawChunkSize -
sizeof(WAVEHeader));
335 wave.audioFormat = qFromBigEndian<quint16>(wave.audioFormat);
337 wave.audioFormat = qFromLittleEndian<quint16>(wave.audioFormat);
340 if (wave.audioFormat != 0 && wave.audioFormat != 1) {
350 bps = qFromBigEndian<quint16>(wave.bitsPerSample);
351 rate = qFromBigEndian<quint32>(wave.sampleRate);
352 channels = qFromBigEndian<quint16>(wave.numChannels);
354 bps = qFromLittleEndian<quint16>(wave.bitsPerSample);
355 rate = qFromLittleEndian<quint32>(wave.sampleRate);
356 channels = qFromLittleEndian<quint16>(wave.numChannels);
381 format.setChannelCount(channels);
383 state = QWaveDecoder::WaitingForDataState;
387 if (state == QWaveDecoder::WaitingForDataState) {
388 if (findChunk(
"data")) {
392 device->
read(
reinterpret_cast<char *
>(&descriptor),
sizeof(chunk));
394 descriptor.size = qFromBigEndian<quint32>(descriptor.size);
396 descriptor.size = qFromLittleEndian<quint32>(descriptor.size);
411 if (device->
atEnd()) {
416bool QWaveDecoder::enoughDataAvailable()
419 if (!peekChunk(&descriptor,
false))
424 if (
qstrncmp(descriptor.id,
"RIFX", 4) == 0)
425 descriptor.size = qFromBigEndian<quint32>(descriptor.size);
426 if (
qstrncmp(descriptor.id,
"RIFF", 4) == 0)
427 descriptor.size = qFromLittleEndian<quint32>(descriptor.size);
435bool QWaveDecoder::findChunk(
const char *chunkId)
440 if (!peekChunk(&descriptor))
443 if (
qstrncmp(descriptor.id, chunkId, 4) == 0)
450 const quint32 sizeWithPad = descriptor.size + (descriptor.size & 1);
454 junkToSkip =
qint64(
sizeof(chunk) + sizeWithPad);
458 discardBytes(junkToSkip);
470bool QWaveDecoder::peekChunk(chunk *pChunk,
bool handleEndianness)
475 if (!device->
peek(
reinterpret_cast<char *
>(pChunk),
sizeof(chunk)))
478 if (handleEndianness) {
480 pChunk->size = qFromBigEndian<quint32>(pChunk->size);
482 pChunk->size = qFromLittleEndian<quint32>(pChunk->size);
487void QWaveDecoder::discardBytes(
qint64 numBytes)
494 if (
r.size() < numBytes)
495 junkToSkip = numBytes -
r.size();
500 device->
seek(device->
pos() + numBytes);
501 junkToSkip = origPos + numBytes - device->
pos();
507#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
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
void setIODevice(QIODevice *device)
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
QT_BEGIN_NAMESPACE constexpr void qSwap(T &value1, T &value2) noexcept(std::is_nothrow_swappable_v< T >)
unsigned long long quint64
QVideoFrameFormat::PixelFormat fmt
myObject disconnect()
[26]