Ignore:
Timestamp:
Aug 2, 2010, 9:27:30 PM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.6.3 sources from branches/vendor/nokia/qt.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/examples/multimedia/audioinput/audioinput.cpp

    r651 r769  
    4949#include <QAudioDeviceInfo>
    5050#include <QAudioInput>
     51
     52#include <QtCore/qendian.h>
     53
    5154#include "audioinput.h"
    5255
    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;
     56const QString InputTest::PushModeLabel(tr("Enable push mode"));
     57const QString InputTest::PullModeLabel(tr("Enable pull mode"));
     58const QString InputTest::SuspendLabel(tr("Suspend recording"));
     59const QString InputTest::ResumeLabel(tr("Resume recording"));
     60
     61const int BufferSize = 4096;
     62
     63AudioInfo::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    }
    6194}
    6295
     
    85118qint64 AudioInfo::writeData(const char *data, qint64 len)
    86119{
    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    }
    111158
    112159    emit update();
    113 
    114160    return len;
    115 }
    116 
    117 int AudioInfo::LinearMax()
    118 {
    119     return m_maxValue;
    120161}
    121162
     
    126167    setAutoFillBackground(true);
    127168
    128     level = 0;
     169    m_level = 0;
    129170    setMinimumHeight(30);
    130171    setMinimumWidth(200);
     
    140181                           painter.viewport().right()-20,
    141182                           painter.viewport().bottom()-20));
    142     if (level == 0)
     183    if (m_level == 0.0)
    143184        return;
    144185
    145186    painter.setPen(Qt::red);
    146187
    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;
    148189    for (int i = 0; i < 10; ++i) {
    149190        int x1 = painter.viewport().left()+11;
     
    158199}
    159200
    160 void RenderArea::setLevel(int value)
    161 {
    162     level = value;
     201void RenderArea::setLevel(qreal value)
     202{
     203    m_level = value;
    163204    repaint();
    164205}
     
    166207
    167208InputTest::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
     224InputTest::~InputTest() {}
     225
     226void 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);
    176235    QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
    177236    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
     260void 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");
    207270
    208271    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
     283void 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
     292void InputTest::notified()
     293{
     294    qWarning() << "bytesReady = " << m_audioInput->bytesReady()
     295               << ", " << "elapsedUSecs = " <<m_audioInput->elapsedUSecs()
     296               << ", " << "processedUSecs = "<<m_audioInput->processedUSecs();
     297}
     298
     299void InputTest::readMore()
     300{
     301    if(!m_audioInput)
    219302        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();
    243304    if(len > 4096)
    244305        len = 4096;
    245     qint64 l = input->read(buffer,len);
     306    qint64 l = m_input->read(m_buffer.data(), len);
    246307    if(l > 0) {
    247         audioinfo->write(buffer,l);
     308        m_audioInfo->write(m_buffer.constData(), l);
    248309    }
    249310}
     
    252313{
    253314    // 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;
    261322    } 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);
    266329}
    267330
     
    269332{
    270333    // toggle suspend/resume
    271     if(audioInput->state() == QAudio::SuspendedState) {
     334    if(m_audioInput->state() == QAudio::SuspendedState) {
    272335        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) {
    276339        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) {
    280343        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) {
    284347        qWarning() << "status: IdleState";
    285348    }
    286349}
    287350
    288 void InputTest::state(QAudio::State state)
    289 {
    290     qWarning() << " state=" << state;
     351void InputTest::stateChanged(QAudio::State state)
     352{
     353    qWarning() << "state = " << state;
    291354}
    292355
    293356void InputTest::refreshDisplay()
    294357{
    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
     362void 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.