00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include <stdlib.h>
00043 #include <math.h>
00044
00045 #include <QDebug>
00046 #include <QPainter>
00047 #include <QPalette>
00048 #include <QVBoxLayout>
00049
00050 #include <QAudioDeviceInfo>
00051 #include <QAudioInput>
00052 #include "audioinput.h"
00053 #include "wavefile.h"
00054
00055 ATRASR_CLIENT _atrasrClient;
00056 int _epdPort = 0;
00057
00058 static int _logCounter = 0;
00059 static int _speakCount = 0;
00060 static int _filenum = 1;
00061
00062 static int _epdOnFrameNo = -1;
00063 static int _epdOffFrameNo = -1;
00064
00065 #define BUFFER_SIZE 4096
00066
00067 AudioInfo::AudioInfo(QObject* parent, QAudioInput* device, SoundServer *server)
00068 :QIODevice( parent )
00069 {
00070 input = device;
00071 m_server = server;
00072
00073 m_bRec = false;
00074 m_file = NULL;
00075
00076 m_bEpdOn = true;
00077 m_bEpdEnabled = m_bEpdOn;
00078 if (_atrasrClient.socket != NULL){
00079 connect(_atrasrClient.socket, SIGNAL(readyRead()), this, SLOT(epdRead()));
00080 }
00081 connect(server, SIGNAL(onCmd(QString)), this, SLOT(onCmd(QString)));
00082 connect(server, SIGNAL(clientConnected(QHostAddress)), this, SLOT(onClientConnected(QHostAddress)));
00083 }
00084
00085 AudioInfo::~AudioInfo()
00086 {
00087 }
00088
00089 QList<AudioInfo::Level> AudioInfo::getLevels()
00090 {
00091 QList<Level> levels = m_levels;
00092 m_levels.clear();
00093 return levels;
00094 }
00095
00096 bool AudioInfo::epdEnabled() const
00097 {
00098 return m_bEpdEnabled;
00099 }
00100
00101 void AudioInfo::setEpdEnabled(bool bEnabled)
00102 {
00103 m_bEpdEnabled = bEnabled;
00104 m_bEpdOn = bEnabled;
00105
00106 if ( bEnabled ) {
00107 m_server->SendEpdOn();
00108 } else {
00109 m_server->SendEpdOff();
00110 recstop(false);
00111 }
00112 }
00113
00114 void AudioInfo::start()
00115 {
00116 open(QIODevice::WriteOnly);
00117 }
00118
00119 void AudioInfo::stop()
00120 {
00121 recstop();
00122 close();
00123 }
00124
00125 qint64 AudioInfo::readData(char *data, qint64 maxlen)
00126 {
00127 Q_UNUSED(data)
00128 Q_UNUSED(maxlen)
00129
00130 return 0;
00131 }
00132
00133 qint64 AudioInfo::writeData(const char *data, qint64 len)
00134 {
00135 if (_atrasrClient.socket == NULL){
00136 processWave(data, len);
00137 }
00138 else{
00139 AtrasrSendDATA(&_atrasrClient, data, len);
00140 }
00141
00142 return len;
00143 }
00144
00145 void AudioInfo::processWave(const void *data, qint64 len)
00146 {
00147 if (m_bRec){
00148 if (m_file != NULL){
00149 m_file->write((const char*)data,len);
00150 }
00151 m_server->SendData(data,len);
00152 m_sampleSize += len;
00153 }
00154
00155
00156 int min = 0;
00157 int max = 0;
00158
00159 int samples = len/2;
00160 qint16* s = (qint16*)data;
00161 for(int i = 0; i < samples; i++) {
00162 qint16 sample = *s;
00163 s++;
00164 if(sample < min) min = sample;
00165 if(sample > max) max = sample;
00166
00167 if (i > 0 && i % 480 == 0){
00168 m_levels.append(Level(min,max,m_bRec,m_bEpdOn));
00169 min = 0;
00170 max = 0;
00171 }
00172 }
00173 m_levels.append(Level(min,max,m_bRec,m_bEpdOn));
00174
00175 emit update();
00176 }
00177
00178 void AudioInfo::epdRead()
00179 {
00180 long frameType;
00181 int frameIndex;
00182 unsigned char *pData;
00183 static unsigned char recvData[ATRASR_RECV_BUF_FRAME_COUNT * ATRASR_FRAME_DATA_SIZE];
00184 int recvSize = 0;
00185
00186 int frameCount = AtrasrReceiveFrame( &_atrasrClient );
00187
00188 for ( frameIndex = 0; frameIndex < frameCount; frameIndex++ )
00189 {
00190 pData = AtrasrParseFrame( &_atrasrClient, frameIndex, &frameType );
00191
00192 if ( frameType == ATRASR_TOF ) {
00193 qDebug() << "ATRASR : TOF frame received.";
00194
00195 if ( m_bEpdOn ) {
00196 m_server->SendEpdOn();
00197 } else {
00198 m_server->SendEpdOff();
00199 }
00200 }
00201 else if ( frameType == ATRASR_DATA ) {
00202 memcpy( recvData + recvSize, pData, ATRASR_FRAME_DATA_SIZE );
00203 recvSize += ATRASR_FRAME_DATA_SIZE;
00204
00205 if(_logCounter % 80 == 0){
00206 _logCounter = 0;
00207 qDebug() << "send : " << _atrasrClient.sendFrameCount << "recv : " << _atrasrClient.recvFrameCount << "Off : " << _epdOffFrameNo << "On : " << _epdOnFrameNo;
00208 }
00209 _logCounter++;
00210
00211
00212 if (_epdOnFrameNo >= 0 && _atrasrClient.sendFrameCount >= _epdOnFrameNo){
00213 qDebug() << "EPD ON.";
00214 _speakCount--;
00215 if(_speakCount<=0){
00216 _speakCount=0;
00217 m_bEpdOn = true;
00218 emit validateRecButton(true);
00219 m_server->SendEpdOn();
00220 }
00221 _epdOnFrameNo = -1;
00222 }
00223
00224 if (_epdOffFrameNo >= 0 &&_atrasrClient.sendFrameCount >= _epdOffFrameNo ) {
00225 qDebug() << "EPD OFF.";
00226 m_bEpdOn = false;
00227 m_server->SendEpdOff();
00228 _epdOffFrameNo = -1;
00229 }
00230 }
00231 else if ( frameType == ATRASR_EOF ) {
00232 qDebug() << "ATRASR : EOF frame received.";
00233 qDebug() << "ATRASR : " << _atrasrClient.sendFrameCount << " frames sent. " << _atrasrClient.recvFrameCount << " frames received";
00234 }
00235 else if ( frameType == ATRASR_START ) {
00236 if ( recvSize > 0 ) {
00237 qDebug() << "RECVSIZE : " << recvSize;
00238 processWave( recvData, recvSize );
00239 recvSize = 0;
00240 }
00241
00242 qDebug() << "ATRASR : START frame received. (" << _atrasrClient.sendFrameCount << " sent, " << _atrasrClient.recvFrameCount << " received)";
00243
00244 if ( m_bEpdOn ){
00245 recstart();
00246 }
00247 }
00248 else if ( frameType == ATRASR_END || frameType == ATRASR_CANCEL ) {
00249 if ( recvSize > 0 ) {
00250 processWave( recvData, recvSize );
00251 recvSize = 0;
00252 }
00253
00254 qDebug() << "ATRASR : " << (( frameType == ATRASR_END ) ? "END" : "CANCEL") << " frame received. ";
00255
00256 if ( m_bEpdOn ){
00257 recstop( frameType == ATRASR_END );
00258 }
00259 }
00260 else {
00261 qDebug() << "ATRASR : Unknown frame type : " << frameType;
00262 }
00263 }
00264
00265 if ( recvSize > 0 ) {
00266 processWave( recvData, recvSize );
00267 }
00268 }
00269
00270 void AudioInfo::onCmd(const QString &cmd)
00271 {
00272 qDebug() << "Command Received - " << cmd;
00273
00274 if (cmd.isEmpty()){
00275 return;
00276 }
00277
00278
00279 if (m_bRec){
00280 recstop(false);
00281 }
00282
00283
00284 if ( cmd == "epdon" || cmd == "epdoff" ){
00285
00286 if ( _atrasrClient.socket && m_bEpdEnabled ){
00287
00288 const int OFFSET = 80;
00289 if ( cmd == "epdon" ){
00290 _epdOnFrameNo = _atrasrClient.sendFrameCount;
00291 _epdOnFrameNo += OFFSET;
00292 }
00293
00294 else{
00295 _epdOffFrameNo = _atrasrClient.sendFrameCount;
00296 _speakCount++;
00297 emit validateRecButton(false);
00298 m_bEpdOn = false;
00299 }
00300
00301 qDebug() << "Send frame count:" << _atrasrClient.sendFrameCount << " Recv frame count: " << _atrasrClient.recvFrameCount;
00302 }
00303 else{
00304 qDebug() << "Invalid command in non-auto-detect mode : " << cmd;
00305 }
00306 }
00307 else{
00308 qDebug() << "Unknown command - " << cmd;
00309 }
00310 }
00311
00312 void AudioInfo::onClientConnected(const QHostAddress &addr)
00313 {
00314 if (_epdPort == 0 || _atrasrClient.socket != NULL){
00315 return;
00316 }
00317
00318 if ( AtrasrConnect( &_atrasrClient, addr.toString().toAscii(), _epdPort ) != -1 ){
00319 AtrasrSendTOF( &_atrasrClient );
00320 AtrasrSendSTARTPU( &_atrasrClient );
00321 connect(_atrasrClient.socket, SIGNAL(readyRead()), this, SLOT(epdRead()));
00322 connect(_atrasrClient.socket, SIGNAL(disconnected()), this, SLOT(epdDisconnected()));
00323 }
00324 }
00325
00326 void AudioInfo::epdDisconnected()
00327 {
00328 _atrasrClient.socket->deleteLater();
00329 _atrasrClient.socket = NULL;
00330
00331 _speakCount = 0;
00332 _epdOnFrameNo = -1;
00333 if (m_bEpdEnabled){
00334 m_bEpdOn = true;
00335 }
00336
00337 recstop(false);
00338 }
00339
00340 void AudioInfo::recstart()
00341 {
00342 m_bRec = true;
00343
00344 QString fileSufix;
00345 if (!m_filename.isEmpty()){
00346 fileSufix.sprintf(".%04d", _filenum++);
00347 m_file = WaveFile::createHeader(m_filename + fileSufix);
00348 }
00349 m_sampleSize = 0;
00350
00351 m_server->SendStart();
00352 }
00353
00354 void AudioInfo::recstop(bool bEnd)
00355 {
00356 if (m_bRec){
00357 m_bRec = false;
00358 if (m_file != NULL){
00359 WaveFile::fillHeader(m_file, m_sampleSize);
00360 QString filename = m_file->fileName();
00361 m_file->close();
00362 delete m_file;
00363 m_file = NULL;
00364 QFile::remove(filename+".wav");
00365 QFile::rename(filename, filename+".wav");
00366 }
00367 if (bEnd){
00368 m_server->SendEnd();
00369 }
00370 else{
00371 m_server->SendEnd();
00372
00373 }
00374 }
00375 }
00376
00377 QString AudioInfo::m_filename;
00378
00379 void AudioInfo::setFileName(const QString &filename)
00380 {
00381 m_filename = filename;
00382 }
00383
00384 int RenderArea::STEP = 150;
00385
00386 RenderArea::RenderArea(QWidget *parent)
00387 : QWidget(parent)
00388 {
00389
00390
00391
00392 setMinimumHeight(30);
00393 setMinimumWidth(200);
00394
00395 for(int i = 0; i < STEP; i++){
00396 m_levels.enqueue(AudioInfo::Level());
00397 }
00398 }
00399
00400 void RenderArea::paintEvent(QPaintEvent * )
00401 {
00402 QPainter painter(this);
00403
00404 int centerY = painter.viewport().center().y();
00405
00406 for(int i = 0; i < STEP; i++){
00407 AudioInfo::Level level = m_levels.at(i);
00408
00409 QRect rect(
00410 (double)painter.viewport().left() + i*(double)painter.viewport().width()/STEP,
00411 painter.viewport().top(),
00412 (double)painter.viewport().width()/STEP,
00413 painter.viewport().height()
00414 );
00415 QColor color = !level.epdOn ? Qt::lightGray :(level.recording ? Qt::blue : Qt::black);
00416 painter.setPen(color);
00417 painter.setBrush(QBrush(color, Qt::SolidPattern));
00418 painter.drawRect(rect);
00419
00420 rect.setTop( centerY - level.max*painter.viewport().height()/2 );
00421 rect.setHeight( (level.max-level.min)*painter.viewport().height()/2);
00422
00423 color = level.recording ? Qt::yellow : QColor(127, 255, 255);
00424 painter.setPen(color);
00425 painter.setBrush(QBrush(color, Qt::SolidPattern));
00426 painter.drawRect(rect);
00427 }
00428 }
00429
00430 void RenderArea::setLevel(const QList<AudioInfo::Level> &levels)
00431 {
00432 m_levels.append(levels);
00433 while (m_levels.count() > STEP){
00434 m_levels.dequeue();
00435 }
00436 repaint();
00437 }
00438
00439
00440 SoundServerApp::SoundServerApp(SoundServer *_server)
00441 : server(_server)
00442 {
00443 QWidget *window = new QWidget;
00444 QVBoxLayout* layout = new QVBoxLayout;
00445
00446 canvas = new RenderArea;
00447 layout->addWidget(canvas);
00448
00449 recButton = new QPushButton(this);
00450 recButton->setText(tr("REC"));
00451 recButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
00452 layout->addWidget(recButton);
00453
00454 deviceBox = new QComboBox(this);
00455 QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
00456 for(int i = 0; i < devices.size(); ++i) {
00457 deviceBox->addItem(devices.at(i).deviceName(), qVariantFromValue(devices.at(i)));
00458 }
00459 connect(deviceBox,SIGNAL(activated(int)),SLOT(deviceChanged(int)));
00460 layout->addWidget(deviceBox);
00461
00462 window->setLayout(layout);
00463 setCentralWidget(window);
00464 window->show();
00465
00466 buffer = new char[BUFFER_SIZE];
00467
00468 pullMode = true;
00469
00470
00471 format.setFrequency(WaveFile::SAMPLING_RATE);
00472 format.setChannels(1);
00473 format.setSampleSize(WaveFile::SAMPLE_BYTE*8);
00474 format.setSampleType(QAudioFormat::SignedInt);
00475 format.setByteOrder(QAudioFormat::LittleEndian);
00476 format.setCodec("audio/pcm");
00477
00478 audioInput = new QAudioInput(format,this);
00479 connect(audioInput,SIGNAL(notify()),SLOT(status()));
00480 connect(audioInput,SIGNAL(stateChanged(QAudio::State)),SLOT(state(QAudio::State)));
00481 audioinfo = new AudioInfo(this,audioInput,server);
00482 connect(audioinfo,SIGNAL(update()),SLOT(refreshDisplay()));
00483 connect(audioinfo,SIGNAL(validateRecButton(bool)),this,SLOT(epdSpeechChanged(bool)));
00484 audioinfo->start();
00485 audioInput->start(audioinfo);
00486
00487 if (!devices.empty()){
00488 deviceChanged(0);
00489 }
00490
00491
00492 if (_epdPort > 0){
00493 recButton->setCheckable(true);
00494 recButton->setChecked(true);
00495 epdEnableChanged(true);
00496 connect(recButton,SIGNAL(toggled(bool)),this,SLOT(epdEnableChanged(bool)));
00497 }
00498 else{
00499 connect(recButton,SIGNAL(pressed()),audioinfo,SLOT(recstart()));
00500 connect(recButton,SIGNAL(released()),audioinfo,SLOT(recstop()));
00501 }
00502 }
00503
00504 SoundServerApp::~SoundServerApp() {}
00505
00506 void SoundServerApp::status()
00507 {
00508
00509 }
00510
00511 void SoundServerApp::readMore()
00512 {
00513 if(!audioInput)
00514 return;
00515 qint64 len = audioInput->bytesReady();
00516 if(len > 4096)
00517 len = 4096;
00518 qint64 l = input->read(buffer,len);
00519 if(l > 0) {
00520 audioinfo->write(buffer,l);
00521 }
00522 }
00523
00524 void SoundServerApp::toggleMode()
00525 {
00526
00527 audioInput->stop();
00528
00529 if (pullMode) {
00530 button->setText(tr("Click for Pull Mode"));
00531 input = audioInput->start();
00532 connect(input,SIGNAL(readyRead()),SLOT(readMore()));
00533 pullMode = false;
00534 } else {
00535 button->setText(tr("Click for Push Mode"));
00536 pullMode = true;
00537 audioInput->start(audioinfo);
00538 }
00539 }
00540
00541 void SoundServerApp::toggleSuspend()
00542 {
00543
00544 if(audioInput->state() == QAudio::SuspendedState) {
00545 qWarning()<<"status: Suspended, resume()";
00546 audioInput->resume();
00547 button2->setText("Click To Suspend");
00548 } else if (audioInput->state() == QAudio::ActiveState) {
00549 qWarning()<<"status: Active, suspend()";
00550 audioInput->suspend();
00551 button2->setText("Click To Resume");
00552 } else if (audioInput->state() == QAudio::StoppedState) {
00553 qWarning()<<"status: Stopped, resume()";
00554 audioInput->resume();
00555 button2->setText("Click To Suspend");
00556 } else if (audioInput->state() == QAudio::IdleState) {
00557 qWarning()<<"status: IdleState";
00558 }
00559 }
00560
00561 void SoundServerApp::state(QAudio::State state)
00562 {
00563 qWarning()<<" state="<<state;
00564 }
00565
00566 void SoundServerApp::refreshDisplay()
00567 {
00568 canvas->setLevel(audioinfo->getLevels());
00569 canvas->repaint();
00570 }
00571
00572 void SoundServerApp::deviceChanged(int idx)
00573 {
00574 audioinfo->stop();
00575 audioInput->stop();
00576 audioInput->disconnect(this);
00577 delete audioInput;
00578
00579 device = deviceBox->itemData(idx).value<QAudioDeviceInfo>();
00580 audioInput = new QAudioInput(device, format, this);
00581 connect(audioInput,SIGNAL(notify()),SLOT(status()));
00582 connect(audioInput,SIGNAL(stateChanged(QAudio::State)),SLOT(state(QAudio::State)));
00583 audioinfo->start();
00584 audioInput->start(audioinfo);
00585 }
00586
00587 void SoundServerApp::epdEnableChanged(bool bEnabled)
00588 {
00589 recButton->setText(bEnabled ? "Speech Detection ON" : "Speech Detection OFF");
00590 audioinfo->setEpdEnabled(bEnabled);
00591 }
00592
00593 void SoundServerApp::epdSpeechChanged(bool bEnabled)
00594 {
00595 recButton->setEnabled(bEnabled);
00596 }
00597
00598 void SoundServerApp::recstart()
00599 {
00600 audioinfo->recstart();
00601 }