QAudioInput recording while serial data receive (signal-slot)
-
Hello! I'm using a Qtimer and QEventLoop for signal-slot connection to start and end audio recording with QAudioInput.
QEventLoop event_loop(this); QTimer exit_timer(this); exit_timer.setSingleShot(true); connect(&exit_timer, SIGNAL(timeout()), &event_loop, SLOT(quit())); QString path = SAVE_AUDIO_PATH+filename.left( filename.lastIndexOf( '.' ) )+"_"+QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss"); m_file.setFileName(path+".log"); m_audio->StartRecording(path+".wav", record_time_sec); exit_timer.start((record_time_sec+4)*1000); event_loop.exec();
While recording, I'm also receiving a data from microcontroller. How can I change a Signal-Slot connection to make recording while data (via serial/UART) will be received?
-
@Fracture said in QAudioInput recording while serial data receive (signal-slot):
I'm using a Qtimer and QEventLoop for signal-slot connection to start and end audio recording with QAudioInpu
Why?
Why not simply use asynchronous APIs properly?
There is really no need for additional event loop. -
Hmm, how did it works? Sorry I'm new in QT.
for Example there are my Audio files,
all files should have the same length, but something goes wrong:My code is
Measure.cpp
// ************************************************************************************************ // Measure-Class // ************************************************************************************************ //class initialisation #include "Measure.h" #include "Conf.h" #include "Audio.h" // ************************************************************************************************ Measure::Measure(Audio *audio) { //member variables init m_audio = audio; //UART-status debug if (0 == connectSerial()) { qDebug() << "Serial connection OK!\n"; } else { qDebug() << "Serial connection Error!\n"; return; } auto info = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); foreach (auto i, info) qDebug() << i.deviceName(); //m_timer = new QTimer(this); double //set serial connection //connect(m_timer, SIGNAL(timeout()), this, SLOT(processMeas()),Qt::QueuedConnection); measure_cnt = 0; qDebug()<<"Starting programm"; } // ************************************************************************************************ // Start measure void Measure::start() { //QTimer *m_timer = new QTimer(this); //m_timer->setSingleShot(true); //m_timer->start(1000); 555 processMeas(); } // ************************************************************************************************ // Serial connection initialization and signal-slot connection uint32_t Measure::connectSerial(void) { //serial connection configuration m_serial.setPortName("/dev/ttyACM0"); m_serial.setBaudRate(QSerialPort::Baud115200); m_serial.setDataBits(QSerialPort::Data8); m_serial.setParity(QSerialPort::NoParity); m_serial.setStopBits(QSerialPort::OneStop); m_serial.setFlowControl(QSerialPort::NoFlowControl); if (!m_serial.open(QIODevice::ReadWrite)) return 1; //einable serial connection connect(&m_serial, SIGNAL(readyRead()), this, SLOT(readRequest())); return 0; } // ************************************************************************************************ // State maschine // ************************************************************************************************ void Measure::processMeas() { // Declaration ************************************************************ static uint32_t i = 0; static uint32_t j = 0; static uint8_t stm = 0; static uint16_t m1 = 0; static uint16_t m2 = 0; static uint16_t m3 = 0; static uint16_t m4 = 0; static uint16_t var; static QByteArray hextest; // Read config files *********************************************************************************** QDir directory("/home/nikitajarocky/workspace/QT/Software_2.0_QT/Config_files/"); QStringList config_files = directory.entryList(QStringList() << "*.config", QDir::Files); config_files_cnt = config_files.count(); foreach(QString filename, config_files) { Conf *conf = new Conf(directory.absoluteFilePath(filename)); qDebug() << "Config file: " << filename << " is processed"; // Error message ************************* if(conf->getConf_lines().size() == 0) { qDebug()<<"Error conf file!!"; return; } record_time_msec = 0; // Prepare measure **************************************************************** qDebug()<<"Debug: Prepare measure"; QStringList lines = conf->getConf_lines(); //read all rows of config files record_time_100ms = lines.count()-9; record_time_msec = record_time_100ms * 100; QThread::msleep(4000); for(i=0; i < (uint32_t)lines.length(); i++) //prepare single rows of config files { //uint32_t j = 0; QString uart; QString uart_hex; if(i > 5 && i < lines.length()) { QStringList speed_chunks = lines.at(i).split(","); //split rows by decimal point m1 = speed_chunks.at(2).toInt(); m2 = speed_chunks.at(3).toInt(); m3 = speed_chunks.at(4).toInt(); m4 = speed_chunks.at(5).toInt(); hextest.resize(10); hextest[0]=255; hextest[1]=m1>>8; hextest[2]=m1; hextest[3]=m2>>8; hextest[4]=m2; hextest[5]=m3>>8; hextest[6]=m3; hextest[7]=m4>>8; hextest[8]=m4; hextest[9]=238; qDebug()<< "Transfer data: " << i << " from " << lines.count()-1 << " rows transmitted"; qDebug() << "Config file: " << filename << " is processed"; m_serial.write(hextest); m_serial.waitForBytesWritten(30000); //QThread::usleep(50000); }//if(lines.at(i).contains(",")) end }//for end }//for end // Measurement ****************************************************************** qDebug()<<"Debug: Measurement in progress"; QEventLoop event_loop(this); //create method class QEventLoop QTimer exit_timer(this); //create method class QTimer exit_timer.setSingleShot(true); //set timer in mode singleShot connect(&exit_timer, SIGNAL(timeout()), &event_loop, SLOT(quit())); //connect exit timer to event loop slot QString path = SAVE_AUDIO_PATH+filename.left( filename.lastIndexOf( '.' ) )+"_"+QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss"); m_file.setFileName(path+".log"); //m_audio->StartRecording(path+".wav"); m_audio->StartRecording(path+".wav", record_time_msec); //exit_timer.start(15000); exit_timer.start(record_time_msec+4000);//event loop timer durring measure time event_loop.exec(); qDebug()<<"Measurement takes " << record_time_msec+4000 << " seconds"; // Stop measure ************************************ stm=0; measure_cnt++; // All configs files done ********************************* if(measure_cnt>=config_files_cnt) { qDebug()<<"All measure done"; qApp->quit(); } }//foreach }//processMeas() // ************************************************************************************************ // Data from STM32 receive void Measure::readRequest() { m_file.open(QIODevice::WriteOnly | QIODevice::Append); m_file.write(m_serial.readAll()); m_file.close(); } // ************************************************************************************************ // save received data to log File void Measure::saveFile(QByteArray buffer) { m_file.write(buffer); }
and Audio.cpp
// ************************************************************************************************ // Audio-Class // ************************************************************************************************ #include "Audio.h" #include "Measure.h" #include <QAudioInput> #include <QTimer> // ************************************************************************************************ Audio::Audio() { QTimer *m_timer = new QTimer(this); m_timer->setSingleShot(true); AudioRecord(); } // ************************************************************************************************ //Initialization and signal-slot connection void Audio::AudioRecord() { //Set audio configuration QAudioFormat format; format.setSampleRate(44100); format.setChannelCount(1); format.setSampleSize(16); format.setCodec("audio/PCM"); format.setByteOrder(QAudioFormat::LittleEndian); format.setSampleType(QAudioFormat::SignedInt); //Wrong configuration detection QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice(); if (!info.isFormatSupported(format)) { qWarning() << "Default format not supported"; format = info.nearestFormat(format); } //Signal-slot connection to show actual Audio state or errors output m_audio = new QAudioInput(format, this); connect(m_audio, SIGNAL(stateChanged(QAudio::State)), this, SLOT(handleStateChanged(QAudio::State))); } // ************************************************************************************************ //Start recording //void Audio::StartRecording(QString rec_file_path) void Audio::StartRecording(QString rec_file_path, quint32 record_time_sec) { m_file.setFileName(rec_file_path); //audio recording path format m_file.open(QIODevice::WriteOnly); //audio access mode initialisation writeHeader(); //writing header to convert PCM to *.wav (Step 1) m_audio->start(&m_file); //start recording //QTimer::singleShot((15000), this, SLOT(StopRecording())); QTimer::singleShot((record_time_sec+4000), this, SLOT(StopRecording())); QCoreApplication::processEvents(); qDebug()<< m_audio->format(); //qDebug()<< m_file.open(); QAudioDeviceInfo::defaultInputDevice(); QAudioDeviceInfo::availableDevices(QAudio::AudioInput); //qDebug()<< m_audio->error(); //qDebug()<< m_audio->notifyInterval(); } // ************************************************************************************************ //Write Header // ************************************************************************************************ void Audio::writeHeader(){ quint64 data64 = 0; quint32 data_Filesize_fill = 0; quint32 data_lenght = 16; quint16 data_PCM = 1; quint16 data_Chanel = 1; quint32 data_SamplRate = 44100; quint32 data_Value = (44100 * 16 * 1)/8; quint16 data_mono = (16 * 1)/8; quint16 data_BPS = 16; quint32 data_FileSize = 44; m_file.write("RIFF",4); m_file.write((char*)&data_Filesize_fill, 4); m_file.write("WAVE",4); m_file.write("fmt ",4); // "fmt " chunk size (always 16 for PCM) m_file.write((char*)&data_lenght, 4); m_file.write((char*)&data_PCM, 2); m_file.write((char*)&data_Chanel, 2); m_file.write((char*)&data_SamplRate, 4); m_file.write((char*)&data_Value, 4); // bytes per second m_file.write((char*)&data_mono, 2); // Block align m_file.write((char*)&data_BPS, 2); // Bits per sample m_file.write("data",4); m_file.write((char*)&data_FileSize, 4); m_file.flush(); } // ************************************************************************************************ //Stop recording void Audio::StopRecording() { m_audio->stop(); qDebug() << "stop"; writeHeaderFinal(); m_file.close(); qDebug() << "close"; } // ************************************************************************************************ //Write Header void Audio::writeHeaderFinal(){ quint32 data_Filesize_fill_after = m_file.size() - 8; quint32 data_FileSize_after = m_file.size() - 44; m_file.seek(4); m_file.write((char*)&data_Filesize_fill_after, 4); m_file.seek(40); m_file.write((char*)&data_FileSize_after, 4); } // ************************************************************************************************ //Recording DEBUG output void Audio::handleStateChanged(QAudio::State newState) { switch (newState) { case QAudio::StoppedState: if (m_audio->error() != QAudio::NoError) { qDebug() << "Error audio recording!!"; } else { qDebug() << "Finished audio recording"; } break; case QAudio::ActiveState: qDebug() << "Started audio recording"; break; default: break; } } // ************************************************************************************************
I have multiple config-Files with value of lines for example 300, for every line should be 100ms recording, so 300 lines = 30sek (except 2 sec on beginning and 2 sek on the end - see 2kHz lines in spectrogram), but anytime i get different length of recording . And important is - that the values that I get from microcontroller should by synchronous witch audio-data recordings between 2kHz peaks!
Do you see what is wrong, or what do you will to change? -
@Fracture said in QAudioInput recording while serial data receive (signal-slot):
Audio::Audio()
{
QTimer *m_timer = new QTimer(this);
m_timer->setSingleShot(true);What is this m_timer used for? You do not connect any slot to it.
-
Oh, it was old connection - in
void Measure::start() { //QTimer *m_timer = new QTimer(this); //m_timer->setSingleShot(true); //m_timer->start(1000); 555 processMeas(); }
Sorry, I don't clean my code
It's also not all cpp-files what I use - i have also conf.cpp, control.cpp and main.cpp - tell me please when you want to see this!
P.S. But m_timer was not a reason. It just trash part of code...