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() << "NICTASR : 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() << "NICTASR : EOF frame received.";
00233 qDebug() << "NICTASR : " << _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() << "NICTASR : 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() << "NICTASR : " << (( frameType == ATRASR_END ) ? "END" : "CANCEL") << " frame received. ";
00255
00256 if ( m_bEpdOn ){
00257 recstop( frameType == ATRASR_END );
00258 }
00259 }
00260 else {
00261 qDebug() << "NICTASR : 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().toLatin1(), _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(50);
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 QString deviceName = devices.at(i).deviceName();
00458 if (deviceName.length() > 20) {
00459 deviceName = deviceName.left(19).append("...");
00460 }
00461 deviceBox->addItem(deviceName, qVariantFromValue(devices.at(i)));
00462 }
00463 connect(deviceBox,SIGNAL(activated(int)),SLOT(deviceChanged(int)));
00464 layout->addWidget(deviceBox);
00465
00466 window->setLayout(layout);
00467 setCentralWidget(window);
00468 window->show();
00469
00470 buffer = new char[BUFFER_SIZE];
00471
00472 pullMode = true;
00473
00474
00475 format.setSampleRate(WaveFile::SAMPLING_RATE);
00476 format.setChannelCount(1);
00477 format.setSampleSize(WaveFile::SAMPLE_BYTE*8);
00478 format.setSampleType(QAudioFormat::SignedInt);
00479 format.setByteOrder(QAudioFormat::LittleEndian);
00480 format.setCodec("audio/pcm");
00481
00482 audioInput = new QAudioInput(format,this);
00483 connect(audioInput,SIGNAL(notify()),SLOT(status()));
00484 connect(audioInput,SIGNAL(stateChanged(QAudio::State)),SLOT(state(QAudio::State)));
00485 audioinfo = new AudioInfo(this,audioInput,server);
00486 connect(audioinfo,SIGNAL(update()),SLOT(refreshDisplay()));
00487 connect(audioinfo,SIGNAL(validateRecButton(bool)),this,SLOT(epdSpeechChanged(bool)));
00488 audioinfo->start();
00489 audioInput->start(audioinfo);
00490
00491 if (!devices.empty()){
00492 deviceChanged(0);
00493 }
00494
00495
00496 if (_epdPort > 0){
00497 recButton->setCheckable(true);
00498 recButton->setChecked(true);
00499 epdEnableChanged(true);
00500 connect(recButton,SIGNAL(toggled(bool)),this,SLOT(epdEnableChanged(bool)));
00501 }
00502 else{
00503 connect(recButton,SIGNAL(pressed()),audioinfo,SLOT(recstart()));
00504 connect(recButton,SIGNAL(released()),audioinfo,SLOT(recstop()));
00505 }
00506 }
00507
00508 SoundServerApp::~SoundServerApp() {}
00509
00510 void SoundServerApp::status()
00511 {
00512
00513 }
00514
00515 void SoundServerApp::readMore()
00516 {
00517 if(!audioInput)
00518 return;
00519 qint64 len = audioInput->bytesReady();
00520 if(len > 4096)
00521 len = 4096;
00522 qint64 l = input->read(buffer,len);
00523 if(l > 0) {
00524 audioinfo->write(buffer,l);
00525 }
00526 }
00527
00528 void SoundServerApp::toggleMode()
00529 {
00530
00531 audioInput->stop();
00532
00533 if (pullMode) {
00534 button->setText(tr("Click for Pull Mode"));
00535 input = audioInput->start();
00536 connect(input,SIGNAL(readyRead()),SLOT(readMore()));
00537 pullMode = false;
00538 } else {
00539 button->setText(tr("Click for Push Mode"));
00540 pullMode = true;
00541 audioInput->start(audioinfo);
00542 }
00543 }
00544
00545 void SoundServerApp::toggleSuspend()
00546 {
00547
00548 if(audioInput->state() == QAudio::SuspendedState) {
00549 qWarning()<<"status: Suspended, resume()";
00550 audioInput->resume();
00551 button2->setText("Click To Suspend");
00552 } else if (audioInput->state() == QAudio::ActiveState) {
00553 qWarning()<<"status: Active, suspend()";
00554 audioInput->suspend();
00555 button2->setText("Click To Resume");
00556 } else if (audioInput->state() == QAudio::StoppedState) {
00557 qWarning()<<"status: Stopped, resume()";
00558 audioInput->resume();
00559 button2->setText("Click To Suspend");
00560 } else if (audioInput->state() == QAudio::IdleState) {
00561 qWarning()<<"status: IdleState";
00562 }
00563 }
00564
00565 void SoundServerApp::state(QAudio::State state)
00566 {
00567 qWarning()<<" state="<<state;
00568 }
00569
00570 void SoundServerApp::refreshDisplay()
00571 {
00572 canvas->setLevel(audioinfo->getLevels());
00573 canvas->repaint();
00574 }
00575
00576 void SoundServerApp::deviceChanged(int idx)
00577 {
00578 audioinfo->stop();
00579 audioInput->stop();
00580 audioInput->disconnect(this);
00581 delete audioInput;
00582
00583 device = deviceBox->itemData(idx).value<QAudioDeviceInfo>();
00584 audioInput = new QAudioInput(device, format, this);
00585 connect(audioInput,SIGNAL(notify()),SLOT(status()));
00586 connect(audioInput,SIGNAL(stateChanged(QAudio::State)),SLOT(state(QAudio::State)));
00587 audioinfo->start();
00588 audioInput->start(audioinfo);
00589 }
00590
00591 void SoundServerApp::epdEnableChanged(bool bEnabled)
00592 {
00593 recButton->setText(bEnabled ? "Speech Detection ON" : "Speech Detection OFF");
00594 audioinfo->setEpdEnabled(bEnabled);
00595 }
00596
00597 void SoundServerApp::epdSpeechChanged(bool bEnabled)
00598 {
00599 recButton->setEnabled(bEnabled);
00600 }
00601
00602 void SoundServerApp::recstart()
00603 {
00604 audioinfo->recstart();
00605 }