Changeset 769 for trunk/examples/multimedia/audioinput/audioinput.cpp
- Timestamp:
- Aug 2, 2010, 9:27:30 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/vendor/nokia/qt/4.6.3 (added) merged: 768 /branches/vendor/nokia/qt/current merged: 767 /branches/vendor/nokia/qt/4.6.2 removed
- Property svn:mergeinfo changed
-
trunk/examples/multimedia/audioinput/audioinput.cpp
r651 r769 49 49 #include <QAudioDeviceInfo> 50 50 #include <QAudioInput> 51 52 #include <QtCore/qendian.h> 53 51 54 #include "audioinput.h" 52 55 53 #define BUFFER_SIZE 4096 54 55 AudioInfo::AudioInfo(QObject *parent, QAudioInput *device) 56 :QIODevice(parent) 57 { 58 input = device; 59 60 m_maxValue = 0; 56 const QString InputTest::PushModeLabel(tr("Enable push mode")); 57 const QString InputTest::PullModeLabel(tr("Enable pull mode")); 58 const QString InputTest::SuspendLabel(tr("Suspend recording")); 59 const QString InputTest::ResumeLabel(tr("Resume recording")); 60 61 const int BufferSize = 4096; 62 63 AudioInfo::AudioInfo(const QAudioFormat &format, QObject *parent) 64 : QIODevice(parent) 65 , m_format(format) 66 , m_maxAmplitude(0) 67 , m_level(0.0) 68 69 { 70 switch (m_format.sampleSize()) { 71 case 8: 72 switch (m_format.sampleType()) { 73 case QAudioFormat::UnSignedInt: 74 m_maxAmplitude = 255; 75 break; 76 case QAudioFormat::SignedInt: 77 m_maxAmplitude = 127; 78 break; 79 default: ; 80 } 81 break; 82 case 16: 83 switch (m_format.sampleType()) { 84 case QAudioFormat::UnSignedInt: 85 m_maxAmplitude = 65535; 86 break; 87 case QAudioFormat::SignedInt: 88 m_maxAmplitude = 32767; 89 break; 90 default: ; 91 } 92 break; 93 } 61 94 } 62 95 … … 85 118 qint64 AudioInfo::writeData(const char *data, qint64 len) 86 119 { 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); 120 if (m_maxAmplitude) { 121 Q_ASSERT(m_format.sampleSize() % 8 == 0); 122 const int channelBytes = m_format.sampleSize() / 8; 123 const int sampleBytes = m_format.channels() * channelBytes; 124 Q_ASSERT(len % sampleBytes == 0); 125 const int numSamples = len / sampleBytes; 126 127 quint16 maxValue = 0; 128 const unsigned char *ptr = reinterpret_cast<const unsigned char *>(data); 129 130 for (int i = 0; i < numSamples; ++i) { 131 for(int j = 0; j < m_format.channels(); ++j) { 132 quint16 value = 0; 133 134 if (m_format.sampleSize() == 8 && m_format.sampleType() == QAudioFormat::UnSignedInt) { 135 value = *reinterpret_cast<const quint8*>(ptr); 136 } else if (m_format.sampleSize() == 8 && m_format.sampleType() == QAudioFormat::SignedInt) { 137 value = qAbs(*reinterpret_cast<const qint8*>(ptr)); 138 } else if (m_format.sampleSize() == 16 && m_format.sampleType() == QAudioFormat::UnSignedInt) { 139 if (m_format.byteOrder() == QAudioFormat::LittleEndian) 140 value = qFromLittleEndian<quint16>(ptr); 141 else 142 value = qFromBigEndian<quint16>(ptr); 143 } else if (m_format.sampleSize() == 16 && m_format.sampleType() == QAudioFormat::SignedInt) { 144 if (m_format.byteOrder() == QAudioFormat::LittleEndian) 145 value = qAbs(qFromLittleEndian<qint16>(ptr)); 146 else 147 value = qAbs(qFromBigEndian<qint16>(ptr)); 148 } 149 150 maxValue = qMax(value, maxValue); 151 ptr += channelBytes; 152 } 153 } 154 155 maxValue = qMin(maxValue, m_maxAmplitude); 156 m_level = qreal(maxValue) / m_maxAmplitude; 157 } 111 158 112 159 emit update(); 113 114 160 return len; 115 }116 117 int AudioInfo::LinearMax()118 {119 return m_maxValue;120 161 } 121 162 … … 126 167 setAutoFillBackground(true); 127 168 128 level = 0;169 m_level = 0; 129 170 setMinimumHeight(30); 130 171 setMinimumWidth(200); … … 140 181 painter.viewport().right()-20, 141 182 painter.viewport().bottom()-20)); 142 if ( level ==0)183 if (m_level == 0.0) 143 184 return; 144 185 145 186 painter.setPen(Qt::red); 146 187 147 int pos = ((painter.viewport().right()-20)-(painter.viewport().left()+11))* level/100;188 int pos = ((painter.viewport().right()-20)-(painter.viewport().left()+11))*m_level; 148 189 for (int i = 0; i < 10; ++i) { 149 190 int x1 = painter.viewport().left()+11; … … 158 199 } 159 200 160 void RenderArea::setLevel( intvalue)161 { 162 level = value;201 void RenderArea::setLevel(qreal value) 202 { 203 m_level = value; 163 204 repaint(); 164 205 } … … 166 207 167 208 InputTest::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); 209 : m_canvas(0) 210 , m_modeButton(0) 211 , m_suspendResumeButton(0) 212 , m_deviceBox(0) 213 , m_device(QAudioDeviceInfo::defaultInputDevice()) 214 , m_audioInfo(0) 215 , m_audioInput(0) 216 , m_input(0) 217 , m_pullMode(false) 218 , m_buffer(BufferSize, 0) 219 { 220 initializeWindow(); 221 initializeAudio(); 222 } 223 224 InputTest::~InputTest() {} 225 226 void InputTest::initializeWindow() 227 { 228 QScopedPointer<QWidget> window(new QWidget); 229 QScopedPointer<QVBoxLayout> layout(new QVBoxLayout); 230 231 m_canvas = new RenderArea(this); 232 layout->addWidget(m_canvas); 233 234 m_deviceBox = new QComboBox(this); 176 235 QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); 177 236 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"); 237 m_deviceBox->addItem(devices.at(i).deviceName(), qVariantFromValue(devices.at(i))); 238 239 connect(m_deviceBox, SIGNAL(activated(int)), SLOT(deviceChanged(int))); 240 layout->addWidget(m_deviceBox); 241 242 m_modeButton = new QPushButton(this); 243 m_modeButton->setText(PushModeLabel); 244 connect(m_modeButton, SIGNAL(clicked()), SLOT(toggleMode())); 245 layout->addWidget(m_modeButton); 246 247 m_suspendResumeButton = new QPushButton(this); 248 m_suspendResumeButton->setText(SuspendLabel); 249 connect(m_suspendResumeButton, SIGNAL(clicked()), SLOT(toggleSuspend())); 250 layout->addWidget(m_suspendResumeButton); 251 252 window->setLayout(layout.data()); 253 layout.take(); // ownership transferred 254 255 setCentralWidget(window.data()); 256 QWidget *const windowPtr = window.take(); // ownership transferred 257 windowPtr->show(); 258 } 259 260 void InputTest::initializeAudio() 261 { 262 m_pullMode = true; 263 264 m_format.setFrequency(8000); 265 m_format.setChannels(1); 266 m_format.setSampleSize(16); 267 m_format.setSampleType(QAudioFormat::SignedInt); 268 m_format.setByteOrder(QAudioFormat::LittleEndian); 269 m_format.setCodec("audio/pcm"); 207 270 208 271 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); 272 if (!info.isFormatSupported(m_format)) { 273 qWarning() << "Default format not supported - trying to use nearest"; 274 m_format = info.nearestFormat(m_format); 275 } 276 277 m_audioInfo = new AudioInfo(m_format, this); 278 connect(m_audioInfo, SIGNAL(update()), SLOT(refreshDisplay())); 279 280 createAudioInput(); 281 } 282 283 void InputTest::createAudioInput() 284 { 285 m_audioInput = new QAudioInput(m_device, m_format, this); 286 connect(m_audioInput, SIGNAL(notify()), SLOT(notified())); 287 connect(m_audioInput, SIGNAL(stateChanged(QAudio::State)), SLOT(stateChanged(QAudio::State))); 288 m_audioInfo->start(); 289 m_audioInput->start(m_audioInfo); 290 } 291 292 void InputTest::notified() 293 { 294 qWarning() << "bytesReady = " << m_audioInput->bytesReady() 295 << ", " << "elapsedUSecs = " <<m_audioInput->elapsedUSecs() 296 << ", " << "processedUSecs = "<<m_audioInput->processedUSecs(); 297 } 298 299 void InputTest::readMore() 300 { 301 if(!m_audioInput) 219 302 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 231 InputTest::~InputTest() {} 232 233 void InputTest::status() 234 { 235 qWarning()<<"bytesReady = "<<audioInput->bytesReady()<<" bytes, elapsedUSecs = "<<audioInput->elapsedUSecs()<<", processedUSecs = "<<audioInput->processedUSecs(); 236 } 237 238 void InputTest::readMore() 239 { 240 if(!audioInput) 241 return; 242 qint64 len = audioInput->bytesReady(); 303 qint64 len = m_audioInput->bytesReady(); 243 304 if(len > 4096) 244 305 len = 4096; 245 qint64 l = input->read(buffer,len);306 qint64 l = m_input->read(m_buffer.data(), len); 246 307 if(l > 0) { 247 audioinfo->write(buffer,l);308 m_audioInfo->write(m_buffer.constData(), l); 248 309 } 249 310 } … … 252 313 { 253 314 // 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;315 m_audioInput->stop(); 316 317 if (m_pullMode) { 318 m_modeButton->setText(PullModeLabel); 319 m_input = m_audioInput->start(); 320 connect(m_input, SIGNAL(readyRead()), SLOT(readMore())); 321 m_pullMode = false; 261 322 } else { 262 button->setText(tr("Click for Push Mode")); 263 pullMode = true; 264 audioInput->start(audioinfo); 265 } 323 m_modeButton->setText(PushModeLabel); 324 m_pullMode = true; 325 m_audioInput->start(m_audioInfo); 326 } 327 328 m_suspendResumeButton->setText(SuspendLabel); 266 329 } 267 330 … … 269 332 { 270 333 // toggle suspend/resume 271 if( audioInput->state() == QAudio::SuspendedState) {334 if(m_audioInput->state() == QAudio::SuspendedState) { 272 335 qWarning() << "status: Suspended, resume()"; 273 audioInput->resume();274 button2->setText("Click To Suspend");275 } else if ( audioInput->state() == QAudio::ActiveState) {336 m_audioInput->resume(); 337 m_suspendResumeButton->setText(SuspendLabel); 338 } else if (m_audioInput->state() == QAudio::ActiveState) { 276 339 qWarning() << "status: Active, suspend()"; 277 audioInput->suspend();278 button2->setText("Click To Resume");279 } else if ( audioInput->state() == QAudio::StoppedState) {340 m_audioInput->suspend(); 341 m_suspendResumeButton->setText(ResumeLabel); 342 } else if (m_audioInput->state() == QAudio::StoppedState) { 280 343 qWarning() << "status: Stopped, resume()"; 281 audioInput->resume();282 button2->setText("Click To Suspend");283 } else if ( audioInput->state() == QAudio::IdleState) {344 m_audioInput->resume(); 345 m_suspendResumeButton->setText(SuspendLabel); 346 } else if (m_audioInput->state() == QAudio::IdleState) { 284 347 qWarning() << "status: IdleState"; 285 348 } 286 349 } 287 350 288 void InputTest::state (QAudio::State state)289 { 290 qWarning() << " state=" << state;351 void InputTest::stateChanged(QAudio::State state) 352 { 353 qWarning() << "state = " << state; 291 354 } 292 355 293 356 void InputTest::refreshDisplay() 294 357 { 295 canvas->setLevel(audioinfo->LinearMax()); 296 canvas->repaint(); 297 } 298 299 void 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 } 358 m_canvas->setLevel(m_audioInfo->level()); 359 m_canvas->repaint(); 360 } 361 362 void InputTest::deviceChanged(int index) 363 { 364 m_audioInfo->stop(); 365 m_audioInput->stop(); 366 m_audioInput->disconnect(this); 367 delete m_audioInput; 368 369 m_device = m_deviceBox->itemData(index).value<QAudioDeviceInfo>(); 370 createAudioInput(); 371 }
Note:
See TracChangeset
for help on using the changeset viewer.