PDA

View Full Version : QAudioInput && QTcpSocket help !



Con Nít
14th February 2011, 09:35
i am writing the application to send voice by lan network using...
i am having trouble because code doesn't work
below is the class ThreadInputAudio using thread to constantly send my voice
threadinputaudio.h

#ifndef THREADINPUTAUDIO_H
#define THREADINPUTAUDIO_H

#include <QThread>
#include <QByteArray>
#include <QAudioInput>
#include <QTcpSocket>
#include <QVariant>

class ThreadInputAudio : public QThread
{
Q_OBJECT
public:
ThreadInputAudio();
void stop();
QTcpSocket* socket;
protected:
void run();
private:
bool stopped;
QByteArray m_buffer;
QAudioInput *m_audioInput;
QAudioFormat m_format;
QIODevice *m_input;
void stopRecording();

private slots:

void readMore();
};

#endif // THREADINPUTAUDIO_H


threadinputaudio.cpp

#include "threadinputaudio.h"

ThreadInputAudio::ThreadInputAudio()
:m_audioInput(0)
,m_input(0)
{
stopped = false;

}
void ThreadInputAudio::run(){
m_format.setFrequency(8000);
m_format.setChannels(1);
m_format.setSampleSize(16);
m_format.setSampleType(QAudioFormat::SignedInt);
m_format.setByteOrder(QAudioFormat::LittleEndian);
m_format.setCodec("audio/pcm");
QAudioDeviceInfo info(QAudioDeviceInfo::defaultInputDevice());
if (!info.isFormatSupported(m_format)) {
qDebug() << "Default format not supported - trying to use nearest";
m_format = info.nearestFormat(m_format);
}
while (!stopped){
m_audioInput = new QAudioInput(m_format);
m_input = m_audioInput->start();
connect(m_input, SIGNAL(readyRead()), SLOT(readMore()));
QThread::sleep(500);
stopRecording();
}
stopped = false;
}
void ThreadInputAudio::stop(){
stopped = true;
}
void ThreadInputAudio::stopRecording(){
m_audioInput->stop();
delete m_audioInput;
}
void ThreadInputAudio::readMore(){
qDebug() << "start send voice";
if(!m_audioInput)
return;
qint64 len = m_audioInput->bytesReady();
qint64 l = m_input->read(m_buffer.data(), len);
if(l > 0) {
if(socket == NULL) return;
if(socket->state() != QAbstractSocket::ConnectedState ) return;
QString msg = "VOICE";
QVariant data = QVariant(m_buffer);
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_2);
out << (quint32) 0;
out << msg;
out << data;
out.device()->seek(0);
out << (quint32)(block.size() - sizeof(quint32));

socket->write(block);
socket->flush();

qDebug() << "send voice ok";
}
}

i can't figure out why the method readmore() is never done
help me to decide whether the code on receiving the data is correct or not? how can i fix it.

void MainWindow::onVoiceMessage(const QByteArray &data){
qDebug() << "nhan duoc am thanh";
QAudioFormat format;
inputFile->write(data.constData(),(qint64)data.size());
format.setFrequency(8000);
format.setChannels(1);
format.setSampleSize(8);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::UnSignedInt);

QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
if (!info.isFormatSupported(format)) {
qDebug() <<"raw audio format not supported by backend, cannot play audio.";
return;
}

audio = new QAudioOutput(format);
connect(audio,SIGNAL(stateChanged(QAudio::State)), SLOT(finishedPlaying(QAudio::State)));
audio->start(inputFile);
}

void MainWindow::finishedPlaying(QAudio::State state)
{
if(state == QAudio::IdleState) {
audio->stop();
delete audio;
}
}

high_flyer
14th February 2011, 09:40
i can't figure out why the method readmore() is never done
What are the symptoms you are having?

