void tst_QWaveDecoder::readAllAtOnce() { QFile stream; stream.setFileName(testFilePath("isawav_2_8_44100.wav")); stream.open(QIODevice::ReadOnly); QVERIFY(stream.isOpen()); QWaveDecoder waveDecoder(&stream); QSignalSpy validFormatSpy(&waveDecoder, SIGNAL(formatKnown())); QTRY_COMPARE(validFormatSpy.count(), 1); QVERIFY(waveDecoder.size() > 0); QByteArray buffer; buffer.resize(waveDecoder.size()); qint64 readSize = waveDecoder.read(buffer.data(), waveDecoder.size()); QVERIFY(readSize == waveDecoder.size()); readSize = waveDecoder.read(buffer.data(), 1); QVERIFY(readSize == 0); stream.close(); }
void QSoundEffectPrivate::loadSample() { m_sampleLoaded = false; m_dataUploaded = 0; m_waveDecoder = new WaveDecoder(m_stream); connect(m_waveDecoder, SIGNAL(formatKnown()), SLOT(decoderReady())); connect(m_waveDecoder, SIGNAL(invalidFormat()), SLOT(decoderError())); }
void tst_QWaveDecoder::file() { QFETCH(QString, file); QFETCH(tst_QWaveDecoder::Corruption, corruption); QFETCH(int, channels); QFETCH(int, samplesize); QFETCH(int, samplerate); QFETCH(QAudioFormat::Endian, byteorder); QFile stream; stream.setFileName(file); stream.open(QIODevice::ReadOnly); QVERIFY(stream.isOpen()); QWaveDecoder waveDecoder(&stream); QSignalSpy validFormatSpy(&waveDecoder, SIGNAL(formatKnown())); QSignalSpy parsingErrorSpy(&waveDecoder, SIGNAL(parsingError())); if (corruption == NotAWav) { QSKIP("Not all failures detected correctly yet"); QTRY_COMPARE(parsingErrorSpy.count(), 1); QCOMPARE(validFormatSpy.count(), 0); } else if (corruption == NoSampleData) { QTRY_COMPARE(validFormatSpy.count(), 1); QCOMPARE(parsingErrorSpy.count(), 0); QVERIFY(waveDecoder.audioFormat().isValid()); QVERIFY(waveDecoder.size() == 0); QVERIFY(waveDecoder.duration() == 0); } else if (corruption == FormatDescriptor) { QTRY_COMPARE(parsingErrorSpy.count(), 1); QCOMPARE(validFormatSpy.count(), 0); } else if (corruption == FormatString) { QTRY_COMPARE(parsingErrorSpy.count(), 1); QCOMPARE(validFormatSpy.count(), 0); QVERIFY(!waveDecoder.audioFormat().isValid()); } else if (corruption == DataDescriptor) { QTRY_COMPARE(parsingErrorSpy.count(), 1); QCOMPARE(validFormatSpy.count(), 0); QVERIFY(waveDecoder.size() == 0); } else if (corruption == None) { QTRY_COMPARE(validFormatSpy.count(), 1); QCOMPARE(parsingErrorSpy.count(), 0); QVERIFY(waveDecoder.audioFormat().isValid()); QVERIFY(waveDecoder.size() > 0); QVERIFY(waveDecoder.duration() == 250); QAudioFormat format = waveDecoder.audioFormat(); QVERIFY(format.isValid()); QVERIFY(format.channelCount() == channels); QVERIFY(format.sampleSize() == samplesize); QVERIFY(format.sampleRate() == samplerate); if (format.sampleSize() != 8) { QVERIFY(format.byteOrder() == byteorder); } } stream.close(); }
// Called in loading thread // Essentially a second ctor, doesn't need locks (?) void QSample::load() { Q_ASSERT(QThread::currentThread()->objectName() == "QSampleCache::LoadingThread"); #ifdef QT_SAMPLECACHE_DEBUG qDebug() << "QSample: load [" << m_url << "]"; #endif m_stream = m_parent->networkAccessManager().get(QNetworkRequest(m_url)); connect(m_stream, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(decoderError())); m_waveDecoder = new QWaveDecoder(m_stream); connect(m_waveDecoder, SIGNAL(formatKnown()), SLOT(decoderReady())); connect(m_waveDecoder, SIGNAL(invalidFormat()), SLOT(decoderError())); connect(m_waveDecoder, SIGNAL(readyRead()), SLOT(readSample())); }
void WaveDecoder::handleData() { if (source->bytesAvailable() < qint64(sizeof(CombinedHeader) + sizeof(DATAHeader) + sizeof(quint16))) return; source->disconnect(SIGNAL(readyRead()), this, SLOT(handleData())); source->read((char*)&header, sizeof(CombinedHeader)); if (qstrncmp(header.riff.descriptor.id, "RIFF", 4) != 0 || qstrncmp(header.riff.type, "WAVE", 4) != 0 || qstrncmp(header.wave.descriptor.id, "fmt ", 4) != 0 || (header.wave.audioFormat != 0 && header.wave.audioFormat != 1)) { emit invalidFormat(); } else { DATAHeader dataHeader; if (qFromLittleEndian<quint32>(header.wave.descriptor.size) > sizeof(WAVEHeader)) { // Extended data available quint16 extraFormatBytes; source->peek((char*)&extraFormatBytes, sizeof(quint16)); extraFormatBytes = qFromLittleEndian<quint16>(extraFormatBytes); source->read(sizeof(quint16) + extraFormatBytes); // dump it all } source->read((char*)&dataHeader, sizeof(DATAHeader)); int bps = qFromLittleEndian<quint16>(header.wave.bitsPerSample); format.setCodec(QLatin1String("audio/pcm")); format.setSampleType(bps == 8 ? QAudioFormat::UnSignedInt : QAudioFormat::SignedInt); format.setByteOrder(QAudioFormat::LittleEndian); format.setFrequency(qFromLittleEndian<quint32>(header.wave.sampleRate)); format.setSampleSize(bps); format.setChannels(qFromLittleEndian<quint16>(header.wave.numChannels)); dataSize = qFromLittleEndian<quint32>(dataHeader.descriptor.size); haveFormat = true; connect(source, SIGNAL(readyRead()), SIGNAL(readyRead())); emit formatKnown(); } }
void tst_QWaveDecoder::readPerByte() { QFile stream; stream.setFileName(testFilePath("isawav_2_8_44100.wav")); stream.open(QIODevice::ReadOnly); QVERIFY(stream.isOpen()); QWaveDecoder waveDecoder(&stream); QSignalSpy validFormatSpy(&waveDecoder, SIGNAL(formatKnown())); QTRY_COMPARE(validFormatSpy.count(), 1); QVERIFY(waveDecoder.size() > 0); qint64 readSize = 0; char buf; for (int ii = 0; ii < waveDecoder.size(); ++ii) readSize += waveDecoder.read(&buf, 1); QVERIFY(readSize == waveDecoder.size()); QVERIFY(waveDecoder.read(&buf,1) == 0); stream.close(); }
void QWaveDecoder::handleData() { // As a special "state", if we have junk to skip, we do if (junkToSkip > 0) { discardBytes(junkToSkip); // this also updates junkToSkip // If we couldn't skip all the junk, return if (junkToSkip > 0) { // We might have run out if (source->atEnd()) parsingFailed(); return; } } if (state == QWaveDecoder::InitialState) { if (source->bytesAvailable() < qint64(sizeof(RIFFHeader))) return; RIFFHeader riff; source->read(reinterpret_cast<char *>(&riff), sizeof(RIFFHeader)); // RIFF = little endian RIFF, RIFX = big endian RIFF if (((qstrncmp(riff.descriptor.id, "RIFF", 4) != 0) && (qstrncmp(riff.descriptor.id, "RIFX", 4) != 0)) || qstrncmp(riff.type, "WAVE", 4) != 0) { parsingFailed(); return; } else { state = QWaveDecoder::WaitingForFormatState; if (qstrncmp(riff.descriptor.id, "RIFX", 4) == 0) bigEndian = true; else bigEndian = false; } } if (state == QWaveDecoder::WaitingForFormatState) { if (findChunk("fmt ")) { chunk descriptor; peekChunk(&descriptor); quint32 rawChunkSize = descriptor.size + sizeof(chunk); if (source->bytesAvailable() < qint64(rawChunkSize)) return; WAVEHeader wave; source->read(reinterpret_cast<char *>(&wave), sizeof(WAVEHeader)); if (rawChunkSize > sizeof(WAVEHeader)) discardBytes(rawChunkSize - sizeof(WAVEHeader)); // Swizzle this if (bigEndian) { wave.audioFormat = qFromBigEndian<quint16>(wave.audioFormat); } else { wave.audioFormat = qFromLittleEndian<quint16>(wave.audioFormat); } if (wave.audioFormat != 0 && wave.audioFormat != 1) { // 32bit wave files have format == 0xFFFE (WAVE_FORMAT_EXTENSIBLE). // but don't support them at the moment. parsingFailed(); return; } else { format.setCodec(QLatin1String("audio/pcm")); if (bigEndian) { int bps = qFromBigEndian<quint16>(wave.bitsPerSample); format.setSampleType(bps == 8 ? QAudioFormat::UnSignedInt : QAudioFormat::SignedInt); format.setByteOrder(QAudioFormat::BigEndian); format.setSampleRate(qFromBigEndian<quint32>(wave.sampleRate)); format.setSampleSize(bps); format.setChannelCount(qFromBigEndian<quint16>(wave.numChannels)); } else { int bps = qFromLittleEndian<quint16>(wave.bitsPerSample); format.setSampleType(bps == 8 ? QAudioFormat::UnSignedInt : QAudioFormat::SignedInt); format.setByteOrder(QAudioFormat::LittleEndian); format.setSampleRate(qFromLittleEndian<quint32>(wave.sampleRate)); format.setSampleSize(bps); format.setChannelCount(qFromLittleEndian<quint16>(wave.numChannels)); } state = QWaveDecoder::WaitingForDataState; } } } if (state == QWaveDecoder::WaitingForDataState) { if (findChunk("data")) { source->disconnect(SIGNAL(readyRead()), this, SLOT(handleData())); chunk descriptor; source->read(reinterpret_cast<char *>(&descriptor), sizeof(chunk)); if (bigEndian) descriptor.size = qFromBigEndian<quint32>(descriptor.size); else descriptor.size = qFromLittleEndian<quint32>(descriptor.size); dataSize = descriptor.size; haveFormat = true; connect(source, SIGNAL(readyRead()), SIGNAL(readyRead())); emit formatKnown(); return; } } // If we hit the end without finding data, it's a parsing error if (source->atEnd()) { parsingFailed(); } }
void QWaveDecoder::handleData() { if (state == QWaveDecoder::InitialState) { if (source->bytesAvailable() < qint64(sizeof(RIFFHeader))) return; RIFFHeader riff; source->read(reinterpret_cast<char *>(&riff), sizeof(RIFFHeader)); if (qstrncmp(riff.descriptor.id, "RIFF", 4) != 0 || qstrncmp(riff.type, "WAVE", 4) != 0) { source->disconnect(SIGNAL(readyRead()), this, SLOT(handleData())); emit invalidFormat(); return; } else { state = QWaveDecoder::WaitingForFormatState; } } if (state == QWaveDecoder::WaitingForFormatState) { if (findChunk("fmt ")) { chunk descriptor; source->peek(reinterpret_cast<char *>(&descriptor), sizeof(chunk)); if (source->bytesAvailable() < qint64(descriptor.size + sizeof(chunk))) return; WAVEHeader wave; source->read(reinterpret_cast<char *>(&wave), sizeof(WAVEHeader)); if (descriptor.size > sizeof(WAVEHeader)) discardBytes(descriptor.size - sizeof(WAVEHeader)); if (wave.audioFormat != 0 && wave.audioFormat != 1) { source->disconnect(SIGNAL(readyRead()), this, SLOT(handleData())); emit invalidFormat(); return; } else { int bps = qFromLittleEndian<quint16>(wave.bitsPerSample); format.setCodec(QLatin1String("audio/pcm")); format.setSampleType(bps == 8 ? QAudioFormat::UnSignedInt : QAudioFormat::SignedInt); format.setByteOrder(QAudioFormat::LittleEndian); format.setFrequency(qFromLittleEndian<quint32>(wave.sampleRate)); format.setSampleSize(bps); format.setChannels(qFromLittleEndian<quint16>(wave.numChannels)); state = QWaveDecoder::WaitingForDataState; } } } if (state == QWaveDecoder::WaitingForDataState) { if (findChunk("data")) { source->disconnect(SIGNAL(readyRead()), this, SLOT(handleData())); chunk descriptor; source->read(reinterpret_cast<char *>(&descriptor), sizeof(chunk)); dataSize = descriptor.size; haveFormat = true; connect(source, SIGNAL(readyRead()), SIGNAL(readyRead())); emit formatKnown(); return; } } if (source->atEnd()) { source->disconnect(SIGNAL(readyRead()), this, SLOT(handleData())); emit invalidFormat(); return; } }