creating app server that read from microphone, send to socket, and on client play audio
-
Hi, my problem is the microphone disappear immediately once it start.
Then readyRead signal isn't' emmited.
I edit mythread, it isn't a QThread because I meet some problems with it.Where I'm wrong?
main.cpp
#include <QCoreApplication> #include <myserver.h> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); MyServer server; server.startServer(); return a.exec(); }
myserver.cpp
#include "myserver.h" MyServer::MyServer() { } void MyServer::startServer() { int port = 12345; QString ipAddress; QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses(); for (int i = 0; i < ipAddressesList.size(); ++i) { if (ipAddressesList.at(i) != QHostAddress::LocalHost && ipAddressesList.at(i).toIPv4Address()) { ipAddress = ipAddressesList.at(i).toString(); break; } } if(!this->listen( QHostAddress(ipAddress),port ) ) { qDebug() << "Could not start server"; } else { qDebug() << "The server is running on\n\nIP: "<< ipAddress; qDebug() << "\nport: " << this->serverPort() << "\n\n"; } } void MyServer::incomingConnection(int socketDescriptor) { qDebug() << socketDescriptor << " Connecting..."; audioInput = NULL; MyThread1 *thread = new MyThread1(socketDescriptor); thread->moveToThread(QCoreApplication::instance()->thread()); thread->setParent(QCoreApplication::instance()->thread()); //connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); thread->run(); }
mythread.cpp
#include "mythread.h" #include <QCoreApplication> #include <QBuffer> MyThread1::MyThread1( int ID) { this->socketDescriptor = ID; this->speaker = NULL; } void MyThread1::run() { qDebug() << " Thread started"; socket = new QTcpSocket(); if(!socket->setSocketDescriptor(this->socketDescriptor)) { emit error(socket->error()); return; } QAudioFormat format; format.setSampleRate(44100); format.setChannelCount(1); format.setSampleSize(16); format.setCodec("audio/pcm"); format.setByteOrder(QAudioFormat::LittleEndian); format.setSampleType(QAudioFormat::UnSignedInt); QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice(); if (!info.isFormatSupported(format)) { qWarning()<<"default format not supported try to use nearest"; format = info.nearestFormat(format); } this->speaker = new QAudioInput(format, socket); QBuffer mInputBuffer; mInputBuffer.open(QBuffer::ReadWrite); QIODevice *dev = speaker->start(); connect(dev, SIGNAL( readyRead() ), this, SLOT( sendData() ) , Qt::DirectConnection); qDebug() << socketDescriptor << " Microphone connected"; } void MyThread1::onfinishThread(){ qDebug()<<"thread is finished!"; } void MyThread1::sendData() { qDebug() << " Thread sendData"; QByteArray Data = speaker->start()->readAll(); //QDataStream l_vStream(&Data, QIODevice::WriteOnly); //l_vStream.setByteOrder(QDataStream::LittleEndian); socket->write(Data, Data.length()); socket->waitForBytesWritten(); } void MyThread1::disconnected( ) { qDebug() << socketDescriptor << "Mic Disconnected"; speaker->stop(); delete speaker; socket->deleteLater(); exit(0); }
-
It would be good, if you'd also show your class definitions/header files and let us know which Qt version you use.
Regarding style, you initialize your members socketDescriptor and speaker using thethis
pointer. You also call your member functions withthis->
. Why? That's unnecessary and confusing. Since the class member speaker is aQAudioInput *
, initialize it withnullptr
instead of NULL.Hi, my problem is the microphone disappear immediately once it start.
What do you mean by "disappear"?this->speaker = new QAudioInput(format, socket);
Here you create a new audio input and store it in the member speaker. Leave out thethis->
and consider renaming the member variable intomicrophone
, the opposite of a speaker. But that is what you actually mean.QBuffer mInputBuffer; mInputBuffer.open(QBuffer::ReadWrite);
=> What's that? These two lines will have no effect at all.
QIODevice *dev = speaker->start();
=> Now you start the audio input device called "speaker" and being a microphone. You obtain the pointer to aQIODevice
and store it locally indev
. That way, the pointer to the IO device is forgotten whendev
goes out of scope.dev
should be a class member, not a local variable.connect(dev, SIGNAL( readyRead() ), this, SLOT( sendData() ) , Qt::DirectConnection);
=> Well done... But you could wrap the line in aQ_ASSERT()
as long as you debug. That way your application will fail here, ifconnect
goes wrong.Then readyRead signal isn't' emmited.
=>That probably has two reasons.
I edit mythread, it isn't a QThread because I meet some problems with it.
Why not a
QThread
? And what are you using instead to make sure that an event loop is running and taking care of your signal / slot connection? Without an event loop, your signal/slot connections will never be executed.Where I'm wrong?
QByteArray Data = speaker->start()->readAll();
=> Here.
You need to access the IO device by the pointer you obtain upon your firststart()
call. If you callstart()
again (probably in the assumption you just re-obtain the previous pointer), you actually discard the input that has fired the signal and create a new IO device. That's why you have to makedev
a member, initialize it withnullptr
and use it here:if (!dev) { qDebug() << "IO error"; return; } QByteArray Data = dev->readAll(); // continue with your code
-
Please share your header files, operating system and Qt version with us.
Unless you have already,#include <QDebug>
and add the following line to after each of the statementsspeaker->start()
andQByteArray Data = dev->readAll();
:qDebug() << speaker->state() << speaker->error();
Let us know what the output is.
You could also append
Data
to a file and dump it to aQAudioSink
to see what it contains. -
Qt 5.12 and Microsoft Windows 10 Operating system
I solve withthis->dev = mic->start()
in connect function
now it emit correctly readyRead signal many times.
I can't however play row audio sound on client socketLater I will share header files and client socket source code.
meanwhile thank you very much
-
Why
this->
before thedev
? -
@Axel-Spoerl said in creating app server that read from microphone, send to socket, and on client play audio:
Why this->before the dev?
I don't understand why you are promoting dropping
this
. (Just to be clear, I don't use it; mostly because I'm too lazy to type it). It is a valid style choice. Also, it makes clear that you want to access a member variable (same for member function calls). It even helps to catch errors if you apply this style consistently: If you don't have that member variable, it will fail to compile. If you introduce a local variable with the same name by accident, it will still to the right thing. Usually, being more explicit is considered better style.Let's not fight over style in this forum. @zabitqt might have his reasons why he chose this style. If he's still a beginner, you might even confuse him. This is unnecessary and does not help to solve his problems.
-
in class I declared
QIODevice *dev;In class constructor
this.->dev = nullptr;In method it return instance of QIODevice *
this->dev = mic->start();or simple
dev = mic->start();I use "this->" to differentiate class variables from local method variables but I could have use only dev.
-
Can you please share your entire class definition / header file with us?
Sorry for asking aboutthis
- we don't know what yourthis
actually is.
Do you subclass QObject? Or QThread? Have you overridden virtual methods, e.g. QThread's run()?
Have you added the debug statements I proposed and if so, what's their output?