summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorGareth Stockwell <ext-gareth.stockwell@nokia.com>2010-02-16 16:43:20 (GMT)
committerGareth Stockwell <ext-gareth.stockwell@nokia.com>2010-02-16 17:57:48 (GMT)
commit479e26ab077a9d43e37b0706db4f5cb61964b327 (patch)
treeb8906650d2d326a75e967c71b3e63bb4071da425 /examples
parentd17060663236c0cf4d3eec79f8f76e30edfca636 (diff)
downloadQt-479e26ab077a9d43e37b0706db4f5cb61964b327.zip
Qt-479e26ab077a9d43e37b0706db4f5cb61964b327.tar.gz
Qt-479e26ab077a9d43e37b0706db4f5cb61964b327.tar.bz2
Made level calculation in audio input example work for all formats
The previous code only worked correctly for little-endian PCM16 formats. If the audio input device does not support such a format, the example previously would not run. Reviewed-by: trustme
Diffstat (limited to 'examples')
-rw-r--r--examples/multimedia/audioinput/audioinput.cpp110
-rw-r--r--examples/multimedia/audioinput/audioinput.h12
2 files changed, 80 insertions, 42 deletions
diff --git a/examples/multimedia/audioinput/audioinput.cpp b/examples/multimedia/audioinput/audioinput.cpp
index d00dd02..36fc5ac 100644
--- a/examples/multimedia/audioinput/audioinput.cpp
+++ b/examples/multimedia/audioinput/audioinput.cpp
@@ -48,14 +48,42 @@
#include <QAudioDeviceInfo>
#include <QAudioInput>
+
+#include <QtCore/qendian.h>
+
#include "audioinput.h"
#define BUFFER_SIZE 4096
-AudioInfo::AudioInfo(QObject *parent)
- :QIODevice(parent)
+AudioInfo::AudioInfo(const QAudioFormat &format, QObject *parent)
+ : QIODevice(parent)
+ , m_format(format)
+ , m_maxAmplitude(0)
+ , m_level(0.0)
+
{
- m_maxValue = 0;
+ switch (m_format.sampleSize()) {
+ case 8:
+ switch (m_format.sampleType()) {
+ case QAudioFormat::UnSignedInt:
+ m_maxAmplitude = 255;
+ break;
+ case QAudioFormat::SignedInt:
+ m_maxAmplitude = 127;
+ break;
+ }
+ break;
+ case 16:
+ switch (m_format.sampleType()) {
+ case QAudioFormat::UnSignedInt:
+ m_maxAmplitude = 65535;
+ break;
+ case QAudioFormat::SignedInt:
+ m_maxAmplitude = 32767;
+ break;
+ }
+ break;
+ }
}
AudioInfo::~AudioInfo()
@@ -82,41 +110,49 @@ qint64 AudioInfo::readData(char *data, qint64 maxlen)
qint64 AudioInfo::writeData(const char *data, qint64 len)
{
- int samples = len/2; // 2 bytes per sample
- int maxAmp = 32768; // max for S16 samples
- bool clipping = false;
-
- m_maxValue = 0;
-
- qint16 *s = (qint16*)data;
-
- // sample format is S16LE, only!
-
- for (int i = 0; i < samples; ++i) {
- qint16 sample = *s;
- s++;
- if (abs(sample) > m_maxValue) m_maxValue = abs(sample);
+ if (m_maxAmplitude) {
+ Q_ASSERT(m_format.sampleSize() % 8 == 0);
+ const int channelBytes = m_format.sampleSize() / 8;
+ const int sampleBytes = m_format.channels() * channelBytes;
+ Q_ASSERT(len % sampleBytes == 0);
+ const int numSamples = len / sampleBytes;
+
+ quint16 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.channels(); ++j) {
+ quint16 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));
+ }
+
+ maxValue = qMax(value, maxValue);
+ ptr += channelBytes;
+ }
+ }
+
+ maxValue = qMin(maxValue, m_maxAmplitude);
+ m_level = qreal(maxValue) / m_maxAmplitude;
}
- // check for clipping
- if (m_maxValue >= (maxAmp - 1))
- clipping = true;
-
- float value = ((float)m_maxValue/(float)maxAmp);
- if (clipping)
- m_maxValue = 100;
- else
- m_maxValue = (int)(value*100);
emit update();
-
return len;
}
-int AudioInfo::LinearMax()
-{
- return m_maxValue;
-}
-
RenderArea::RenderArea(QWidget *parent)
: QWidget(parent)
{
@@ -137,12 +173,12 @@ void RenderArea::paintEvent(QPaintEvent * /* event */)
painter.viewport().top()+10,
painter.viewport().right()-20,
painter.viewport().bottom()-20));
- if (level == 0)
+ if (level == 0.0)
return;
painter.setPen(Qt::red);
- int pos = ((painter.viewport().right()-20)-(painter.viewport().left()+11))*level/100;
+ int pos = ((painter.viewport().right()-20)-(painter.viewport().left()+11))*level;
for (int i = 0; i < 10; ++i) {
int x1 = painter.viewport().left()+11;
int y1 = painter.viewport().top()+10+i;
@@ -155,7 +191,7 @@ void RenderArea::paintEvent(QPaintEvent * /* event */)
}
}
-void RenderArea::setLevel(int value)
+void RenderArea::setLevel(qreal value)
{
level = value;
repaint();
@@ -220,7 +256,7 @@ InputTest::InputTest()
audioInput = new QAudioInput(format,this);
connect(audioInput, SIGNAL(notify()), SLOT(status()));
connect(audioInput, SIGNAL(stateChanged(QAudio::State)), SLOT(state(QAudio::State)));
- audioinfo = new AudioInfo(this);
+ audioinfo = new AudioInfo(format, this);
connect(audioinfo, SIGNAL(update()), SLOT(refreshDisplay()));
audioinfo->start();
audioInput->start(audioinfo);
@@ -292,7 +328,7 @@ void InputTest::state(QAudio::State state)
void InputTest::refreshDisplay()
{
- canvas->setLevel(audioinfo->LinearMax());
+ canvas->setLevel(audioinfo->level());
canvas->repaint();
}
diff --git a/examples/multimedia/audioinput/audioinput.h b/examples/multimedia/audioinput/audioinput.h
index 6f6c8eb..33b9ac6 100644
--- a/examples/multimedia/audioinput/audioinput.h
+++ b/examples/multimedia/audioinput/audioinput.h
@@ -52,19 +52,21 @@ class AudioInfo : public QIODevice
{
Q_OBJECT
public:
- AudioInfo(QObject *parent);
+ AudioInfo(const QAudioFormat &format, QObject *parent);
~AudioInfo();
void start();
void stop();
- int LinearMax();
+ qreal level() const { return m_level; }
qint64 readData(char *data, qint64 maxlen);
qint64 writeData(const char *data, qint64 len);
private:
- int m_maxValue;
+ const QAudioFormat m_format;
+ quint16 m_maxAmplitude;
+ qreal m_level; // 0.0 <= m_level <= 1.0
signals:
void update();
@@ -78,13 +80,13 @@ class RenderArea : public QWidget
public:
RenderArea(QWidget *parent = 0);
- void setLevel(int value);
+ void setLevel(qreal value);
protected:
void paintEvent(QPaintEvent *event);
private:
- int level;
+ qreal level;
QPixmap pixmap;
};