summaryrefslogtreecommitdiffstats
path: root/examples
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 /examples
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>
Diffstat (limited to 'examples')
-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
17 files changed, 259 insertions, 688 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)