source: trunk/examples/multimedia/audioinput/audioinput.cpp@ 561

Last change on this file since 561 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

  • Property svn:eol-style set to native
File size: 8.4 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the examples of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <stdlib.h>
43#include <math.h>
44
45#include <QDebug>
46#include <QPainter>
47#include <QVBoxLayout>
48
49#include <QAudioDeviceInfo>
50#include <QAudioInput>
51#include "audioinput.h"
52
53#define BUFFER_SIZE 4096
54
55AudioInfo::AudioInfo(QObject* parent, QAudioInput* device)
56 :QIODevice( parent )
57{
58 input = device;
59
60 m_maxValue = 0;
61}
62
63AudioInfo::~AudioInfo()
64{
65}
66
67void AudioInfo::start()
68{
69 open(QIODevice::WriteOnly);
70}
71
72void AudioInfo::stop()
73{
74 close();
75}
76
77qint64 AudioInfo::readData(char *data, qint64 maxlen)
78{
79 Q_UNUSED(data)
80 Q_UNUSED(maxlen)
81
82 return 0;
83}
84
85qint64 AudioInfo::writeData(const char *data, qint64 len)
86{
87 int samples = len/2; // 2 bytes per sample
88 int maxAmp = 32768; // max for S16 samples
89 bool clipping = false;
90
91 m_maxValue = 0;
92
93 qint16* s = (qint16*)data;
94
95 // sample format is S16LE, only!
96
97 for(int i=0;i<samples;i++) {
98 qint16 sample = *s;
99 s++;
100 if(abs(sample) > m_maxValue) m_maxValue = abs(sample);
101 }
102 // check for clipping
103 if(m_maxValue>=(maxAmp-1)) clipping = true;
104
105 float value = ((float)m_maxValue/(float)maxAmp);
106 if(clipping) m_maxValue = 100;
107 else m_maxValue = (int)(value*100);
108
109 emit update();
110
111 return len;
112}
113
114int AudioInfo::LinearMax()
115{
116 return m_maxValue;
117}
118
119RenderArea::RenderArea(QWidget *parent)
120 : QWidget(parent)
121{
122 setBackgroundRole(QPalette::Base);
123 setAutoFillBackground(true);
124
125 level = 0;
126 setMinimumHeight(30);
127 setMinimumWidth(200);
128}
129
130void RenderArea::paintEvent(QPaintEvent * /* event */)
131{
132 QPainter painter(this);
133
134 painter.setPen(Qt::black);
135 painter.drawRect(QRect(painter.viewport().left()+10, painter.viewport().top()+10,
136 painter.viewport().right()-20, painter.viewport().bottom()-20));
137
138 if(level == 0)
139 return;
140
141 painter.setPen(Qt::red);
142
143 int pos = ((painter.viewport().right()-20)-(painter.viewport().left()+11))*level/100;
144 int x1,y1,x2,y2;
145 for(int i=0;i<10;i++) {
146 x1 = painter.viewport().left()+11;
147 y1 = painter.viewport().top()+10+i;
148 x2 = painter.viewport().left()+20+pos;
149 y2 = painter.viewport().top()+10+i;
150 if(x2 < painter.viewport().left()+10)
151 x2 = painter.viewport().left()+10;
152
153 painter.drawLine(QPoint(x1,y1),QPoint(x2,y2));
154 }
155}
156
157void RenderArea::setLevel(int value)
158{
159 level = value;
160 repaint();
161}
162
163
164InputTest::InputTest()
165{
166 QWidget *window = new QWidget;
167 QVBoxLayout* layout = new QVBoxLayout;
168
169 canvas = new RenderArea;
170 layout->addWidget(canvas);
171
172 deviceBox = new QComboBox(this);
173 QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
174 for(int i = 0; i < devices.size(); ++i) {
175 deviceBox->addItem(devices.at(i).deviceName(), qVariantFromValue(devices.at(i)));
176 }
177 connect(deviceBox,SIGNAL(activated(int)),SLOT(deviceChanged(int)));
178 layout->addWidget(deviceBox);
179
180 button = new QPushButton(this);
181 button->setText(tr("Click for Push Mode"));
182 connect(button,SIGNAL(clicked()),SLOT(toggleMode()));
183 layout->addWidget(button);
184
185 button2 = new QPushButton(this);
186 button2->setText(tr("Click To Suspend"));
187 connect(button2,SIGNAL(clicked()),SLOT(toggleSuspend()));
188 layout->addWidget(button2);
189
190 window->setLayout(layout);
191 setCentralWidget(window);
192 window->show();
193
194 buffer = new char[BUFFER_SIZE];
195
196 pullMode = true;
197
198 format.setFrequency(8000);
199 format.setChannels(1);
200 format.setSampleSize(16);
201 format.setSampleType(QAudioFormat::SignedInt);
202 format.setByteOrder(QAudioFormat::LittleEndian);
203 format.setCodec("audio/pcm");
204
205 QAudioDeviceInfo info(QAudioDeviceInfo::defaultInputDevice());
206 if (!info.isFormatSupported(format)) {
207 qWarning()<<"default format not supported try to use nearest";
208 format = info.nearestFormat(format);
209 }
210
211 if(format.sampleSize() != 16) {
212 qWarning()<<"audio device doesn't support 16 bit samples, example cannot run";
213 return;
214 }
215
216 audioInput = new QAudioInput(format,this);
217 connect(audioInput,SIGNAL(notify()),SLOT(status()));
218 connect(audioInput,SIGNAL(stateChanged(QAudio::State)),SLOT(state(QAudio::State)));
219 audioinfo = new AudioInfo(this,audioInput);
220 connect(audioinfo,SIGNAL(update()),SLOT(refreshDisplay()));
221 audioinfo->start();
222 audioInput->start(audioinfo);
223}
224
225InputTest::~InputTest() {}
226
227void InputTest::status()
228{
229 qWarning()<<"bytesReady = "<<audioInput->bytesReady()<<" bytes, elapsedUSecs = "<<audioInput->elapsedUSecs()<<", processedUSecs = "<<audioInput->processedUSecs();
230}
231
232void InputTest::readMore()
233{
234 if(!audioInput)
235 return;
236 qint64 len = audioInput->bytesReady();
237 if(len > 4096)
238 len = 4096;
239 qint64 l = input->read(buffer,len);
240 if(l > 0) {
241 audioinfo->write(buffer,l);
242 }
243}
244
245void InputTest::toggleMode()
246{
247 // Change bewteen pull and push modes
248 audioInput->stop();
249
250 if (pullMode) {
251 button->setText(tr("Click for Pull Mode"));
252 input = audioInput->start();
253 connect(input,SIGNAL(readyRead()),SLOT(readMore()));
254 pullMode = false;
255 } else {
256 button->setText(tr("Click for Push Mode"));
257 pullMode = true;
258 audioInput->start(audioinfo);
259 }
260}
261
262void InputTest::toggleSuspend()
263{
264 // toggle suspend/resume
265 if(audioInput->state() == QAudio::SuspendedState) {
266 qWarning()<<"status: Suspended, resume()";
267 audioInput->resume();
268 button2->setText("Click To Suspend");
269 } else if (audioInput->state() == QAudio::ActiveState) {
270 qWarning()<<"status: Active, suspend()";
271 audioInput->suspend();
272 button2->setText("Click To Resume");
273 } else if (audioInput->state() == QAudio::StoppedState) {
274 qWarning()<<"status: Stopped, resume()";
275 audioInput->resume();
276 button2->setText("Click To Suspend");
277 } else if (audioInput->state() == QAudio::IdleState) {
278 qWarning()<<"status: IdleState";
279 }
280}
281
282void InputTest::state(QAudio::State state)
283{
284 qWarning()<<" state="<<state;
285}
286
287void InputTest::refreshDisplay()
288{
289 canvas->setLevel(audioinfo->LinearMax());
290 canvas->repaint();
291}
292
293void InputTest::deviceChanged(int idx)
294{
295 audioinfo->stop();
296 audioInput->stop();
297 audioInput->disconnect(this);
298 delete audioInput;
299
300 device = deviceBox->itemData(idx).value<QAudioDeviceInfo>();
301 audioInput = new QAudioInput(device, format, this);
302 connect(audioInput,SIGNAL(notify()),SLOT(status()));
303 connect(audioInput,SIGNAL(stateChanged(QAudio::State)),SLOT(state(QAudio::State)));
304 audioinfo->start();
305 audioInput->start(audioinfo);
306}
Note: See TracBrowser for help on using the repository browser.