Con Nít
14th February 2011, 10:17
in class mainwindow i declare an object ThreadInputAudio tIA;
when socket already connected to server, i added tIA.start();
as usual, the method readmore() of class ThreadInputAudio is supposed to be processed by the statement connect(m_input, SIGNAL(readyRead()), SLOT(readMore())); in the method run() of the class ThreadInputAudio but readmore() is not processed.


help me check whether my method is correct or not (input >>> send >>> reic >>> output ).

thank in advance .

high_flyer
14th February 2011, 10:25
Ok, try this:

while (!stopped){ //set a break point here - does it stop here?
m_audioInput = new QAudioInput(m_format); //step through, do you get in here?
m_input = m_audioInput->start();
connect(m_input, SIGNAL(readyRead()), SLOT(readMore()));
QThread::sleep(500);
stopRecording();
}

tbscope
14th February 2011, 10:36
Again, this is the classic thread affinity problem of signals, slots and QThread.

You can't just subclass QThread and add slots to it and call these slots from within another thread.

high_flyer
14th February 2011, 10:43
You can't just subclass QThread and add slots to it and call these slots from within another thread.
Maybe I misunderstand, but you can - if you use queued connection, which if I remember right is the default between threads.

But I agree that the code above is asking for trouble.

Also - in his code, he is connecting from an object in the new thread, so the emitting object has the current thread affinity.

Con Nít
14th February 2011, 14:27
i fix my code into this:
threadinputaudio.cpp

#include "threadinputaudio.h"

ThreadInputAudio::ThreadInputAudio()
:m_audioInput(0)
,m_input(0)
{
stopped = false;

}
void ThreadInputAudio::run(){
m_format.setFrequency(8000);
m_format.setChannels(1);
m_format.setSampleSize(16);
m_format.setSampleType(QAudioFormat::SignedInt);
m_format.setByteOrder(QAudioFormat::LittleEndian);
m_format.setCodec("audio/pcm");
QAudioDeviceInfo info(QAudioDeviceInfo::defaultInputDevice());
if (!info.isFormatSupported(m_format)) {
qDebug() << "Default format not supported - trying to use nearest";
m_format = info.nearestFormat(m_format);
}

while (!stopped){
m_audioInput = new QAudioInput(m_format);
m_input = m_audioInput->start();
QThread::sleep(0.5);

m_audioInput->stop();
readMore();
stopRecording();

}

stopped = false;
}
void ThreadInputAudio::stop(){
stopped = true;
}
void ThreadInputAudio::stopRecording(){
delete m_audioInput;
}
void ThreadInputAudio::readMore(){

if(!m_audioInput)
return;

qint64 len = m_audioInput->bytesReady();
qint64 l = m_input->read(m_buffer.data(), len);
if(l > 0) {
// not work
if(socket == NULL) return;
if(socket->state() != QAbstractSocket::ConnectedState ) return;
QString msg = "VOICE";
QVariant data = QVariant(m_buffer);
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_2);
out << (quint32) 0;
out << msg;
out << data;
out.device()->seek(0);
out << (quint32)(block.size() - sizeof(quint32));

socket->write(block);
socket->flush();


}
}


the part in if statement is not processed...the bytes which are read..
what 's wrong with my code

high_flyer
14th February 2011, 14:48
i fix my code into this:
Please note in next posts what the changes are, preferably via comments in the code, otherwise its hard to follow.

Try to get the state() of the device before your read form it, maybe it is in error state...

Con Nít
18th February 2011, 04:52
who can help me fix my class ThreadInputAudio to be able to send Audio Input.
That's necessary for me .

Con Nít
21st February 2011, 10:11
up ... please help me :-S

high_flyer
21st February 2011, 10:15
Did you try getting the state as I suggested to you?

Con Nít
22nd February 2011, 10:42
I've modified my code.

threadinputaudio.h

#ifndef THREADINPUTAUDIO_H
#define THREADINPUTAUDIO_H

#include <QThread>
#include <QByteArray>
#include <QAudioInput>
#include <QTcpSocket>
#include <QVariant>

