summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2021-01-27 19:31:13 +0100
committerLars Knoll <lars.knoll@qt.io>2021-02-09 14:33:28 +0000
commit89f4db5857ea0c30c52510785f505a9217750db5 (patch)
tree9f8ed97cddf1ae0c21a8a5d829e61ee8401a8fcd
parentc401a0dc71dc49cd34f8a5dd2fd7320f451e98bf (diff)
Cleanup QAudioFormat and friends
Reduce the amount of available formats, and always use host endianness. Return both sample rate and channel count as a range, not a list of values. Change-Id: I88389b49ace077764fb647f50834236448e55c0e Reviewed-by: Doris Verria <doris.verria@qt.io> Reviewed-by: Lars Knoll <lars.knoll@qt.io>
-rw-r--r--examples/multimedia/audiodecoder/audiodecoder.cpp3
-rw-r--r--examples/multimedia/audiodecoder/wavefilewriter.cpp10
-rw-r--r--examples/multimedia/audiodevices/audiodevices.cpp194
-rw-r--r--examples/multimedia/audiodevices/audiodevices.h4
-rw-r--r--examples/multimedia/audiodevices/audiodevicesbase.ui185
-rw-r--r--examples/multimedia/audioinput/audioinput.cpp117
-rw-r--r--examples/multimedia/audioinput/audioinput.h1
-rw-r--r--examples/multimedia/audiooutput/audiooutput.cpp54
-rw-r--r--examples/multimedia/audiorecorder/audiorecorder.cpp95
-rw-r--r--examples/multimedia/spectrum/app/engine.cpp79
-rw-r--r--examples/multimedia/spectrum/app/spectrumanalyser.cpp14
-rw-r--r--examples/multimedia/spectrum/app/tonegenerator.cpp4
-rw-r--r--examples/multimedia/spectrum/app/utils.cpp49
-rw-r--r--examples/multimedia/spectrum/app/utils.h9
-rw-r--r--examples/multimedia/spectrum/app/waveform.cpp2
-rw-r--r--examples/multimedia/spectrum/app/wavfile.cpp26
-rw-r--r--examples/multimediawidgets/player/histogramwidget.cpp101
-rw-r--r--src/multimedia/audio/qaudiobuffer.cpp23
-rw-r--r--src/multimedia/audio/qaudiodeviceinfo.cpp130
-rw-r--r--src/multimedia/audio/qaudiodeviceinfo.h17
-rw-r--r--src/multimedia/audio/qaudiodeviceinfo_p.h23
-rw-r--r--src/multimedia/audio/qaudioformat.cpp336
-rw-r--r--src/multimedia/audio/qaudioformat.h63
-rw-r--r--src/multimedia/audio/qaudiohelpers.cpp95
-rw-r--r--src/multimedia/audio/qwavedecoder_p.cpp111
-rw-r--r--src/multimedia/audio/qwavedecoder_p.h13
-rw-r--r--src/multimedia/platform/alsa/qalsaaudiodeviceinfo.cpp207
-rw-r--r--src/multimedia/platform/alsa/qalsaaudiodeviceinfo_p.h28
-rw-r--r--src/multimedia/platform/alsa/qalsaaudioinput.cpp79
-rw-r--r--src/multimedia/platform/alsa/qalsaaudiooutput.cpp68
-rw-r--r--src/multimedia/platform/alsa/qalsadevicemanager.cpp3
-rw-r--r--src/multimedia/platform/android/audio/qopenslesdeviceinfo.cpp64
-rw-r--r--src/multimedia/platform/android/audio/qopenslesdeviceinfo_p.h10
-rw-r--r--src/multimedia/platform/android/audio/qopenslesengine.cpp22
-rw-r--r--src/multimedia/platform/darwin/audio/qcoreaudiodeviceinfo.mm102
-rw-r--r--src/multimedia/platform/darwin/audio/qcoreaudiodeviceinfo_p.h9
-rw-r--r--src/multimedia/platform/darwin/audio/qcoreaudiooutput.mm2
-rw-r--r--src/multimedia/platform/darwin/audio/qcoreaudioutils.mm59
-rw-r--r--src/multimedia/platform/darwin/qdarwindevicemanager.mm4
-rw-r--r--src/multimedia/platform/gstreamer/audio/qaudiodeviceinfo_gstreamer.cpp70
-rw-r--r--src/multimedia/platform/gstreamer/audio/qaudiodeviceinfo_gstreamer_p.h10
-rw-r--r--src/multimedia/platform/gstreamer/audio/qaudiooutput_gstreamer.cpp4
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstutils.cpp116
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstutils_p.h4
-rw-r--r--src/multimedia/platform/gstreamer/qgstreamerdevicemanager.cpp6
-rw-r--r--src/multimedia/platform/pulseaudio/qaudiodeviceinfo_pulse.cpp69
-rw-r--r--src/multimedia/platform/pulseaudio/qaudiodeviceinfo_pulse_p.h11
-rw-r--r--src/multimedia/platform/pulseaudio/qaudioengine_pulse.cpp15
-rw-r--r--src/multimedia/platform/pulseaudio/qaudioengine_pulse_p.h1
-rw-r--r--src/multimedia/platform/pulseaudio/qaudiooutput_pulse.cpp6
-rw-r--r--src/multimedia/platform/pulseaudio/qpulsehelpers.cpp105
-rw-r--r--src/multimedia/platform/pulseaudio/qpulsehelpers_p.h1
-rw-r--r--tests/auto/integration/qaudiodecoderbackend/tst_qaudiodecoderbackend.cpp12
-rw-r--r--tests/auto/integration/qaudiodeviceinfo/tst_qaudiodeviceinfo.cpp74
-rw-r--r--tests/auto/integration/qaudioinput/tst_qaudioinput.cpp33
-rw-r--r--tests/auto/integration/qaudioinput/wavheader.cpp27
-rw-r--r--tests/auto/integration/qaudiooutput/tst_qaudiooutput.cpp69
-rw-r--r--tests/auto/integration/qaudiooutput/wavheader.cpp25
-rw-r--r--tests/auto/unit/mockbackend/mockaudiodecodercontrol.h3
-rw-r--r--tests/auto/unit/multimedia/qaudiobuffer/tst_qaudiobuffer.cpp24
-rw-r--r--tests/auto/unit/multimedia/qaudioformat/tst_qaudioformat.cpp74
61 files changed, 946 insertions, 2228 deletions
diff --git a/examples/multimedia/audiodecoder/audiodecoder.cpp b/examples/multimedia/audiodecoder/audiodecoder.cpp
index fb64dc93a..686256544 100644
--- a/examples/multimedia/audiodecoder/audiodecoder.cpp
+++ b/examples/multimedia/audiodecoder/audiodecoder.cpp
@@ -61,9 +61,8 @@ AudioDecoder::AudioDecoder(bool isPlayback, bool isDelete)
// Our wav file writer only supports SignedInt sample type.
QAudioFormat format;
format.setChannelCount(2);
- format.setSampleSize(16);
+ format.setSampleFormat(QAudioFormat::Int16);
format.setSampleRate(48000);
- format.setSampleType(QAudioFormat::SignedInt);
m_decoder.setAudioFormat(format);
connect(&m_decoder, &QAudioDecoder::bufferReady,
diff --git a/examples/multimedia/audiodecoder/wavefilewriter.cpp b/examples/multimedia/audiodecoder/wavefilewriter.cpp
index 52c78c08f..a7bac62b4 100644
--- a/examples/multimedia/audiodecoder/wavefilewriter.cpp
+++ b/examples/multimedia/audiodecoder/wavefilewriter.cpp
@@ -105,7 +105,7 @@ bool WaveFileWriter::open(const QString& fileName, const QAudioFormat& format)
if (file.isOpen())
return false; // file already open
- if (format.sampleType() != QAudioFormat::SignedInt)
+ if (format.sampleFormat() != QAudioFormat::Int16)
return false; // data format is not supported
file.setFileName(fileName);
@@ -145,7 +145,7 @@ bool WaveFileWriter::close()
bool WaveFileWriter::writeHeader(const QAudioFormat &format)
{
// check if format is supported
- if (format.byteOrder() == QAudioFormat::BigEndian || format.sampleType() != QAudioFormat::SignedInt)
+ if (format.sampleFormat() != QAudioFormat::Int16)
return false;
CombinedHeader header;
@@ -166,9 +166,9 @@ bool WaveFileWriter::writeHeader(const QAudioFormat &format)
header.wave.audioFormat = quint16(1);
header.wave.numChannels = quint16(format.channelCount());
header.wave.sampleRate = quint32(format.sampleRate());
- header.wave.byteRate = quint32(format.sampleRate() * format.channelCount() * format.sampleSize() / 8);
- header.wave.blockAlign = quint16(format.channelCount() * format.sampleSize() / 8);
- header.wave.bitsPerSample = quint16(format.sampleSize());
+ header.wave.byteRate = quint32(format.sampleRate() * format.channelCount() * format.bytesPerSample());
+ header.wave.blockAlign = quint16(format.channelCount() * format.bytesPerSample());
+ header.wave.bitsPerSample = quint16(format.bytesPerSample() * 8);
// DATA header
memcpy(header.data.descriptor.id,"data", 4);
diff --git a/examples/multimedia/audiodevices/audiodevices.cpp b/examples/multimedia/audiodevices/audiodevices.cpp
index 3a6dd4c2d..c624fcb3a 100644
--- a/examples/multimedia/audiodevices/audiodevices.cpp
+++ b/examples/multimedia/audiodevices/audiodevices.cpp
@@ -53,40 +53,23 @@
// Utility functions for converting QAudioFormat fields into text
-static QString toString(QAudioFormat::SampleType sampleType)
+static QString toString(QAudioFormat::SampleFormat sampleFormat)
{
- QString result("Unknown");
- switch (sampleType) {
- case QAudioFormat::SignedInt:
- result = "SignedInt";
- break;
- case QAudioFormat::UnSignedInt:
- result = "UnSignedInt";
- break;
- case QAudioFormat::Float:
- result = "Float";
- break;
+ switch (sampleFormat) {
case QAudioFormat::Unknown:
- result = "Unknown";
- }
- return result;
-}
-
-static QString toString(QAudioFormat::Endian endian)
-{
- QString result("Unknown");
- switch (endian) {
- case QAudioFormat::LittleEndian:
- result = "LittleEndian";
- break;
- case QAudioFormat::BigEndian:
- result = "BigEndian";
- break;
+ case QAudioFormat::NSampleFormats:
+ return "Unknown";
+ case QAudioFormat::UInt8:
+ return "Unsigned 8 bit";
+ case QAudioFormat::Int16:
+ return "Signed 16 bit";
+ case QAudioFormat::Int32:
+ return "Signed 32 bit";
+ case QAudioFormat::Float:
+ return "Float";
}
- return result;
}
-
AudioDevicesBase::AudioDevicesBase(QWidget *parent)
: QMainWindow(parent)
{
@@ -102,11 +85,9 @@ AudioTest::AudioTest(QWidget *parent)
connect(testButton, &QPushButton::clicked, this, &AudioTest::test);
connect(modeBox, QOverload<int>::of(&QComboBox::activated), this, &AudioTest::modeChanged);
connect(deviceBox, QOverload<int>::of(&QComboBox::activated), this, &AudioTest::deviceChanged);
- connect(sampleRateBox, QOverload<int>::of(&QComboBox::activated), this, &AudioTest::sampleRateChanged);
- connect(channelsBox, QOverload<int>::of(&QComboBox::activated), this, &AudioTest::channelChanged);
- connect(sampleSizesBox, QOverload<int>::of(&QComboBox::activated), this, &AudioTest::sampleSizeChanged);
- connect(sampleTypesBox, QOverload<int>::of(&QComboBox::activated), this, &AudioTest::sampleTypeChanged);
- connect(endianBox, QOverload<int>::of(&QComboBox::activated), this, &AudioTest::endianChanged);
+ connect(sampleRateSpinBox, &QSpinBox::valueChanged, this, &AudioTest::sampleRateChanged);
+ connect(channelsSpinBox, &QSpinBox::valueChanged, this, &AudioTest::channelChanged);
+ connect(sampleFormatBox, QOverload<int>::of(&QComboBox::activated), this, &AudioTest::sampleFormatChanged);
connect(populateTableButton, &QPushButton::clicked, this, &AudioTest::populateTable);
connect(QMediaDeviceManager::instance(), &QMediaDeviceManager::audioInputsChanged, this, &AudioTest::updateAudioDevices);
connect(QMediaDeviceManager::instance(), &QMediaDeviceManager::audioOutputsChanged, this, &AudioTest::updateAudioDevices);
@@ -127,17 +108,13 @@ void AudioTest::test()
testResult->setText(tr("Success"));
nearestSampleRate->setText("");
nearestChannel->setText("");
- nearestSampleSize->setText("");
- nearestSampleType->setText("");
- nearestEndian->setText("");
+ nearestSampleFormat->setText("");
} else {
- QAudioFormat nearest = m_deviceInfo.nearestFormat(m_settings);
+ QAudioFormat nearest = m_deviceInfo.preferredFormat();
testResult->setText(tr("Failed"));
nearestSampleRate->setText(QString("%1").arg(nearest.sampleRate()));
nearestChannel->setText(QString("%1").arg(nearest.channelCount()));
- nearestSampleSize->setText(QString("%1").arg(nearest.sampleSize()));
- nearestSampleType->setText(toString(nearest.sampleType()));
- nearestEndian->setText(toString(nearest.byteOrder()));
+ nearestSampleFormat->setText(toString(nearest.sampleFormat()));
}
}
else
@@ -173,40 +150,27 @@ void AudioTest::deviceChanged(int idx)
// device has changed
m_deviceInfo = deviceBox->itemData(idx).value<QAudioDeviceInfo>();
- sampleRateBox->clear();
- const QList<int> sampleRatez = m_deviceInfo.supportedSampleRates();
- for (int i = 0; i < sampleRatez.size(); ++i)
- sampleRateBox->addItem(QString("%1").arg(sampleRatez.at(i)));
- if (sampleRatez.size())
- m_settings.setSampleRate(sampleRatez.at(0));
-
- channelsBox->clear();
- const QList<int> chz = m_deviceInfo.supportedChannelCounts();
- for (int i = 0; i < chz.size(); ++i)
- channelsBox->addItem(QString("%1").arg(chz.at(i)));
- if (chz.size())
- m_settings.setChannelCount(chz.at(0));
-
- sampleSizesBox->clear();
- const QList<int> sampleSizez = m_deviceInfo.supportedSampleSizes();
- for (int i = 0; i < sampleSizez.size(); ++i)
- sampleSizesBox->addItem(QString("%1").arg(sampleSizez.at(i)));
- if (sampleSizez.size())
- m_settings.setSampleSize(sampleSizez.at(0));
-
- sampleTypesBox->clear();
- const QList<QAudioFormat::SampleType> sampleTypez = m_deviceInfo.supportedSampleTypes();
- for (int i = 0; i < sampleTypez.size(); ++i)
- sampleTypesBox->addItem(toString(sampleTypez.at(i)));
- if (sampleTypez.size())
- m_settings.setSampleType(sampleTypez.at(0));
-
- endianBox->clear();
- const QList<QAudioFormat::Endian> endianz = m_deviceInfo.supportedByteOrders();
- for (int i = 0; i < endianz.size(); ++i)
- endianBox->addItem(toString(endianz.at(i)));
- if (endianz.size())
- m_settings.setByteOrder(endianz.at(0));
+ sampleRateSpinBox->clear();
+ auto sampleRates = m_deviceInfo.supportedSampleRates();
+ sampleRateSpinBox->setMinimum(sampleRates.minimum);
+ sampleRateSpinBox->setMaximum(sampleRates.maximum);
+ int sampleValue = qBound(sampleRates.minimum, 48000, sampleRates.maximum);
+ sampleRateSpinBox->setValue(sampleValue);
+ m_settings.setSampleRate(sampleValue);
+
+ channelsSpinBox->clear();
+ auto channelRates = m_deviceInfo.supportedChannelCounts();
+ channelsSpinBox->setMinimum(channelRates.minimum);
+ channelsSpinBox->setMaximum(channelRates.maximum);
+ int channelValue = qBound(channelRates.minimum, 2, channelRates.maximum);
+ channelsSpinBox->setValue(channelValue);
+
+ sampleFormatBox->clear();
+ const QList<QAudioFormat::SampleFormat> sampleFormats = m_deviceInfo.supportedSampleFormats();
+ for (int i = 0; i < sampleFormats.size(); ++i)
+ sampleFormatBox->addItem(toString(sampleFormats.at(i)));
+ if (sampleFormats.size())
+ m_settings.setSampleFormat(sampleFormats.at(0));
allFormatsTable->clearContents();
}
@@ -215,81 +179,37 @@ void AudioTest::populateTable()
{
int row = 0;
- QAudioFormat format;
- for (auto sampleRate: m_deviceInfo.supportedSampleRates()) {
- format.setSampleRate(sampleRate);
- for (auto channels: m_deviceInfo.supportedChannelCounts()) {
- format.setChannelCount(channels);
- for (auto sampleType: m_deviceInfo.supportedSampleTypes()) {
- format.setSampleType(sampleType);
- for (auto sampleSize: m_deviceInfo.supportedSampleSizes()) {
- format.setSampleSize(sampleSize);
- for (auto endian: m_deviceInfo.supportedByteOrders()) {
- format.setByteOrder(endian);
- if (m_deviceInfo.isFormatSupported(format)) {
- allFormatsTable->setRowCount(row + 1);
+ for (auto sampleFormat : m_deviceInfo.supportedSampleFormats()) {
+ allFormatsTable->setRowCount(row + 1);
- QTableWidgetItem *sampleRateItem = new QTableWidgetItem(QString("%1").arg(format.sampleRate()));
- allFormatsTable->setItem(row, 0, sampleRateItem);
+ QTableWidgetItem *sampleTypeItem = new QTableWidgetItem(toString(sampleFormat));
+ allFormatsTable->setItem(row, 2, sampleTypeItem);
- QTableWidgetItem *channelsItem = new QTableWidgetItem(QString("%1").arg(format.channelCount()));
- allFormatsTable->setItem(row, 1, channelsItem);
+ auto sampleRates = m_deviceInfo.supportedSampleRates();
+ QTableWidgetItem *sampleRateItem = new QTableWidgetItem(QString("%1 - %2").arg(sampleRates.minimum).arg(sampleRates.maximum));
+ allFormatsTable->setItem(row, 0, sampleRateItem);
- QTableWidgetItem *sampleTypeItem = new QTableWidgetItem(toString(format.sampleType()));
- allFormatsTable->setItem(row, 2, sampleTypeItem);
+ auto channels = m_deviceInfo.supportedChannelCounts();
+ QTableWidgetItem *channelsItem = new QTableWidgetItem(QString("%1 - %2").arg(channels.minimum).arg(channels.maximum));
+ allFormatsTable->setItem(row, 1, channelsItem);
- QTableWidgetItem *sampleSizeItem = new QTableWidgetItem(QString("%1").arg(format.sampleSize()));
- allFormatsTable->setItem(row, 3, sampleSizeItem);
-
- QTableWidgetItem *byteOrderItem = new QTableWidgetItem(toString(format.byteOrder()));
- allFormatsTable->setItem(row, 4, byteOrderItem);
-
- ++row;
- }
- }
- }
- }
- }
+ ++row;
}
}
-void AudioTest::sampleRateChanged(int idx)
+void AudioTest::sampleRateChanged(int value)
{
// sample rate has changed
- m_settings.setSampleRate(sampleRateBox->itemText(idx).toInt());
-}
-
-void AudioTest::channelChanged(int idx)
-{
- m_settings.setChannelCount(channelsBox->itemText(idx).toInt());
+ m_settings.setSampleRate(value);
}
-void AudioTest::sampleSizeChanged(int idx)
+void AudioTest::channelChanged(int channels)
{
- m_settings.setSampleSize(sampleSizesBox->itemText(idx).toInt());
+ m_settings.setChannelCount(channels);
}
-void AudioTest::sampleTypeChanged(int idx)
+void AudioTest::sampleFormatChanged(int idx)
{
- switch (sampleTypesBox->itemText(idx).toInt()) {
- case QAudioFormat::SignedInt:
- m_settings.setSampleType(QAudioFormat::SignedInt);
- break;
- case QAudioFormat::UnSignedInt:
- m_settings.setSampleType(QAudioFormat::UnSignedInt);
- break;
- case QAudioFormat::Float:
- m_settings.setSampleType(QAudioFormat::Float);
- }
-}
-
-void AudioTest::endianChanged(int idx)
-{
- switch (endianBox->itemText(idx).toInt()) {
- case QAudioFormat::LittleEndian:
- m_settings.setByteOrder(QAudioFormat::LittleEndian);
- break;
- case QAudioFormat::BigEndian:
- m_settings.setByteOrder(QAudioFormat::BigEndian);
- }
+ auto formats = m_deviceInfo.supportedSampleFormats();
+ m_settings.setSampleFormat(formats.at(idx));
}
diff --git a/examples/multimedia/audiodevices/audiodevices.h b/examples/multimedia/audiodevices/audiodevices.h
index be9b36ff7..31ec479df 100644
--- a/examples/multimedia/audiodevices/audiodevices.h
+++ b/examples/multimedia/audiodevices/audiodevices.h
@@ -82,9 +82,7 @@ private slots:
void deviceChanged(int idx);
void sampleRateChanged(int idx);
void channelChanged(int idx);
- void sampleSizeChanged(int idx);
- void sampleTypeChanged(int idx);
- void endianChanged(int idx);
+ void sampleFormatChanged(int idx);
void test();
void populateTable();
diff --git a/examples/multimedia/audiodevices/audiodevicesbase.ui b/examples/multimedia/audiodevices/audiodevicesbase.ui
index 5d5ef4835..9618a3d22 100644
--- a/examples/multimedia/audiodevices/audiodevicesbase.ui
+++ b/examples/multimedia/audiodevices/audiodevicesbase.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>679</width>
- <height>598</height>
+ <width>646</width>
+ <height>528</height>
</rect>
</property>
<property name="windowTitle">
@@ -31,8 +31,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>653</width>
- <height>545</height>
+ <width>626</width>
+ <height>480</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_4">
@@ -72,134 +72,72 @@
<item row="2" column="0" colspan="2">
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
- <number>1</number>
+ <number>0</number>
</property>
<widget class="QWidget" name="testFormatTab">
<attribute name="title">
<string>Test format</string>
</attribute>
<layout class="QGridLayout" name="gridLayout">
- <item row="14" column="1">
+ <item row="12" column="1">
<widget class="QPushButton" name="testButton">
<property name="text">
<string>Test</string>
</property>
</widget>
</item>
- <item row="0" column="2">
- <widget class="QLabel" name="nearestLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Plain</enum>
- </property>
- <property name="text">
- <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
-&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
-p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Nearest Settings&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
- </property>
- <property name="textFormat">
- <enum>Qt::RichText</enum>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- <item row="8" column="2">
- <widget class="QLineEdit" name="nearestSampleSize">
- <property name="enabled">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item row="14" column="2">
+ <item row="12" column="2">
<widget class="QLabel" name="testResult">
<property name="text">
<string/>
</property>
</widget>
</item>
- <item row="5" column="0">
- <widget class="QLabel" name="actualSampleTypeLabel">
- <property name="text">
- <string>SampleType</string>
- </property>
- </widget>
- </item>
- <item row="8" column="0">
- <widget class="QLabel" name="actualSampleSizeLabel">
- <property name="text">
- <string>Sample size (bits)</string>
- </property>
- </widget>
- </item>
- <item row="13" column="0">
- <widget class="QLabel" name="actualEndianLabel">
+ <item row="4" column="0">
+ <widget class="QLabel" name="actualChannelLabel">
<property name="text">
- <string>Endianness</string>
+ <string>Channels</string>
</property>
</widget>
</item>
- <item row="5" column="2">
- <widget class="QLineEdit" name="nearestSampleType">
+ <item row="2" column="2">
+ <widget class="QLineEdit" name="nearestSampleRate">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
- <item row="5" column="1">
- <widget class="QComboBox" name="sampleTypesBox"/>
- </item>
- <item row="4" column="2">
- <widget class="QLineEdit" name="nearestChannel">
+ <item row="5" column="2">
+ <widget class="QLineEdit" name="nearestSampleFormat">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
- <item row="4" column="0">
- <widget class="QLabel" name="actualChannelLabel">
+ <item row="5" column="0">
+ <widget class="QLabel" name="actualSampleTypeLabel">
<property name="text">
- <string>Channels</string>
+ <string>Sample Format</string>
</property>
</widget>
</item>
- <item row="13" column="1">
- <widget class="QComboBox" name="endianBox"/>
- </item>
- <item row="8" column="1">
- <widget class="QComboBox" name="sampleSizesBox"/>
- </item>
- <item row="2" column="2">
- <widget class="QLineEdit" name="nearestSampleRate">
+ <item row="4" column="2">
+ <widget class="QLineEdit" name="nearestChannel">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
- <item row="2" column="1">
- <widget class="QComboBox" name="sampleRateBox">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
+ <item row="5" column="1">
+ <widget class="QComboBox" name="sampleFormatBox"/>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="actualFreqLabel">
+ <property name="text">
+ <string>Frequency (Hz)</string>
</property>
</widget>
</item>
- <item row="4" column="1">
- <widget class="QComboBox" name="channelsBox"/>
- </item>
<item row="0" column="1">
<widget class="QLabel" name="actualLabel">
<property name="sizePolicy">
@@ -225,19 +163,53 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
- <item row="2" column="0">
- <widget class="QLabel" name="actualFreqLabel">
+ <item row="0" column="2">
+ <widget class="QLabel" name="nearestLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
<property name="text">
- <string>Frequency (Hz)</string>
+ <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Nearest Settings&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::RichText</enum>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
</property>
</widget>
</item>
- <item row="13" column="2">
- <widget class="QLineEdit" name="nearestEndian">
- <property name="enabled">
- <bool>false</bool>
+ <item row="13" column="1">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
</property>
- </widget>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="1">
+ <widget class="QSpinBox" name="sampleRateSpinBox"/>
+ </item>
+ <item row="4" column="1">
+ <widget class="QSpinBox" name="channelsSpinBox"/>
</item>
</layout>
</widget>
@@ -280,7 +252,7 @@ p, li { white-space: pre-wrap; }
<bool>false</bool>
</property>
<property name="columnCount">
- <number>5</number>
+ <number>3</number>
</property>
<attribute name="horizontalHeaderHighlightSections">
<bool>false</bool>
@@ -296,15 +268,7 @@ p, li { white-space: pre-wrap; }
</attribute>
<column>
<property name="text">
- <string>Frequency (Hz)</string>
- </property>
- <property name="textAlignment">
- <set>AlignCenter</set>
- </property>
- </column>
- <column>
- <property name="text">
- <string>Channels</string>
+ <string>Sample Format</string>
</property>
<property name="textAlignment">
<set>AlignCenter</set>
@@ -312,7 +276,7 @@ p, li { white-space: pre-wrap; }
</column>
<column>
<property name="text">
- <string>Sample type</string>
+ <string>Frequency (Hz)</string>
</property>
<property name="textAlignment">
<set>AlignCenter</set>
@@ -320,17 +284,12 @@ p, li { white-space: pre-wrap; }
</column>
<column>
<property name="text">
- <string>Sample size (bits)</string>
+ <string>Channels</string>
</property>
<property name="textAlignment">
<set>AlignCenter</set>
</property>
</column>
- <column>
- <property name="text">
- <string>Endianness</string>
- </property>
- </column>
</widget>
</item>
</layout>
diff --git a/examples/multimedia/audioinput/audioinput.cpp b/examples/multimedia/audioinput/audioinput.cpp
index d86f2d33c..40303340f 100644
--- a/examples/multimedia/audioinput/audioinput.cpp
+++ b/examples/multimedia/audioinput/audioinput.cpp
@@ -64,50 +64,6 @@
AudioInfo::AudioInfo(const QAudioFormat &format)
: m_format(format)
{
- switch (m_format.sampleSize()) {
- case 8:
- switch (m_format.sampleType()) {
- case QAudioFormat::UnSignedInt:
- m_maxAmplitude = 255;
- break;
- case QAudioFormat::SignedInt:
- m_maxAmplitude = 127;
- break;
- default:
- break;
- }
- break;
- case 16:
- switch (m_format.sampleType()) {
- case QAudioFormat::UnSignedInt:
- m_maxAmplitude = 65535;
- break;
- case QAudioFormat::SignedInt:
- m_maxAmplitude = 32767;
- break;
- default:
- break;
- }
- break;
-
- case 32:
- switch (m_format.sampleType()) {
- case QAudioFormat::UnSignedInt:
- m_maxAmplitude = 0xffffffff;
- break;
- case QAudioFormat::SignedInt:
- m_maxAmplitude = 0x7fffffff;
- break;
- case QAudioFormat::Float:
- m_maxAmplitude = 0x7fffffff; // Kind of
- default:
- break;
- }
- break;
-
- default:
- break;
- }
}
void AudioInfo::start()
@@ -130,57 +86,25 @@ qint64 AudioInfo::readData(char *data, qint64 maxlen)
qint64 AudioInfo::writeData(const char *data, qint64 len)
{
- if (m_maxAmplitude) {
- Q_ASSERT(m_format.sampleSize() % 8 == 0);
- const int channelBytes = m_format.sampleSize() / 8;
- const int sampleBytes = m_format.channelCount() * channelBytes;
- Q_ASSERT(len % sampleBytes == 0);
- const int numSamples = len / sampleBytes;
-
- quint32 maxValue = 0;
- const unsigned char *ptr = reinterpret_cast<const unsigned char *>(data);
-
- for (int i = 0; i < numSamples; ++i) {
- for (int j = 0; j < m_format.channelCount(); ++j) {
- quint32 value = 0;
-
- if (m_format.sampleSize() == 8 && m_format.sampleType() == QAudioFormat::UnSignedInt) {
- value = *reinterpret_cast<const quint8*>(ptr);
- } else if (m_format.sampleSize() == 8 && m_format.sampleType() == QAudioFormat::SignedInt) {
- value = qAbs(*reinterpret_cast<const qint8*>(ptr));
- } else if (m_format.sampleSize() == 16 && m_format.sampleType() == QAudioFormat::UnSignedInt) {
- if (m_format.byteOrder() == QAudioFormat::LittleEndian)
- value = qFromLittleEndian<quint16>(ptr);
- else
- value = qFromBigEndian<quint16>(ptr);
- } else if (m_format.sampleSize() == 16 && m_format.sampleType() == QAudioFormat::SignedInt) {
- if (m_format.byteOrder() == QAudioFormat::LittleEndian)
- value = qAbs(qFromLittleEndian<qint16>(ptr));
- else
- value = qAbs(qFromBigEndian<qint16>(ptr));
- } else if (m_format.sampleSize() == 32 && m_format.sampleType() == QAudioFormat::UnSignedInt) {
- if (m_format.byteOrder() == QAudioFormat::LittleEndian)
- value = qFromLittleEndian<quint32>(ptr);
- else
- value = qFromBigEndian<quint32>(ptr);
- } else if (m_format.sampleSize() == 32 && m_format.sampleType() == QAudioFormat::SignedInt) {
- if (m_format.byteOrder() == QAudioFormat::LittleEndian)
- value = qAbs(qFromLittleEndian<qint32>(ptr));
- else
- value = qAbs(qFromBigEndian<qint32>(ptr));
- } else if (m_format.sampleSize() == 32 && m_format.sampleType() == QAudioFormat::Float) {
- value = qAbs(*reinterpret_cast<const float*>(ptr) * 0x7fffffff); // assumes 0-1.0
- }
-
- maxValue = qMax(value, maxValue);
- ptr += channelBytes;
- }
- }
+ const int channelBytes = m_format.bytesPerSample();
+ const int sampleBytes = m_format.bytesPerFrame();
+ Q_ASSERT(len % sampleBytes == 0);
+ const int numSamples = len / sampleBytes;
- maxValue = qMin(maxValue, m_maxAmplitude);
- m_level = qreal(maxValue) / m_maxAmplitude;
+ float maxValue = 0;
+ const unsigned char *ptr = reinterpret_cast<const unsigned char *>(data);
+
+ for (int i = 0; i < numSamples; ++i) {
+ for (int j = 0; j < m_format.channelCount(); ++j) {
+ float value = m_format.normalizedSampleValue(ptr);
+
+ maxValue = qMax(value, maxValue);
+ ptr += channelBytes;
+ }
}
+ m_level = maxValue;
+
emit update();
return len;
}
@@ -274,14 +198,7 @@ void InputTest::initializeAudio(const QAudioDeviceInfo &deviceInfo)
QAudioFormat format;
format.setSampleRate(8000);
format.setChannelCount(1);
- format.setSampleSize(16);
- format.setSampleType(QAudioFormat::SignedInt);
- format.setByteOrder(QAudioFormat::LittleEndian);
-
- if (!deviceInfo.isFormatSupported(format)) {
- qWarning() << "Default format not supported - trying to use nearest";
- format = deviceInfo.nearestFormat(format);
- }
+ format.setSampleFormat(QAudioFormat::Int16);
m_audioInfo.reset(new AudioInfo(format));
connect(m_audioInfo.data(), &AudioInfo::update, [this]() {
diff --git a/examples/multimedia/audioinput/audioinput.h b/examples/multimedia/audioinput/audioinput.h
index 7bfe3ea24..ea24069a0 100644
--- a/examples/multimedia/audioinput/audioinput.h
+++ b/examples/multimedia/audioinput/audioinput.h
@@ -80,7 +80,6 @@ public:
private:
const QAudioFormat m_format;
- quint32 m_maxAmplitude = 0;
qreal m_level = 0.0; // 0.0 <= m_level <= 1.0
signals:
diff --git a/examples/multimedia/audiooutput/audiooutput.cpp b/examples/multimedia/audiooutput/audiooutput.cpp
index e2133d941..971972cab 100644
--- a/examples/multimedia/audiooutput/audiooutput.cpp
+++ b/examples/multimedia/audiooutput/audiooutput.cpp
@@ -76,10 +76,9 @@ void Generator::stop()
void Generator::generateData(const QAudioFormat &format, qint64 durationUs, int sampleRate)
{
- const int channelBytes = format.sampleSize() / 8;
+ const int channelBytes = format.bytesPerSample();
const int sampleBytes = format.channelCount() * channelBytes;
- qint64 length = (format.sampleRate() * format.channelCount() * (format.sampleSize() / 8))
- * durationUs / 1000000;
+ qint64 length = format.bytesForDuration(durationUs);
Q_ASSERT(length % sampleBytes == 0);
Q_UNUSED(sampleBytes); // suppress warning in release builds
@@ -91,28 +90,21 @@ void Generator::generateData(const QAudioFormat &format, qint64 durationUs, int
// Produces value (-1..1)
const qreal x = qSin(2 * M_PI * sampleRate * qreal(sampleIndex++ % format.sampleRate()) / format.sampleRate());
for (int i=0; i<format.channelCount(); ++i) {
- if (format.sampleSize() == 8) {
- if (format.sampleType() == QAudioFormat::UnSignedInt) {
- const quint8 value = static_cast<quint8>((1.0 + x) / 2 * 255);
- *reinterpret_cast<quint8 *>(ptr) = value;
- } else if (format.sampleType() == QAudioFormat::SignedInt) {
- const qint8 value = static_cast<qint8>(x * 127);
- *reinterpret_cast<qint8 *>(ptr) = value;
- }
- } else if (format.sampleSize() == 16) {
- if (format.sampleType() == QAudioFormat::UnSignedInt) {
- quint16 value = static_cast<quint16>((1.0 + x) / 2 * 65535);
- if (format.byteOrder() == QAudioFormat::LittleEndian)
- qToLittleEndian<quint16>(value, ptr);
- else
- qToBigEndian<quint16>(value, ptr);
- } else if (format.sampleType() == QAudioFormat::SignedInt) {
- qint16 value = static_cast<qint16>(x * 32767);
- if (format.byteOrder() == QAudioFormat::LittleEndian)
- qToLittleEndian<qint16>(value, ptr);
- else
- qToBigEndian<qint16>(value, ptr);
- }
+ switch(format.sampleFormat()) {
+ case QAudioFormat::UInt8:
+ *reinterpret_cast<quint8 *>(ptr) = static_cast<quint8>((1.0 + x) / 2 * 255);
+ break;
+ case QAudioFormat::Int16:
+ *reinterpret_cast<qint16 *>(ptr) = static_cast<qint16>(x * 32767);
+ break;
+ case QAudioFormat::Int32:
+ *reinterpret_cast<qint32 *>(ptr) = static_cast<qint32>(x * std::numeric_limits<qint32>::max());
+ break;
+ case QAudioFormat::Float:
+ *reinterpret_cast<float *>(ptr) = x;
+ break;
+ default:
+ break;
}
ptr += channelBytes;
@@ -204,17 +196,7 @@ void AudioTest::initializeWindow()
void AudioTest::initializeAudio(const QAudioDeviceInfo &deviceInfo)
{
- QAudioFormat format;
- format.setSampleRate(44100);
- format.setChannelCount(1);
- format.setSampleSize(16);
- format.setByteOrder(QAudioFormat::LittleEndian);
- format.setSampleType(QAudioFormat::SignedInt);
-
- if (!deviceInfo.isFormatSupported(format)) {
- qWarning() << "Default format not supported - trying to use nearest";
- format = deviceInfo.nearestFormat(format);
- }
+ QAudioFormat format = deviceInfo.preferredFormat();
const int durationSeconds = 1;
const int toneSampleRateHz = 600;
diff --git a/examples/multimedia/audiorecorder/audiorecorder.cpp b/examples/multimedia/audiorecorder/audiorecorder.cpp
index dd3a22fa3..ddd28bcdf 100644
--- a/examples/multimedia/audiorecorder/audiorecorder.cpp
+++ b/examples/multimedia/audiorecorder/audiorecorder.cpp
@@ -62,12 +62,8 @@
#include <qaudiodeviceinfo.h>
#include <qaudiobuffer.h>
-static qreal getPeakValue(const QAudioFormat &format);
static QList<qreal> getBufferLevels(const QAudioBuffer &buffer);
-template<class T>
-static QList<qreal> getBufferLevels(const T *buffer, int frames, int channels);
-
AudioRecorder::AudioRecorder()
: ui(new Ui::AudioRecorder)
{
@@ -254,100 +250,29 @@ void AudioRecorder::clearAudioLevels()
m_audioLevel->setLevel(0);
}
-// This function returns the maximum possible sample value for a given audio format
-qreal getPeakValue(const QAudioFormat& format)
-{
- // Note: Only the most common sample formats are supported
- if (!format.isValid())
- return qreal(0);
-
- switch (format.sampleType()) {
- case QAudioFormat::Unknown:
- break;
- case QAudioFormat::Float:
- if (format.sampleSize() != 32) // other sample formats are not supported
- return qreal(0);
- return qreal(1.00003);
- case QAudioFormat::SignedInt:
- if (format.sampleSize() == 32)
- return qreal(INT_MAX);
- if (format.sampleSize() == 16)
- return qreal(SHRT_MAX);
- if (format.sampleSize() == 8)
- return qreal(CHAR_MAX);
- break;
- case QAudioFormat::UnSignedInt:
- if (format.sampleSize() == 32)
- return qreal(UINT_MAX);
- if (format.sampleSize() == 16)
- return qreal(USHRT_MAX);
- if (format.sampleSize() == 8)
- return qreal(UCHAR_MAX);
- break;
- }
-
- return qreal(0);
-}
-
// returns the audio level for each channel
QList<qreal> getBufferLevels(const QAudioBuffer &buffer)
{
QList<qreal> values;
- if (!buffer.format().isValid() || buffer.format().byteOrder() != QAudioFormat::LittleEndian)
+ auto format = buffer.format();
+ if (!format.isValid())
return values;
- int channelCount = buffer.format().channelCount();
- values.fill(0, channelCount);
- qreal peak_value = getPeakValue(buffer.format());
- if (qFuzzyCompare(peak_value, qreal(0)))
- return values;
+ int channels = buffer.format().channelCount();
+ values.fill(0, channels);
- switch (buffer.format().sampleType()) {
- case QAudioFormat::Unknown:
- case QAudioFormat::UnSignedInt:
- if (buffer.format().sampleSize() == 32)
- values = getBufferLevels(buffer.constData<quint32>(), buffer.frameCount(), channelCount);
- if (buffer.format().sampleSize() == 16)
- values = getBufferLevels(buffer.constData<quint16>(), buffer.frameCount(), channelCount);
- if (buffer.format().sampleSize() == 8)
- values = getBufferLevels(buffer.constData<quint8>(), buffer.frameCount(), channelCount);
- for (double &value : values)
- value = qAbs(value - peak_value / 2) / (peak_value / 2);
- break;
- case QAudioFormat::Float:
- if (buffer.format().sampleSize() == 32) {
- values = getBufferLevels(buffer.constData<float>(), buffer.frameCount(), channelCount);
- for (double &value : values)
- value /= peak_value;
- }
- break;
- case QAudioFormat::SignedInt:
- if (buffer.format().sampleSize() == 32)
- values = getBufferLevels(buffer.constData<qint32>(), buffer.frameCount(), channelCount);
- if (buffer.format().sampleSize() == 16)
- values = getBufferLevels(buffer.constData<qint16>(), buffer.frameCount(), channelCount);
- if (buffer.format().sampleSize() == 8)
- values = getBufferLevels(buffer.constData<qint8>(), buffer.frameCount(), channelCount);
- for (double &value : values)
- value /= peak_value;
- break;
- }
-
- return values;
-}
-
-template<class T>
-QList<qreal> getBufferLevels(const T *buffer, int frames, int channels)
-{
+ int bytesPerSample = format.bytesPerSample();
QList<qreal> max_values;
max_values.fill(0, channels);
- for (int i = 0; i < frames; ++i) {
+ const char *data = buffer.constData<char>();
+ for (int i = 0; i < buffer.frameCount(); ++i) {
for (int j = 0; j < channels; ++j) {
- qreal value = qAbs(qreal(buffer[i * channels + j]));
+ qreal value = qAbs(format.normalizedSampleValue(data));
if (value > max_values.at(j))
- max_values.replace(j, value);
+ max_values[j] = value;
+ data += bytesPerSample;
}
}
diff --git a/examples/multimedia/spectrum/app/engine.cpp b/examples/multimedia/spectrum/app/engine.cpp
index 8977f85cd..7c678333d 100644
--- a/examples/multimedia/spectrum/app/engine.cpp
+++ b/examples/multimedia/spectrum/app/engine.cpp
@@ -155,7 +155,7 @@ bool Engine::loadFile(const QString &fileName)
Q_ASSERT(!fileName.isEmpty());
m_file = new WavFile(this);
if (m_file->open(fileName)) {
- if (isPCMS16LE(m_file->fileFormat())) {
+ if (m_file->fileFormat().sampleFormat() == QAudioFormat::Int16) {
result = initialize();
} else {
emit errorMessage(tr("Audio format not supported"),
@@ -333,7 +333,7 @@ void Engine::audioNotify()
{
switch (m_mode) {
case QAudio::AudioInput: {
- const qint64 recordPosition = qMin(m_bufferLength, audioLength(m_format, m_audioInput->processedUSecs()));
+ const qint64 recordPosition = qMin(m_bufferLength, m_format.bytesForDuration(m_audioInput->processedUSecs()));
setRecordPosition(recordPosition);
const qint64 levelPosition = m_dataLength - m_levelBufferLength;
if (levelPosition >= 0)
@@ -346,7 +346,7 @@ void Engine::audioNotify()
}
break;
case QAudio::AudioOutput: {
- const qint64 playPosition = audioLength(m_format, m_audioOutput->processedUSecs());
+ const qint64 playPosition = m_format.bytesForDuration(m_audioOutput->processedUSecs());
setPlayPosition(qMin(bufferLength(), playPosition));
const qint64 levelPosition = playPosition - m_levelBufferLength;
const qint64 spectrumPosition = playPosition - m_spectrumBufferLength;
@@ -359,7 +359,7 @@ void Engine::audioNotify()
// Data needs to be read into m_buffer in order to be analysed
const qint64 readPos = qMax(qint64(0), qMin(levelPosition, spectrumPosition));
const qint64 readEnd = qMin(m_analysisFile->size(), qMax(levelPosition + m_levelBufferLength, spectrumPosition + m_spectrumBufferLength));
- const qint64 readLen = readEnd - readPos + audioLength(m_format, WaveformWindowDuration);
+ const qint64 readLen = readEnd - readPos + m_format.bytesForDuration(WaveformWindowDuration);
qDebug() << "Engine::audioNotify [1]"
<< "analysisFileSize" << m_analysisFile->size()
<< "readPos" << readPos
@@ -494,7 +494,7 @@ bool Engine::initialize()
setRecordPosition(bufferLength());
result = true;
} else {
- m_bufferLength = audioLength(m_format, BufferDurationUs);
+ m_bufferLength = m_format.bytesForDuration(BufferDurationUs);
m_buffer.resize(m_bufferLength);
m_buffer.fill(0);
emit bufferLengthChanged(bufferLength());
@@ -555,56 +555,24 @@ bool Engine::selectFormat()
}
} else {
- QList<int> sampleRatesList;
- #ifdef Q_OS_WIN
- // The Windows audio backend does not correctly report format support
- // (see QTBUG-9100). Furthermore, although the audio subsystem captures
- // at 11025Hz, the resulting audio is corrupted.
- sampleRatesList += 8000;
- #endif
-
- if (!m_generateTone)
- sampleRatesList += m_audioInputDevice.supportedSampleRates();
-
- sampleRatesList += m_audioOutputDevice.supportedSampleRates();
- std::sort(sampleRatesList.begin(), sampleRatesList.end());
- const auto uniqueRatesEnd = std::unique(sampleRatesList.begin(), sampleRatesList.end());
- sampleRatesList.erase(uniqueRatesEnd, sampleRatesList.end());
- ENGINE_DEBUG << "Engine::initialize frequenciesList" << sampleRatesList;
-
- QList<int> channelsList;
- channelsList += m_audioInputDevice.supportedChannelCounts();
- channelsList += m_audioOutputDevice.supportedChannelCounts();
- std::sort(channelsList.begin(), channelsList.end());
- const auto uniqueChannelsEnd = std::unique(channelsList.begin(), channelsList.end());
- channelsList.erase(uniqueChannelsEnd, channelsList.end());
- ENGINE_DEBUG << "Engine::initialize channelsList" << channelsList;
+ QAudioDeviceInfo::Range sampleRange = m_audioInputDevice.supportedSampleRates();
+ QAudioDeviceInfo::Range outputSampleRange = m_audioOutputDevice.supportedSampleRates();
+ if (sampleRange.minimum < outputSampleRange.minimum)
+ sampleRange.minimum = outputSampleRange.minimum;
+ if (sampleRange.maximum > outputSampleRange.maximum)
+ sampleRange.maximum = outputSampleRange.maximum;
- QAudioFormat format;
- format.setByteOrder(QAudioFormat::LittleEndian);
- format.setSampleSize(16);
- format.setSampleType(QAudioFormat::SignedInt);
- for (int sampleRate : qAsConst(sampleRatesList)) {
- if (foundSupportedFormat)
- break;
- format.setSampleRate(sampleRate);
- for (int channels : qAsConst(channelsList)) {
- format.setChannelCount(channels);
- const bool inputSupport = m_generateTone ||
- m_audioInputDevice.isFormatSupported(format);
- const bool outputSupport = m_audioOutputDevice.isFormatSupported(format);
- ENGINE_DEBUG << "Engine::initialize checking " << format
- << "input" << inputSupport
- << "output" << outputSupport;
- if (inputSupport && outputSupport) {
- foundSupportedFormat = true;
- break;
- }
- }
- }
+ QAudioDeviceInfo::Range channelRange = m_audioInputDevice.supportedChannelCounts();
+ QAudioDeviceInfo::Range outputChannelRange = m_audioOutputDevice.supportedChannelCounts();
+ if (channelRange.minimum < outputChannelRange.minimum)
+ channelRange.minimum = outputChannelRange.minimum;
+ if (channelRange.maximum > outputChannelRange.maximum)
+ channelRange.maximum = outputChannelRange.maximum;
- if (!foundSupportedFormat)
- format = QAudioFormat();
+ QAudioFormat format;
+ format.setSampleFormat(QAudioFormat::Int16);
+ format.setSampleRate(qBound(sampleRange.minimum, 48000, sampleRange.maximum));
+ format.setChannelCount(qBound(channelRange.minimum, 2, channelRange.maximum));
setFormat(format);
}
@@ -728,9 +696,8 @@ void Engine::setFormat(const QAudioFormat &format)
{
const bool changed = (format != m_format);
m_format = format;
- m_levelBufferLength = audioLength(m_format, LevelWindowUs);
- m_spectrumBufferLength = SpectrumLengthSamples *
- (m_format.sampleSize() / 8) * m_format.channelCount();
+ m_levelBufferLength = m_format.bytesForDuration(LevelWindowUs);
+ m_spectrumBufferLength = SpectrumLengthSamples * format.bytesPerFrame();
if (changed)
emit formatChanged(m_format);
}
diff --git a/examples/multimedia/spectrum/app/spectrumanalyser.cpp b/examples/multimedia/spectrum/app/spectrumanalyser.cpp
index d0d1d6cf5..848aac9d6 100644
--- a/examples/multimedia/spectrum/app/spectrumanalyser.cpp
+++ b/examples/multimedia/spectrum/app/spectrumanalyser.cpp
@@ -116,10 +116,10 @@ void SpectrumAnalyserThread::calculateWindow()
void SpectrumAnalyserThread::calculateSpectrum(const QByteArray &buffer,
int inputFrequency,
- int bytesPerSample)
+ int bytesPerFrame)
{
#ifndef DISABLE_FFT
- Q_ASSERT(buffer.size() == m_numSamples * bytesPerSample);
+ Q_ASSERT(buffer.size() == m_numSamples * bytesPerFrame);
// Initialize data array
const char *ptr = buffer.constData();
@@ -129,7 +129,7 @@ void SpectrumAnalyserThread::calculateSpectrum(const QByteArray &buffer,
const DataType realSample = pcmToReal(pcmSample);
const DataType windowedSample = realSample * m_window[i];
m_input[i] = windowedSample;
- ptr += bytesPerSample;
+ ptr += bytesPerFrame;
}
// Calculate the FFT
@@ -214,16 +214,16 @@ void SpectrumAnalyser::calculate(const QByteArray &buffer,
<< "state" << m_state;
if (isReady()) {
- Q_ASSERT(isPCMS16LE(format));
+ Q_ASSERT(format.sampleFormat() == QAudioFormat::Int16);
- const int bytesPerSample = format.sampleSize() * format.channelCount() / 8;
+ const int bytesPerFrame = format.bytesPerFrame();
#ifdef DUMP_SPECTRUMANALYSER
m_count++;
const QString pcmFileName = m_outputDir.filePath(QString("spectrum_%1.pcm").arg(m_count, 4, 10, QChar('0')));
QFile pcmFile(pcmFileName);
pcmFile.open(QIODevice::WriteOnly);
- const int bufferLength = m_numSamples * bytesPerSample;
+ const int bufferLength = m_numSamples * bytesPerFrame;
pcmFile.write(buffer, bufferLength);
m_textStream << "TimeDomain " << m_count << "\n";
@@ -245,7 +245,7 @@ void SpectrumAnalyser::calculate(const QByteArray &buffer,
Qt::AutoConnection,
Q_ARG(QByteArray, buffer),
Q_ARG(int, format.sampleRate()),
- Q_ARG(int, bytesPerSample));
+ Q_ARG(int, bytesPerFrame));
Q_ASSERT(b);
Q_UNUSED(b); // suppress warnings in release builds
diff --git a/examples/multimedia/spectrum/app/tonegenerator.cpp b/examples/multimedia/spectrum/app/tonegenerator.cpp
index 2e549ab4f..3e70180fd 100644
--- a/examples/multimedia/spectrum/app/tonegenerator.cpp
+++ b/examples/multimedia/spectrum/app/tonegenerator.cpp
@@ -57,9 +57,9 @@
void generateTone(const SweptTone &tone, const QAudioFormat &format, QByteArray &buffer)
{
- Q_ASSERT(isPCMS16LE(format));
+ Q_ASSERT(format.sampleFormat() == QAudioFormat::Int16);
- const int channelBytes = format.sampleSize() / 8;
+ const int channelBytes = format.bytesPerSample();
const int sampleBytes = format.channelCount() * channelBytes;
int length = buffer.size();
const int numSamples = buffer.size() / sampleBytes;
diff --git a/examples/multimedia/spectrum/app/utils.cpp b/examples/multimedia/spectrum/app/utils.cpp
index 7e635b509..2a6b2a33e 100644
--- a/examples/multimedia/spectrum/app/utils.cpp
+++ b/examples/multimedia/spectrum/app/utils.cpp
@@ -51,20 +51,6 @@
#include <QAudioFormat>
#include "utils.h"
-qint64 audioDuration(const QAudioFormat &format, qint64 bytes)
-{
- return (bytes * 1000000) /
- (format.sampleRate() * format.channelCount() * (format.sampleSize() / 8));
-}
-
-qint64 audioLength(const QAudioFormat &format, qint64 microSeconds)
-{
- qint64 result = (format.sampleRate() * format.channelCount() * (format.sampleSize() / 8))
- * microSeconds / 1000000;
- result -= result % (format.channelCount() * format.sampleSize());
- return result;
-}
-
qreal nyquistFrequency(const QAudioFormat &format)
{
return format.sampleRate() / 2;
@@ -75,24 +61,23 @@ QString formatToString(const QAudioFormat &format)
QString result;
if (QAudioFormat() != format) {
- Q_ASSERT(format.sampleType() == QAudioFormat::SignedInt);
-
- const QString formatEndian = (format.byteOrder() == QAudioFormat::LittleEndian)
- ? QString("LE") : QString("BE");
QString formatType;
- switch (format.sampleType()) {
- case QAudioFormat::SignedInt:
- formatType = "signed";
+ switch (format.sampleFormat()) {
+ case QAudioFormat::UInt8:
+ formatType = "Unsigned8";
+ break;
+ case QAudioFormat::Int16:
+ formatType = "Signed16";
break;
- case QAudioFormat::UnSignedInt:
- formatType = "unsigned";
+ case QAudioFormat::Int32:
+ formatType = "Signed32";
break;
case QAudioFormat::Float:
- formatType = "float";
+ formatType = "Float";
break;
- case QAudioFormat::Unknown:
- formatType = "unknown";
+ default:
+ formatType = "Unknown";
break;
}
@@ -106,24 +91,16 @@ QString formatToString(const QAudioFormat &format)
break;
}
- result = QString("%1 Hz %2 bit %3 %4 %5")
+ result = QString("%1 Hz %2 bit %3 %4")
.arg(format.sampleRate())
- .arg(format.sampleSize())
+ .arg(format.bytesPerSample() * 8)
.arg(formatType)
- .arg(formatEndian)
.arg(formatChannels);
}
return result;
}
-bool isPCMS16LE(const QAudioFormat &format)
-{
- return format.sampleType() == QAudioFormat::SignedInt &&
- format.sampleSize() == 16 &&
- format.byteOrder() == QAudioFormat::LittleEndian;
-}
-
const qint16 PCMS16MaxValue = 32767;
const quint16 PCMS16MaxAmplitude = 32768; // because minimum is -32768
diff --git a/examples/multimedia/spectrum/app/utils.h b/examples/multimedia/spectrum/app/utils.h
index cd6357182..d143a83f7 100644
--- a/examples/multimedia/spectrum/app/utils.h
+++ b/examples/multimedia/spectrum/app/utils.h
@@ -60,9 +60,6 @@ QT_FORWARD_DECLARE_CLASS(QAudioFormat)
// Miscellaneous utility functions
//-----------------------------------------------------------------------------
-qint64 audioDuration(const QAudioFormat &format, qint64 bytes);
-qint64 audioLength(const QAudioFormat &format, qint64 microSeconds);
-
QString formatToString(const QAudioFormat &format);
qreal nyquistFrequency(const QAudioFormat &format);
@@ -73,12 +70,6 @@ qreal pcmToReal(qint16 pcm);
// Scale real value in [-1.0, 1.0] to PCM
qint16 realToPcm(qreal real);
-// Check whether the audio format is PCM
-bool isPCM(const QAudioFormat &format);
-
-// Check whether the audio format is signed, little-endian, 16-bit PCM
-bool isPCMS16LE(const QAudioFormat &format);
-
// Compile-time calculation of powers of two
template<int N> class PowerOfTwo
diff --git a/examples/multimedia/spectrum/app/waveform.cpp b/examples/multimedia/spectrum/app/waveform.cpp
index 7dbd6057f..5f9563a8d 100644
--- a/examples/multimedia/spectrum/app/waveform.cpp
+++ b/examples/multimedia/spectrum/app/waveform.cpp
@@ -172,7 +172,7 @@ void Waveform::initialize(const QAudioFormat &format, qint64 audioBufferSize, qi
m_tileLength = audioBufferSize;
// Calculate window size
- m_windowLength = audioLength(m_format, windowDurationUs);
+ m_windowLength = m_format.bytesForDuration(windowDurationUs);
// Calculate number of tiles required
int nTiles;
diff --git a/examples/multimedia/spectrum/app/wavfile.cpp b/examples/multimedia/spectrum/app/wavfile.cpp
index bd545d701..609ec94f0 100644
--- a/examples/multimedia/spectrum/app/wavfile.cpp
+++ b/examples/multimedia/spectrum/app/wavfile.cpp
@@ -138,16 +138,28 @@ bool WavFile::readHeader()
return false;
// Establish format
- if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0)
- m_fileFormat.setByteOrder(QAudioFormat::LittleEndian);
- else
- m_fileFormat.setByteOrder(QAudioFormat::BigEndian);
+ // ### do byte swapping for RIFX
+// if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0)
+// m_fileFormat.setByteOrder(QAudioFormat::LittleEndian);
+// else
+// m_fileFormat.setByteOrder(QAudioFormat::BigEndian);
- int bps = qFromLittleEndian<quint16>(header.wave.bitsPerSample);
m_fileFormat.setChannelCount(qFromLittleEndian<quint16>(header.wave.numChannels));
m_fileFormat.setSampleRate(qFromLittleEndian<quint32>(header.wave.sampleRate));
- m_fileFormat.setSampleSize(qFromLittleEndian<quint16>(header.wave.bitsPerSample));
- m_fileFormat.setSampleType(bps == 8 ? QAudioFormat::UnSignedInt : QAudioFormat::SignedInt);
+ switch(header.wave.bitsPerSample) {
+ case 8:
+ m_fileFormat.setSampleFormat(QAudioFormat::UInt8);
+ break;
+ case 16:
+ m_fileFormat.setSampleFormat(QAudioFormat::Int16);
+ break;
+ case 24:
+ m_fileFormat.setSampleFormat(QAudioFormat::Unknown);
+ break;
+ case 32:
+ m_fileFormat.setSampleFormat(QAudioFormat::Int32);
+ break;
+ }
} else {
result = false;
}
diff --git a/examples/multimediawidgets/player/histogramwidget.cpp b/examples/multimediawidgets/player/histogramwidget.cpp
index 928d6816e..cdf4b62b2 100644
--- a/examples/multimediawidgets/player/histogramwidget.cpp
+++ b/examples/multimediawidgets/player/histogramwidget.cpp
@@ -52,9 +52,6 @@
#include <QPainter>
#include <QHBoxLayout>
-template<class T>
-static QList<qreal> getBufferLevels(const T *buffer, int frames, int channels);
-
class QAudioLevel : public QWidget
{
Q_OBJECT
@@ -124,41 +121,6 @@ void HistogramWidget::processFrame(const QVideoFrame &frame)
Qt::QueuedConnection, Q_ARG(QVideoFrame, frame), Q_ARG(int, m_levels));
}
-// This function returns the maximum possible sample value for a given audio format
-qreal getPeakValue(const QAudioFormat& format)
-{
- // Note: Only the most common sample formats are supported
- if (!format.isValid())
- return qreal(0);
-
- switch (format.sampleType()) {
- case QAudioFormat::Unknown:
- break;
- case QAudioFormat::Float:
- if (format.sampleSize() != 32) // other sample formats are not supported
- return qreal(0);
- return qreal(1.00003);
- case QAudioFormat::SignedInt:
- if (format.sampleSize() == 32)
- return qreal(INT_MAX);
- if (format.sampleSize() == 16)
- return qreal(SHRT_MAX);
- if (format.sampleSize() == 8)
- return qreal(CHAR_MAX);
- break;
- case QAudioFormat::UnSignedInt:
- if (format.sampleSize() == 32)
- return qreal(UINT_MAX);
- if (format.sampleSize() == 16)
- return qreal(USHRT_MAX);
- if (format.sampleSize() == 8)
- return qreal(UCHAR_MAX);
- break;
- }
-
- return qreal(0);
-}
-
// returns the audio level for each channel
QList<qreal> getBufferLevels(const QAudioBuffer &buffer)
{
@@ -167,64 +129,27 @@ QList<qreal> getBufferLevels(const QAudioBuffer &buffer)
if (!buffer.isValid())
return values;
- if (!buffer.format().isValid() || buffer.format().byteOrder() != QAudioFormat::LittleEndian)
+ if (!buffer.format().isValid())
return values;
- int channelCount = buffer.format().channelCount();
- values.fill(0, channelCount);
- qreal peak_value = getPeakValue(buffer.format());
- if (qFuzzyCompare(peak_value, qreal(0)))
- return values;
+ auto format = buffer.format();
+ int channelCount = format.channelCount();
+ int bytesPerSample = format.bytesPerFrame();
+ int frames = buffer.frameCount();
- switch (buffer.format().sampleType()) {
- case QAudioFormat::Unknown:
- case QAudioFormat::UnSignedInt:
- if (buffer.format().sampleSize() == 32)
- values = getBufferLevels(buffer.constData<quint32>(), buffer.frameCount(), channelCount);
- if (buffer.format().sampleSize() == 16)
- values = getBufferLevels(buffer.constData<quint16>(), buffer.frameCount(), channelCount);
- if (buffer.format().sampleSize() == 8)
- values = getBufferLevels(buffer.constData<quint8>(), buffer.frameCount(), channelCount);
- for (double &value : values)
- value = qAbs(value - peak_value / 2) / (peak_value / 2);
- break;
- case QAudioFormat::Float:
- if (buffer.format().sampleSize() == 32) {
- values = getBufferLevels(buffer.constData<float>(), buffer.frameCount(), channelCount);
- for (double &value : values)
- value /= peak_value;
- }
- break;
- case QAudioFormat::SignedInt:
- if (buffer.format().sampleSize() == 32)
- values = getBufferLevels(buffer.constData<qint32>(), buffer.frameCount(), channelCount);
- if (buffer.format().sampleSize() == 16)
- values = getBufferLevels(buffer.constData<qint16>(), buffer.frameCount(), channelCount);
- if (buffer.format().sampleSize() == 8)
- values = getBufferLevels(buffer.constData<qint8>(), buffer.frameCount(), channelCount);
- for (double &value : values)
- value /= peak_value;
- break;
- }
-
- return values;
-}
-
-template<class T>
-QList<qreal> getBufferLevels(const T *buffer, int frames, int channels)
-{
- QList<qreal> max_values;
- max_values.fill(0, channels);
+ values.fill(0, channelCount);
+ const char *data = buffer.constData<char>();
for (int i = 0; i < frames; ++i) {
- for (int j = 0; j < channels; ++j) {
- qreal value = qAbs(qreal(buffer[i * channels + j]));
- if (value > max_values.at(j))
- max_values.replace(j, value);
+ for (int j = 0; j < channelCount; ++j) {
+ qreal value = format.normalizedSampleValue(data);
+ if (value > values.at(j))
+ values[j] = value;
+ data += bytesPerSample;
}
}
- return max_values;
+ return values;
}
void HistogramWidget::processBuffer(const QAudioBuffer &buffer)
diff --git a/src/multimedia/audio/qaudiobuffer.cpp b/src/multimedia/audio/qaudiobuffer.cpp
index 10feed5d1..919245e1a 100644
--- a/src/multimedia/audio/qaudiobuffer.cpp
+++ b/src/multimedia/audio/qaudiobuffer.cpp
@@ -118,15 +118,19 @@ public:
if (data) {
memcpy(mBuffer, data, numBytes);
} else {
- // We have to fill with the zero value..
- switch (format.sampleType()) {
- case QAudioFormat::SignedInt:
- // Signed int means 0x80, 0x8000 is zero
- // XXX this is not right for > 8 bits(0x8080 vs 0x8000)
- memset(mBuffer, 0x80, numBytes);
- break;
- default:
- memset(mBuffer, 0x0, numBytes);
+ // We have to fill with the zero value
+ switch (format.sampleFormat()) {
+ case QAudioFormat::Unknown:
+ case QAudioFormat::NSampleFormats:
+ return;
+ case QAudioFormat::UInt8:
+ memset(mBuffer, 0x80, numBytes);
+ break;
+ case QAudioFormat::Int16:
+ case QAudioFormat::Int32:
+ case QAudioFormat::Float:
+ memset(mBuffer, 0x0, numBytes);
+ break;
}
}
}
@@ -348,7 +352,6 @@ int QAudioBuffer::sampleCount() const
*/
int QAudioBuffer::byteCount() const
{
- const QAudioFormat f(format());
return format().bytesForFrames(frameCount());
}
diff --git a/src/multimedia/audio/qaudiodeviceinfo.cpp b/src/multimedia/audio/qaudiodeviceinfo.cpp
index 5b4ff7c80..f034d732e 100644
--- a/src/multimedia/audio/qaudiodeviceinfo.cpp
+++ b/src/multimedia/audio/qaudiodeviceinfo.cpp
@@ -53,11 +53,6 @@ static void qRegisterAudioDeviceInfoMetaTypes()
Q_CONSTRUCTOR_FUNCTION(qRegisterAudioDeviceInfoMetaTypes)
-QAudioDeviceInfoPrivate::QAudioDeviceInfoPrivate(const QByteArray &h, QAudio::Mode m)
- : id(h), mode(m)
-{
-}
-
QAudioDeviceInfoPrivate::~QAudioDeviceInfoPrivate()
{
}
@@ -198,7 +193,7 @@ QByteArray QAudioDeviceInfo::id() const
*/
QString QAudioDeviceInfo::description() const
{
- return isNull() ? QString() : d->description();
+ return isNull() ? QString() : d->description;
}
/*!
@@ -215,7 +210,15 @@ bool QAudioDeviceInfo::isDefault() const
*/
bool QAudioDeviceInfo::isFormatSupported(const QAudioFormat &settings) const
{
- return isNull() ? false : d->isFormatSupported(settings);
+ if (isNull())
+ return false;
+ if (settings.sampleRate() < d->supportedSampleRates.minimum || settings.sampleRate() > d->supportedSampleRates.maximum)
+ return false;
+ if (settings.channelCount() < d->supportedChannelCounts.minimum || settings.channelCount() > d->supportedChannelCounts.maximum)
+ return false;
+ if (!d->supportedSampleFormats.contains(settings.sampleFormat()))
+ return false;
+ return true;
}
/*!
@@ -233,96 +236,16 @@ bool QAudioDeviceInfo::isFormatSupported(const QAudioFormat &settings) const
*/
QAudioFormat QAudioDeviceInfo::preferredFormat() const
{
- return isNull() ? QAudioFormat() : d->preferredFormat();
-}
-
-/*!
- Returns the closest QAudioFormat to the supplied \a settings that the system supports.
-
- These settings are provided by the platform/audio plugin being used.
-
- They are also dependent on the \l {QAudio}::Mode being used.
-*/
-QAudioFormat QAudioDeviceInfo::nearestFormat(const QAudioFormat &settings) const
-{
- if (isFormatSupported(settings))
- return settings;
-
- QAudioFormat nearest = settings;
-
- QList<int> testChannels = supportedChannelCounts();
- QList<QAudioFormat::Endian> testByteOrders = supportedByteOrders();
- QList<QAudioFormat::SampleType> testSampleTypes;
- QList<QAudioFormat::SampleType> sampleTypesAvailable = supportedSampleTypes();
- QMap<int,int> testSampleRates;
- QList<int> sampleRatesAvailable = supportedSampleRates();
- QMap<int,int> testSampleSizes;
- QList<int> sampleSizesAvailable = supportedSampleSizes();
-
- testChannels.removeAll(settings.channelCount());
- testChannels.insert(0, settings.channelCount());
- testByteOrders.removeAll(settings.byteOrder());
- testByteOrders.insert(0, settings.byteOrder());
-
- if (sampleTypesAvailable.contains(settings.sampleType()))
- testSampleTypes.append(settings.sampleType());
- if (sampleTypesAvailable.contains(QAudioFormat::SignedInt))
- testSampleTypes.append(QAudioFormat::SignedInt);
- if (sampleTypesAvailable.contains(QAudioFormat::UnSignedInt))
- testSampleTypes.append(QAudioFormat::UnSignedInt);
- if (sampleTypesAvailable.contains(QAudioFormat::Float))
- testSampleTypes.append(QAudioFormat::Float);
-
- if (sampleSizesAvailable.contains(settings.sampleSize()))
- testSampleSizes.insert(0,settings.sampleSize());
- sampleSizesAvailable.removeAll(settings.sampleSize());
- for (int size : qAsConst(sampleSizesAvailable)) {
- int larger = (size > settings.sampleSize()) ? size : settings.sampleSize();
- int smaller = (size > settings.sampleSize()) ? settings.sampleSize() : size;
- bool isMultiple = ( 0 == (larger % smaller));
- int diff = larger - smaller;
- testSampleSizes.insert((isMultiple ? diff : diff+100000), size);
- }
- if (sampleRatesAvailable.contains(settings.sampleRate()))
- testSampleRates.insert(0,settings.sampleRate());
- sampleRatesAvailable.removeAll(settings.sampleRate());
- for (int sampleRate : qAsConst(sampleRatesAvailable)) {
- int larger = (sampleRate > settings.sampleRate()) ? sampleRate : settings.sampleRate();
- int smaller = (sampleRate > settings.sampleRate()) ? settings.sampleRate() : sampleRate;
- bool isMultiple = ( 0 == (larger % smaller));
- int diff = larger - smaller;
- testSampleRates.insert((isMultiple ? diff : diff+100000), sampleRate);
- }
-
- // Try to find nearest
- for (QAudioFormat::Endian order : qAsConst(testByteOrders)) {
- nearest.setByteOrder(order);
- for (QAudioFormat::SampleType sample : qAsConst(testSampleTypes)) {
- nearest.setSampleType(sample);
- for (int sampleSize : qAsConst(testSampleSizes)) {
- nearest.setSampleSize(sampleSize);
- for (int channel : qAsConst(testChannels)) {
- nearest.setChannelCount(channel);
- for (int sampleRate : qAsConst(testSampleRates)) {
- nearest.setSampleRate(sampleRate);
- if (isFormatSupported(nearest))
- return nearest;
- }
- }
- }
- }
- }
- //Fallback
- return preferredFormat();
+ return isNull() ? QAudioFormat() : d->preferredFormat;
}
/*!
Returns a list of supported sample rates (in Hertz).
*/
-QList<int> QAudioDeviceInfo::supportedSampleRates() const
+QAudioDeviceInfo::Range QAudioDeviceInfo::supportedSampleRates() const
{
- return isNull() ? QList<int>() : d->supportedSampleRates();
+ return isNull() ? Range{0, 0} : d->supportedSampleRates;
}
/*!
@@ -331,36 +254,17 @@ QList<int> QAudioDeviceInfo::supportedSampleRates() const
This is typically 1 for mono sound, or 2 for stereo sound.
*/
-QList<int> QAudioDeviceInfo::supportedChannelCounts() const
-{
- return isNull() ? QList<int>() : d->supportedChannelCounts();
-}
-
-/*!
- Returns a list of supported sample sizes (in bits).
-
- Typically this will include 8 and 16 bit sample sizes.
-
-*/
-QList<int> QAudioDeviceInfo::supportedSampleSizes() const
-{
- return isNull() ? QList<int>() : d->supportedSampleSizes();
-}
-
-/*!
- Returns a list of supported byte orders.
-*/
-QList<QAudioFormat::Endian> QAudioDeviceInfo::supportedByteOrders() const
+QAudioDeviceInfo::Range QAudioDeviceInfo::supportedChannelCounts() const
{
- return isNull() ? QList<QAudioFormat::Endian>() : d->supportedByteOrders();
+ return isNull() ? Range{0, 0} : d->supportedChannelCounts;
}
/*!
Returns a list of supported sample types.
*/
-QList<QAudioFormat::SampleType> QAudioDeviceInfo::supportedSampleTypes() const
+QList<QAudioFormat::SampleFormat> QAudioDeviceInfo::supportedSampleFormats() const
{
- return isNull() ? QList<QAudioFormat::SampleType>() : d->supportedSampleTypes();
+ return isNull() ? QList<QAudioFormat::SampleFormat>() : d->supportedSampleFormats;
}
QAudioDeviceInfo::QAudioDeviceInfo(QAudioDeviceInfoPrivate *p)
diff --git a/src/multimedia/audio/qaudiodeviceinfo.h b/src/multimedia/audio/qaudiodeviceinfo.h
index 13b2ad659..b9af01cc6 100644
--- a/src/multimedia/audio/qaudiodeviceinfo.h
+++ b/src/multimedia/audio/qaudiodeviceinfo.h
@@ -78,18 +78,21 @@ public:
bool isFormatSupported(const QAudioFormat &format) const;
QAudioFormat preferredFormat() const;
- QAudioFormat nearestFormat(const QAudioFormat &format) const;
- QList<int> supportedSampleRates() const;
- QList<int> supportedChannelCounts() const;
- QList<int> supportedSampleSizes() const;
- QList<QAudioFormat::Endian> supportedByteOrders() const;
- QList<QAudioFormat::SampleType> supportedSampleTypes() const;
+ struct Range {
+ int minimum = 0;
+ int maximum = 0;
+ };
+
+ Range supportedSampleRates() const;
+ Range supportedChannelCounts() const;
+ QList<QAudioFormat::SampleFormat> supportedSampleFormats() const;
- QAudioDeviceInfo(QAudioDeviceInfoPrivate *p);
const QAudioDeviceInfoPrivate *handle() const { return d.get(); }
private:
+ friend class QAudioDeviceInfoPrivate;
+ QAudioDeviceInfo(QAudioDeviceInfoPrivate *p);
QSharedDataPointer<QAudioDeviceInfoPrivate> d;
};
diff --git a/src/multimedia/audio/qaudiodeviceinfo_p.h b/src/multimedia/audio/qaudiodeviceinfo_p.h
index 341dff608..d7cc836ae 100644
--- a/src/multimedia/audio/qaudiodeviceinfo_p.h
+++ b/src/multimedia/audio/qaudiodeviceinfo_p.h
@@ -59,21 +59,22 @@ QT_BEGIN_NAMESPACE
class QAudioDeviceInfoPrivate : public QSharedData
{
public:
- QAudioDeviceInfoPrivate(const QByteArray &h, QAudio::Mode m);
+ QAudioDeviceInfoPrivate(const QByteArray &i, QAudio::Mode m)
+ : id(i),
+ mode(m)
+ {}
virtual ~QAudioDeviceInfoPrivate();
-
- virtual QAudioFormat preferredFormat() const = 0;
- virtual bool isFormatSupported(const QAudioFormat &format) const = 0;
- virtual QString description() const = 0;
- virtual QList<int> supportedSampleRates() const = 0;
- virtual QList<int> supportedChannelCounts() const = 0;
- virtual QList<int> supportedSampleSizes() const = 0;
- virtual QList<QAudioFormat::Endian> supportedByteOrders() const = 0;
- virtual QList<QAudioFormat::SampleType> supportedSampleTypes() const = 0;
-
QByteArray id;
QAudio::Mode mode = QAudio::AudioOutput;
bool isDefault = false;
+
+ QAudioFormat preferredFormat;
+ QString description;
+ QAudioDeviceInfo::Range supportedSampleRates;
+ QAudioDeviceInfo::Range supportedChannelCounts;
+ QList<QAudioFormat::SampleFormat> supportedSampleFormats;
+
+ QAudioDeviceInfo create() { return QAudioDeviceInfo(this); }
};
QT_END_NAMESPACE
diff --git a/src/multimedia/audio/qaudioformat.cpp b/src/multimedia/audio/qaudioformat.cpp
index 389112f80..536cb52c2 100644
--- a/src/multimedia/audio/qaudioformat.cpp
+++ b/src/multimedia/audio/qaudioformat.cpp
@@ -42,58 +42,6 @@
QT_BEGIN_NAMESPACE
-static void qRegisterAudioFormatMetaTypes()
-{
- qRegisterMetaType<QAudioFormat>();
- qRegisterMetaType<QAudioFormat::SampleType>();
- qRegisterMetaType<QAudioFormat::Endian>();
-}
-
-Q_CONSTRUCTOR_FUNCTION(qRegisterAudioFormatMetaTypes)
-
-class QAudioFormatPrivate : public QSharedData
-{
-public:
- QAudioFormatPrivate()
- {
- sampleRate = -1;
- channels = -1;
- sampleSize = -1;
- byteOrder = QAudioFormat::Endian(QSysInfo::ByteOrder);
- sampleType = QAudioFormat::Unknown;
- }
-
- QAudioFormatPrivate(const QAudioFormatPrivate &other):
- QSharedData(other),
- codec(other.codec),
- byteOrder(other.byteOrder),
- sampleType(other.sampleType),
- sampleRate(other.sampleRate),
- channels(other.channels),
- sampleSize(other.sampleSize)
- {
- }
-
- QAudioFormatPrivate& operator=(const QAudioFormatPrivate &other)
- {
- codec = other.codec;
- byteOrder = other.byteOrder;
- sampleType = other.sampleType;
- sampleRate = other.sampleRate;
- channels = other.channels;
- sampleSize = other.sampleSize;
-
- return *this;
- }
-
- QString codec;
- QAudioFormat::Endian byteOrder;
- QAudioFormat::SampleType sampleType;
- int sampleRate;
- int channels;
- int sampleSize;
-};
-
/*!
\class QAudioFormat
\brief The QAudioFormat class stores audio stream parameter information.
@@ -102,14 +50,12 @@ public:
\ingroup multimedia
\ingroup multimedia_audio
- An audio format specifies how data in an audio stream is arranged,
- i.e, how the stream is to be interpreted. The encoding itself is
- specified by the codec() used for the stream.
+ An audio format specifies how data in a raw audio stream is arranged,
+ i.e, how the stream is to be interpreted.
- In addition to the encoding, QAudioFormat contains other
- parameters that further specify how the audio sample data is arranged.
- These are the frequency, the number of channels, the sample size,
- the sample type, and the byte order. The following table describes
+ QAudioFormat contains parameters that specify how the audio sample data
+ is arranged. These are the frequency, the number of channels, and the
+ sameple format. The following table describes
these in more detail.
\table
@@ -122,21 +68,14 @@ public:
\row
\li Number of channels
\li The number of audio channels (typically one for mono
- or two for stereo)
+ or two for stereo). These are the amount of consecutive
+ samples that together form one frame in the stream
\row
- \li Sample size
- \li How much data is stored in each sample (typically 8
- or 16 bits)
- \row
- \li Sample type
- \li Numerical representation of sample (typically signed integer,
- unsigned integer or float)
- \row
- \li Byte order
- \li Byte ordering of sample (typically little endian, big endian)
+ \li Sample format
+ \li The format of the audio samples in the stream
\endtable
- This class is typically used in conjunction with QAudioInput or
+ This class is used in conjunction with QAudioInput or
QAudioOutput to allow you to specify the parameters of the audio
stream being read or written, or with QAudioBuffer when dealing with
samples in memory.
@@ -148,177 +87,90 @@ public:
description for details. You need to know the format of the audio
streams you wish to play or record.
- In the common case of interleaved linear PCM data, the codec will
- be "audio/x-raw", and the samples for all channels will be interleaved.
+ Samples for all channels will be interleaved.
One sample for each channel for the same instant in time is referred
to as a frame in Qt Multimedia (and other places).
*/
/*!
+ \fn QAudioFormat::QAudioFormat()
+
Construct a new audio format.
Values are initialized as follows:
\list
- \li sampleRate() = -1
- \li channelCount() = -1
- \li sampleSize() = -1
- \li byteOrder() = QAudioFormat::Endian(QSysInfo::ByteOrder)
- \li sampleType() = QAudioFormat::Unknown
- \c codec() = ""
+ \li sampleRate() = 0
+ \li channelCount() = 0
+ \li sampleFormat() = QAudioFormat::Unknown
\endlist
*/
-QAudioFormat::QAudioFormat():
- d(new QAudioFormatPrivate)
-{
-}
/*!
- Construct a new audio format using \a other.
-*/
-QAudioFormat::QAudioFormat(const QAudioFormat &other):
- d(other.d)
-{
-}
-
-/*!
- Destroy this audio format.
-*/
-QAudioFormat::~QAudioFormat()
-{
-}
+ \fn QAudioFormat::QAudioFormat(const QAudioFormat &other)
-/*!
- Assigns \a other to this QAudioFormat implementation.
+ Construct a new audio format using \a other.
*/
-QAudioFormat& QAudioFormat::operator=(const QAudioFormat &other)
-{
- d = other.d;
- return *this;
-}
/*!
- Returns true if this QAudioFormat is equal to the \a other
- QAudioFormat; otherwise returns false.
+ \fn QAudioFormat::~QAudioFormat()
- All elements of QAudioFormat are used for the comparison.
+ Destroy this audio format.
*/
-bool QAudioFormat::operator==(const QAudioFormat &other) const
-{
- return d->sampleRate == other.d->sampleRate &&
- d->channels == other.d->channels &&
- d->sampleSize == other.d->sampleSize &&
- d->byteOrder == other.d->byteOrder &&
- d->codec == other.d->codec &&
- d->sampleType == other.d->sampleType;
-}
/*!
- Returns true if this QAudioFormat is not equal to the \a other
- QAudioFormat; otherwise returns false.
+ \fn QAudioFormat& QAudioFormat::operator=(const QAudioFormat &other)
- All elements of QAudioFormat are used for the comparison.
+ Assigns \a other to this QAudioFormat implementation.
*/
-bool QAudioFormat::operator!=(const QAudioFormat& other) const
-{
- return !(*this == other);
-}
/*!
Returns true if all of the parameters are valid.
*/
bool QAudioFormat::isValid() const
{
- return d->sampleRate != -1 && d->channels != -1 && d->sampleSize != -1 &&
- d->sampleType != QAudioFormat::Unknown && !d->codec.isEmpty();
+ return m_sampleRate > 0 && m_channelCount > 0 && m_sampleFormat != Unknown;
}
/*!
- Sets the sample rate to \a samplerate Hertz.
+ \fn void QAudioFormat::setSampleRate(int samplerate)
+ Sets the sample rate to \a samplerate Hertz.
*/
-void QAudioFormat::setSampleRate(int samplerate)
-{
- d->sampleRate = samplerate;
-}
/*!
- Returns the current sample rate in Hertz.
+ \fn int QAudioFormat::sampleRate() const
+ Returns the current sample rate in Hertz.
*/
-int QAudioFormat::sampleRate() const
-{
- return d->sampleRate;
-}
/*!
- Sets the channel count to \a channels.
+ \fn void QAudioFormat::setChannelCount(int channels)
-*/
-void QAudioFormat::setChannelCount(int channels)
-{
- d->channels = channels;
-}
-
-/*!
- Returns the current channel count value.
+ Sets the channel count to \a channels.
*/
-int QAudioFormat::channelCount() const
-{
- return d->channels;
-}
/*!
- Sets the sample size to the \a sampleSize specified, in bits.
+ \fn int QAudioFormat::channelCount() const
- This is typically 8 or 16, but some systems may support higher sample sizes.
-*/
-void QAudioFormat::setSampleSize(int sampleSize)
-{
- d->sampleSize = sampleSize;
-}
-
-/*!
- Returns the current sample size value, in bits.
+ Returns the current channel count value.
- \sa bytesPerFrame()
*/
-int QAudioFormat::sampleSize() const
-{
- return d->sampleSize;
-}
/*!
- Sets the byteOrder to \a byteOrder.
-*/
-void QAudioFormat::setByteOrder(QAudioFormat::Endian byteOrder)
-{
- d->byteOrder = byteOrder;
-}
+ \fn void QAudioFormat::setSampleFormat(SampleFormat format)
-/*!
- Returns the current byteOrder value.
-*/
-QAudioFormat::Endian QAudioFormat::byteOrder() const
-{
- return d->byteOrder;
-}
+ Sets the sample format to \a format.
-/*!
- Sets the sampleType to \a sampleType.
+ \sa QAudioFormat::SampleFormat
*/
-void QAudioFormat::setSampleType(QAudioFormat::SampleType sampleType)
-{
- d->sampleType = sampleType;
-}
/*!
- Returns the current SampleType value.
+ \fn QAudioFormat::SampleFormat QAudioFormat::sampleFormat() const
+ Returns the current sample format.
+
+ \sa setSampleFormat()
*/
-QAudioFormat::SampleType QAudioFormat::sampleType() const
-{
- return d->sampleType;
-}
/*!
Returns the number of bytes required for this audio format for \a duration microseconds.
@@ -410,79 +262,97 @@ qint64 QAudioFormat::durationForFrames(qint32 frameCount) const
}
/*!
+ \fn int QAudioFormat::bytesPerFrame() const
+
Returns the number of bytes required to represent one frame (a sample in each channel) in this format.
Returns 0 if this format is invalid.
*/
-int QAudioFormat::bytesPerFrame() const
+
+/*!
+ Returns the number of bytes required to represent one sample in this format.
+
+ Returns 0 if this format is invalid.
+*/
+int QAudioFormat::bytesPerSample() const
{
- if (!isValid())
+ switch (m_sampleFormat) {
+ case Unknown:
+ case NSampleFormats:
return 0;
-
- return (sampleSize() * channelCount()) / 8;
+ case UInt8:
+ return 1;
+ case Int16:
+ return 2;
+ case Int32:
+ case Float:
+ return 4;
+ }
}
/*!
- \enum QAudioFormat::SampleType
-
- \value Unknown Not Set
- \value SignedInt Samples are signed integers
- \value UnSignedInt Samples are unsigned intergers
- \value Float Samples are floats
+ Normalizes the sample value to a number between -1 and 1.
*/
+float QAudioFormat::normalizedSampleValue(const void *sample) const
+{
+ switch (m_sampleFormat) {
+ case UInt8:
+ return ((float)*reinterpret_cast<const quint8 *>(sample))/(float)std::numeric_limits<qint8>::max() - 1.;
+ case Int16:
+ return ((float)*reinterpret_cast<const qint16 *>(sample))/(float)std::numeric_limits<qint16>::max();
+ case Int32:
+ return ((float)*reinterpret_cast<const qint32 *>(sample))/(float)std::numeric_limits<qint32>::max();
+ case Float:
+ return *reinterpret_cast<const float *>(sample);
+ case Unknown:
+ case NSampleFormats:
+ break;
+ }
+
+ return 0.;
+}
/*!
- \enum QAudioFormat::Endian
+ \enum QAudioFormat::SampleFormat
+
+ Qt will always expect and use samples in the endianness of the host platform. When processing audio data
+ from external sources yourself, ensure you convert them to the correct endianness before writing them to
+ a QAudioOutput or QAudioBuffer
- \value BigEndian Samples are big endian byte order
- \value LittleEndian Samples are little endian byte order
+ \value Unknown Not Set
+ \value Int16 Samples are 16 bit signed integers
+ \value Int32 Samples are 32 bit signed intergers
+ \value Float Samples are floats
*/
#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug dbg, QAudioFormat::Endian endian)
-{
- QDebugStateSaver saver(dbg);
- dbg.nospace();
- switch (endian) {
- case QAudioFormat::BigEndian:
- dbg << "BigEndian";
- break;
- case QAudioFormat::LittleEndian:
- dbg << "LittleEndian";
- break;
- }
- return dbg;
-}
-
-QDebug operator<<(QDebug dbg, QAudioFormat::SampleType type)
+QDebug operator<<(QDebug dbg, QAudioFormat::SampleFormat type)
{
QDebugStateSaver saver(dbg);
dbg.nospace();
switch (type) {
- case QAudioFormat::SignedInt:
- dbg << "SignedInt";
- break;
- case QAudioFormat::UnSignedInt:
- dbg << "UnSignedInt";
- break;
- case QAudioFormat::Float:
- dbg << "Float";
- break;
- default:
- dbg << "Unknown";
- break;
+ case QAudioFormat::UInt8:
+ dbg << "UInt8";
+ break;
+ case QAudioFormat::Int16:
+ dbg << "Int16";
+ break;
+ case QAudioFormat::Int32:
+ dbg << "Int32";
+ break;
+ case QAudioFormat::Float:
+ dbg << "Float";
+ break;
+ default:
+ dbg << "Unknown";
+ break;
}
return dbg;
}
QDebug operator<<(QDebug dbg, const QAudioFormat &f)
{
- QDebugStateSaver saver(dbg);
- dbg.nospace();
- dbg << "QAudioFormat(" << f.sampleRate() << "Hz, "
- << f.sampleSize() << "bit, channelCount=" << f.channelCount()
- << ", sampleType=" << f.sampleType() << ", byteOrder=" << f.byteOrder();
-
+ dbg << "QAudioFormat(" << f.sampleRate() << "Hz, " << f.channelCount() << "Channels, " << f.sampleFormat() << "Format";
return dbg;
}
#endif
diff --git a/src/multimedia/audio/qaudioformat.h b/src/multimedia/audio/qaudioformat.h
index c04cd63a3..04d6eb560 100644
--- a/src/multimedia/audio/qaudioformat.h
+++ b/src/multimedia/audio/qaudioformat.h
@@ -54,33 +54,25 @@ class QAudioFormatPrivate;
class Q_MULTIMEDIA_EXPORT QAudioFormat
{
public:
- enum SampleType { Unknown, SignedInt, UnSignedInt, Float };
- enum Endian { BigEndian = QSysInfo::BigEndian, LittleEndian = QSysInfo::LittleEndian };
-
- QAudioFormat();
- QAudioFormat(const QAudioFormat &other);
- ~QAudioFormat();
-
- QAudioFormat& operator=(const QAudioFormat &other);
- bool operator==(const QAudioFormat &other) const;
- bool operator!=(const QAudioFormat &other) const;
+ enum SampleFormat {
+ Unknown,
+ UInt8,
+ Int16,
+ Int32,
+ Float,
+ NSampleFormats
+ };
bool isValid() const;
- void setSampleRate(int sampleRate);
- int sampleRate() const;
-
- void setChannelCount(int channelCount);
- int channelCount() const;
-
- void setSampleSize(int sampleSize);
- int sampleSize() const;
+ void setSampleRate(int sampleRate) { m_sampleRate = sampleRate; }
+ int sampleRate() const { return m_sampleRate; }
- void setByteOrder(QAudioFormat::Endian byteOrder);
- QAudioFormat::Endian byteOrder() const;
+ void setChannelCount(int channelCount) { m_channelCount = channelCount; }
+ int channelCount() const { return m_channelCount; }
- void setSampleType(QAudioFormat::SampleType sampleType);
- QAudioFormat::SampleType sampleType() const;
+ void setSampleFormat(SampleFormat f) { m_sampleFormat = f; }
+ SampleFormat sampleFormat() const { return m_sampleFormat; }
// Helper functions
qint32 bytesForDuration(qint64 duration) const;
@@ -92,22 +84,33 @@ public:
qint32 framesForDuration(qint64 duration) const;
qint64 durationForFrames(qint32 frameCount) const;
- int bytesPerFrame() const;
+ int bytesPerFrame() const { return bytesPerSample()*channelCount(); }
+ int bytesPerSample() const;
+
+ float normalizedSampleValue(const void *sample) const;
+
+ friend bool operator==(const QAudioFormat &a, const QAudioFormat &b)
+ {
+ return a.m_sampleRate == b.m_sampleRate &&
+ a.m_channelCount == b.m_channelCount &&
+ a.m_sampleFormat == b.m_sampleFormat;
+ }
+ friend bool operator!=(const QAudioFormat &a, const QAudioFormat &b)
+ {
+ return !(a == b);
+ }
private:
- QSharedDataPointer<QAudioFormatPrivate> d;
+ int m_sampleRate = 0;
+ short m_channelCount = 0;
+ SampleFormat m_sampleFormat = SampleFormat::Unknown;
};
#ifndef QT_NO_DEBUG_STREAM
Q_MULTIMEDIA_EXPORT QDebug operator<<(QDebug, const QAudioFormat &);
-Q_MULTIMEDIA_EXPORT QDebug operator<<(QDebug, QAudioFormat::SampleType);
-Q_MULTIMEDIA_EXPORT QDebug operator<<(QDebug, QAudioFormat::Endian);
+Q_MULTIMEDIA_EXPORT QDebug operator<<(QDebug, QAudioFormat::SampleFormat);
#endif
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QAudioFormat)
-Q_DECLARE_METATYPE(QAudioFormat::SampleType)
-Q_DECLARE_METATYPE(QAudioFormat::Endian)
-
#endif // QAUDIOFORMAT_H
diff --git a/src/multimedia/audio/qaudiohelpers.cpp b/src/multimedia/audio/qaudiohelpers.cpp
index ac5e308aa..4d8e983cf 100644
--- a/src/multimedia/audio/qaudiohelpers.cpp
+++ b/src/multimedia/audio/qaudiohelpers.cpp
@@ -43,49 +43,6 @@
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>
- [[nodiscard]] 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
{
@@ -106,18 +63,6 @@ template<> struct signedVersion<quint8>
enum {offset = 0x80};
};
-template<> struct signedVersion<quint16>
-{
- using TS = qint16;
- enum {offset = 0x8000};
-};
-
-template<> struct signedVersion<quint32>
-{
- using TS = qint32;
- enum {offset = 0x80000000};
-};
-
template<class T> void adjustUnsignedSamples(qreal factor, const void *src, void *dst, int samples)
{
const T *pSrc = (const T *)src;
@@ -129,34 +74,24 @@ template<class T> void adjustUnsignedSamples(qreal factor, const void *src, void
void qMultiplySamples(qreal factor, const QAudioFormat &format, const void* src, void* dest, int len)
{
- int samplesCount = len / (format.sampleSize()/8);
-
- switch ( format.sampleSize() ) {
- case 8:
- if (format.sampleType() == QAudioFormat::SignedInt)
- QAudioHelperInternal::adjustSamples<qint8>(factor,src,dest,samplesCount);
- else if (format.sampleType() == QAudioFormat::UnSignedInt)
- QAudioHelperInternal::adjustUnsignedSamples<quint8>(factor,src,dest,samplesCount);
+ int samplesCount = len / (format.bytesPerSample());
+
+ switch (format.sampleFormat()) {
+ case QAudioFormat::Unknown:
+ case QAudioFormat::NSampleFormats:
+ return;
+ case QAudioFormat::UInt8:
+ QAudioHelperInternal::adjustUnsignedSamples<quint8>(factor,src,dest,samplesCount);
+ break;
+ case QAudioFormat::Int16:
+ QAudioHelperInternal::adjustSamples<qint16>(factor,src,dest,samplesCount);
break;
- case 16:
- if (format.sampleType() == QAudioFormat::SignedInt)
- QAudioHelperInternal::adjustSamples<qint16>(factor,src,dest,samplesCount);
- else if (format.sampleType() == QAudioFormat::UnSignedInt)
- QAudioHelperInternal::adjustUnsignedSamples<quint16>(factor,src,dest,samplesCount);
+ case QAudioFormat::Int32:
+ QAudioHelperInternal::adjustSamples<qint32>(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);
+ case QAudioFormat::Float:
+ QAudioHelperInternal::adjustSamples<float>(factor,src,dest,samplesCount);
break;
- default:
- if (format.sampleType() == QAudioFormat::SignedInt)
- QAudioHelperInternal::adjustSamples<qint32>(factor,src,dest,samplesCount);
- else if (format.sampleType() == QAudioFormat::UnSignedInt)
- QAudioHelperInternal::adjustUnsignedSamples<quint32>(factor,src,dest,samplesCount);
- else if (format.sampleType() == QAudioFormat::Float)
- QAudioHelperInternal::adjustSamples<float>(factor,src,dest,samplesCount);
}
}
}
diff --git a/src/multimedia/audio/qwavedecoder_p.cpp b/src/multimedia/audio/qwavedecoder_p.cpp
index 18bff97eb..f3c664cb4 100644
--- a/src/multimedia/audio/qwavedecoder_p.cpp
+++ b/src/multimedia/audio/qwavedecoder_p.cpp
@@ -44,14 +44,41 @@
QT_BEGIN_NAMESPACE
-QWaveDecoder::QWaveDecoder(QIODevice *s, QObject *parent):
- QIODevice(parent),
- haveFormat(false),
- dataSize(0),
- source(s),
- state(QWaveDecoder::InitialState),
- junkToSkip(0),
- bigEndian(false)
+namespace {
+
+void bswap2(char *data, qsizetype count) noexcept
+{
+ for (qsizetype i = 0; i < count; ++i) {
+ qSwap(data[0], data[1]);
+ ++count;
+ data += 2;
+ }
+}
+
+void bswap3(char *data, qsizetype count) noexcept
+{
+ for (qsizetype i = 0; i < count; ++i) {
+ qSwap(data[0], data[2]);
+ ++count;
+ data += 3;
+ }
+}
+
+void bswap4(char *data, qsizetype count) noexcept
+{
+ for (qsizetype i = 0; i < count; ++i) {
+ qSwap(data[0], data[3]);
+ qSwap(data[1], data[2]);
+ ++count;
+ data += 4;
+ }
+}
+
+}
+
+QWaveDecoder::QWaveDecoder(QIODevice *s, QObject *parent)
+ : QIODevice(parent),
+ source(s)
{
open(QIODevice::ReadOnly | QIODevice::Unbuffered);
@@ -72,7 +99,7 @@ QAudioFormat QWaveDecoder::audioFormat() const
int QWaveDecoder::duration() const
{
- return size() * 1000 / (format.sampleSize() / 8) / format.channelCount() / format.sampleRate();
+ return size() * 1000 / (format.bytesPerFrame() * format.sampleRate());
}
qint64 QWaveDecoder::size() const
@@ -92,7 +119,28 @@ qint64 QWaveDecoder::bytesAvailable() const
qint64 QWaveDecoder::readData(char *data, qint64 maxlen)
{
- return haveFormat ? source->read(data, maxlen) : 0;
+ if (!haveFormat)
+ return 0;
+
+ qint64 nSamples = maxlen / format.bytesPerSample();
+ maxlen = nSamples * format.bytesPerFrame();
+ source->read(data, maxlen);
+
+ if (!byteSwap || format.bytesPerFrame() == 1)
+ return maxlen;
+
+ switch (format.bytesPerSample()) {
+ case 2:
+ bswap2(data, nSamples);
+ break;
+ case 3:
+ bswap3(data, nSamples);
+ break;
+ case 4:
+ bswap4(data, nSamples);
+ break;
+ }
+ return maxlen;
}
qint64 QWaveDecoder::writeData(const char *data, qint64 len)
@@ -141,6 +189,7 @@ void QWaveDecoder::handleData()
state = QWaveDecoder::WaitingForFormatState;
bigEndian = (qstrncmp(riff.descriptor.id, "RIFX", 4) == 0);
+ byteSwap = (bigEndian != (QSysInfo::ByteOrder == QSysInfo::BigEndian));
}
if (state == QWaveDecoder::WaitingForFormatState) {
@@ -172,23 +221,39 @@ void QWaveDecoder::handleData()
return;
}
+ int bps;
+ int rate;
+ int channels;
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));
+ bps = qFromBigEndian<quint16>(wave.bitsPerSample);
+ rate = qFromBigEndian<quint32>(wave.sampleRate);
+ channels = qFromBigEndian<quint16>(wave.numChannels);
} else {
- int bps = qFromLittleEndian<quint16>(wave.bitsPerSample);
+ bps = qFromLittleEndian<quint16>(wave.bitsPerSample);
+ rate = qFromLittleEndian<quint32>(wave.sampleRate);
+ channels = qFromLittleEndian<quint16>(wave.numChannels);
+ }
- 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));
+ QAudioFormat::SampleFormat fmt = QAudioFormat::Unknown;
+ switch(bps) {
+ case 8:
+ fmt = QAudioFormat::UInt8;
+ break;
+ case 16:
+ fmt = QAudioFormat::Int16;
+ case 24:
+ fmt = QAudioFormat::Unknown;
+ case 32:
+ fmt = QAudioFormat::Int32;
}
+ if (fmt == QAudioFormat::Unknown || rate == 0 || channels == 0) {
+ parsingFailed();
+ return;
+ }
+
+ format.setSampleFormat(fmt);
+ format.setSampleRate(qFromBigEndian<quint32>(wave.sampleRate));
+ format.setChannelCount(qFromBigEndian<quint16>(wave.numChannels));
state = QWaveDecoder::WaitingForDataState;
}
diff --git a/src/multimedia/audio/qwavedecoder_p.h b/src/multimedia/audio/qwavedecoder_p.h
index 651b03fd2..650aabbb6 100644
--- a/src/multimedia/audio/qwavedecoder_p.h
+++ b/src/multimedia/audio/qwavedecoder_p.h
@@ -119,13 +119,14 @@ private:
quint16 bitsPerSample;
};
- bool haveFormat;
- qint64 dataSize;
+ bool haveFormat = false;
+ qint64 dataSize = 0;
QAudioFormat format;
- QIODevice *source;
- State state;
- quint32 junkToSkip;
- bool bigEndian;
+ QIODevice *source = nullptr;
+ State state = InitialState;
+ quint32 junkToSkip = 0;
+ bool bigEndian = false;
+ bool byteSwap = false;
};
QT_END_NAMESPACE
diff --git a/src/multimedia/platform/alsa/qalsaaudiodeviceinfo.cpp b/src/multimedia/platform/alsa/qalsaaudiodeviceinfo.cpp
index 92716220f..946d7c97a 100644
--- a/src/multimedia/platform/alsa/qalsaaudiodeviceinfo.cpp
+++ b/src/multimedia/platform/alsa/qalsaaudiodeviceinfo.cpp
@@ -54,209 +54,30 @@
QT_BEGIN_NAMESPACE
-QAlsaAudioDeviceInfo::QAlsaAudioDeviceInfo(const QByteArray &dev, const QString &description, QAudio::Mode mode)
+QAlsaAudioDeviceInfo::QAlsaAudioDeviceInfo(const QByteArray &dev, const QString &desc, QAudio::Mode mode)
: QAudioDeviceInfoPrivate(dev, mode)
- , m_description(description)
{
- handle = 0;
-
- this->mode = mode;
+ description = desc;
checkSurround();
-}
-
-QAlsaAudioDeviceInfo::~QAlsaAudioDeviceInfo()
-{
- close();
-}
-
-bool QAlsaAudioDeviceInfo::isFormatSupported(const QAudioFormat& format) const
-{
- return testSettings(format);
-}
-QAudioFormat QAlsaAudioDeviceInfo::preferredFormat() const
-{
- QAudioFormat nearest;
- nearest.setSampleRate(44100);
- nearest.setByteOrder(QAudioFormat::LittleEndian);
- nearest.setSampleType(QAudioFormat::SignedInt);
- nearest.setSampleSize(16);
- nearest.setChannelCount(2);
- if(mode == QAudio::AudioInput && !testSettings(nearest))
- nearest.setChannelCount(1);
- return nearest;
-}
+ supportedChannelCounts.minimum = 1;
+ supportedChannelCounts.maximum = 2;
+ if (surround71)
+ supportedChannelCounts.maximum = 8;
+ else if (surround40)
+ supportedChannelCounts.maximum = 4;
+ else if (surround51)
+ supportedChannelCounts.maximum = 6;
-QList<int> QAlsaAudioDeviceInfo::supportedSampleRates() const
-{
- updateLists();
- return sampleRatez;
-}
+ supportedSampleRates.minimum = 8000;
+ supportedSampleRates.maximum = 48000;
-QList<int> QAlsaAudioDeviceInfo::supportedChannelCounts() const
-{
- updateLists();
- return channelz;
+ supportedSampleFormats << QAudioFormat::UInt8 << QAudioFormat::Int16 << QAudioFormat::Int32 << QAudioFormat::Float;
}
-QList<int> QAlsaAudioDeviceInfo::supportedSampleSizes() const
-{
- updateLists();
- return sizez;
-}
-
-QList<QAudioFormat::Endian> QAlsaAudioDeviceInfo::supportedByteOrders() const
-{
- updateLists();
- return byteOrderz;
-}
-
-QList<QAudioFormat::SampleType> QAlsaAudioDeviceInfo::supportedSampleTypes() const
-{
- updateLists();
- return typez;
-}
-
-QByteArray QAlsaAudioDeviceInfo::defaultDevice(QAudio::Mode)
-{
- return "default";
-}
-
-bool QAlsaAudioDeviceInfo::open() const
-{
- int err = 0;
-
- if(mode == QAudio::AudioOutput) {
- err = snd_pcm_open(&handle, id.constData(), SND_PCM_STREAM_PLAYBACK,0);
- } else {
- err = snd_pcm_open(&handle, id.constData(), SND_PCM_STREAM_CAPTURE,0);
- }
- if(err < 0) {
- handle = 0;
- return false;
- }
- return true;
-}
-
-void QAlsaAudioDeviceInfo::close() const
-{
- if(handle)
- snd_pcm_close(handle);
- handle = 0;
-}
-
-bool QAlsaAudioDeviceInfo::testSettings(const QAudioFormat& format) const
-{
- // Set nearest to closest settings that do work.
- // See if what is in settings will work (return value).
- int err = -1;
- snd_pcm_t* pcmHandle;
- snd_pcm_hw_params_t *params;
-
- snd_pcm_stream_t stream = mode == QAudio::AudioOutput
- ? SND_PCM_STREAM_PLAYBACK : SND_PCM_STREAM_CAPTURE;
-
- if (snd_pcm_open(&pcmHandle, id.constData(), stream, 0) < 0)
- return false;
-
- snd_pcm_nonblock(pcmHandle, 0);
- snd_pcm_hw_params_alloca(&params);
- snd_pcm_hw_params_any(pcmHandle, params);
-
- // set the values!
- snd_pcm_hw_params_set_channels(pcmHandle, params, format.channelCount());
- snd_pcm_hw_params_set_rate(pcmHandle, params, format.sampleRate(), 0);
-
- snd_pcm_format_t pcmFormat = SND_PCM_FORMAT_UNKNOWN;
- switch (format.sampleSize()) {
- case 8:
- if (format.sampleType() == QAudioFormat::SignedInt)
- pcmFormat = SND_PCM_FORMAT_S8;
- else if (format.sampleType() == QAudioFormat::UnSignedInt)
- pcmFormat = SND_PCM_FORMAT_U8;
- break;
- case 16:
- if (format.sampleType() == QAudioFormat::SignedInt) {
- pcmFormat = format.byteOrder() == QAudioFormat::LittleEndian
- ? SND_PCM_FORMAT_S16_LE : SND_PCM_FORMAT_S16_BE;
- } else if (format.sampleType() == QAudioFormat::UnSignedInt) {
- pcmFormat = format.byteOrder() == QAudioFormat::LittleEndian
- ? SND_PCM_FORMAT_U16_LE : SND_PCM_FORMAT_U16_BE;
- }
- break;
- case 32:
- if (format.sampleType() == QAudioFormat::SignedInt) {
- pcmFormat = format.byteOrder() == QAudioFormat::LittleEndian
- ? SND_PCM_FORMAT_S32_LE : SND_PCM_FORMAT_S32_BE;
- } else if (format.sampleType() == QAudioFormat::UnSignedInt) {
- pcmFormat = format.byteOrder() == QAudioFormat::LittleEndian
- ? SND_PCM_FORMAT_U32_LE : SND_PCM_FORMAT_U32_BE;
- } else if (format.sampleType() == QAudioFormat::Float) {
- pcmFormat = format.byteOrder() == QAudioFormat::LittleEndian
- ? SND_PCM_FORMAT_FLOAT_LE : SND_PCM_FORMAT_FLOAT_BE;
- }
- }
-
- if (pcmFormat != SND_PCM_FORMAT_UNKNOWN)
- err = snd_pcm_hw_params_set_format(pcmHandle, params, pcmFormat);
-
- if (err >= 0 && format.channelCount() != -1) {
- err = snd_pcm_hw_params_test_channels(pcmHandle, params, format.channelCount());
- if (err >= 0)
- err = snd_pcm_hw_params_set_channels(pcmHandle, params, format.channelCount());
- }
-
- if (err >= 0 && format.sampleRate() != -1) {
- err = snd_pcm_hw_params_test_rate(pcmHandle, params, format.sampleRate(), 0);
- if (err >= 0)
- err = snd_pcm_hw_params_set_rate(pcmHandle, params, format.sampleRate(), 0);
- }
-
- if (err >= 0 && pcmFormat != SND_PCM_FORMAT_UNKNOWN)
- err = snd_pcm_hw_params_set_format(pcmHandle, params, pcmFormat);
-
- if (err >= 0)
- err = snd_pcm_hw_params(pcmHandle, params);
-
- snd_pcm_close(pcmHandle);
-
- return (err == 0);
-}
-
-void QAlsaAudioDeviceInfo::updateLists() const
+QAlsaAudioDeviceInfo::~QAlsaAudioDeviceInfo()
{
- // redo all lists based on current settings
- sampleRatez.clear();
- channelz.clear();
- sizez.clear();
- byteOrderz.clear();
- typez.clear();
-
- if(!handle)
- open();
-
- if(!handle)
- return;
-
- for(int i=0; i<(int)MAX_SAMPLE_RATES; i++) {
- //if(snd_pcm_hw_params_test_rate(handle, params, SAMPLE_RATES[i], dir) == 0)
- sampleRatez.append(SAMPLE_RATES[i]);
- }
- channelz.append(1);
- channelz.append(2);
- if (surround40) channelz.append(4);
- if (surround51) channelz.append(6);
- if (surround71) channelz.append(8);
- sizez.append(8);
- sizez.append(16);
- sizez.append(32);
- byteOrderz.append(QAudioFormat::LittleEndian);
- byteOrderz.append(QAudioFormat::BigEndian);
- typez.append(QAudioFormat::SignedInt);
- typez.append(QAudioFormat::UnSignedInt);
- typez.append(QAudioFormat::Float);
- close();
}
void QAlsaAudioDeviceInfo::checkSurround()
diff --git a/src/multimedia/platform/alsa/qalsaaudiodeviceinfo_p.h b/src/multimedia/platform/alsa/qalsaaudiodeviceinfo_p.h
index 80b2f85d5..92dbccce0 100644
--- a/src/multimedia/platform/alsa/qalsaaudiodeviceinfo_p.h
+++ b/src/multimedia/platform/alsa/qalsaaudiodeviceinfo_p.h
@@ -66,45 +66,17 @@
QT_BEGIN_NAMESPACE
-const unsigned int MAX_SAMPLE_RATES = 5;
-const unsigned int SAMPLE_RATES[] =
- { 8000, 11025, 22050, 44100, 48000 };
-
class QAlsaAudioDeviceInfo : public QAudioDeviceInfoPrivate
{
public:
QAlsaAudioDeviceInfo(const QByteArray &dev, const QString &description, QAudio::Mode mode);
~QAlsaAudioDeviceInfo();
- bool testSettings(const QAudioFormat& format) const;
- void updateLists() const;
- QAudioFormat preferredFormat() const override;
- bool isFormatSupported(const QAudioFormat& format) const override;
- QString description() const override { return m_description; }
- QList<int> supportedSampleRates() const override;
- QList<int> supportedChannelCounts() const override;
- QList<int> supportedSampleSizes() const override;
- QList<QAudioFormat::Endian> supportedByteOrders() const override;
- QList<QAudioFormat::SampleType> supportedSampleTypes() const override;
- static QByteArray defaultDevice(QAudio::Mode mode);
-
private:
- bool open() const;
- void close() const;
-
void checkSurround();
bool surround40;
bool surround51;
bool surround71;
-
- QString m_description;
- QAudioFormat nearest;
- mutable QList<int> sampleRatez;
- mutable QList<int> channelz;
- mutable QList<int> sizez;
- mutable QList<QAudioFormat::Endian> byteOrderz;
- mutable QList<QAudioFormat::SampleType> typez;
- mutable snd_pcm_t* handle;
};
QT_END_NAMESPACE
diff --git a/src/multimedia/platform/alsa/qalsaaudioinput.cpp b/src/multimedia/platform/alsa/qalsaaudioinput.cpp
index abfc7a0ac..2b4815188 100644
--- a/src/multimedia/platform/alsa/qalsaaudioinput.cpp
+++ b/src/multimedia/platform/alsa/qalsaaudioinput.cpp
@@ -171,60 +171,35 @@ int QAlsaAudioInput::xrun_recovery(int err)
int QAlsaAudioInput::setFormat()
{
- snd_pcm_format_t format = SND_PCM_FORMAT_UNKNOWN;
-
- if(settings.sampleSize() == 8) {
- format = SND_PCM_FORMAT_U8;
- } else if(settings.sampleSize() == 16) {
- if(settings.sampleType() == QAudioFormat::SignedInt) {
- if(settings.byteOrder() == QAudioFormat::LittleEndian)
- format = SND_PCM_FORMAT_S16_LE;
- else
- format = SND_PCM_FORMAT_S16_BE;
- } else if(settings.sampleType() == QAudioFormat::UnSignedInt) {
- if(settings.byteOrder() == QAudioFormat::LittleEndian)
- format = SND_PCM_FORMAT_U16_LE;
- else
- format = SND_PCM_FORMAT_U16_BE;
- }
- } else if(settings.sampleSize() == 24) {
- if(settings.sampleType() == QAudioFormat::SignedInt) {
- if(settings.byteOrder() == QAudioFormat::LittleEndian)
- format = SND_PCM_FORMAT_S24_LE;
- else
- format = SND_PCM_FORMAT_S24_BE;
- } else if(settings.sampleType() == QAudioFormat::UnSignedInt) {
- if(settings.byteOrder() == QAudioFormat::LittleEndian)
- format = SND_PCM_FORMAT_U24_LE;
- else
- format = SND_PCM_FORMAT_U24_BE;
- }
- } else if(settings.sampleSize() == 32) {
- if(settings.sampleType() == QAudioFormat::SignedInt) {
- if(settings.byteOrder() == QAudioFormat::LittleEndian)
- format = SND_PCM_FORMAT_S32_LE;
- else
- format = SND_PCM_FORMAT_S32_BE;
- } else if(settings.sampleType() == QAudioFormat::UnSignedInt) {
- if(settings.byteOrder() == QAudioFormat::LittleEndian)
- format = SND_PCM_FORMAT_U32_LE;
- else
- format = SND_PCM_FORMAT_U32_BE;
- } else if(settings.sampleType() == QAudioFormat::Float) {
- if(settings.byteOrder() == QAudioFormat::LittleEndian)
- format = SND_PCM_FORMAT_FLOAT_LE;
- else
- format = SND_PCM_FORMAT_FLOAT_BE;
- }
- } else if(settings.sampleSize() == 64) {
- if(settings.byteOrder() == QAudioFormat::LittleEndian)
- format = SND_PCM_FORMAT_FLOAT64_LE;
+ snd_pcm_format_t pcmformat = SND_PCM_FORMAT_UNKNOWN;
+
+ switch (settings.sampleFormat()) {
+ case QAudioFormat::UInt8:
+ pcmformat = SND_PCM_FORMAT_U8;
+ break;
+ case QAudioFormat::Int16:
+ if constexpr (QSysInfo::ByteOrder == QSysInfo::BigEndian)
+ pcmformat = SND_PCM_FORMAT_S16_LE;
+ else
+ pcmformat = SND_PCM_FORMAT_S16_BE;
+ break;
+ case QAudioFormat::Int32:
+ if constexpr (QSysInfo::ByteOrder == QSysInfo::BigEndian)
+ pcmformat = SND_PCM_FORMAT_S32_LE;
+ else
+ pcmformat = SND_PCM_FORMAT_S32_BE;
+ break;
+ case QAudioFormat::Float:
+ if constexpr (QSysInfo::ByteOrder == QSysInfo::BigEndian)
+ pcmformat = SND_PCM_FORMAT_FLOAT_LE;
else
- format = SND_PCM_FORMAT_FLOAT64_BE;
+ pcmformat = SND_PCM_FORMAT_FLOAT_BE;
+ default:
+ break;
}
- return format != SND_PCM_FORMAT_UNKNOWN
- ? snd_pcm_hw_params_set_format( handle, hwparams, format)
+ return pcmformat != SND_PCM_FORMAT_UNKNOWN
+ ? snd_pcm_hw_params_set_format( handle, hwparams, pcmformat)
: -1;
}
@@ -679,7 +654,7 @@ int QAlsaAudioInput::notifyInterval() const
qint64 QAlsaAudioInput::processedUSecs() const
{
qint64 result = qint64(1000000) * totalTimeValue /
- (settings.channelCount()*(settings.sampleSize()/8)) /
+ settings.bytesPerFrame() /
settings.sampleRate();
return result;
diff --git a/src/multimedia/platform/alsa/qalsaaudiooutput.cpp b/src/multimedia/platform/alsa/qalsaaudiooutput.cpp
index 327548bdf..0589c254c 100644
--- a/src/multimedia/platform/alsa/qalsaaudiooutput.cpp
+++ b/src/multimedia/platform/alsa/qalsaaudiooutput.cpp
@@ -166,55 +166,29 @@ int QAlsaAudioOutput::setFormat()
{
snd_pcm_format_t pcmformat = SND_PCM_FORMAT_UNKNOWN;
- if(settings.sampleSize() == 8) {
+ switch (settings.sampleFormat()) {
+ case QAudioFormat::UInt8:
pcmformat = SND_PCM_FORMAT_U8;
-
- } else if(settings.sampleSize() == 16) {
- if(settings.sampleType() == QAudioFormat::SignedInt) {
- if(settings.byteOrder() == QAudioFormat::LittleEndian)
- pcmformat = SND_PCM_FORMAT_S16_LE;
- else
- pcmformat = SND_PCM_FORMAT_S16_BE;
- } else if(settings.sampleType() == QAudioFormat::UnSignedInt) {
- if(settings.byteOrder() == QAudioFormat::LittleEndian)
- pcmformat = SND_PCM_FORMAT_U16_LE;
- else
- pcmformat = SND_PCM_FORMAT_U16_BE;
- }
- } else if(settings.sampleSize() == 24) {
- if(settings.sampleType() == QAudioFormat::SignedInt) {
- if(settings.byteOrder() == QAudioFormat::LittleEndian)
- pcmformat = SND_PCM_FORMAT_S24_LE;
- else
- pcmformat = SND_PCM_FORMAT_S24_BE;
- } else if(settings.sampleType() == QAudioFormat::UnSignedInt) {
- if(settings.byteOrder() == QAudioFormat::LittleEndian)
- pcmformat = SND_PCM_FORMAT_U24_LE;
- else
- pcmformat = SND_PCM_FORMAT_U24_BE;
- }
- } else if(settings.sampleSize() == 32) {
- if(settings.sampleType() == QAudioFormat::SignedInt) {
- if(settings.byteOrder() == QAudioFormat::LittleEndian)
- pcmformat = SND_PCM_FORMAT_S32_LE;
- else
- pcmformat = SND_PCM_FORMAT_S32_BE;
- } else if(settings.sampleType() == QAudioFormat::UnSignedInt) {
- if(settings.byteOrder() == QAudioFormat::LittleEndian)
- pcmformat = SND_PCM_FORMAT_U32_LE;
- else
- pcmformat = SND_PCM_FORMAT_U32_BE;
- } else if(settings.sampleType() == QAudioFormat::Float) {
- if(settings.byteOrder() == QAudioFormat::LittleEndian)
- pcmformat = SND_PCM_FORMAT_FLOAT_LE;
- else
- pcmformat = SND_PCM_FORMAT_FLOAT_BE;
- }
- } else if(settings.sampleSize() == 64) {
- if(settings.byteOrder() == QAudioFormat::LittleEndian)
- pcmformat = SND_PCM_FORMAT_FLOAT64_LE;
+ break;
+ case QAudioFormat::Int16:
+ if constexpr (QSysInfo::ByteOrder == QSysInfo::BigEndian)
+ pcmformat = SND_PCM_FORMAT_S16_LE;
+ else
+ pcmformat = SND_PCM_FORMAT_S16_BE;
+ break;
+ case QAudioFormat::Int32:
+ if constexpr (QSysInfo::ByteOrder == QSysInfo::BigEndian)
+ pcmformat = SND_PCM_FORMAT_S32_LE;
+ else
+ pcmformat = SND_PCM_FORMAT_S32_BE;
+ break;
+ case QAudioFormat::Float:
+ if constexpr (QSysInfo::ByteOrder == QSysInfo::BigEndian)
+ pcmformat = SND_PCM_FORMAT_FLOAT_LE;
else
- pcmformat = SND_PCM_FORMAT_FLOAT64_BE;
+ pcmformat = SND_PCM_FORMAT_FLOAT_BE;
+ default:
+ break;
}
return pcmformat != SND_PCM_FORMAT_UNKNOWN
diff --git a/src/multimedia/platform/alsa/qalsadevicemanager.cpp b/src/multimedia/platform/alsa/qalsadevicemanager.cpp
index 20fbe6c53..24662980f 100644
--- a/src/multimedia/platform/alsa/qalsadevicemanager.cpp
+++ b/src/multimedia/platform/alsa/qalsadevicemanager.cpp
@@ -84,8 +84,7 @@ static QList<QAudioDeviceInfo> availableDevices(QAudio::Mode mode)
if ((descr != NULL) && ((io == NULL) || (io == filter))) {
auto *infop = new QAlsaAudioDeviceInfo(name, QString::fromUtf8(descr), mode);
- QAudioDeviceInfo info(infop);
- devices.append(info);
+ devices.append(infop->create());
if (strcmp(name, "default") == 0)
infop->isDefault = true;
}
diff --git a/src/multimedia/platform/android/audio/qopenslesdeviceinfo.cpp b/src/multimedia/platform/android/audio/qopenslesdeviceinfo.cpp
index 5c60ad6f9..dfc9ca0c0 100644
--- a/src/multimedia/platform/android/audio/qopenslesdeviceinfo.cpp
+++ b/src/multimedia/platform/android/audio/qopenslesdeviceinfo.cpp
@@ -47,59 +47,23 @@ QOpenSLESDeviceInfo::QOpenSLESDeviceInfo(const QByteArray &device, QAudio::Mode
: QAudioDeviceInfoPrivate(device, mode),
m_engine(QOpenSLESEngine::instance())
{
-}
-
-bool QOpenSLESDeviceInfo::isFormatSupported(const QAudioFormat &format) const
-{
- QOpenSLESDeviceInfo *that = const_cast<QOpenSLESDeviceInfo*>(this);
- return that->supportedSampleRates().contains(format.sampleRate())
- && that->supportedChannelCounts().contains(format.channelCount())
- && that->supportedSampleSizes().contains(format.sampleSize())
- && that->supportedByteOrders().contains(format.byteOrder())
- && that->supportedSampleTypes().contains(format.sampleType());
-}
-
-QAudioFormat QOpenSLESDeviceInfo::preferredFormat() const
-{
- QAudioFormat format;
- format.setSampleSize(16);
- format.setSampleType(QAudioFormat::SignedInt);
- format.setSampleRate(QOpenSLESEngine::getOutputValue(QOpenSLESEngine::SampleRate, 48000));
- format.setChannelCount(mode == QAudio::AudioInput ? 1 : 2);
- return format;
-}
-
-QString QOpenSLESDeviceInfo::deviceName() const
-{
- return id;
-}
-
-QList<int> QOpenSLESDeviceInfo::supportedSampleRates() const
-{
- return m_engine->supportedSampleRates(mode);
-}
-
-QList<int> QOpenSLESDeviceInfo::supportedChannelCounts() const
-{
- return m_engine->supportedChannelCounts(mode);
-}
+ auto channels = m_engine->supportedChannelCounts(mode);
+ if (channels.size())
+ supportedChannelCounts = { channels.first(), channels.last() };
-QList<int> QOpenSLESDeviceInfo::supportedSampleSizes() const
-{
+ auto sampleRates = m_engine->supportedSampleRates(mode);
+ if (sampleRates.size())
+ supportedSampleRates = { sampleRates.first(), sampleRates.last() };
if (mode == QAudio::AudioInput)
- return QList<int>() << 16;
- else
- return QList<int>() << 8 << 16;
-}
+ supportedSampleFormats.append(QAudioFormat::UInt8);
+ supportedSampleFormats.append(QAudioFormat::Int16);
-QList<QAudioFormat::Endian> QOpenSLESDeviceInfo::supportedByteOrders() const
-{
- return QList<QAudioFormat::Endian>() << QAudioFormat::LittleEndian;
-}
-
-QList<QAudioFormat::SampleType> QOpenSLESDeviceInfo::supportedSampleTypes() const
-{
- return QList<QAudioFormat::SampleType>() << QAudioFormat::SignedInt;
+ preferredFormat.setChannelCount(2);
+ preferredFormat.setSampleRate(48000);
+ QAudioFormat::SampleFormat f = QAudioFormat::Int16;
+ if (!supportedSampleFormats.contains(f))
+ f = supportedSampleFormats.value(0, QAudioFormat::Unknown);
+ preferredFormat.setSampleFormat(f);
}
QT_END_NAMESPACE
diff --git a/src/multimedia/platform/android/audio/qopenslesdeviceinfo_p.h b/src/multimedia/platform/android/audio/qopenslesdeviceinfo_p.h
index 5d5c36541..692915635 100644
--- a/src/multimedia/platform/android/audio/qopenslesdeviceinfo_p.h
+++ b/src/multimedia/platform/android/audio/qopenslesdeviceinfo_p.h
@@ -64,16 +64,6 @@ public:
QOpenSLESDeviceInfo(const QByteArray &device, QAudio::Mode mode);
~QOpenSLESDeviceInfo() {}
- QAudioFormat preferredFormat() const;
- bool isFormatSupported(const QAudioFormat &format) const;
- QString deviceName() const;
- QString description() const { return deviceName(); }
- QList<int> supportedSampleRates() const;
- QList<int> supportedChannelCounts() const;
- QList<int> supportedSampleSizes() const;
- QList<QAudioFormat::Endian> supportedByteOrders() const;
- QList<QAudioFormat::SampleType> supportedSampleTypes() const;
-
private:
QOpenSLESEngine *m_engine;
};
diff --git a/src/multimedia/platform/android/audio/qopenslesengine.cpp b/src/multimedia/platform/android/audio/qopenslesengine.cpp
index 87ed1bf14..52a7db9e1 100644
--- a/src/multimedia/platform/android/audio/qopenslesengine.cpp
+++ b/src/multimedia/platform/android/audio/qopenslesengine.cpp
@@ -91,12 +91,12 @@ SLDataFormat_PCM QOpenSLESEngine::audioFormatToSLFormatPCM(const QAudioFormat &f
format_pcm.formatType = SL_DATAFORMAT_PCM;
format_pcm.numChannels = format.channelCount();
format_pcm.samplesPerSec = format.sampleRate() * 1000;
- format_pcm.bitsPerSample = format.sampleSize();
- format_pcm.containerSize = format.sampleSize();
+ format_pcm.bitsPerSample = format.bytesPerSample() * 8;
+ format_pcm.containerSize = format.bytesPerSample() * 8;
format_pcm.channelMask = (format.channelCount() == 1 ?
SL_SPEAKER_FRONT_CENTER :
SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT);
- format_pcm.endianness = (format.byteOrder() == QAudioFormat::LittleEndian ?
+ format_pcm.endianness = (QSysInfo::ByteOrder == QSysInfo::LittleEndian ?
SL_BYTEORDER_LITTLEENDIAN :
SL_BYTEORDER_BIGENDIAN);
return format_pcm;
@@ -108,14 +108,14 @@ QList<QAudioDeviceInfo> QOpenSLESEngine::availableDevices(QAudio::Mode mode)
QList<QAudioDeviceInfo> devices;
#ifdef ANDROID
if (mode == QAudio::AudioInput) {
- devices << QAudioDeviceInfo(new QOpenSLESDeviceInfo(QT_ANDROID_PRESET_MIC, mode))
- << QAudioDeviceInfo(new QOpenSLESDeviceInfo(QT_ANDROID_PRESET_CAMCORDER, mode))
- << QAudioDeviceInfo(new QOpenSLESDeviceInfo(QT_ANDROID_PRESET_VOICE_RECOGNITION, mode))
- << QAudioDeviceInfo(new QOpenSLESDeviceInfo(QT_ANDROID_PRESET_VOICE_COMMUNICATION, mode));
+ devices << (new QOpenSLESDeviceInfo(QT_ANDROID_PRESET_MIC, mode))->create()
+ << (new QOpenSLESDeviceInfo(QT_ANDROID_PRESET_CAMCORDER, mode))->create()
+ << (new QOpenSLESDeviceInfo(QT_ANDROID_PRESET_VOICE_RECOGNITION, mode))->create()
+ << (new QOpenSLESDeviceInfo(QT_ANDROID_PRESET_VOICE_COMMUNICATION, mode))->create();
return devices;
}
#endif
- devices << QAudioDeviceInfo(new QOpenSLESDeviceInfo("default", mode));
+ devices << (new QOpenSLESDeviceInfo("default", mode))->create();
return devices;
}
@@ -223,11 +223,11 @@ int QOpenSLESEngine::getDefaultBufferSize(const QAudioFormat &format)
const int audioFormat = [&format]() -> int
{
- if (format.sampleType() == QAudioFormat::Float && QtAndroidPrivate::androidSdkVersion() >= 21)
+ if (format.sampleFormat() == QAudioFormat::Float && QtAndroidPrivate::androidSdkVersion() >= 21)
return 4; /* PCM_FLOAT */
- else if (format.sampleSize() == 8)
+ else if (format.sampleFormat() == QAudioFormat::UInt8)
return 3; /* PCM_8BIT */
- else if (format.sampleSize() == 16)
+ else if (format.sampleFormat() == QAudioFormat::Int16)
return 2; /* PCM_16BIT*/
else
return 1; /* DEFAULT */
diff --git a/src/multimedia/platform/darwin/audio/qcoreaudiodeviceinfo.mm b/src/multimedia/platform/darwin/audio/qcoreaudiodeviceinfo.mm
index 4b0e441f2..66bf49a5a 100644
--- a/src/multimedia/platform/darwin/audio/qcoreaudiodeviceinfo.mm
+++ b/src/multimedia/platform/darwin/audio/qcoreaudiodeviceinfo.mm
@@ -56,10 +56,15 @@ QCoreAudioDeviceInfo::QCoreAudioDeviceInfo(AudioDeviceID id, const QByteArray &d
: QAudioDeviceInfoPrivate(device, mode),
m_deviceId(id)
{
+ preferredFormat = determinePreferredFormat();
+ description = getDescription();
+ supportedSampleRates = { 1, 96000 };
+ supportedChannelCounts = { 1, 16 };
+ supportedSampleFormats << QAudioFormat::UInt8 << QAudioFormat::Int16 << QAudioFormat::Int32 << QAudioFormat::Float;
}
-QAudioFormat QCoreAudioDeviceInfo::preferredFormat() const
+QAudioFormat QCoreAudioDeviceInfo::determinePreferredFormat() const
{
QAudioFormat format;
@@ -102,32 +107,19 @@ QAudioFormat QCoreAudioDeviceInfo::preferredFormat() const
delete[] streams;
}
}
-#else //iOS
- format.setSampleSize(16);
- format.setSampleRate(44100);
- format.setByteOrder(QAudioFormat::LittleEndian);
- format.setSampleType(QAudioFormat::SignedInt);
- format.setChannelCount(mode == QAudio::AudioInput ? 1 : 2);
+ if (!format.isValid())
#endif
+ {
+ format.setSampleRate(44100);
+ format.setSampleFormat(QAudioFormat::Int16);
+ format.setChannelCount(mode == QAudio::AudioInput ? 1 : 2);
+ }
return format;
}
-bool QCoreAudioDeviceInfo::isFormatSupported(const QAudioFormat &format) const
-{
- QCoreAudioDeviceInfo *self = const_cast<QCoreAudioDeviceInfo*>(this);
-
- //Sample rates are more of a suggestion with CoreAudio so as long as we get a
- //sane value then we can likely use it.
- return format.isValid()
- && format.sampleRate() > 0
- && self->supportedChannelCounts().contains(format.channelCount())
- && self->supportedSampleSizes().contains(format.sampleSize());
-}
-
-
-QString QCoreAudioDeviceInfo::description() const
+QString QCoreAudioDeviceInfo::getDescription() const
{
#ifdef Q_OS_MACOS
CFStringRef name;
@@ -151,72 +143,4 @@ QString QCoreAudioDeviceInfo::description() const
#endif
}
-QList<int> QCoreAudioDeviceInfo::supportedSampleRates() const
-{
- QSet<int> sampleRates;
-
-#if defined(Q_OS_OSX)
- UInt32 propSize = 0;
- AudioObjectPropertyScope scope = mode == QAudio::AudioInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput;
- AudioObjectPropertyAddress availableNominalSampleRatesAddress = { kAudioDevicePropertyAvailableNominalSampleRates,
- scope,
- kAudioObjectPropertyElementMaster };
-
- if (AudioObjectGetPropertyDataSize(m_deviceId, &availableNominalSampleRatesAddress, 0, NULL, &propSize) == noErr) {
- const int pc = propSize / sizeof(AudioValueRange);
-
- if (pc > 0) {
- AudioValueRange* vr = new AudioValueRange[pc];
-
- if (AudioObjectGetPropertyData(m_deviceId, &availableNominalSampleRatesAddress, 0, NULL, &propSize, vr) == noErr) {
- for (int i = 0; i < pc; ++i) {
- sampleRates << vr[i].mMinimum << vr[i].mMaximum;
- }
- }
-
- delete[] vr;
- }
- }
-#else //iOS
- //iOS doesn't have a way to query available sample rates
- //instead we provide reasonable targets
- //It may be necessary have CoreAudioSessionManger test combinations
- //with available hardware
- sampleRates << 8000 << 11025 << 22050 << 44100 << 48000;
-#endif
- return sampleRates.values();
-}
-
-
-QList<int> QCoreAudioDeviceInfo::supportedChannelCounts() const
-{
- static QList<int> supportedChannels;
-
- if (supportedChannels.isEmpty()) {
- // If the number of channels is not supported by an audio device, Core Audio will
- // automatically convert the audio data.
- for (int i = 1; i <= 16; ++i)
- supportedChannels.append(i);
- }
-
- return supportedChannels;
-}
-
-
-QList<int> QCoreAudioDeviceInfo::supportedSampleSizes() const
-{
- return QList<int>() << 8 << 16 << 24 << 32 << 64;
-}
-
-
-QList<QAudioFormat::Endian> QCoreAudioDeviceInfo::supportedByteOrders() const
-{
- return QList<QAudioFormat::Endian>() << QAudioFormat::LittleEndian << QAudioFormat::BigEndian;
-}
-
-QList<QAudioFormat::SampleType> QCoreAudioDeviceInfo::supportedSampleTypes() const
-{
- return QList<QAudioFormat::SampleType>() << QAudioFormat::SignedInt << QAudioFormat::UnSignedInt << QAudioFormat::Float;
-}
-
QT_END_NAMESPACE
diff --git a/src/multimedia/platform/darwin/audio/qcoreaudiodeviceinfo_p.h b/src/multimedia/platform/darwin/audio/qcoreaudiodeviceinfo_p.h
index 5fe600909..80da914a1 100644
--- a/src/multimedia/platform/darwin/audio/qcoreaudiodeviceinfo_p.h
+++ b/src/multimedia/platform/darwin/audio/qcoreaudiodeviceinfo_p.h
@@ -65,17 +65,12 @@ public:
QCoreAudioDeviceInfo(AudioDeviceID id, const QByteArray &device, QAudio::Mode mode);
~QCoreAudioDeviceInfo() {}
- QAudioFormat preferredFormat() const;
bool isFormatSupported(const QAudioFormat &format) const;
- QString description() const;
- QList<int> supportedSampleRates() const;
- QList<int> supportedChannelCounts() const;
- QList<int> supportedSampleSizes() const;
- QList<QAudioFormat::Endian> supportedByteOrders() const;
- QList<QAudioFormat::SampleType> supportedSampleTypes() const;
AudioDeviceID deviceID() const { return m_deviceId; }
private:
+ QAudioFormat determinePreferredFormat() const;
+ QString getDescription() const;
#if defined(Q_OS_OSX)
AudioDeviceID m_deviceId;
#endif
diff --git a/src/multimedia/platform/darwin/audio/qcoreaudiooutput.mm b/src/multimedia/platform/darwin/audio/qcoreaudiooutput.mm
index d432aa55f..f79bce38c 100644
--- a/src/multimedia/platform/darwin/audio/qcoreaudiooutput.mm
+++ b/src/multimedia/platform/darwin/audio/qcoreaudiooutput.mm
@@ -67,7 +67,7 @@ QCoreAudioOutputBuffer::QCoreAudioOutputBuffer(int bufferSize, int maxPeriodSize
, m_device(0)
{
m_buffer = new CoreAudioRingBuffer(bufferSize + (bufferSize % maxPeriodSize == 0 ? 0 : maxPeriodSize - (bufferSize % maxPeriodSize)));
- m_bytesPerFrame = (audioFormat.sampleSize() / 8) * audioFormat.channelCount();
+ m_bytesPerFrame = audioFormat.bytesPerFrame();
m_periodTime = m_maxPeriodSize / m_bytesPerFrame * 1000 / audioFormat.sampleRate();
m_fillTimer = new QTimer(this);
diff --git a/src/multimedia/platform/darwin/audio/qcoreaudioutils.mm b/src/multimedia/platform/darwin/audio/qcoreaudioutils.mm
index 065bff707..6b0721b60 100644
--- a/src/multimedia/platform/darwin/audio/qcoreaudioutils.mm
+++ b/src/multimedia/platform/darwin/audio/qcoreaudioutils.mm
@@ -71,17 +71,36 @@ double CoreAudioUtils::frequency()
QAudioFormat CoreAudioUtils::toQAudioFormat(AudioStreamBasicDescription const& sf)
{
QAudioFormat audioFormat;
+ // all Darwin HW is little endian, we ignore those formats
+ if ((sf.mFormatFlags & kAudioFormatFlagIsBigEndian) != 0 && QSysInfo::ByteOrder != QSysInfo::LittleEndian)
+ return audioFormat;
+
+ // filter out the formats we're interested in
+ QAudioFormat::SampleFormat format = QAudioFormat::Unknown;
+ switch (sf.mBitsPerChannel) {
+ case 8:
+ if ((sf.mFormatFlags & kAudioFormatFlagIsSignedInteger) == 0)
+ format = QAudioFormat::UInt8;
+ break;
+ case 16:
+ if ((sf.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0)
+ format = QAudioFormat::Int16;
+ break;
+ case 32:
+ if ((sf.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0)
+ format = QAudioFormat::Int32;
+ else if ((sf.mFormatFlags & kAudioFormatFlagIsFloat) != 0)
+ format = QAudioFormat::Float;
+ break;
+ default:
+ break;
+ }
+
+ if (format == QAudioFormat::Unknown)
+ return audioFormat;
audioFormat.setSampleRate(sf.mSampleRate);
audioFormat.setChannelCount(sf.mChannelsPerFrame);
- audioFormat.setSampleSize(sf.mBitsPerChannel);
- audioFormat.setByteOrder((sf.mFormatFlags & kAudioFormatFlagIsBigEndian) != 0 ? QAudioFormat::BigEndian : QAudioFormat::LittleEndian);
- QAudioFormat::SampleType type = QAudioFormat::UnSignedInt;
- if ((sf.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0)
- type = QAudioFormat::SignedInt;
- else if ((sf.mFormatFlags & kAudioFormatFlagIsFloat) != 0)
- type = QAudioFormat::Float;
- audioFormat.setSampleType(type);
return audioFormat;
}
@@ -94,21 +113,25 @@ AudioStreamBasicDescription CoreAudioUtils::toAudioStreamBasicDescription(QAudio
sf.mSampleRate = audioFormat.sampleRate();
sf.mFramesPerPacket = 1;
sf.mChannelsPerFrame = audioFormat.channelCount();
- sf.mBitsPerChannel = audioFormat.sampleSize();
- sf.mBytesPerFrame = sf.mChannelsPerFrame * (sf.mBitsPerChannel / 8);
+ sf.mBitsPerChannel = audioFormat.bytesPerSample() * 8;
+ sf.mBytesPerFrame = audioFormat.bytesPerFrame();
sf.mBytesPerPacket = sf.mFramesPerPacket * sf.mBytesPerFrame;
sf.mFormatID = kAudioFormatLinearPCM;
- switch (audioFormat.sampleType()) {
- case QAudioFormat::SignedInt: sf.mFormatFlags |= kAudioFormatFlagIsSignedInteger; break;
- case QAudioFormat::UnSignedInt: /* default */ break;
- case QAudioFormat::Float: sf.mFormatFlags |= kAudioFormatFlagIsFloat; break;
- case QAudioFormat::Unknown: default: break;
+ switch (audioFormat.sampleFormat()) {
+ case QAudioFormat::Int16:
+ case QAudioFormat::Int32:
+ sf.mFormatFlags |= kAudioFormatFlagIsSignedInteger;
+ break;
+ case QAudioFormat::Float:
+ sf.mFormatFlags |= kAudioFormatFlagIsFloat;
+ break;
+ case QAudioFormat::UInt8:
+ /* default */
+ case QAudioFormat::Unknown:
+ break;
}
- if (audioFormat.byteOrder() == QAudioFormat::BigEndian)
- sf.mFormatFlags |= kAudioFormatFlagIsBigEndian;
-
return sf;
}
diff --git a/src/multimedia/platform/darwin/qdarwindevicemanager.mm b/src/multimedia/platform/darwin/qdarwindevicemanager.mm
index ca3babb6c..04802cb99 100644
--- a/src/multimedia/platform/darwin/qdarwindevicemanager.mm
+++ b/src/multimedia/platform/darwin/qdarwindevicemanager.mm
@@ -103,7 +103,7 @@ QList<QAudioDeviceInfo> availableAudioDevices(QAudio::Mode mode)
QList<QAudioDeviceInfo> devices;
AudioDeviceID defaultDevice = defaultAudioDevice(mode);
- devices << QAudioDeviceInfo(new QCoreAudioDeviceInfo(defaultDevice, uniqueId(defaultDevice, mode), mode));
+ devices << (new QCoreAudioDeviceInfo(defaultDevice, uniqueId(defaultDevice, mode), mode))->create();
UInt32 propSize = 0;
AudioObjectPropertyAddress audioDevicesPropertyAddress = { kAudioHardwarePropertyDevices,
@@ -131,7 +131,7 @@ QList<QAudioDeviceInfo> availableAudioDevices(QAudio::Mode mode)
kAudioObjectPropertyElementMaster };
if (AudioObjectGetPropertyData(audioDevices[i], &audioDeviceStreamFormatPropertyAddress, 0, NULL, &size, &sf) == noErr)
- devices << QAudioDeviceInfo(new QCoreAudioDeviceInfo(audioDevices[i], uniqueId(audioDevices[i], mode), mode));
+ devices << (new QCoreAudioDeviceInfo(audioDevices[i], uniqueId(audioDevices[i], mode), mode))->create();
}
}
diff --git a/src/multimedia/platform/gstreamer/audio/qaudiodeviceinfo_gstreamer.cpp b/src/multimedia/platform/gstreamer/audio/qaudiodeviceinfo_gstreamer.cpp
index 19e5aefdf..68279a25a 100644
--- a/src/multimedia/platform/gstreamer/audio/qaudiodeviceinfo_gstreamer.cpp
+++ b/src/multimedia/platform/gstreamer/audio/qaudiodeviceinfo_gstreamer.cpp
@@ -54,8 +54,30 @@ QGStreamerAudioDeviceInfo::QGStreamerAudioDeviceInfo(const QByteArray &device, Q
if (gstDevice) {
gst_object_ref(gstDevice);
auto *n = gst_device_get_display_name(gstDevice);
- m_description = QString::fromUtf8(n);
+ description = QString::fromUtf8(n);
g_free(n);
+
+ QGstCaps caps = gst_device_get_caps(gstDevice);
+ int size = caps.size();
+ for (int i = 0; i < size; ++i) {
+ auto c = caps.at(i);
+ if (c.name() == "audio/x-raw") {
+ auto rate = c["rate"].toIntRange();
+ if (rate)
+ supportedSampleRates = { rate->min, rate->max };
+ auto channels = c["channels"].toIntRange();
+ if (channels)
+ supportedChannelCounts = { channels->min, channels->max };
+ supportedSampleFormats = c["format"].getSampleFormats();
+ }
+ }
+
+ preferredFormat.setChannelCount(qBound(supportedChannelCounts.minimum, 2, supportedChannelCounts.maximum));
+ preferredFormat.setSampleRate(qBound(supportedSampleRates.minimum, 48000, supportedSampleRates.maximum));
+ QAudioFormat::SampleFormat f = QAudioFormat::Int16;
+ if (!supportedSampleFormats.contains(f))
+ f = supportedSampleFormats.value(0, QAudioFormat::Unknown);
+ preferredFormat.setSampleFormat(f);
}
}
@@ -65,50 +87,4 @@ QGStreamerAudioDeviceInfo::~QGStreamerAudioDeviceInfo()
gst_object_unref(gstDevice);
}
-bool QGStreamerAudioDeviceInfo::isFormatSupported(const QAudioFormat &) const
-{
- // ####
- return true;
-}
-
-QAudioFormat QGStreamerAudioDeviceInfo::preferredFormat() const
-{
- QAudioFormat format;
- format.setByteOrder(QAudioFormat::LittleEndian);
- format.setChannelCount(2);
- format.setSampleRate(48000);
- format.setSampleSize(16);
- return format;
-}
-
-QString QGStreamerAudioDeviceInfo::description() const
-{
- return m_description;
-}
-
-QList<int> QGStreamerAudioDeviceInfo::supportedSampleRates() const
-{
- return QList<int>() << 8000 << 11025 << 22050 << 44100 << 48000;
-}
-
-QList<int> QGStreamerAudioDeviceInfo::supportedChannelCounts() const
-{
- return QList<int>() << 1 << 2 << 4 << 6 << 8;
-}
-
-QList<int> QGStreamerAudioDeviceInfo::supportedSampleSizes() const
-{
- return QList<int>() << 8 << 16 << 24 << 32;
-}
-
-QList<QAudioFormat::Endian> QGStreamerAudioDeviceInfo::supportedByteOrders() const
-{
- return QList<QAudioFormat::Endian>() << QAudioFormat::BigEndian << QAudioFormat::LittleEndian;
-}
-
-QList<QAudioFormat::SampleType> QGStreamerAudioDeviceInfo::supportedSampleTypes() const
-{
- return QList<QAudioFormat::SampleType>() << QAudioFormat::SignedInt << QAudioFormat::UnSignedInt << QAudioFormat::Float;
-}
-
QT_END_NAMESPACE
diff --git a/src/multimedia/platform/gstreamer/audio/qaudiodeviceinfo_gstreamer_p.h b/src/multimedia/platform/gstreamer/audio/qaudiodeviceinfo_gstreamer_p.h
index 79cd1a51d..72df0c43d 100644
--- a/src/multimedia/platform/gstreamer/audio/qaudiodeviceinfo_gstreamer_p.h
+++ b/src/multimedia/platform/gstreamer/audio/qaudiodeviceinfo_gstreamer_p.h
@@ -69,16 +69,6 @@ public:
QGStreamerAudioDeviceInfo(const QByteArray &device, QAudio::Mode mode);
~QGStreamerAudioDeviceInfo();
- QAudioFormat preferredFormat() const override;
- bool isFormatSupported(const QAudioFormat &format) const override;
- QString description() const override;
- QList<int> supportedSampleRates() const override;
- QList<int> supportedChannelCounts() const override;
- QList<int> supportedSampleSizes() const override;
- QList<QAudioFormat::Endian> supportedByteOrders() const override;
- QList<QAudioFormat::SampleType> supportedSampleTypes() const override;
-
- QString m_description;
GstDevice *gstDevice = nullptr;
};
diff --git a/src/multimedia/platform/gstreamer/audio/qaudiooutput_gstreamer.cpp b/src/multimedia/platform/gstreamer/audio/qaudiooutput_gstreamer.cpp
index eaa4c52f2..a221fcf85 100644
--- a/src/multimedia/platform/gstreamer/audio/qaudiooutput_gstreamer.cpp
+++ b/src/multimedia/platform/gstreamer/audio/qaudiooutput_gstreamer.cpp
@@ -286,7 +286,7 @@ int QGStreamerAudioOutput::bytesFree() const
int QGStreamerAudioOutput::periodSize() const
{
// max 5ms periods. Gstreamer itself will ask for 4k data at a time
- return qMin(4096, 5*m_format.sampleRate()*m_format.sampleSize()*m_format.channelCount()/8/1000);
+ return qMin(4096, 5*m_format.sampleRate()*m_format.bytesPerFrame()/1000);
}
void QGStreamerAudioOutput::setBufferSize(int value)
@@ -314,7 +314,7 @@ int QGStreamerAudioOutput::notifyInterval() const
qint64 QGStreamerAudioOutput::processedUSecs() const
{
qint64 result = qint64(1000000) * m_totalTimeValue /
- (m_format.channelCount() * (m_format.sampleSize() / 8)) /
+ m_format.bytesPerFrame() /
m_format.sampleRate();
return result;
diff --git a/src/multimedia/platform/gstreamer/common/qgstutils.cpp b/src/multimedia/platform/gstreamer/common/qgstutils.cpp
index 5f1c64333..694bc751f 100644
--- a/src/multimedia/platform/gstreamer/common/qgstutils.cpp
+++ b/src/multimedia/platform/gstreamer/common/qgstutils.cpp
@@ -219,35 +219,33 @@ QSize QGstUtils::capsCorrectedResolution(const GstCaps *caps)
namespace {
-struct AudioFormat
-{
- GstAudioFormat format;
- QAudioFormat::SampleType sampleType;
- QAudioFormat::Endian byteOrder;
- int sampleSize;
-};
-static const AudioFormat qt_audioLookup[] =
-{
- { GST_AUDIO_FORMAT_S8 , QAudioFormat::SignedInt , QAudioFormat::LittleEndian, 8 },
- { GST_AUDIO_FORMAT_U8 , QAudioFormat::UnSignedInt, QAudioFormat::LittleEndian, 8 },
- { GST_AUDIO_FORMAT_S16LE, QAudioFormat::SignedInt , QAudioFormat::LittleEndian, 16 },
- { GST_AUDIO_FORMAT_S16BE, QAudioFormat::SignedInt , QAudioFormat::BigEndian , 16 },
- { GST_AUDIO_FORMAT_U16LE, QAudioFormat::UnSignedInt, QAudioFormat::LittleEndian, 16 },
- { GST_AUDIO_FORMAT_U16BE, QAudioFormat::UnSignedInt, QAudioFormat::BigEndian , 16 },
- { GST_AUDIO_FORMAT_S32LE, QAudioFormat::SignedInt , QAudioFormat::LittleEndian, 32 },
- { GST_AUDIO_FORMAT_S32BE, QAudioFormat::SignedInt , QAudioFormat::BigEndian , 32 },
- { GST_AUDIO_FORMAT_U32LE, QAudioFormat::UnSignedInt, QAudioFormat::LittleEndian, 32 },
- { GST_AUDIO_FORMAT_U32BE, QAudioFormat::UnSignedInt, QAudioFormat::BigEndian , 32 },
- { GST_AUDIO_FORMAT_S24LE, QAudioFormat::SignedInt , QAudioFormat::LittleEndian, 24 },
- { GST_AUDIO_FORMAT_S24BE, QAudioFormat::SignedInt , QAudioFormat::BigEndian , 24 },
- { GST_AUDIO_FORMAT_U24LE, QAudioFormat::UnSignedInt, QAudioFormat::LittleEndian, 24 },
- { GST_AUDIO_FORMAT_U24BE, QAudioFormat::UnSignedInt, QAudioFormat::BigEndian , 24 },
- { GST_AUDIO_FORMAT_F32LE, QAudioFormat::Float , QAudioFormat::LittleEndian, 32 },
- { GST_AUDIO_FORMAT_F32BE, QAudioFormat::Float , QAudioFormat::BigEndian , 32 },
- { GST_AUDIO_FORMAT_F64LE, QAudioFormat::Float , QAudioFormat::LittleEndian, 64 },
- { GST_AUDIO_FORMAT_F64BE, QAudioFormat::Float , QAudioFormat::BigEndian , 64 }
+static const char *audioSampleFormatNames[QAudioFormat::NSampleFormats] = {
+ nullptr,
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ "U8",
+ "S16LE",
+ "S32LE",
+ "F32LE"
+#else
+ "U8",
+ "S16BE",
+ "S32BE",
+ "F32BE"
+#endif
};
+static QAudioFormat::SampleFormat gstSampleFormatToSampleFormat(const char *fmt)
+{
+ if (fmt) {
+ for (int i = 1; i < QAudioFormat::NSampleFormats; ++i) {
+ if (strcmp(fmt, audioSampleFormatNames[i]))
+ continue;
+ return QAudioFormat::SampleFormat(i);
+ }
+ }
+ return QAudioFormat::Unknown;
+}
+
}
/*!
@@ -258,21 +256,19 @@ static const AudioFormat qt_audioLookup[] =
QAudioFormat QGstUtils::audioFormatForCaps(const GstCaps *caps)
{
QAudioFormat format;
- GstAudioInfo info;
- if (gst_audio_info_from_caps(&info, caps)) {
- for (int i = 0; i < lengthOf(qt_audioLookup); ++i) {
- if (qt_audioLookup[i].format != info.finfo->format)
- continue;
+ QGstStructure s = QGstCaps(caps).at(0);
+ if (s.name() != "audio/x-raw")
+ return format;
- format.setSampleType(qt_audioLookup[i].sampleType);
- format.setByteOrder(qt_audioLookup[i].byteOrder);
- format.setSampleSize(qt_audioLookup[i].sampleSize);
- format.setSampleRate(info.rate);
- format.setChannelCount(info.channels);
+ auto rate = s["rate"].toInt();
+ auto channels = s["channels"].toInt();
+ QAudioFormat::SampleFormat fmt = gstSampleFormatToSampleFormat(s["format"].toString());
+ if (!rate || !channels || fmt == QAudioFormat::Unknown)
+ return format;
- return format;
- }
- }
+ format.setSampleRate(*rate);
+ format.setChannelCount(*channels);
+ format.setSampleFormat(fmt);
return format;
}
@@ -301,26 +297,32 @@ GstCaps *QGstUtils::capsForAudioFormat(const QAudioFormat &format)
if (!format.isValid())
return 0;
- const QAudioFormat::SampleType sampleType = format.sampleType();
- const QAudioFormat::Endian byteOrder = format.byteOrder();
- const int sampleSize = format.sampleSize();
+ auto sampleFormat = format.sampleFormat();
+ return gst_caps_new_simple(
+ "audio/x-raw",
+ "format" , G_TYPE_STRING, audioSampleFormatNames[sampleFormat],
+ "rate" , G_TYPE_INT , format.sampleRate(),
+ "channels", G_TYPE_INT , format.channelCount(),
+ "layout" , G_TYPE_STRING, "interleaved",
+ nullptr);
+}
- for (int i = 0; i < lengthOf(qt_audioLookup); ++i) {
- if (qt_audioLookup[i].sampleType != sampleType
- || qt_audioLookup[i].byteOrder != byteOrder
- || qt_audioLookup[i].sampleSize != sampleSize) {
- continue;
- }
+QList<QAudioFormat::SampleFormat> QGValue::getSampleFormats() const
+{
+ if (!GST_VALUE_HOLDS_LIST(value))
+ return {};
- return gst_caps_new_simple(
- "audio/x-raw",
- "format" , G_TYPE_STRING, gst_audio_format_to_string(qt_audioLookup[i].format),
- "rate" , G_TYPE_INT , format.sampleRate(),
- "channels", G_TYPE_INT , format.channelCount(),
- "layout" , G_TYPE_STRING, "interleaved",
- nullptr);
+ QList<QAudioFormat::SampleFormat> formats;
+ guint nFormats = gst_value_list_get_size(value);
+ for (guint f = 0; f < nFormats; ++f) {
+ QGValue v = gst_value_list_get_value(value, f);
+ auto *name = v.toString();
+ QAudioFormat::SampleFormat fmt = gstSampleFormatToSampleFormat(name);
+ if (fmt == QAudioFormat::Unknown)
+ continue;;
+ formats.append(fmt);
}
- return 0;
+ return formats;
}
void QGstUtils::initializeGst()
diff --git a/src/multimedia/platform/gstreamer/common/qgstutils_p.h b/src/multimedia/platform/gstreamer/common/qgstutils_p.h
index bcc5ac4f4..75c525771 100644
--- a/src/multimedia/platform/gstreamer/common/qgstutils_p.h
+++ b/src/multimedia/platform/gstreamer/common/qgstutils_p.h
@@ -163,13 +163,14 @@ public:
return QGRange<float>{ *min.getFraction(), *max.getFraction() };
}
- std::optional<QGRange<int>> getIntRange() const
+ std::optional<QGRange<int>> toIntRange() const
{
if (!GST_VALUE_HOLDS_INT_RANGE(value))
return std::nullopt;
return QGRange<int>{ gst_value_get_int_range_min(value), gst_value_get_int_range_max(value) };
}
+ Q_MULTIMEDIA_EXPORT QList<QAudioFormat::SampleFormat> getSampleFormats() const;
};
class QGstStructure {
@@ -188,7 +189,6 @@ public:
Q_MULTIMEDIA_EXPORT QVideoFrame::PixelFormat pixelFormat() const;
Q_MULTIMEDIA_EXPORT QSize pixelAspectRatio() const;
Q_MULTIMEDIA_EXPORT QGRange<float> frameRateRange() const;
-
};
class QGstCaps {
diff --git a/src/multimedia/platform/gstreamer/qgstreamerdevicemanager.cpp b/src/multimedia/platform/gstreamer/qgstreamerdevicemanager.cpp
index f3707ffad..5250c6e69 100644
--- a/src/multimedia/platform/gstreamer/qgstreamerdevicemanager.cpp
+++ b/src/multimedia/platform/gstreamer/qgstreamerdevicemanager.cpp
@@ -111,11 +111,11 @@ static QList<QAudioDeviceInfo> devicesFromSet(const QSet<GstDevice *> &deviceSet
if (strcmp(klass, "monitor")) {
auto *name = gst_structure_get_string(properties, "sysfs.path");
gboolean def;
- QAudioDeviceInfo info(new QGStreamerAudioDeviceInfo(name, mode));
+ auto *info = new QGStreamerAudioDeviceInfo(name, mode);
if (gst_structure_get_boolean(properties, "is-default", &def) && def)
- devices.prepend(info);
+ devices.prepend(info->create());
else
- devices.append(info);
+ devices.append(info->create());
}
gst_structure_free(properties);
diff --git a/src/multimedia/platform/pulseaudio/qaudiodeviceinfo_pulse.cpp b/src/multimedia/platform/pulseaudio/qaudiodeviceinfo_pulse.cpp
index d9a01750c..5f8fad2ae 100644
--- a/src/multimedia/platform/pulseaudio/qaudiodeviceinfo_pulse.cpp
+++ b/src/multimedia/platform/pulseaudio/qaudiodeviceinfo_pulse.cpp
@@ -43,54 +43,43 @@
QT_BEGIN_NAMESPACE
-QPulseAudioDeviceInfo::QPulseAudioDeviceInfo(const char *device, const char *description, bool isDef, QAudio::Mode mode)
- : QAudioDeviceInfoPrivate(device, mode),
- m_description(QString::fromUtf8(description))
+QPulseAudioDeviceInfo::QPulseAudioDeviceInfo(const char *device, const char *desc, bool isDef, QAudio::Mode mode)
+ : QAudioDeviceInfoPrivate(device, mode)
{
+ description = QString::fromUtf8(desc);
isDefault = isDef;
-}
-bool QPulseAudioDeviceInfo::isFormatSupported(const QAudioFormat &format) const
-{
- pa_sample_spec spec = QPulseAudioInternal::audioFormatToSampleSpec(format);
- return pa_sample_spec_valid(&spec) != 0;
-}
-
-QAudioFormat QPulseAudioDeviceInfo::preferredFormat() const
-{
- QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance();
- QAudioFormat format = pulseEngine->m_preferredFormats.value(id);
- return format;
-}
-
-QString QPulseAudioDeviceInfo::description() const
-{
- return m_description;
-}
+ supportedChannelCounts = { 1, PA_CHANNELS_MAX };
+ supportedSampleRates = { 1, PA_RATE_MAX };
-QList<int> QPulseAudioDeviceInfo::supportedSampleRates() const
-{
- return QList<int>() << 8000 << 11025 << 22050 << 44100 << 48000;
-}
+ constexpr bool isBigEndian = QSysInfo::ByteOrder == QSysInfo::BigEndian;
-QList<int> QPulseAudioDeviceInfo::supportedChannelCounts() const
-{
- return QList<int>() << 1 << 2 << 4 << 6 << 8;
-}
+ const struct {
+ pa_sample_format pa_fmt;
+ QAudioFormat::SampleFormat qt_fmt;
+ } formatMap[] = {
+ { PA_SAMPLE_U8, QAudioFormat::UInt8 },
+ { isBigEndian ? PA_SAMPLE_S16BE : PA_SAMPLE_S16LE, QAudioFormat::Int16 },
+ { isBigEndian ? PA_SAMPLE_S32BE : PA_SAMPLE_S32LE, QAudioFormat::Int32 },
+ { isBigEndian ? PA_SAMPLE_FLOAT32BE : PA_SAMPLE_FLOAT32LE, QAudioFormat::Float },
+ };
-QList<int> QPulseAudioDeviceInfo::supportedSampleSizes() const
-{
- return QList<int>() << 8 << 16 << 24 << 32;
-}
+ pa_sample_spec spec;
+ spec.channels = 1;
+ spec.rate = 48000;
-QList<QAudioFormat::Endian> QPulseAudioDeviceInfo::supportedByteOrders() const
-{
- return QList<QAudioFormat::Endian>() << QAudioFormat::BigEndian << QAudioFormat::LittleEndian;
-}
+ for (const auto &f : formatMap) {
+ spec.format = f.pa_fmt;
+ if (pa_sample_spec_valid(&spec) != 0)
+ supportedSampleFormats.append(f.qt_fmt);
+ }
-QList<QAudioFormat::SampleType> QPulseAudioDeviceInfo::supportedSampleTypes() const
-{
- return QList<QAudioFormat::SampleType>() << QAudioFormat::SignedInt << QAudioFormat::UnSignedInt << QAudioFormat::Float;
+ preferredFormat.setChannelCount(2);
+ preferredFormat.setSampleRate(48000);
+ QAudioFormat::SampleFormat f = QAudioFormat::Int16;
+ if (!supportedSampleFormats.contains(f))
+ f = supportedSampleFormats.value(0, QAudioFormat::Unknown);
+ preferredFormat.setSampleFormat(f);
}
QT_END_NAMESPACE
diff --git a/src/multimedia/platform/pulseaudio/qaudiodeviceinfo_pulse_p.h b/src/multimedia/platform/pulseaudio/qaudiodeviceinfo_pulse_p.h
index ffc7d16df..2178f4c6c 100644
--- a/src/multimedia/platform/pulseaudio/qaudiodeviceinfo_pulse_p.h
+++ b/src/multimedia/platform/pulseaudio/qaudiodeviceinfo_pulse_p.h
@@ -67,17 +67,6 @@ class QPulseAudioDeviceInfo : public QAudioDeviceInfoPrivate
public:
QPulseAudioDeviceInfo(const char *device, const char *description, bool isDefault, QAudio::Mode mode);
~QPulseAudioDeviceInfo() {}
-
- QAudioFormat preferredFormat() const override;
- bool isFormatSupported(const QAudioFormat &format) const override;
- QString description() const override;
- QList<int> supportedSampleRates() const override;
- QList<int> supportedChannelCounts() const override;
- QList<int> supportedSampleSizes() const override;
- QList<QAudioFormat::Endian> supportedByteOrders() const override;
- QList<QAudioFormat::SampleType> supportedSampleTypes() const override;
-
- QString m_description;
};
QT_END_NAMESPACE
diff --git a/src/multimedia/platform/pulseaudio/qaudioengine_pulse.cpp b/src/multimedia/platform/pulseaudio/qaudioengine_pulse.cpp
index 50152395f..32d105f99 100644
--- a/src/multimedia/platform/pulseaudio/qaudioengine_pulse.cpp
+++ b/src/multimedia/platform/pulseaudio/qaudioengine_pulse.cpp
@@ -123,13 +123,10 @@ static void sinkInfoCallback(pa_context *context, const pa_sink_info *info, int
info->description);
#endif
- QAudioFormat format = QPulseAudioInternal::sampleSpecToAudioFormat(info->sample_spec);
-
QWriteLocker locker(&pulseEngine->m_sinkLock);
- pulseEngine->m_preferredFormats.insert(info->name, format);
bool isDefault = pulseEngine->m_defaultSink == info->name;
- QAudioDeviceInfo dinfo(new QPulseAudioDeviceInfo(info->name, info->description, isDefault, QAudio::AudioOutput));
- pulseEngine->m_sinks.insert(info->index, dinfo);
+ auto *dinfo = new QPulseAudioDeviceInfo(info->name, info->description, isDefault, QAudio::AudioOutput);
+ pulseEngine->m_sinks.insert(info->index, dinfo->create());
}
static void sourceInfoCallback(pa_context *context, const pa_source_info *info, int isLast, void *userdata)
@@ -161,15 +158,13 @@ static void sourceInfoCallback(pa_context *context, const pa_source_info *info,
info->description);
#endif
- QAudioFormat format = QPulseAudioInternal::sampleSpecToAudioFormat(info->sample_spec);
-
QWriteLocker locker(&pulseEngine->m_sourceLock);
// skip monitor channels
if (info->monitor_of_sink != PA_INVALID_INDEX)
return;
bool isDefault = pulseEngine->m_defaultSink == info->name;
- QAudioDeviceInfo dinfo(new QPulseAudioDeviceInfo(info->name, info->description, isDefault, QAudio::AudioInput));
- pulseEngine->m_sources.insert(info->index, dinfo);
+ auto *dinfo = new QPulseAudioDeviceInfo(info->name, info->description, isDefault, QAudio::AudioInput);
+ pulseEngine->m_sources.insert(info->index, dinfo->create());
}
static void event_cb(pa_context* context, pa_subscription_event_type_t t, uint32_t index, void* userdata)
@@ -215,13 +210,11 @@ static void event_cb(pa_context* context, pa_subscription_event_type_t t, uint32
switch (facility) {
case PA_SUBSCRIPTION_EVENT_SINK:
pulseEngine->m_sinkLock.lockForWrite();
- pulseEngine->m_preferredFormats.remove(pulseEngine->m_sinks.value(index).id());
pulseEngine->m_sinks.remove(index);
pulseEngine->m_sinkLock.unlock();
break;
case PA_SUBSCRIPTION_EVENT_SOURCE:
pulseEngine->m_sourceLock.lockForWrite();
- pulseEngine->m_preferredFormats.remove(pulseEngine->m_sources.value(index).id());
pulseEngine->m_sources.remove(index);
pulseEngine->m_sourceLock.unlock();
break;
diff --git a/src/multimedia/platform/pulseaudio/qaudioengine_pulse_p.h b/src/multimedia/platform/pulseaudio/qaudioengine_pulse_p.h
index 8fc949b65..8d48b3b68 100644
--- a/src/multimedia/platform/pulseaudio/qaudioengine_pulse_p.h
+++ b/src/multimedia/platform/pulseaudio/qaudioengine_pulse_p.h
@@ -107,7 +107,6 @@ private:
public:
QMap<int, QAudioDeviceInfo> m_sinks;
QMap<int, QAudioDeviceInfo> m_sources;
- QMap<QByteArray, QAudioFormat> m_preferredFormats;
QByteArray m_defaultSink;
QByteArray m_defaultSource;
diff --git a/src/multimedia/platform/pulseaudio/qaudiooutput_pulse.cpp b/src/multimedia/platform/pulseaudio/qaudiooutput_pulse.cpp
index 7466f5b46..b5adccd85 100644
--- a/src/multimedia/platform/pulseaudio/qaudiooutput_pulse.cpp
+++ b/src/multimedia/platform/pulseaudio/qaudiooutput_pulse.cpp
@@ -304,7 +304,7 @@ bool QPulseAudioOutput::open()
pulseEngine->lock();
- qint64 bytesPerSecond = m_format.sampleRate() * m_format.channelCount() * m_format.sampleSize() / 8;
+ qint64 bytesPerSecond = m_format.sampleRate() * m_format.bytesPerFrame();
pa_proplist *propList = pa_proplist_new();
if (!m_category.isNull())
@@ -591,9 +591,7 @@ int QPulseAudioOutput::notifyInterval() const
qint64 QPulseAudioOutput::processedUSecs() const
{
- qint64 result = qint64(1000000) * m_totalTimeValue /
- (m_format.channelCount() * (m_format.sampleSize() / 8)) /
- m_format.sampleRate();
+ qint64 result = qint64(1000000) * m_totalTimeValue / m_format.bytesPerFrame() / m_format.sampleRate();
return result;
}
diff --git a/src/multimedia/platform/pulseaudio/qpulsehelpers.cpp b/src/multimedia/platform/pulseaudio/qpulsehelpers.cpp
index 56ebbc4e4..c3ca6f8c9 100644
--- a/src/multimedia/platform/pulseaudio/qpulsehelpers.cpp
+++ b/src/multimedia/platform/pulseaudio/qpulsehelpers.cpp
@@ -50,22 +50,16 @@ pa_sample_spec audioFormatToSampleSpec(const QAudioFormat &format)
spec.rate = format.sampleRate();
spec.channels = format.channelCount();
spec.format = PA_SAMPLE_INVALID;
- const bool isBigEndian = (format.byteOrder() == QAudioFormat::BigEndian);
-
- if (format.sampleType() == QAudioFormat::UnSignedInt) {
- if (format.sampleSize() == 8)
- spec.format = PA_SAMPLE_U8;
- } else if (format.sampleType() == QAudioFormat::SignedInt) {
- if (format.sampleSize() == 16) {
- spec.format = isBigEndian ? PA_SAMPLE_S16BE : PA_SAMPLE_S16LE;
- } else if (format.sampleSize() == 24) {
- spec.format = isBigEndian ? PA_SAMPLE_S24BE : PA_SAMPLE_S24LE;
- } else if (format.sampleSize() == 32) {
- spec.format = isBigEndian ? PA_SAMPLE_S32BE : PA_SAMPLE_S32LE;
- }
- } else if (format.sampleType() == QAudioFormat::Float) {
- if (format.sampleSize() == 32)
- spec.format = isBigEndian ? PA_SAMPLE_FLOAT32BE : PA_SAMPLE_FLOAT32LE;
+ const bool isBigEndian = QSysInfo::ByteOrder == QSysInfo::BigEndian;
+
+ if (format.sampleFormat() == QAudioFormat::UInt8) {
+ spec.format = PA_SAMPLE_U8;
+ } else if (format.sampleFormat() == QAudioFormat::Int16) {
+ spec.format = isBigEndian ? PA_SAMPLE_S16BE : PA_SAMPLE_S16LE;
+ } else if (format.sampleFormat() == QAudioFormat::Int32) {
+ spec.format = isBigEndian ? PA_SAMPLE_S32BE : PA_SAMPLE_S32LE;
+ } else if (format.sampleFormat() == QAudioFormat::Float) {
+ spec.format = isBigEndian ? PA_SAMPLE_FLOAT32BE : PA_SAMPLE_FLOAT32LE;
}
return spec;
@@ -127,85 +121,6 @@ QString stateToQString(pa_context_state_t state)
}
#endif
-QAudioFormat sampleSpecToAudioFormat(pa_sample_spec spec)
-{
- QAudioFormat format;
- format.setSampleRate(spec.rate);
- format.setChannelCount(spec.channels);
- format.setCodec(QString::fromLatin1("audio/x-raw"));
-
- switch (spec.format) {
- case PA_SAMPLE_U8:
- format.setByteOrder(QAudioFormat::LittleEndian);
- format.setSampleType(QAudioFormat::UnSignedInt);
- format.setSampleSize(8);
- break;
- case PA_SAMPLE_ALAW:
- // TODO:
- break;
- case PA_SAMPLE_ULAW:
- // TODO:
- break;
- case PA_SAMPLE_S16LE:
- format.setByteOrder(QAudioFormat::LittleEndian);
- format.setSampleType(QAudioFormat::SignedInt);
- format.setSampleSize(16);
- break;
- case PA_SAMPLE_S16BE:
- format.setByteOrder(QAudioFormat::BigEndian);
- format.setSampleType(QAudioFormat::SignedInt);
- format.setSampleSize(16);
- break;
- case PA_SAMPLE_FLOAT32LE:
- format.setByteOrder(QAudioFormat::LittleEndian);
- format.setSampleType(QAudioFormat::Float);
- format.setSampleSize(32);
- break;
- case PA_SAMPLE_FLOAT32BE:
- format.setByteOrder(QAudioFormat::BigEndian);
- format.setSampleType(QAudioFormat::Float);
- format.setSampleSize(32);
- break;
- case PA_SAMPLE_S32LE:
- format.setByteOrder(QAudioFormat::LittleEndian);
- format.setSampleType(QAudioFormat::SignedInt);
- format.setSampleSize(32);
- break;
- case PA_SAMPLE_S32BE:
- format.setByteOrder(QAudioFormat::BigEndian);
- format.setSampleType(QAudioFormat::SignedInt);
- format.setSampleSize(32);
- break;
- case PA_SAMPLE_S24LE:
- format.setByteOrder(QAudioFormat::LittleEndian);
- format.setSampleType(QAudioFormat::SignedInt);
- format.setSampleSize(24);
- break;
- case PA_SAMPLE_S24BE:
- format.setByteOrder(QAudioFormat::BigEndian);
- format.setSampleType(QAudioFormat::SignedInt);
- format.setSampleSize(24);
- break;
- case PA_SAMPLE_S24_32LE:
- format.setByteOrder(QAudioFormat::LittleEndian);
- format.setSampleType(QAudioFormat::SignedInt);
- format.setSampleSize(24);
- break;
- case PA_SAMPLE_S24_32BE:
- format.setByteOrder(QAudioFormat::BigEndian);
- format.setSampleType(QAudioFormat::SignedInt);
- format.setSampleSize(24);
- break;
- case PA_SAMPLE_MAX:
- case PA_SAMPLE_INVALID:
- default:
- format.setByteOrder(QAudioFormat::LittleEndian);
- format.setSampleType(QAudioFormat::Unknown);
- format.setSampleSize(0);
- }
-
- return format;
-}
}
QT_END_NAMESPACE
diff --git a/src/multimedia/platform/pulseaudio/qpulsehelpers_p.h b/src/multimedia/platform/pulseaudio/qpulsehelpers_p.h
index 279cecc2f..30192e4d1 100644
--- a/src/multimedia/platform/pulseaudio/qpulsehelpers_p.h
+++ b/src/multimedia/platform/pulseaudio/qpulsehelpers_p.h
@@ -63,7 +63,6 @@ pa_sample_spec audioFormatToSampleSpec(const QAudioFormat &format);
QString stateToQString(pa_stream_state_t state);
QString stateToQString(pa_context_state_t state);
QString sampleFormatToQString(pa_sample_format format);
-QAudioFormat sampleSpecToAudioFormat(pa_sample_spec spec);
}
QT_END_NAMESPACE
diff --git a/tests/auto/integration/qaudiodecoderbackend/tst_qaudiodecoderbackend.cpp b/tests/auto/integration/qaudiodecoderbackend/tst_qaudiodecoderbackend.cpp
index 1f4ff9959..f5f2069e6 100644
--- a/tests/auto/integration/qaudiodecoderbackend/tst_qaudiodecoderbackend.cpp
+++ b/tests/auto/integration/qaudiodecoderbackend/tst_qaudiodecoderbackend.cpp
@@ -137,8 +137,7 @@ void tst_QAudioDecoderBackend::fileTest()
// Test file is 44.1K 16bit mono, 44094 samples
QCOMPARE(buffer.format().channelCount(), 1);
QCOMPARE(buffer.format().sampleRate(), 44100);
- QCOMPARE(buffer.format().sampleSize(), 16);
- QCOMPARE(buffer.format().sampleType(), QAudioFormat::SignedInt);
+ QCOMPARE(buffer.format().sampleFormat(), QAudioFormat::Int16);
QCOMPARE(buffer.byteCount(), buffer.sampleCount() * 2); // 16bit mono
// The decoder should still have no format set
@@ -194,9 +193,8 @@ void tst_QAudioDecoderBackend::fileTest()
// change output audio format
QAudioFormat format;
format.setChannelCount(2);
- format.setSampleSize(8);
format.setSampleRate(11050);
- format.setSampleType(QAudioFormat::SignedInt);
+ format.setSampleFormat(QAudioFormat::UInt8);
d.setAudioFormat(format);
@@ -477,8 +475,7 @@ void tst_QAudioDecoderBackend::deviceTest()
// Test file is 44.1K 16bit mono
QCOMPARE(buffer.format().channelCount(), 1);
QCOMPARE(buffer.format().sampleRate(), 44100);
- QCOMPARE(buffer.format().sampleSize(), 16);
- QCOMPARE(buffer.format().sampleType(), QAudioFormat::SignedInt);
+ QCOMPARE(buffer.format().sampleFormat(), QAudioFormat::Int16);
QVERIFY(errorSpy.isEmpty());
@@ -527,9 +524,8 @@ void tst_QAudioDecoderBackend::deviceTest()
// Now try changing formats
QAudioFormat format;
format.setChannelCount(2);
- format.setSampleSize(8);
format.setSampleRate(8000);
- format.setSampleType(QAudioFormat::SignedInt);
+ format.setSampleFormat(QAudioFormat::UInt8);
d.setAudioFormat(format);
diff --git a/tests/auto/integration/qaudiodeviceinfo/tst_qaudiodeviceinfo.cpp b/tests/auto/integration/qaudiodeviceinfo/tst_qaudiodeviceinfo.cpp
index be565c8b3..44e58fa84 100644
--- a/tests/auto/integration/qaudiodeviceinfo/tst_qaudiodeviceinfo.cpp
+++ b/tests/auto/integration/qaudiodeviceinfo/tst_qaudiodeviceinfo.cpp
@@ -48,15 +48,10 @@ private slots:
void checkAvailableDefaultInput();
void checkAvailableDefaultOutput();
void channels();
- void sampleSizes();
- void byteOrders();
- void sampleTypes();
+ void sampleFormat();
void sampleRates();
void isFormatSupported();
void preferred();
- void nearest();
- void supportedChannelCounts();
- void supportedSampleRates();
void assignOperator();
void id();
void defaultConstructor();
@@ -99,32 +94,22 @@ void tst_QAudioDeviceInfo::checkAvailableDefaultOutput()
void tst_QAudioDeviceInfo::channels()
{
- QList<int> avail = device->supportedChannelCounts();
- QVERIFY(avail.size() > 0);
+ auto range = device->supportedChannelCounts();
+ QVERIFY(range.minimum > 0);
+ QVERIFY(range.maximum > range.minimum);
}
-void tst_QAudioDeviceInfo::sampleSizes()
+void tst_QAudioDeviceInfo::sampleFormat()
{
- QList<int> avail = device->supportedSampleSizes();
- QVERIFY(avail.size() > 0);
-}
-
-void tst_QAudioDeviceInfo::byteOrders()
-{
- QList<QAudioFormat::Endian> avail = device->supportedByteOrders();
- QVERIFY(avail.size() > 0);
-}
-
-void tst_QAudioDeviceInfo::sampleTypes()
-{
- QList<QAudioFormat::SampleType> avail = device->supportedSampleTypes();
+ QList<QAudioFormat::SampleFormat> avail = device->supportedSampleFormats();
QVERIFY(avail.size() > 0);
}
void tst_QAudioDeviceInfo::sampleRates()
{
- QList<int> avail = device->supportedSampleRates();
- QVERIFY(avail.size() > 0);
+ auto range = device->supportedSampleRates();
+ QVERIFY(range.minimum > 0);
+ QVERIFY(range.maximum > range.minimum);
}
void tst_QAudioDeviceInfo::isFormatSupported()
@@ -132,9 +117,7 @@ void tst_QAudioDeviceInfo::isFormatSupported()
QAudioFormat format;
format.setSampleRate(44100);
format.setChannelCount(2);
- format.setSampleType(QAudioFormat::SignedInt);
- format.setByteOrder(QAudioFormat::LittleEndian);
- format.setSampleSize(16);
+ format.setSampleFormat(QAudioFormat::Int16);
// Should always be true for these format
QVERIFY(device->isFormatSupported(format));
@@ -145,43 +128,6 @@ void tst_QAudioDeviceInfo::preferred()
QAudioFormat format = device->preferredFormat();
QVERIFY(format.isValid());
QVERIFY(device->isFormatSupported(format));
- QVERIFY(device->nearestFormat(format) == format);
-}
-
-// Returns closest QAudioFormat to settings that system audio supports.
-void tst_QAudioDeviceInfo::nearest()
-{
- /*
- QAudioFormat format1, format2;
- format1.setSampleRate(8000);
- format2 = device->nearestFormat(format1);
- QVERIFY(format2.sampleRate() == 44100);
- */
- QAudioFormat format;
- format.setSampleRate(44100);
- format.setChannelCount(2);
- format.setSampleType(QAudioFormat::SignedInt);
- format.setByteOrder(QAudioFormat::LittleEndian);
- format.setSampleSize(16);
-
- QAudioFormat format2 = device->nearestFormat(format);
-
- // This is definitely dependent on platform support (but isFormatSupported tests that above)
- QVERIFY(format2.sampleRate() == 44100);
-}
-
-// Returns a list of supported channel counts.
-void tst_QAudioDeviceInfo::supportedChannelCounts()
-{
- QList<int> avail = device->supportedChannelCounts();
- QVERIFY(avail.size() > 0);
-}
-
-// Returns a list of supported sample rates.
-void tst_QAudioDeviceInfo::supportedSampleRates()
-{
- QList<int> avail = device->supportedSampleRates();
- QVERIFY(avail.size() > 0);
}
// QAudioDeviceInfo's assignOperator method
diff --git a/tests/auto/integration/qaudioinput/tst_qaudioinput.cpp b/tests/auto/integration/qaudioinput/tst_qaudioinput.cpp
index b6f04428f..300dc9116 100644
--- a/tests/auto/integration/qaudioinput/tst_qaudioinput.cpp
+++ b/tests/auto/integration/qaudioinput/tst_qaudioinput.cpp
@@ -139,17 +139,9 @@ void tst_QAudioInput::generate_audiofile_testrows()
QString tst_QAudioInput::formatToFileName(const QAudioFormat &format)
{
- const QString formatEndian = (format.byteOrder() == QAudioFormat::LittleEndian)
- ? QString("LE") : QString("BE");
-
- const QString formatSigned = (format.sampleType() == QAudioFormat::SignedInt)
- ? QString("signed") : QString("unsigned");
-
- return QString("%1_%2_%3_%4_%5")
+ return QString("%1_%2_%3")
.arg(format.sampleRate())
- .arg(format.sampleSize())
- .arg(formatSigned)
- .arg(formatEndian)
+ .arg(format.bytesPerSample())
.arg(format.channelCount());
}
@@ -173,16 +165,14 @@ void tst_QAudioInput::initTestCase()
// PCM 8000 mono S8
format.setSampleRate(8000);
- format.setSampleSize(8);
- format.setSampleType(QAudioFormat::SignedInt);
- format.setByteOrder(QAudioFormat::LittleEndian);
+ format.setSampleFormat(QAudioFormat::UInt8);
format.setChannelCount(1);
if (audioDevice.isFormatSupported(format))
testFormats.append(format);
// PCM 11025 mono S16LE
format.setSampleRate(11025);
- format.setSampleSize(16);
+ format.setSampleFormat(QAudioFormat::Int16);
if (audioDevice.isFormatSupported(format))
testFormats.append(format);
@@ -236,12 +226,9 @@ void tst_QAudioInput::format()
QString("channels: requested=%1, actual=%2").arg(requested.channelCount()).arg(actual.channelCount()).toLocal8Bit().constData());
QVERIFY2((requested.sampleRate() == actual.sampleRate()),
QString("sampleRate: requested=%1, actual=%2").arg(requested.sampleRate()).arg(actual.sampleRate()).toLocal8Bit().constData());
- QVERIFY2((requested.sampleSize() == actual.sampleSize()),
- QString("sampleSize: requested=%1, actual=%2").arg(requested.sampleSize()).arg(actual.sampleSize()).toLocal8Bit().constData());
- QVERIFY2((requested.byteOrder() == actual.byteOrder()),
- QString("byteOrder: requested=%1, actual=%2").arg(requested.byteOrder()).arg(actual.byteOrder()).toLocal8Bit().constData());
- QVERIFY2((requested.sampleType() == actual.sampleType()),
- QString("sampleType: requested=%1, actual=%2").arg(requested.sampleType()).arg(actual.sampleType()).toLocal8Bit().constData());
+ QVERIFY2((requested.sampleFormat() == actual.sampleFormat()),
+ QString("sampleFormat: requested=%1, actual=%2").arg(requested.sampleFormat()).arg(actual.sampleFormat()).toUtf8().constData());
+ QCOMPARE(actual, requested);
}
void tst_QAudioInput::invalidFormat_data()
@@ -264,7 +251,7 @@ void tst_QAudioInput::invalidFormat_data()
<< format;
format = audioDevice.preferredFormat();
- format.setSampleSize(0);
+ format.setSampleFormat(QAudioFormat::Unknown);
QTest::newRow("Sample size 0")
<< format;
}
@@ -633,7 +620,7 @@ void tst_QAudioInput::push()
qint64 totalBytesRead = 0;
bool firstBuffer = true;
QByteArray buffer(AUDIO_BUFFER, 0);
- qint64 len = (audioFormat.sampleRate()*audioFormat.channelCount()*(audioFormat.sampleSize()/8)*2); // 2 seconds
+ qint64 len = audioFormat.sampleRate()*audioFormat.bytesPerFrame()*2; // 2 seconds
while (totalBytesRead < len) {
QTRY_VERIFY_WITH_TIMEOUT(audioInput.bytesReady() >= audioInput.periodSize(), 10000);
qint64 bytesRead = feed->read(buffer.data(), audioInput.periodSize());
@@ -714,7 +701,7 @@ void tst_QAudioInput::pushSuspendResume()
qint64 totalBytesRead = 0;
bool firstBuffer = true;
QByteArray buffer(AUDIO_BUFFER, 0);
- qint64 len = (audioFormat.sampleRate()*audioFormat.channelCount()*(audioFormat.sampleSize()/8)); // 1 seconds
+ qint64 len = audioFormat.sampleRate() * audioFormat.bytesPerFrame(); // 1 second
while (totalBytesRead < len) {
QTRY_VERIFY_WITH_TIMEOUT(audioInput.bytesReady() >= audioInput.periodSize(), 10000);
qint64 bytesRead = feed->read(buffer.data(), audioInput.periodSize());
diff --git a/tests/auto/integration/qaudioinput/wavheader.cpp b/tests/auto/integration/qaudioinput/wavheader.cpp
index 1899480fd..b53bd5f0b 100644
--- a/tests/auto/integration/qaudioinput/wavheader.cpp
+++ b/tests/auto/integration/qaudioinput/wavheader.cpp
@@ -93,21 +93,21 @@ bool WavHeader::read(QIODevice &device)
&& memcmp(&header.wave.descriptor.id, "fmt ", 4) == 0
&& header.wave.audioFormat == 1 // PCM
) {
- if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0)
- m_format.setByteOrder(QAudioFormat::LittleEndian);
- else
- m_format.setByteOrder(QAudioFormat::BigEndian);
+ // ### FIX Big endian handling
+// if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0)
+// m_format.setByteOrder(QAudioFormat::LittleEndian);
+// else
+// m_format.setByteOrder(QAudioFormat::BigEndian);
m_format.setChannelCount(qFromLittleEndian<quint16>(header.wave.numChannels));
m_format.setSampleRate(qFromLittleEndian<quint32>(header.wave.sampleRate));
- m_format.setSampleSize(qFromLittleEndian<quint16>(header.wave.bitsPerSample));
switch(header.wave.bitsPerSample) {
case 8:
- m_format.setSampleType(QAudioFormat::UnSignedInt);
+ m_format.setSampleFormat(QAudioFormat::UInt8);
break;
case 16:
- m_format.setSampleType(QAudioFormat::SignedInt);
+ m_format.setSampleFormat(QAudioFormat::Int16);
break;
default:
result = false;
@@ -130,10 +130,11 @@ bool WavHeader::write(QIODevice &device)
memset(&header, 0, HeaderLength);
// RIFF header
- if (m_format.byteOrder() == QAudioFormat::LittleEndian)
+ // ### handle big endian
+// if (m_format.byteOrder() == QAudioFormat::LittleEndian)
memcpy(header.riff.descriptor.id,"RIFF",4);
- else
- memcpy(header.riff.descriptor.id,"RIFX",4);
+// else
+// memcpy(header.riff.descriptor.id,"RIFX",4);
qToLittleEndian<quint32>(quint32(m_dataLength + HeaderLength - 8),
reinterpret_cast<unsigned char*>(&header.riff.descriptor.size));
memcpy(header.riff.type, "WAVE",4);
@@ -148,11 +149,11 @@ bool WavHeader::write(QIODevice &device)
reinterpret_cast<unsigned char*>(&header.wave.numChannels));
qToLittleEndian<quint32>(quint32(m_format.sampleRate()),
reinterpret_cast<unsigned char*>(&header.wave.sampleRate));
- qToLittleEndian<quint32>(quint32(m_format.sampleRate() * m_format.channelCount() * m_format.sampleSize() / 8),
+ qToLittleEndian<quint32>(quint32(m_format.sampleRate() * m_format.bytesPerFrame()),
reinterpret_cast<unsigned char*>(&header.wave.byteRate));
- qToLittleEndian<quint16>(quint16(m_format.channelCount() * m_format.sampleSize() / 8),
+ qToLittleEndian<quint16>(quint16(m_format.bytesPerFrame()),
reinterpret_cast<unsigned char*>(&header.wave.blockAlign));
- qToLittleEndian<quint16>(quint16(m_format.sampleSize()),
+ qToLittleEndian<quint16>(quint16(m_format.bytesPerSample() * 8),
reinterpret_cast<unsigned char*>(&header.wave.bitsPerSample));
// DATA header
diff --git a/tests/auto/integration/qaudiooutput/tst_qaudiooutput.cpp b/tests/auto/integration/qaudiooutput/tst_qaudiooutput.cpp
index b2064ece7..973c4c237 100644
--- a/tests/auto/integration/qaudiooutput/tst_qaudiooutput.cpp
+++ b/tests/auto/integration/qaudiooutput/tst_qaudiooutput.cpp
@@ -121,24 +121,16 @@ private:
QString tst_QAudioOutput::formatToFileName(const QAudioFormat &format)
{
- const QString formatEndian = (format.byteOrder() == QAudioFormat::LittleEndian)
- ? QString("LE") : QString("BE");
-
- const QString formatSigned = (format.sampleType() == QAudioFormat::SignedInt)
- ? QString("signed") : QString("unsigned");
-
- return QString("%1_%2_%3_%4_%5")
+ return QString("%1_%2_%3")
.arg(format.sampleRate())
- .arg(format.sampleSize())
- .arg(formatSigned)
- .arg(formatEndian)
+ .arg(format.bytesPerSample())
.arg(format.channelCount());
}
void tst_QAudioOutput::createSineWaveData(const QAudioFormat &format, qint64 length, int sampleRate)
{
- const int channelBytes = format.sampleSize() / 8;
- const int sampleBytes = format.channelCount() * channelBytes;
+ const int channelBytes = format.bytesPerSample();
+ const int sampleBytes = format.bytesPerFrame();
Q_ASSERT(length % sampleBytes == 0);
Q_UNUSED(sampleBytes); // suppress warning in release builds
@@ -149,25 +141,25 @@ void tst_QAudioOutput::createSineWaveData(const QAudioFormat &format, qint64 len
while (length) {
const qreal x = qSin(2 * M_PI * sampleRate * qreal(sampleIndex % format.sampleRate()) / format.sampleRate());
- for (int i=0; i<format.channelCount(); ++i) {
- if (format.sampleSize() == 8 && format.sampleType() == QAudioFormat::UnSignedInt) {
+ for (int i = 0; i < format.channelCount(); ++i) {
+ switch (format.sampleFormat()) {
+ case QAudioFormat::UInt8: {
const quint8 value = static_cast<quint8>((1.0 + x) / 2 * 255);
- *reinterpret_cast<quint8*>(ptr) = value;
- } else if (format.sampleSize() == 8 && format.sampleType() == QAudioFormat::SignedInt) {
- const qint8 value = static_cast<qint8>(x * 127);
- *reinterpret_cast<quint8*>(ptr) = value;
- } else if (format.sampleSize() == 16 && format.sampleType() == QAudioFormat::UnSignedInt) {
- quint16 value = static_cast<quint16>((1.0 + x) / 2 * 65535);
- if (format.byteOrder() == QAudioFormat::LittleEndian)
- qToLittleEndian<quint16>(value, ptr);
- else
- qToBigEndian<quint16>(value, ptr);
- } else if (format.sampleSize() == 16 && format.sampleType() == QAudioFormat::SignedInt) {
+ *reinterpret_cast<quint8 *>(ptr) = value;
+ }
+ case QAudioFormat::Int16: {
qint16 value = static_cast<qint16>(x * 32767);
- if (format.byteOrder() == QAudioFormat::LittleEndian)
- qToLittleEndian<qint16>(value, ptr);
- else
- qToBigEndian<qint16>(value, ptr);
+ *reinterpret_cast<qint16 *>(ptr) = value;
+ }
+ case QAudioFormat::Int32: {
+ quint32 value = static_cast<quint32>(x) * std::numeric_limits<qint32>::max();
+ *reinterpret_cast<qint32 *>(ptr) = value;
+ }
+ case QAudioFormat::Float:
+ *reinterpret_cast<float *>(ptr) = x;
+ case QAudioFormat::Unknown:
+ case QAudioFormat::NSampleFormats:
+ break;
}
ptr += channelBytes;
@@ -212,16 +204,14 @@ void tst_QAudioOutput::initTestCase()
// PCM 8000 mono S8
format.setSampleRate(8000);
- format.setSampleSize(8);
- format.setSampleType(QAudioFormat::SignedInt);
- format.setByteOrder(QAudioFormat::LittleEndian);
+ format.setSampleFormat(QAudioFormat::UInt8);
format.setChannelCount(1);
if (audioDevice.isFormatSupported(format))
testFormats.append(format);
// PCM 11025 mono S16LE
format.setSampleRate(11025);
- format.setSampleSize(16);
+ format.setSampleFormat(QAudioFormat::Int16);
if (audioDevice.isFormatSupported(format))
testFormats.append(format);
@@ -258,7 +248,7 @@ void tst_QAudioOutput::initTestCase()
const QString temporaryAudioPath = m_temporaryDir->path() + slash;
for (const QAudioFormat &format : qAsConst(testFormats)) {
- qint64 len = (format.sampleRate()*format.channelCount()*(format.sampleSize()/8)*2); // 2 seconds
+ qint64 len = format.sampleRate()*format.bytesPerFrame()*2; // 2 seconds
createSineWaveData(format, len);
// Write generate sine wave data to file
const QString fileName = temporaryAudioPath + QStringLiteral("generated")
@@ -284,12 +274,9 @@ void tst_QAudioOutput::format()
QString("channels: requested=%1, actual=%2").arg(requested.channelCount()).arg(actual.channelCount()).toLocal8Bit().constData());
QVERIFY2((requested.sampleRate() == actual.sampleRate()),
QString("sampleRate: requested=%1, actual=%2").arg(requested.sampleRate()).arg(actual.sampleRate()).toLocal8Bit().constData());
- QVERIFY2((requested.sampleSize() == actual.sampleSize()),
- QString("sampleSize: requested=%1, actual=%2").arg(requested.sampleSize()).arg(actual.sampleSize()).toLocal8Bit().constData());
- QVERIFY2((requested.byteOrder() == actual.byteOrder()),
- QString("byteOrder: requested=%1, actual=%2").arg(requested.byteOrder()).arg(actual.byteOrder()).toLocal8Bit().constData());
- QVERIFY2((requested.sampleType() == actual.sampleType()),
- QString("sampleType: requested=%1, actual=%2").arg(requested.sampleType()).arg(actual.sampleType()).toLocal8Bit().constData());
+ QVERIFY2((requested.sampleFormat() == actual.sampleFormat()),
+ QString("sampleFormat: requested=%1, actual=%2").arg(requested.sampleFormat()).arg(actual.sampleFormat()).toLocal8Bit().constData());
+ QVERIFY(requested == actual);
}
void tst_QAudioOutput::invalidFormat_data()
@@ -312,7 +299,7 @@ void tst_QAudioOutput::invalidFormat_data()
<< format;
format = audioDevice.preferredFormat();
- format.setSampleSize(0);
+ format.setSampleFormat(QAudioFormat::Unknown);
QTest::newRow("Sample size 0")
<< format;
}
diff --git a/tests/auto/integration/qaudiooutput/wavheader.cpp b/tests/auto/integration/qaudiooutput/wavheader.cpp
index 1899480fd..1a4c358e7 100644
--- a/tests/auto/integration/qaudiooutput/wavheader.cpp
+++ b/tests/auto/integration/qaudiooutput/wavheader.cpp
@@ -93,21 +93,20 @@ bool WavHeader::read(QIODevice &device)
&& memcmp(&header.wave.descriptor.id, "fmt ", 4) == 0
&& header.wave.audioFormat == 1 // PCM
) {
- if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0)
- m_format.setByteOrder(QAudioFormat::LittleEndian);
- else
- m_format.setByteOrder(QAudioFormat::BigEndian);
+// if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0)
+// m_format.setByteOrder(QAudioFormat::LittleEndian);
+// else
+// m_format.setByteOrder(QAudioFormat::BigEndian);
m_format.setChannelCount(qFromLittleEndian<quint16>(header.wave.numChannels));
m_format.setSampleRate(qFromLittleEndian<quint32>(header.wave.sampleRate));
- m_format.setSampleSize(qFromLittleEndian<quint16>(header.wave.bitsPerSample));
switch(header.wave.bitsPerSample) {
case 8:
- m_format.setSampleType(QAudioFormat::UnSignedInt);
+ m_format.setSampleFormat(QAudioFormat::UInt8);
break;
case 16:
- m_format.setSampleType(QAudioFormat::SignedInt);
+ m_format.setSampleFormat(QAudioFormat::Int16);
break;
default:
result = false;
@@ -130,10 +129,7 @@ bool WavHeader::write(QIODevice &device)
memset(&header, 0, HeaderLength);
// RIFF header
- if (m_format.byteOrder() == QAudioFormat::LittleEndian)
- memcpy(header.riff.descriptor.id,"RIFF",4);
- else
- memcpy(header.riff.descriptor.id,"RIFX",4);
+ memcpy(header.riff.descriptor.id,"RIFF",4);
qToLittleEndian<quint32>(quint32(m_dataLength + HeaderLength - 8),
reinterpret_cast<unsigned char*>(&header.riff.descriptor.size));
memcpy(header.riff.type, "WAVE",4);
@@ -148,11 +144,11 @@ bool WavHeader::write(QIODevice &device)
reinterpret_cast<unsigned char*>(&header.wave.numChannels));
qToLittleEndian<quint32>(quint32(m_format.sampleRate()),
reinterpret_cast<unsigned char*>(&header.wave.sampleRate));
- qToLittleEndian<quint32>(quint32(m_format.sampleRate() * m_format.channelCount() * m_format.sampleSize() / 8),
+ qToLittleEndian<quint32>(quint32(m_format.sampleRate() * m_format.bytesPerFrame()),
reinterpret_cast<unsigned char*>(&header.wave.byteRate));
- qToLittleEndian<quint16>(quint16(m_format.channelCount() * m_format.sampleSize() / 8),
+ qToLittleEndian<quint16>(quint16(m_format.channelCount() * m_format.bytesPerSample()),
reinterpret_cast<unsigned char*>(&header.wave.blockAlign));
- qToLittleEndian<quint16>(quint16(m_format.sampleSize()),
+ qToLittleEndian<quint16>(quint16(m_format.bytesPerSample() * 8),
reinterpret_cast<unsigned char*>(&header.wave.bitsPerSample));
// DATA header
@@ -185,6 +181,7 @@ bool WavHeader::writeDataLength(QIODevice &device, qint64 dataLength)
device.seek(40);
unsigned char dataLengthLE[4];
qToLittleEndian<quint32>(quint32(dataLength), dataLengthLE);
+ // ### Fix for big endian systems
result = (device.write(reinterpret_cast<const char *>(dataLengthLE), 4) == 4);
}
return result;
diff --git a/tests/auto/unit/mockbackend/mockaudiodecodercontrol.h b/tests/auto/unit/mockbackend/mockaudiodecodercontrol.h
index ec7e8ad83..4216bde86 100644
--- a/tests/auto/unit/mockbackend/mockaudiodecodercontrol.h
+++ b/tests/auto/unit/mockbackend/mockaudiodecodercontrol.h
@@ -55,9 +55,8 @@ public:
, mSerial(0)
{
mFormat.setChannelCount(1);
- mFormat.setSampleSize(8);
+ mFormat.setSampleFormat(QAudioFormat::UInt8);
mFormat.setSampleRate(1000);
- mFormat.setSampleType(QAudioFormat::UnSignedInt);
}
QAudioDecoder::State state() const
diff --git a/tests/auto/unit/multimedia/qaudiobuffer/tst_qaudiobuffer.cpp b/tests/auto/unit/multimedia/qaudiobuffer/tst_qaudiobuffer.cpp
index 6daa7da1b..91401eeeb 100644
--- a/tests/auto/unit/multimedia/qaudiobuffer/tst_qaudiobuffer.cpp
+++ b/tests/auto/unit/multimedia/qaudiobuffer/tst_qaudiobuffer.cpp
@@ -60,8 +60,7 @@ tst_QAudioBuffer::tst_QAudioBuffer()
{
// Initialize some common buffers
mFormat.setChannelCount(2);
- mFormat.setSampleSize(16);
- mFormat.setSampleType(QAudioFormat::UnSignedInt);
+ mFormat.setSampleFormat(QAudioFormat::Int16);
mFormat.setSampleRate(10000);
QByteArray b(4000, char(0x80));
@@ -236,18 +235,16 @@ void tst_QAudioBuffer::data()
void tst_QAudioBuffer::durations()
{
QFETCH(int, channelCount);
- QFETCH(int, sampleSize);
QFETCH(int, frameCount);
int sampleCount = frameCount * channelCount;
- QFETCH(QAudioFormat::SampleType, sampleType);
+ QFETCH(QAudioFormat::SampleFormat, sampleFormat);
QFETCH(int, sampleRate);
QFETCH(qint64, duration);
QFETCH(int, byteCount);
QAudioFormat f;
f.setChannelCount(channelCount);
- f.setSampleType(sampleType);
- f.setSampleSize(sampleSize);
+ f.setSampleFormat(sampleFormat);
f.setSampleRate(sampleRate);
QAudioBuffer b(frameCount, f);
@@ -261,21 +258,20 @@ void tst_QAudioBuffer::durations()
void tst_QAudioBuffer::durations_data()
{
QTest::addColumn<int>("channelCount");
- QTest::addColumn<int>("sampleSize");
QTest::addColumn<int>("frameCount");
- QTest::addColumn<QAudioFormat::SampleType>("sampleType");
+ QTest::addColumn<QAudioFormat::SampleFormat>("sampleType");
QTest::addColumn<int>("sampleRate");
QTest::addColumn<qint64>("duration");
QTest::addColumn<int>("byteCount");
- QTest::newRow("M8_1000_8K") << 1 << 8 << 1000 << QAudioFormat::UnSignedInt << 8000 << 125000LL << 1000;
- QTest::newRow("M8_2000_8K") << 1 << 8 << 2000 << QAudioFormat::UnSignedInt << 8000 << 250000LL << 2000;
- QTest::newRow("M8_1000_4K") << 1 << 8 << 1000 << QAudioFormat::UnSignedInt << 4000 << 250000LL << 1000;
+ QTest::newRow("M8_1000_8K") << 1 << 1000 << QAudioFormat::UInt8 << 8000 << 125000LL << 1000;
+ QTest::newRow("M8_2000_8K") << 1 << 2000 << QAudioFormat::UInt8 << 8000 << 250000LL << 2000;
+ QTest::newRow("M8_1000_4K") << 1 << 1000 << QAudioFormat::UInt8 << 4000 << 250000LL << 1000;
- QTest::newRow("S8_1000_8K") << 2 << 8 << 500 << QAudioFormat::UnSignedInt << 8000 << 62500LL << 1000;
+ QTest::newRow("S8_1000_8K") << 2 << 500 << QAudioFormat::UInt8 << 8000 << 62500LL << 1000;
- QTest::newRow("SF_1000_8K") << 2 << 32 << 500 << QAudioFormat::Float << 8000 << 62500LL << 4000;
+ QTest::newRow("SF_1000_8K") << 2 << 500 << QAudioFormat::Float << 8000 << 62500LL << 4000;
- QTest::newRow("4x128_1000_16K") << 4 << 128 << 250 << QAudioFormat::SignedInt << 16000 << 15625LL << 16000;
+ QTest::newRow("S32_1000_16K") << 4 << 250 << QAudioFormat::Int32 << 16000 << 15625LL << 16000;
}
void tst_QAudioBuffer::stereoSample()
diff --git a/tests/auto/unit/multimedia/qaudioformat/tst_qaudioformat.cpp b/tests/auto/unit/multimedia/qaudioformat/tst_qaudioformat.cpp
index 6558f455d..ff5590a16 100644
--- a/tests/auto/unit/multimedia/qaudioformat/tst_qaudioformat.cpp
+++ b/tests/auto/unit/multimedia/qaudioformat/tst_qaudioformat.cpp
@@ -45,9 +45,7 @@ public:
private slots:
void checkNull();
- void checkSampleSize();
- void checkByteOrder();
- void checkSampleType();
+ void checkSampleFormat();
void checkEquality();
void checkAssignment();
void checkSampleRate();
@@ -69,54 +67,30 @@ void tst_QAudioFormat::checkNull()
audioFormat0.setSampleRate(44100);
audioFormat0.setChannelCount(2);
- audioFormat0.setSampleSize(16);
- audioFormat0.setSampleType(QAudioFormat::SignedInt);
+ audioFormat0.setSampleFormat(QAudioFormat::Int16);
QVERIFY(audioFormat0.isValid());
}
-void tst_QAudioFormat::checkSampleSize()
+void tst_QAudioFormat::checkSampleFormat()
{
QAudioFormat audioFormat;
- audioFormat.setSampleSize(16);
- QVERIFY(audioFormat.sampleSize() == 16);
-}
-
-void tst_QAudioFormat::checkByteOrder()
-{
- QAudioFormat audioFormat;
- audioFormat.setByteOrder(QAudioFormat::LittleEndian);
- QVERIFY(audioFormat.byteOrder() == QAudioFormat::LittleEndian);
-
- QTest::ignoreMessage(QtDebugMsg, "LittleEndian");
- qDebug() << QAudioFormat::LittleEndian;
-
- audioFormat.setByteOrder(QAudioFormat::BigEndian);
- QVERIFY(audioFormat.byteOrder() == QAudioFormat::BigEndian);
-
- QTest::ignoreMessage(QtDebugMsg, "BigEndian");
- qDebug() << QAudioFormat::BigEndian;
-}
-
-void tst_QAudioFormat::checkSampleType()
-{
- QAudioFormat audioFormat;
- audioFormat.setSampleType(QAudioFormat::SignedInt);
- QVERIFY(audioFormat.sampleType() == QAudioFormat::SignedInt);
- QTest::ignoreMessage(QtDebugMsg, "SignedInt");
- qDebug() << QAudioFormat::SignedInt;
+ audioFormat.setSampleFormat(QAudioFormat::Int16);
+ QVERIFY(audioFormat.sampleFormat() == QAudioFormat::Int16);
+ QTest::ignoreMessage(QtDebugMsg, "Int16");
+ qDebug() << QAudioFormat::Int16;
- audioFormat.setSampleType(QAudioFormat::Unknown);
- QVERIFY(audioFormat.sampleType() == QAudioFormat::Unknown);
+ audioFormat.setSampleFormat(QAudioFormat::Unknown);
+ QVERIFY(audioFormat.sampleFormat() == QAudioFormat::Unknown);
QTest::ignoreMessage(QtDebugMsg, "Unknown");
qDebug() << QAudioFormat::Unknown;
- audioFormat.setSampleType(QAudioFormat::UnSignedInt);
- QVERIFY(audioFormat.sampleType() == QAudioFormat::UnSignedInt);
- QTest::ignoreMessage(QtDebugMsg, "UnSignedInt");
- qDebug() << QAudioFormat::UnSignedInt;
+ audioFormat.setSampleFormat(QAudioFormat::UInt8);
+ QVERIFY(audioFormat.sampleFormat() == QAudioFormat::UInt8);
+ QTest::ignoreMessage(QtDebugMsg, "UInt8");
+ qDebug() << QAudioFormat::UInt8;
- audioFormat.setSampleType(QAudioFormat::Float);
- QVERIFY(audioFormat.sampleType() == QAudioFormat::Float);
+ audioFormat.setSampleFormat(QAudioFormat::Float);
+ QVERIFY(audioFormat.sampleFormat() == QAudioFormat::Float);
QTest::ignoreMessage(QtDebugMsg, "Float");
qDebug() << QAudioFormat::Float;
}
@@ -133,15 +107,11 @@ void tst_QAudioFormat::checkEquality()
// on filled formats
audioFormat0.setSampleRate(8000);
audioFormat0.setChannelCount(1);
- audioFormat0.setSampleSize(8);
- audioFormat0.setByteOrder(QAudioFormat::LittleEndian);
- audioFormat0.setSampleType(QAudioFormat::UnSignedInt);
+ audioFormat0.setSampleFormat(QAudioFormat::UInt8);
audioFormat1.setSampleRate(8000);
audioFormat1.setChannelCount(1);
- audioFormat1.setSampleSize(8);
- audioFormat1.setByteOrder(QAudioFormat::LittleEndian);
- audioFormat1.setSampleType(QAudioFormat::UnSignedInt);
+ audioFormat1.setSampleFormat(QAudioFormat::UInt8);
QVERIFY(audioFormat0 == audioFormat1);
QVERIFY(!(audioFormat0 != audioFormat1));
@@ -158,9 +128,7 @@ void tst_QAudioFormat::checkAssignment()
audioFormat0.setSampleRate(8000);
audioFormat0.setChannelCount(1);
- audioFormat0.setSampleSize(8);
- audioFormat0.setByteOrder(QAudioFormat::LittleEndian);
- audioFormat0.setSampleType(QAudioFormat::UnSignedInt);
+ audioFormat0.setSampleFormat(QAudioFormat::UInt8);
audioFormat1 = audioFormat0;
QVERIFY(audioFormat1 == audioFormat0);
@@ -240,11 +208,9 @@ void tst_QAudioFormat::checkSizes_data()
QAudioFormat f;
QTest::newRow("invalid") << f << 0 << 0 << 0LL << 0 << 0 << 0LL << 0 << 0;
- f.setByteOrder(QAudioFormat::LittleEndian);
f.setChannelCount(1);
f.setSampleRate(8000);
- f.setSampleSize(8);
- f.setSampleType(QAudioFormat::SignedInt);
+ f.setSampleFormat(QAudioFormat::UInt8);
qint64 qrtr = 250000LL;
qint64 half = 500000LL;
@@ -257,7 +223,7 @@ void tst_QAudioFormat::checkSizes_data()
QTest::newRow("1ch_8b_8k_signed_16000") << f << 1 << 16000 << two << 16000 << 16000 << two << 16000 << 16000;
// Mono 16bit
- f.setSampleSize(16);
+ f.setSampleFormat(QAudioFormat::Int16);
QTest::newRow("1ch_16b_8k_signed_8000") << f << 2 << 8000 << half << 4000 << 8000 << half << 8000 << 4000;
QTest::newRow("1ch_16b_8k_signed_16000") << f << 2 << 16000 << one << 8000 << 16000 << one << 16000 << 8000;