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 }