examples/multimedia/audioinput/audioinput.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     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 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    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 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    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 
       
    55 AudioInfo::AudioInfo(QObject* parent, QAudioInput* device)
       
    56     :QIODevice( parent )
       
    57 {
       
    58     input = device;
       
    59 
       
    60     m_maxValue = 0;
       
    61 }
       
    62 
       
    63 AudioInfo::~AudioInfo()
       
    64 {
       
    65 }
       
    66 
       
    67 void AudioInfo::start()
       
    68 {
       
    69     open(QIODevice::WriteOnly);
       
    70 }
       
    71 
       
    72 void AudioInfo::stop()
       
    73 {
       
    74     close();
       
    75 }
       
    76 
       
    77 qint64 AudioInfo::readData(char *data, qint64 maxlen)
       
    78 {
       
    79     Q_UNUSED(data)
       
    80     Q_UNUSED(maxlen)
       
    81 
       
    82     return 0;
       
    83 }
       
    84 
       
    85 qint64 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 
       
   114 int AudioInfo::LinearMax()
       
   115 {
       
   116     return m_maxValue;
       
   117 }
       
   118 
       
   119 RenderArea::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 
       
   130 void 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 
       
   157 void RenderArea::setLevel(int value)
       
   158 {
       
   159     level = value;
       
   160     repaint();
       
   161 }
       
   162 
       
   163 
       
   164 InputTest::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::deviceList(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     // AudioInfo class only supports mono S16LE samples!
       
   199     format.setFrequency(8000);
       
   200     format.setChannels(1);
       
   201     format.setSampleSize(16);
       
   202     format.setSampleType(QAudioFormat::SignedInt);
       
   203     format.setByteOrder(QAudioFormat::LittleEndian);
       
   204     format.setCodec("audio/pcm");
       
   205 
       
   206     audioInput = new QAudioInput(format,this);
       
   207     connect(audioInput,SIGNAL(notify()),SLOT(status()));
       
   208     connect(audioInput,SIGNAL(stateChanged(QAudio::State)),SLOT(state(QAudio::State)));
       
   209     audioinfo  = new AudioInfo(this,audioInput);
       
   210     connect(audioinfo,SIGNAL(update()),SLOT(refreshDisplay()));
       
   211     audioinfo->start();
       
   212     audioInput->start(audioinfo);
       
   213 }
       
   214 
       
   215 InputTest::~InputTest() {}
       
   216 
       
   217 void InputTest::status()
       
   218 {
       
   219     qWarning()<<"bytesReady = "<<audioInput->bytesReady()<<" bytes, clock = "<<audioInput->clock()/1000<<"ms, totalTime = "<<audioInput->totalTime()/1000<<"ms";
       
   220 }
       
   221 
       
   222 void InputTest::readMore()
       
   223 {
       
   224     if(!audioInput)
       
   225         return;
       
   226     qint64 len = audioInput->bytesReady();
       
   227     if(len > 4096)
       
   228         len = 4096;
       
   229     qint64 l = input->read(buffer,len);
       
   230     if(l > 0) {
       
   231         audioinfo->write(buffer,l);
       
   232     }
       
   233 }
       
   234 
       
   235 void InputTest::toggleMode()
       
   236 {
       
   237     // Change bewteen pull and push modes
       
   238     audioInput->stop();
       
   239 
       
   240     if (pullMode) {
       
   241         button->setText(tr("Click for Pull Mode"));
       
   242         input = audioInput->start(0);
       
   243         connect(input,SIGNAL(readyRead()),SLOT(readMore()));
       
   244         pullMode = false;
       
   245     } else {
       
   246         button->setText(tr("Click for Push Mode"));
       
   247         pullMode = true;
       
   248         audioInput->start(audioinfo);
       
   249     }
       
   250 }
       
   251 
       
   252 void InputTest::toggleSuspend()
       
   253 {
       
   254     // toggle suspend/resume
       
   255     if(audioInput->state() == QAudio::SuspendState) {
       
   256         qWarning()<<"status: Suspended, resume()";
       
   257         audioInput->resume();
       
   258         button2->setText("Click To Suspend");
       
   259     } else if (audioInput->state() == QAudio::ActiveState) {
       
   260         qWarning()<<"status: Active, suspend()";
       
   261         audioInput->suspend();
       
   262         button2->setText("Click To Resume");
       
   263     } else if (audioInput->state() == QAudio::StopState) {
       
   264         qWarning()<<"status: Stopped, resume()";
       
   265         audioInput->resume();
       
   266         button2->setText("Click To Suspend");
       
   267     } else if (audioInput->state() == QAudio::IdleState) {
       
   268         qWarning()<<"status: IdleState";
       
   269     }
       
   270 }
       
   271 
       
   272 void InputTest::state(QAudio::State state)
       
   273 {
       
   274     qWarning()<<" state="<<state;
       
   275 }
       
   276 
       
   277 void InputTest::refreshDisplay()
       
   278 {
       
   279     canvas->setLevel(audioinfo->LinearMax());
       
   280     canvas->repaint();
       
   281 }
       
   282 
       
   283 void InputTest::deviceChanged(int idx)
       
   284 {
       
   285     audioinfo->stop();
       
   286     audioInput->stop();
       
   287     audioInput->disconnect(this);
       
   288     delete audioInput;
       
   289 
       
   290     device = deviceBox->itemData(idx).value<QAudioDeviceInfo>();
       
   291     audioInput = new QAudioInput(device, format, this);
       
   292     connect(audioInput,SIGNAL(notify()),SLOT(status()));
       
   293     connect(audioInput,SIGNAL(stateChanged(QAudio::State)),SLOT(state(QAudio::State)));
       
   294     audioinfo->start();
       
   295     audioInput->start(audioinfo);
       
   296 }