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

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

trunk: Merged in qt 4.6.2 sources.

  • Property svn:eol-style set to native
File size: 8.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 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))
104 clipping = true;
105
106 float value = ((float)m_maxValue/(float)maxAmp);
107 if (clipping)
108 m_maxValue = 100;
109 else
110 m_maxValue = (int)(value*100);
111
112 emit update();
113
114 return len;
115}
116
117int AudioInfo::LinearMax()
118{
119 return m_maxValue;
120}
121
122RenderArea::RenderArea(QWidget *parent)
123 : QWidget(parent)
124{
125 setBackgroundRole(QPalette::Base);
126 setAutoFillBackground(true);
127
128 level = 0;
129 setMinimumHeight(30);
130 setMinimumWidth(200);
131}
132
133void RenderArea::paintEvent(QPaintEvent * /* event */)
134{
135 QPainter painter(this);
136
137 painter.setPen(Qt::black);
138 painter.drawRect(QRect(painter.viewport().left()+10,
139 painter.viewport().top()+10,
140 painter.viewport().right()-20,
141 painter.viewport().bottom()-20));
142 if (level == 0)
143 return;
144
145 painter.setPen(Qt::red);
146
147 int pos = ((painter.viewport().right()-20)-(painter.viewport().left()+11))*level/100;
148 for (int i = 0; i < 10; ++i) {
149 int x1 = painter.viewport().left()+11;
150 int y1 = painter.viewport().top()+10+i;
151 int x2 = painter.viewport().left()+20+pos;
152 int y2 = painter.viewport().top()+10+i;
153 if (x2 < painter.viewport().left()+10)
154 x2 = painter.viewport().left()+10;
155
156 painter.drawLine(QPoint(x1, y1),QPoint(x2, y2));
157 }
158}
159
160void RenderArea::setLevel(int value)
161{
162 level = value;
163 repaint();
164}
165
166
167InputTest::InputTest()
168{
169 QWidget *window = new QWidget;
170 QVBoxLayout* layout = new QVBoxLayout;
171
172 canvas = new RenderArea;
173 layout->addWidget(canvas);
174
175 deviceBox = new QComboBox(this);
176 QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
177 for(int i = 0; i < devices.size(); ++i)
178 deviceBox->addItem(devices.at(i).deviceName(), qVariantFromValue(devices.at(i)));
179
180 connect(deviceBox, SIGNAL(activated(int)), SLOT(deviceChanged(int)));
181 layout->addWidget(deviceBox);
182
183 button = new QPushButton(this);
184 button->setText(tr("Click for Push Mode"));
185 connect(button, SIGNAL(clicked()), SLOT(toggleMode()));
186 layout->addWidget(button);
187
188 button2 = new QPushButton(this);
189 button2->setText(tr("Click To Suspend"));
190 connect(button2, SIGNAL(clicked()), SLOT(toggleSuspend()));
191 layout->addWidget(button2);
192
193 window->setLayout(layout);
194 setCentralWidget(window);
195 window->show();
196
197 buffer = new char[BUFFER_SIZE];
198
199 pullMode = true;
200
201 format.setFrequency(8000);
202 format.setChannels(1);
203 format.setSampleSize(16);
204 format.setSampleType(QAudioFormat::SignedInt);
205 format.setByteOrder(QAudioFormat::LittleEndian);
206 format.setCodec("audio/pcm");
207
208 QAudioDeviceInfo info(QAudioDeviceInfo::defaultInputDevice());
209 if (!info.isFormatSupported(format)) {
210 qWarning()<<"default format not supported try to use nearest";
211 format = info.nearestFormat(format);
212 }
213
214 if(format.sampleSize() != 16) {
215 qWarning()<<"audio device doesn't support 16 bit samples, example cannot run";
216 audioInput = 0;
217 button->setDisabled(true);
218 button2->setDisabled(true);
219 return;
220 }
221
222 audioInput = new QAudioInput(format,this);
223 connect(audioInput, SIGNAL(notify()), SLOT(status()));
224 connect(audioInput, SIGNAL(stateChanged(QAudio::State)), SLOT(state(QAudio::State)));
225 audioinfo = new AudioInfo(this,audioInput);
226 connect(audioinfo, SIGNAL(update()), SLOT(refreshDisplay()));
227 audioinfo->start();
228 audioInput->start(audioinfo);
229}
230
231InputTest::~InputTest() {}
232
233void InputTest::status()
234{
235 qWarning()<<"bytesReady = "<<audioInput->bytesReady()<<" bytes, elapsedUSecs = "<<audioInput->elapsedUSecs()<<", processedUSecs = "<<audioInput->processedUSecs();
236}
237
238void InputTest::readMore()
239{
240 if(!audioInput)
241 return;
242 qint64 len = audioInput->bytesReady();
243 if(len > 4096)
244 len = 4096;
245 qint64 l = input->read(buffer,len);
246 if(l > 0) {
247 audioinfo->write(buffer,l);
248 }
249}
250
251void InputTest::toggleMode()
252{
253 // Change bewteen pull and push modes
254 audioInput->stop();
255
256 if (pullMode) {
257 button->setText(tr("Click for Pull Mode"));
258 input = audioInput->start();
259 connect(input, SIGNAL(readyRead()), SLOT(readMore()));
260 pullMode = false;
261 } else {
262 button->setText(tr("Click for Push Mode"));
263 pullMode = true;
264 audioInput->start(audioinfo);
265 }
266}
267
268void InputTest::toggleSuspend()
269{
270 // toggle suspend/resume
271 if(audioInput->state() == QAudio::SuspendedState) {
272 qWarning() << "status: Suspended, resume()";
273 audioInput->resume();
274 button2->setText("Click To Suspend");
275 } else if (audioInput->state() == QAudio::ActiveState) {
276 qWarning() << "status: Active, suspend()";
277 audioInput->suspend();
278 button2->setText("Click To Resume");
279 } else if (audioInput->state() == QAudio::StoppedState) {
280 qWarning() << "status: Stopped, resume()";
281 audioInput->resume();
282 button2->setText("Click To Suspend");
283 } else if (audioInput->state() == QAudio::IdleState) {
284 qWarning() << "status: IdleState";
285 }
286}
287
288void InputTest::state(QAudio::State state)
289{
290 qWarning() << " state=" << state;
291}
292
293void InputTest::refreshDisplay()
294{
295 canvas->setLevel(audioinfo->LinearMax());
296 canvas->repaint();
297}
298
299void InputTest::deviceChanged(int idx)
300{
301 audioinfo->stop();
302 audioInput->stop();
303 audioInput->disconnect(this);
304 delete audioInput;
305
306 device = deviceBox->itemData(idx).value<QAudioDeviceInfo>();
307 audioInput = new QAudioInput(device, format, this);
308 connect(audioInput, SIGNAL(notify()), SLOT(status()));
309 connect(audioInput, SIGNAL(stateChanged(QAudio::State)), SLOT(state(QAudio::State)));
310 audioinfo->start();
311 audioInput->start(audioinfo);
312}
Note: See TracBrowser for help on using the repository browser.