class AudioInfo : public QIODevice
{
Q_OBJECT
public:
AudioInfo(QObject *parent);
~AudioInfo();

void start();
void stop();

qint64 readData(char *data, qint64 maxlen);
qint64 writeData(const char *data, qint64 len);
};



class ThreadInputAudio : public QThread
{
Q_OBJECT
public:
ThreadInputAudio();
QTcpSocket* socket;
protected:
void run();
private:
QByteArray m_buffer;
QAudioInput *m_audioInput;
QAudioFormat m_format;
QIODevice *m_input;
AudioInfo *m_audioInfo;


private slots:
void stopRecording();
void readMore();
};

#endif // THREADINPUTAUDIO_H

threadinputaudio.cpp

#include "threadinputaudio.h"

const int BufferSize = 4096;

AudioInfo::AudioInfo(QObject *parent)
: QIODevice(parent)

{
}

AudioInfo::~AudioInfo()
{
}

void AudioInfo::start()
{
open(QIODevice::WriteOnly);
}

void AudioInfo::stop()
{
close();
}
qint64 AudioInfo::readData(char *data, qint64 maxlen)
{
Q_UNUSED(data)
Q_UNUSED(maxlen)

return 0;
}

qint64 AudioInfo::writeData(const char *data, qint64 len)
{
Q_UNUSED(data)
Q_UNUSED(len)

return 0;
}



ThreadInputAudio::ThreadInputAudio()
:m_audioInput(0)
,m_input(0)
,m_buffer(BufferSize, 0)
{
}
void ThreadInputAudio::run(){
connect(socket, SIGNAL(disconnected()), SLOT(stopRecording()));
m_format.setFrequency(8000);
m_format.setChannels(1);
m_format.setSampleSize(16);
m_format.setSampleType(QAudioFormat::SignedInt);
m_format.setByteOrder(QAudioFormat::LittleEndian);
m_format.setCodec("audio/pcm");
QAudioDeviceInfo info(QAudioDeviceInfo::defaultInputDevice());
if (!info.isFormatSupported(m_format)) {
qDebug() << "Default format not supported - trying to use nearest";
m_format = info.nearestFormat(m_format);
}
m_audioInfo = new AudioInfo(this);
m_audioInput = new QAudioInput(m_format);
m_audioInfo->start();
m_audioInput->start(m_audioInfo);

//m_input = m_audioInput->start();
//Q_ASSERT(m_input);
qDebug() << m_audioInput->state();
connect(m_audioInfo, SIGNAL(readyRead()), SLOT(readMore()));
}
void ThreadInputAudio::stopRecording(){
m_audioInfo->stop();
delete m_audioInfo;
delete m_audioInput;
}
void ThreadInputAudio::readMore(){

if(!m_audioInput)
return;
qDebug() << m_audioInput->state(); // display 0
qint64 len = m_audioInput->bytesReady();
m_input->seek(0);
qint64 l = m_input->read(m_buffer.data(), len);
if(l > 0) {
// not work
qDebug() << "not work.";
if(socket == NULL) return;
if(socket->state() != QAbstractSocket::ConnectedState ) return;
QString msg = "VOICE";
QVariant data = QVariant(m_buffer);
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_2);
out << (quint32) 0;
out << msg;
out << data;
out.device()->seek(0);
out << (quint32)(block.size() - sizeof(quint32));

socket->write(block);
socket->flush();


}
}



I tried to do on your own. và state == 0.

please help me.

Con Nít
24th February 2011, 08:16
help me :-((

tbscope
24th February 2011, 08:38
The problem is already described.
You can't just subclass QThread and create slots.

Con Nít
4th March 2011, 09:03
It mean 1 subclass of QThread couldn't create 1 slot which execute subclass? So, do you have the way to solve my problem? I want sending from QaudioInput input data continuous by QTcpsocket. Please,

help me!.

thanks .