summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/src/examples/audioinput.qdoc2
-rw-r--r--examples/multimedia/audio/audioinput/audioinput.cpp198
-rw-r--r--examples/multimedia/audio/audioinput/audioinput.h40
-rw-r--r--examples/multimedia/audio/audiooutput/audiooutput.cpp34
-rw-r--r--examples/multimedia/audio/audiooutput/audiooutput.h2
5 files changed, 83 insertions, 193 deletions
diff --git a/doc/src/examples/audioinput.qdoc b/doc/src/examples/audioinput.qdoc
index 0b1b551..ac44d75 100644
--- a/doc/src/examples/audioinput.qdoc
+++ b/doc/src/examples/audioinput.qdoc
@@ -49,6 +49,6 @@
Qt provides the QAudioInput class to enable audio functionality within
a standard application user interface.
- This example uses a fast-fourier transform on the input audio from the microphone
+ This example calculates the maximum linear value of the input audio from the microphone
and displays the output.
*/
diff --git a/examples/multimedia/audio/audioinput/audioinput.cpp b/examples/multimedia/audio/audioinput/audioinput.cpp
index c09e7d9..05723ae 100644
--- a/examples/multimedia/audio/audioinput/audioinput.cpp
+++ b/examples/multimedia/audio/audioinput/audioinput.cpp
@@ -50,46 +50,31 @@
#include <QAudioInput>
#include "audioinput.h"
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
+#define BUFFER_SIZE 4096
-Spectrum::Spectrum(QObject* parent, QAudioInput* device, float* out)
+AudioInfo::AudioInfo(QObject* parent, QAudioInput* device)
:QIODevice( parent )
{
input = device;
- output = out;
- unsigned int i;
-
- // Allocate sample buffer and initialize sin and cos lookup tables
- fftState = (fft_state *) malloc (sizeof(fft_state));
-
- for(i = 0; i < BUFFER_SIZE; i++) {
- bitReverse[i] = reverseBits(i);
- }
- for(i = 0; i < BUFFER_SIZE / 2; i++) {
- float j = 2 * M_PI * i / BUFFER_SIZE;
- costable[i] = cos(j);
- sintable[i] = sin(j);
- }
+ m_maxValue = 0;
}
-Spectrum::~Spectrum()
+AudioInfo::~AudioInfo()
{
}
-void Spectrum::start()
+void AudioInfo::start()
{
open(QIODevice::WriteOnly);
}
-void Spectrum::stop()
+void AudioInfo::stop()
{
close();
}
-qint64 Spectrum::readData(char *data, qint64 maxlen)
+qint64 AudioInfo::readData(char *data, qint64 maxlen)
{
Q_UNUSED(data)
Q_UNUSED(maxlen)
@@ -97,97 +82,39 @@ qint64 Spectrum::readData(char *data, qint64 maxlen)
return 0;
}
-qint64 Spectrum::writeData(const char *data, qint64 len)
+qint64 AudioInfo::writeData(const char *data, qint64 len)
{
- performFFT((sound_sample*)data);
- emit update();
-
- return len;
-}
-
-int Spectrum::reverseBits(unsigned int initial) {
- // BIT-REVERSE-COPY(a,A)
-
- unsigned int reversed = 0, loop;
- for(loop = 0; loop < BUFFER_SIZE_LOG; loop++) {
- reversed <<= 1;
- reversed += (initial & 1);
- initial >>= 1;
- }
- return reversed;
-}
-
-void Spectrum::performFFT(const sound_sample *input) {
- /* Convert to reverse bit order for FFT */
- prepFFT(input, fftState->real, fftState->imag);
+ int samples = len/2; // 2 bytes per sample
+ int maxAmp = 32768; // max for S16 samples
+ bool clipping = false;
- /* Calculate FFT */
- calcFFT(fftState->real, fftState->imag);
-
- /* Convert FFT to intensities */
- outputFFT(fftState->real, fftState->imag);
-}
+ m_maxValue = 0;
-void Spectrum::prepFFT(const sound_sample *input, float * re, float * im) {
- unsigned int i;
- float *realptr = re;
- float *imagptr = im;
+ qint16* s = (qint16*)data;
- /* Get input, in reverse bit order */
- for(i = 0; i < BUFFER_SIZE; i++) {
- *realptr++ = input[bitReverse[i]];
- *imagptr++ = 0;
- }
-}
+ // sample format is S16LE, only!
-void Spectrum::calcFFT(float * re, float * im) {
- unsigned int i, j, k;
- unsigned int exchanges;
- float fact_real, fact_imag;
- float tmp_real, tmp_imag;
- unsigned int factfact;
-
- /* Set up some variables to reduce calculation in the loops */
- exchanges = 1;
- factfact = BUFFER_SIZE / 2;
-
- /* divide and conquer method */
- for(i = BUFFER_SIZE_LOG; i != 0; i--) {
- for(j = 0; j != exchanges; j++) {
- fact_real = costable[j * factfact];
- fact_imag = sintable[j * factfact];
- for(k = j; k < BUFFER_SIZE; k += exchanges << 1) {
- int k1 = k + exchanges;
- tmp_real = fact_real * re[k1] - fact_imag * im[k1];
- tmp_imag = fact_real * im[k1] + fact_imag * re[k1];
- re[k1] = re[k] - tmp_real;
- im[k1] = im[k] - tmp_imag;
- re[k] += tmp_real;
- im[k] += tmp_imag;
- }
- }
- exchanges <<= 1;
- factfact >>= 1;
+ for(int i=0;i<samples;i++) {
+ qint16 sample = *s;
+ s++;
+ if(abs(sample) > m_maxValue) m_maxValue = abs(sample);
}
-}
+ // check for clipping
+ if(m_maxValue>=(maxAmp-1)) clipping = true;
-void Spectrum::outputFFT(const float * re, const float * im) {
- const float *realptr = re;
- const float *imagptr = im;
- float *outputptr = output;
+ float value = ((float)m_maxValue/(float)maxAmp);
+ if(clipping) m_maxValue = 100;
+ else m_maxValue = (int)(value*100);
- float *endptr = output + BUFFER_SIZE / 2;
-
- /* Convert FFT to intensities */
+ emit update();
- while(outputptr <= endptr) {
- *outputptr = (*realptr * *realptr) + (*imagptr * *imagptr);
- outputptr++; realptr++; imagptr++;
- }
- *output /= 4;
- *endptr /= 4;
+ return len;
}
+int AudioInfo::LinearMax()
+{
+ return m_maxValue;
+}
RenderArea::RenderArea(QWidget *parent)
: QWidget(parent)
@@ -195,8 +122,7 @@ RenderArea::RenderArea(QWidget *parent)
setBackgroundRole(QPalette::Base);
setAutoFillBackground(true);
- samples = 0;
- sampleSize = 0;
+ level = 0;
setMinimumHeight(30);
setMinimumWidth(200);
}
@@ -205,38 +131,32 @@ void RenderArea::paintEvent(QPaintEvent * /* event */)
{
QPainter painter(this);
- if(sampleSize == 0)
+ painter.setPen(Qt::black);
+ painter.drawRect(QRect(painter.viewport().left()+10, painter.viewport().top()+10,
+ painter.viewport().right()-20, painter.viewport().bottom()-20));
+
+ if(level == 0)
return;
painter.setPen(Qt::red);
- int max = 0;
- for(int i=0;i<sampleSize;i++) {
- int m = (int)(sqrt(samples[i])/32768);
- if(m > max)
- max = m;
- }
- int x1,y1,x2,y2;
+ int pos = ((painter.viewport().right()-20)-(painter.viewport().left()+11))*level/100;
+ int x1,y1,x2,y2;
for(int i=0;i<10;i++) {
x1 = painter.viewport().left()+11;
y1 = painter.viewport().top()+10+i;
- x2 = painter.viewport().right()-20-max;
+ x2 = painter.viewport().left()+20+pos;
y2 = painter.viewport().top()+10+i;
if(x2 < painter.viewport().left()+10)
x2 = painter.viewport().left()+10;
painter.drawLine(QPoint(x1,y1),QPoint(x2,y2));
}
-
- painter.setPen(Qt::black);
- painter.drawRect(QRect(painter.viewport().left()+10, painter.viewport().top()+10,
- painter.viewport().right()-20, painter.viewport().bottom()-20));
}
-void RenderArea::spectrum(float* output, int size)
+void RenderArea::setLevel(int value)
{
- samples = output;
- sampleSize = size;
+ level = value;
repaint();
}
@@ -271,25 +191,25 @@ InputTest::InputTest()
setCentralWidget(window);
window->show();
- buffer = new char[BUFFER_SIZE*10];
- output = new float[1024];
+ buffer = new char[BUFFER_SIZE];
pullMode = true;
+ // AudioInfo class only supports mono S16LE samples!
format.setFrequency(8000);
format.setChannels(1);
- format.setSampleSize(8);
- format.setSampleType(QAudioFormat::UnSignedInt);
+ format.setSampleSize(16);
+ format.setSampleType(QAudioFormat::SignedInt);
format.setByteOrder(QAudioFormat::LittleEndian);
format.setCodec("audio/pcm");
audioInput = new QAudioInput(format,this);
connect(audioInput,SIGNAL(notify()),SLOT(status()));
connect(audioInput,SIGNAL(stateChanged(QAudio::State)),SLOT(state(QAudio::State)));
- spec = new Spectrum(this,audioInput,output);
- connect(spec,SIGNAL(update()),SLOT(refreshDisplay()));
- spec->start();
- audioInput->start(spec);
+ audioinfo = new AudioInfo(this,audioInput);
+ connect(audioinfo,SIGNAL(update()),SLOT(refreshDisplay()));
+ audioinfo->start();
+ audioInput->start(audioinfo);
}
InputTest::~InputTest() {}
@@ -304,11 +224,11 @@ void InputTest::readMore()
if(!audioInput)
return;
qint64 len = audioInput->bytesReady();
- if(len > BUFFER_SIZE*10)
- len = BUFFER_SIZE*10;
+ if(len > 4096)
+ len = 4096;
qint64 l = input->read(buffer,len);
if(l > 0) {
- spec->write(buffer,l);
+ audioinfo->write(buffer,l);
}
}
@@ -317,15 +237,15 @@ void InputTest::toggleMode()
// Change bewteen pull and push modes
audioInput->stop();
- if(pullMode) {
- button->setText(tr("Click for Push Mode"));
+ if (pullMode) {
+ button->setText(tr("Click for Pull Mode"));
input = audioInput->start(0);
connect(input,SIGNAL(readyRead()),SLOT(readMore()));
pullMode = false;
} else {
- button->setText(tr("Click for Pull Mode"));
+ button->setText(tr("Click for Push Mode"));
pullMode = true;
- audioInput->start(spec);
+ audioInput->start(audioinfo);
}
}
@@ -356,13 +276,13 @@ void InputTest::state(QAudio::State state)
void InputTest::refreshDisplay()
{
- canvas->spectrum(output,256);
+ canvas->setLevel(audioinfo->LinearMax());
canvas->repaint();
}
void InputTest::deviceChanged(int idx)
{
- spec->stop();
+ audioinfo->stop();
audioInput->stop();
audioInput->disconnect(this);
delete audioInput;
@@ -371,6 +291,6 @@ void InputTest::deviceChanged(int idx)
audioInput = new QAudioInput(device, format, this);
connect(audioInput,SIGNAL(notify()),SLOT(status()));
connect(audioInput,SIGNAL(stateChanged(QAudio::State)),SLOT(state(QAudio::State)));
- spec->start();
- audioInput->start(spec);
+ audioinfo->start();
+ audioInput->start(audioinfo);
}
diff --git a/examples/multimedia/audio/audioinput/audioinput.h b/examples/multimedia/audio/audioinput/audioinput.h
index 7ba6f1f..14e1bac 100644
--- a/examples/multimedia/audio/audioinput/audioinput.h
+++ b/examples/multimedia/audio/audioinput/audioinput.h
@@ -48,42 +48,25 @@
#include <qaudioinput.h>
-#define BUFFER_SIZE_LOG 9
-#define BUFFER_SIZE (1 << BUFFER_SIZE_LOG)
-
-struct _struct_fft_state {
- float real[BUFFER_SIZE];
- float imag[BUFFER_SIZE];
-};
-typedef _struct_fft_state fft_state;
-typedef short int sound_sample;
-
-class Spectrum : public QIODevice
+class AudioInfo : public QIODevice
{
Q_OBJECT
public:
- Spectrum(QObject* parent, QAudioInput* device, float* out);
- ~Spectrum();
+ AudioInfo(QObject* parent, QAudioInput* device);
+ ~AudioInfo();
void start();
void stop();
+ int LinearMax();
+
qint64 readData(char *data, qint64 maxlen);
qint64 writeData(const char *data, qint64 len);
QAudioInput* input;
- float* output;
- fft_state* fftState;
- unsigned int bitReverse[BUFFER_SIZE];
- float sintable[BUFFER_SIZE / 2];
- float costable[BUFFER_SIZE / 2];
-
- void prepFFT (const sound_sample *input, float *re, float *im);
- void calcFFT (float *re, float *im);
- void outputFFT (const float *re, const float *im);
- int reverseBits (unsigned int initial);
- void performFFT (const sound_sample *input);
+private:
+ int m_maxValue;
signals:
void update();
@@ -97,16 +80,14 @@ class RenderArea : public QWidget
public:
RenderArea(QWidget *parent = 0);
- void spectrum(float* output, int size);
+ void setLevel(int value);
protected:
void paintEvent(QPaintEvent *event);
private:
+ int level;
QPixmap pixmap;
-
- float* samples;
- int sampleSize;
};
class InputTest : public QMainWindow
@@ -119,7 +100,7 @@ public:
QAudioDeviceInfo device;
QAudioFormat format;
QAudioInput* audioInput;
- Spectrum* spec;
+ AudioInfo* audioinfo;
QIODevice* input;
RenderArea* canvas;
@@ -130,7 +111,6 @@ public:
QComboBox* deviceBox;
char* buffer;
- float* output;
private slots:
void refreshDisplay();
diff --git a/examples/multimedia/audio/audiooutput/audiooutput.cpp b/examples/multimedia/audio/audiooutput/audiooutput.cpp
index 19f7a3f..9e532cd 100644
--- a/examples/multimedia/audio/audiooutput/audiooutput.cpp
+++ b/examples/multimedia/audio/audiooutput/audiooutput.cpp
@@ -50,18 +50,19 @@
#define M_PI 3.14159265358979323846
#endif
+#define SECONDS 1
+#define FREQ 600
+#define SYSTEM_FREQ 44100
+
Generator::Generator(QObject *parent)
:QIODevice( parent )
{
finished = false;
- buffer = new char[SECONDS*44100*4+1000];
+ buffer = new char[SECONDS*SYSTEM_FREQ*4+1000];
t=buffer;
- len=fillData(t+4,450,SECONDS); /* left channel, 450Hz sine */
- len+=fillData(t+6,452,SECONDS); /* right channel, 452Hz sine */
- putLong(t,len);
- putLong(buffer+4,len+8+16+8);
+ len=fillData(t,FREQ,SECONDS); /* mono FREQHz sine */
pos = 0;
- total = len+8+16+8;
+ total = len;
}
Generator::~Generator()
@@ -86,21 +87,12 @@ int Generator::putShort(char *t, unsigned int value)
return 2;
}
-int Generator::putLong(char *t, unsigned int value)
-{
- *(unsigned char *)(t++)=value&255;
- *(unsigned char *)(t++)=(value/256)&255;
- *(unsigned char *)(t++)=(value/(256*256))&255;
- *(unsigned char *)(t)=(value/(256*256*256))&255;
- return 4;
-}
-
int Generator::fillData(char *start, int frequency, int seconds)
{
int i, len=0;
int value;
- for(i=0; i<seconds*44100; i++) {
- value=(int)(32767.0*sin(2.0*M_PI*((double)(i))*(double)(frequency)/44100.0));
+ for(i=0; i<seconds*SYSTEM_FREQ; i++) {
+ value=(int)(32767.0*sin(2.0*M_PI*((double)(i))*(double)(frequency)/SYSTEM_FREQ));
putShort(start, value);
start += 4;
len+=2;
@@ -114,14 +106,14 @@ qint64 Generator::readData(char *data, qint64 maxlen)
if(len > 16384)
len = 16384;
- if(len < (SECONDS*44100*4+1000)-pos) {
+ if(len < (SECONDS*SYSTEM_FREQ*2)-pos) {
// Normal
memcpy(data,t+pos,len);
pos+=len;
return len;
} else {
// Whats left and reset to start
- qint64 left = (SECONDS*44100*4+1000)-pos;
+ qint64 left = (SECONDS*SYSTEM_FREQ*2)-pos;
memcpy(data,t+pos,left);
pos=0;
return left;
@@ -172,8 +164,8 @@ AudioTest::AudioTest()
gen->start();
- settings.setFrequency(44100);
- settings.setChannels(2);
+ settings.setFrequency(SYSTEM_FREQ);
+ settings.setChannels(1);
settings.setSampleSize(16);
settings.setCodec("audio/pcm");
settings.setByteOrder(QAudioFormat::LittleEndian);
diff --git a/examples/multimedia/audio/audiooutput/audiooutput.h b/examples/multimedia/audio/audiooutput/audiooutput.h
index a5c0289..6c07a3a 100644
--- a/examples/multimedia/audio/audiooutput/audiooutput.h
+++ b/examples/multimedia/audio/audiooutput/audiooutput.h
@@ -42,7 +42,6 @@
#include <math.h>
#define BUFFER_SIZE 32768
-#define SECONDS 3
#include <QObject>
#include <QMainWindow>
@@ -76,7 +75,6 @@ public:
private:
int putShort(char *t, unsigned int value);
- int putLong(char *t, unsigned int value);
int fillData(char *start, int frequency, int seconds);
};