diff --git a/src/multimedia/audio/qaudiohelpers.cpp b/src/multimedia/audio/qaudiohelpers.cpp index 8aa4c090bc55e98c6538562ed38e00a7591bf28e..fae5914773fcad9f1595e419fe442d7ff0f7ebde 100644 --- a/src/multimedia/audio/qaudiohelpers.cpp +++ b/src/multimedia/audio/qaudiohelpers.cpp @@ -43,6 +43,49 @@ QT_BEGIN_NAMESPACE +// Base implementation of 24 bits number. +// Used to adjust 3 bytes values by a factor. +// TODO: Uses little-endian only. +class Int24 +{ +public: + quint8 data[3]; + Int24(qint32 v) { + data[0] = v & 0xFF; + data[1] = (v & 0xFF00) >> 8; + data[2] = (v & 0xFF0000) >> 16; + } + template<class T> + T multiply(qreal factor, T v = 0) const { + v |= data[0]; + v |= data[1] << 8; + v |= data[2] << 16; + v *= factor; + return v; + } +}; + +class qint24: public Int24 +{ +public: + qint24(qint32 v): Int24(v) {} + qint24 operator*(qreal factor) const { + // Checks if it is a signed value. + qint32 v = (data[2] & 0x80) ? 0xFF000000 : 0; + return multiply(factor, v); + } +}; + +class quint24: public Int24 +{ +public: + quint24(quint32 v): Int24(v) {} + quint24 operator*(qreal factor) const { + return multiply<quint32>(factor); + } +}; + + namespace QAudioHelperInternal { @@ -101,6 +144,12 @@ void qMultiplySamples(qreal factor, const QAudioFormat &format, const void* src, else if (format.sampleType() == QAudioFormat::UnSignedInt) QAudioHelperInternal::adjustUnsignedSamples<quint16>(factor,src,dest,samplesCount); break; + case 24: + if (format.sampleType() == QAudioFormat::SignedInt) + QAudioHelperInternal::adjustSamples<qint24>(factor,src,dest,samplesCount); + else if (format.sampleType() == QAudioFormat::UnSignedInt) + QAudioHelperInternal::adjustSamples<quint24>(factor,src,dest,samplesCount); + break; default: if (format.sampleType() == QAudioFormat::SignedInt) QAudioHelperInternal::adjustSamples<qint32>(factor,src,dest,samplesCount); diff --git a/tests/auto/integration/qsoundeffect/test24.wav b/tests/auto/integration/qsoundeffect/test24.wav new file mode 100644 index 0000000000000000000000000000000000000000..9575aaaee3bc7563a0ec8a2157afe6037eca10ad Binary files /dev/null and b/tests/auto/integration/qsoundeffect/test24.wav differ diff --git a/tests/auto/integration/qsoundeffect/tst_qsoundeffect.cpp b/tests/auto/integration/qsoundeffect/tst_qsoundeffect.cpp index 5be889096dc022788ad12c24f3606a073971e12c..fa98c8b1656c85775318b077c6e5637064f8b712 100644 --- a/tests/auto/integration/qsoundeffect/tst_qsoundeffect.cpp +++ b/tests/auto/integration/qsoundeffect/tst_qsoundeffect.cpp @@ -62,12 +62,14 @@ private slots: void testSetSourceWhilePlaying(); void testSupportedMimeTypes(); void testCorruptFile(); + void testPlaying24Bits(); private: QSoundEffect* sound; QUrl url; // test.wav: pcm_s16le, 48000 Hz, stereo, s16 QUrl url2; // test_tone.wav: pcm_s16le, 44100 Hz, mono QUrl urlCorrupted; // test_corrupted.wav: corrupted + QUrl url24Bits; // test24.wav pcm_s24le, 44100 Hz, mono }; void tst_QSoundEffect::init() @@ -105,6 +107,11 @@ void tst_QSoundEffect::initTestCase() QVERIFY2(!fullPath.isEmpty(), qPrintable(QStringLiteral("Unable to locate ") + testFileName)); urlCorrupted = QUrl::fromLocalFile(fullPath); + testFileName = QStringLiteral("test24.wav"); + fullPath = QFINDTESTDATA(testFileName); + QVERIFY2(!fullPath.isEmpty(), qPrintable(QStringLiteral("Unable to locate ") + testFileName)); + url24Bits = QUrl::fromLocalFile(fullPath); + sound = new QSoundEffect(this); QVERIFY(sound->source().isEmpty()); @@ -409,6 +416,26 @@ void tst_QSoundEffect::testCorruptFile() } } +void tst_QSoundEffect::testPlaying24Bits() +{ + sound->setLoopCount(QSoundEffect::Infinite); + sound->setSource(url24Bits); + QTestEventLoop::instance().enterLoop(1); + sound->play(); + QTestEventLoop::instance().enterLoop(1); + QTRY_COMPARE(sound->isPlaying(), true); + sound->stop(); + + QSignalSpy readSignal(sound, SIGNAL(volumeChanged())); + sound->setVolume(0.5); + QCOMPARE(sound->volume(), 0.5); + sound->play(); + QTestEventLoop::instance().enterLoop(1); + QTRY_COMPARE(sound->isPlaying(), true); + QCOMPARE(readSignal.count(), 1); + sound->stop(); +} + QTEST_MAIN(tst_QSoundEffect) #include "tst_qsoundeffect.moc"