/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** ** ** ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include "audiooutput.h" #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #define SECONDS 1 #define FREQ 600 #define SYSTEM_FREQ 44100 Generator::Generator(QObject *parent) :QIODevice( parent ) { finished = false; buffer = new char[SECONDS*SYSTEM_FREQ*4+1000]; t=buffer; len=fillData(t,FREQ,SECONDS); /* mono FREQHz sine */ pos = 0; total = len; } Generator::~Generator() { delete [] buffer; } void Generator::start() { open(QIODevice::ReadOnly); } void Generator::stop() { close(); } int Generator::putShort(char *t, unsigned int value) { *(unsigned char *)(t++)=value&255; *(unsigned char *)(t)=(value/256)&255; return 2; } int Generator::fillData(char *start, int frequency, int seconds) { int i, len=0; int value; for(i=0; i 16384) len = 16384; if(len < (SECONDS*SYSTEM_FREQ*2)-pos) { // Normal memcpy(data,t+pos,len); pos+=len; return len; } else { // Whats left and reset to start qint64 left = (SECONDS*SYSTEM_FREQ*2)-pos; memcpy(data,t+pos,left); pos=0; return left; } } qint64 Generator::writeData(const char *data, qint64 len) { Q_UNUSED(data); Q_UNUSED(len); return 0; } AudioTest::AudioTest() { QWidget *window = new QWidget; QVBoxLayout* layout = new QVBoxLayout; deviceBox = new QComboBox(this); foreach (const QAudioDeviceInfo &deviceInfo, QAudioDeviceInfo::deviceList(QAudio::AudioOutput)) deviceBox->addItem(deviceInfo.deviceName(), qVariantFromValue(deviceInfo)); connect(deviceBox,SIGNAL(activated(int)),SLOT(deviceChanged(int))); layout->addWidget(deviceBox); button = new QPushButton(this); button->setText(tr("Click for Push Mode")); connect(button,SIGNAL(clicked()),SLOT(toggle())); layout->addWidget(button); button2 = new QPushButton(this); button2->setText(tr("Click To Suspend")); connect(button2,SIGNAL(clicked()),SLOT(togglePlay())); layout->addWidget(button2); window->setLayout(layout); setCentralWidget(window); window->show(); buffer = new char[BUFFER_SIZE]; gen = new Generator(this); pullMode = true; timer = new QTimer(this); connect(timer,SIGNAL(timeout()),SLOT(writeMore())); gen->start(); settings.setFrequency(SYSTEM_FREQ); settings.setChannels(1); settings.setSampleSize(16); settings.setCodec("audio/pcm"); settings.setByteOrder(QAudioFormat::LittleEndian); settings.setSampleType(QAudioFormat::SignedInt); audioOutput = new QAudioOutput(settings,this); connect(audioOutput,SIGNAL(notify()),SLOT(status())); connect(audioOutput,SIGNAL(stateChanged(QAudio::State)),SLOT(state(QAudio::State))); audioOutput->start(gen); } AudioTest::~AudioTest() { delete [] buffer; } void AudioTest::deviceChanged(int idx) { timer->stop(); gen->stop(); audioOutput->stop(); audioOutput->disconnect(this); delete audioOutput; device = deviceBox->itemData(idx).value(); audioOutput = new QAudioOutput(device,settings,this); connect(audioOutput,SIGNAL(notify()),SLOT(status())); connect(audioOutput,SIGNAL(stateChanged(QAudio::State)),SLOT(state(QAudio::State))); gen->start(); audioOutput->start(gen); } void AudioTest::status() { qWarning()<<"byteFree = "<bytesFree()<<" bytes, clock = "<clock()/1000<<"ms, totalTime = "<totalTime()/1000<<"ms"; } void AudioTest::writeMore() { if(!audioOutput) return; if(audioOutput->state() == QAudio::StopState) return; int l; int out; int chunks = audioOutput->bytesFree()/audioOutput->periodSize(); while(chunks) { l = gen->read(buffer,audioOutput->periodSize()); if(l > 0) out = output->write(buffer,l); if(l != audioOutput->periodSize()) break; chunks--; } } void AudioTest::toggle() { // Change between pull and push modes timer->stop(); audioOutput->stop(); if (pullMode) { button->setText("Click for Pull Mode"); output = audioOutput->start(0); pullMode = false; timer->start(20); } else { button->setText("Click for Push Mode"); pullMode = true; audioOutput->start(gen); } } void AudioTest::togglePlay() { // toggle suspend/resume if(audioOutput->state() == QAudio::SuspendState) { qWarning()<<"status: Suspended, resume()"; audioOutput->resume(); button2->setText("Click To Suspend"); } else if (audioOutput->state() == QAudio::ActiveState) { qWarning()<<"status: Active, suspend()"; audioOutput->suspend(); button2->setText("Click To Resume"); } else if (audioOutput->state() == QAudio::StopState) { qWarning()<<"status: Stopped, resume()"; audioOutput->resume(); button2->setText("Click To Suspend"); } else if (audioOutput->state() == QAudio::IdleState) { qWarning()<<"status: IdleState"; } } void AudioTest::state(QAudio::State state) { qWarning()<<" state="<