diff options
author | Lev Zelenskiy <lev.zelenskiy@nokia.com> | 2012-02-21 17:35:51 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-02-24 06:51:30 +0100 |
commit | b37ea41ce146ccea28086120c7a0f22855b78b8a (patch) | |
tree | 8dc7a0fbe9c915f267728006df235bddd0ad4601 /examples | |
parent | 03a14a95fe731259aeb104c3ea4ca42ae8b10a09 (diff) |
Audio recorder example updated to display level using QAudioProbe.
Change-Id: I7d5aea306aeb3cd9109615f9ed4905c53125233a
Reviewed-by: Michael Goddard <michael.goddard@nokia.com>
Diffstat (limited to 'examples')
-rw-r--r-- | examples/audiorecorder/audiorecorder.cpp | 93 | ||||
-rw-r--r-- | examples/audiorecorder/audiorecorder.h | 13 | ||||
-rw-r--r-- | examples/audiorecorder/audiorecorder.pro | 6 | ||||
-rw-r--r-- | examples/audiorecorder/audiorecorder.ui | 11 | ||||
-rw-r--r-- | examples/audiorecorder/qaudiolevel.cpp | 68 | ||||
-rw-r--r-- | examples/audiorecorder/qaudiolevel.h | 64 |
6 files changed, 251 insertions, 4 deletions
diff --git a/examples/audiorecorder/audiorecorder.cpp b/examples/audiorecorder/audiorecorder.cpp index 459718f72..b30b1ed84 100644 --- a/examples/audiorecorder/audiorecorder.cpp +++ b/examples/audiorecorder/audiorecorder.cpp @@ -43,6 +43,7 @@ #include <qaudiorecorder.h> #include <qmediarecorder.h> +#include <qaudioprobe.h> #include "audiorecorder.h" @@ -61,6 +62,9 @@ AudioRecorder::AudioRecorder(QWidget *parent) ui->setupUi(this); audioRecorder = new QAudioRecorder(this); + probe = new QAudioProbe; + connect(probe, SIGNAL(audioBufferProbed(const QAudioBuffer&)), this, SLOT(processBuffer(QAudioBuffer))); + probe->setSource(audioRecorder); //audio devices ui->audioDeviceBox->addItem(tr("Default"), QVariant(QString())); @@ -103,11 +107,12 @@ AudioRecorder::AudioRecorder(QWidget *parent) SLOT(updateState(QMediaRecorder::State))); connect(audioRecorder, SIGNAL(error(QMediaRecorder::Error)), this, SLOT(displayErrorMessage())); - } +} AudioRecorder::~AudioRecorder() { delete audioRecorder; + delete probe; } void AudioRecorder::updateProgress(qint64 duration) @@ -221,3 +226,89 @@ QUrl AudioRecorder::generateAudioFilePath() QUrl location(QDir::toNativeSeparators(outputDir.canonicalPath() + QString("/testclip_%1").arg(lastImage + 1, 4, 10, QLatin1Char('0')))); return location; } + +// This function returns the maximum possible sample value for a given audio format +qreal AudioRecorder::GetPeakValue(const QAudioFormat& format) +{ + // Note: Only the most common sample formats are supported + if (!format.isValid()) + return 0.0; + + if (format.codec() != "audio/pcm") + return 0.0; + + switch (format.sampleType()) { + case QAudioFormat::Unknown: + break; + case QAudioFormat::Float: + if (format.sampleSize() != 32) // other sample formats are not supported + return 0.0; + return 1.00003; + case QAudioFormat::SignedInt: + if (format.sampleSize() == 32) + return 2147483648.0; + else if (format.sampleSize() == 16) + return 32768.0; + else if (format.sampleSize() == 8) + return 128.0; + break; + case QAudioFormat::UnSignedInt: + // Unsigned formats are not supported in this example + break; + } + + return 0.0; +} + +qreal AudioRecorder::GetBufferLevel(const QAudioBuffer& buffer) +{ + if (!buffer.format().isValid() || buffer.format().byteOrder() != QAudioFormat::LittleEndian) + return 0.0; + + if (buffer.format().codec() != "audio/pcm") + return 0.0; + + qreal peak_value = GetPeakValue(buffer.format()); + if (qFuzzyCompare(peak_value, 0.0)) + return 0.0; + + switch (buffer.format().sampleType()) { + case QAudioFormat::Unknown: + case QAudioFormat::UnSignedInt: + break; + case QAudioFormat::Float: + if (buffer.format().sampleSize() == 32) + return GetBufferLevel(buffer.constData<float>(), buffer.sampleCount()) / peak_value; + break; + case QAudioFormat::SignedInt: + if (buffer.format().sampleSize() == 32) + return GetBufferLevel(buffer.constData<long int>(), buffer.sampleCount()) / peak_value; + else if (buffer.format().sampleSize() == 16) + return GetBufferLevel(buffer.constData<short int>(), buffer.sampleCount()) / peak_value; + else if (buffer.format().sampleSize() == 8) + return GetBufferLevel(buffer.constData<signed char>(), buffer.sampleCount()) / peak_value; + break; + } + + return 0.0; +} + +template <class T> +qreal AudioRecorder::GetBufferLevel(const T* buffer, int samples) +{ + qreal max_value = 0.0; + + for (int i = 0; i < samples; i++) { + qreal value = qAbs((qreal)buffer[i]); + if (value > max_value) + max_value = value; + } + + return max_value; +} + +void AudioRecorder::processBuffer(const QAudioBuffer& buffer) +{ + qreal level = GetBufferLevel(buffer); + ui->audioLevel->setLevel(level); +} diff --git a/examples/audiorecorder/audiorecorder.h b/examples/audiorecorder/audiorecorder.h index 09d097649..05fbf7985 100644 --- a/examples/audiorecorder/audiorecorder.h +++ b/examples/audiorecorder/audiorecorder.h @@ -54,6 +54,8 @@ namespace Ui { } class QAudioRecorder; +class QAudioProbe; +class QAudioBuffer; QT_END_NAMESPACE QT_USE_NAMESPACE @@ -65,6 +67,9 @@ public: AudioRecorder(QWidget *parent = 0); ~AudioRecorder(); +public slots: + void processBuffer(const QAudioBuffer&); + private slots: void setOutputLocation(); void togglePause(); @@ -76,10 +81,16 @@ private slots: QUrl generateAudioFilePath(); private: + static qreal GetPeakValue(const QAudioFormat& format); + static qreal GetBufferLevel(const QAudioBuffer& buffer); + + template <class T> + static qreal GetBufferLevel(const T* buffer, int samples); + Ui::AudioRecorder *ui; QAudioRecorder* audioRecorder; - QAudioEncoderSettings audioSettings; + QAudioProbe* probe; bool outputLocationSet; }; diff --git a/examples/audiorecorder/audiorecorder.pro b/examples/audiorecorder/audiorecorder.pro index f2af6387e..8c1cfa89f 100644 --- a/examples/audiorecorder/audiorecorder.pro +++ b/examples/audiorecorder/audiorecorder.pro @@ -4,11 +4,13 @@ TARGET = audiorecorder QT += multimedia HEADERS = \ - audiorecorder.h + audiorecorder.h \ + qaudiolevel.h SOURCES = \ main.cpp \ - audiorecorder.cpp + audiorecorder.cpp \ + qaudiolevel.cpp maemo*: { FORMS += audiorecorder_small.ui diff --git a/examples/audiorecorder/audiorecorder.ui b/examples/audiorecorder/audiorecorder.ui index 8ade5ce8c..ff6c2d935 100644 --- a/examples/audiorecorder/audiorecorder.ui +++ b/examples/audiorecorder/audiorecorder.ui @@ -155,6 +155,17 @@ </property> </widget> </item> + <item row="3" column="0"> + <widget class="QLabel" name="levelLabel"> + <property name="text"> + <string>Audio Level:</string> + </property> + </widget> + </item> + <item row="3" column="1" colspan="-1"> + <widget class="QAudioLevel" name="audioLevel"> + </widget> + </item> </layout> </widget> <widget class="QStatusBar" name="statusbar"/> diff --git a/examples/audiorecorder/qaudiolevel.cpp b/examples/audiorecorder/qaudiolevel.cpp new file mode 100644 index 000000000..2e72c1581 --- /dev/null +++ b/examples/audiorecorder/qaudiolevel.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qaudiolevel.h" +#include <QPainter> + +QAudioLevel::QAudioLevel(QWidget *parent) + : QWidget(parent) + , m_level(0.0) +{ +} + +void QAudioLevel::setLevel(qreal level) +{ + if (m_level != level) { + m_level = level; + update(); + } +} + +void QAudioLevel::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + + QPainter painter(this); + // draw level + qreal widthLevel = m_level * width(); + painter.fillRect(0, 0, widthLevel, height(), Qt::red); + // clear the rest of the control + painter.fillRect(widthLevel, 0, width(), height(), Qt::black); +} diff --git a/examples/audiorecorder/qaudiolevel.h b/examples/audiorecorder/qaudiolevel.h new file mode 100644 index 000000000..2c02dbf86 --- /dev/null +++ b/examples/audiorecorder/qaudiolevel.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QAUDIOLEVEL_H +#define QAUDIOLEVEL_H + +#include <QWidget> + +QT_USE_NAMESPACE + +class QAudioLevel : public QWidget +{ + Q_OBJECT +public: + explicit QAudioLevel(QWidget *parent = 0); + + // Using [0; 1.0] range + void setLevel(qreal level); + +protected: + void paintEvent(QPaintEvent *event); + +private: + qreal m_level; +}; + +#endif // QAUDIOLEVEL_H |