applicazione client/server, impostare il buffer per l'audioformat ed eliminare eco e rumori

BigIssue

Utente Attivo
221
18
CPU
intel dual core n3050
Scheda Madre
asus x540s
RAM
4gb
GPU
intel HD
OS
Windows 10
L'applicazione che sto scrivendo solo a scopo educativo per il momento da la possibilità ad un client di collegarsi al server e dal server il client riceve la voce catturata dal microfono.
In pratica si parla dal server per far arrivare la voce al client per sentirla dalle casse audio del pc.

server

micTrial.pro
Codice:
QT -= gui
QT += network
QT += multimedia

CONFIG += c++17 console
CONFIG -= app_bundle

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
        main.cpp \
        mymic.cpp \
        myserver.cpp

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

HEADERS += \
    mymic.h \
    myserver.h

mymic.h
C++:
#ifndef MYMIC_H
#define MYMIC_H

#include <QThread>
#include <QTcpSocket>
#include <QDebug>
#include <QAudioInput>
#include <QDataStream>
#include <QObject>
#include <QIODevice>

class MyMic: public QObject
{
    Q_OBJECT
public:
    explicit MyMic( int ID);
    void run();

signals:
    void error(QTcpSocket::SocketError socketerror);

public slots:
    void sendData();
    void disconnected();
    void onfinish();

private:
    QTcpSocket *socket;
    int socketDescriptor;
    QAudioInput *mic;
    QIODevice *dev;
};
#endif // MYMIC_H

myserver.h
C++:
#ifndef MYSERVER_H
#define MYSERVER_H

#include <QtNetwork>
#include <QTcpServer>

#include <QtMultimedia/QAudioFormat>
#include <QtMultimedia/QAudioInput>
#include <QtMultimedia/QAudioDeviceInfo>
#include "mymic.h"

class MyServer : public QTcpServer
{
    Q_OBJECT
public:
    explicit MyServer();
    void startServer();

signals:

public slots:

protected:
    void incomingConnection(int socketDescriptor);

private:
    QAudioInput *audioInput;
};

#endif // MYSERVER_H

main.cpp
C++:
#include <QCoreApplication>
#include <myserver.h>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    MyServer server;
    server.startServer();

    return a.exec();
}

mymic.cpp
C++:
#include "mymic.h"
#include <QCoreApplication>
#include <QBuffer>
MyMic::MyMic( int ID)
{
    this->socketDescriptor = ID;
    this->mic = nullptr;
    this->dev = nullptr;
}

void MyMic::run()
{
    qDebug() << " MyMic started";

    socket = new QTcpSocket();

    if(!socket->setSocketDescriptor(this->socketDescriptor))
    {
        emit error(socket->error());
        return;
    }

    QAudioFormat format;

    format.setSampleRate(8000);
    format.setChannelCount(1);
    format.setSampleSize(8);
    format.setCodec("audio/pcm");
    format.setByteOrder(QAudioFormat::LittleEndian);
    format.setSampleType(QAudioFormat::SignedInt);

    QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice();
    if (!info.isFormatSupported(format))
    {
        qWarning()<<"default format not supported try to use nearest";
        format = info.nearestFormat(format);
    }

    this->mic = new QAudioInput(format, socket);
    this->mic->setBufferSize(8000 * 8);

    QBuffer mInputBuffer;
    mInputBuffer.open(QBuffer::ReadWrite);

    connect(this->dev = mic->start(), SIGNAL( readyRead() ), this, SLOT( sendData() ) , Qt::DirectConnection);

    qDebug() << socketDescriptor << " Microphone connected";
}

void MyMic::onfinish(){
    qDebug()<<"thread is finished!";
}

void MyMic::sendData()
{
    QByteArray Data = dev->readAll();

    socket->write(Data, Data.length());
    socket->waitForBytesWritten();
}

void MyMic::disconnected( )
{
    qDebug() << socketDescriptor << "Mic Disconnected";

    mic->stop();
    delete mic;

    socket->deleteLater();
    exit(0);
}

myserver.cpp
C++:
#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...";

    MyMic *myMic = new MyMic(socketDescriptor);
    myMic->run();
}

client
micClientTrial.pro
C++:
QT -= gui
QT += network
QT += multimedia

CONFIG += c++11 console
CONFIG -= app_bundle

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
        main.cpp \
        mytcpsocket.cpp

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

HEADERS += \
    mytcpsocket.h

mytcpsocket.h
C++:
#ifndef MYTCPSOCKET_H
#define MYTCPSOCKET_H

#include <QObject>
#include <QTcpSocket>
#include <QAbstractSocket>
#include <QAudioOutput>

class MyTcpSocket : public QObject
{
    Q_OBJECT
public:
    explicit MyTcpSocket(QObject *parent = nullptr);
    void doConnect();

signals:
public slots:
    void connected();
    void disconnected();
    void bytesWritten(qint64 bytes);
    void readyRead();

private:
     QTcpSocket *socket;
     QAudioOutput *qAudioOutput;
     QIODevice *qAudioDevice;
};

#endif // MYTCPSOCKET_H

main.cpp
C++:
#include <QCoreApplication>
#include "mytcpsocket.h"
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    MyTcpSocket s;
    s.doConnect();
    return a.exec();
}

mytcpsocket.cpp
C++:
#include "mytcpsocket.h"
#include <QBuffer>
#include <QMediaPlayer>
#include <QMediaContent>
#include <QAudioOutput>
#include <QThread>


MyTcpSocket::MyTcpSocket(QObject *parent) : QObject(parent)
{
    QAudioFormat format;
    format.setSampleRate(8000);
    format.setChannelCount(1);
    format.setSampleSize(8);
    format.setCodec("audio/pcm");
    format.setByteOrder(QAudioFormat::LittleEndian);
    format.setSampleType(QAudioFormat::SignedInt);
    QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
    if (!info.isFormatSupported(format)) {
        qWarning()<<"raw audio format not supported by backend, cannot play audio.";
        return;
    }

    qAudioOutput = new QAudioOutput(format, NULL);
    qAudioOutput->setBufferSize(8 * 8000);
    qAudioDevice = qAudioOutput->start();
}

void MyTcpSocket::doConnect()
{
    this->socket = new QTcpSocket(this);

    connect(this->socket, SIGNAL(connected()),this, SLOT(connected()));
    connect(this->socket, SIGNAL(disconnected()),this, SLOT(disconnected()));
    connect(this->socket, SIGNAL(bytesWritten(qint64)),this, SLOT(bytesWritten(qint64)));
    connect(this->socket, SIGNAL(readyRead()),this, SLOT(readyRead()));

    qDebug() << "connecting...";

    socket->connectToHost("192.168.56.1", 12345);

    // we need to wait...
    if(!socket->waitForConnected(5000))
    {
        qDebug() << "Error: " << socket->errorString();
    }


}

void MyTcpSocket::connected()
{
    qDebug() << "connected...";


}

void MyTcpSocket::disconnected()
{
    qDebug() << "disconnected...";
}

void MyTcpSocket::bytesWritten(qint64 bytes)
{
    qDebug() << bytes << " bytes written...";
}

void MyTcpSocket::readyRead()
{
    while(socket->bytesAvailable() > 0){

        QByteArray data;
        data = socket->readAll();

        qAudioDevice->write(data,data.length());
    }


}

In particolare imposto sempre questi parametri sia lato server che client
C++:
    QAudioFormat format;
    format.setSampleRate(8000);
    format.setChannelCount(1);
    format.setSampleSize(8);
    format.setCodec("audio/pcm");
    format.setByteOrder(QAudioFormat::LittleEndian);
    format.setSampleType(QAudioFormat::SignedInt);

e quindi imposto il buffer di questa dimensione 8000 * 16
C++:
qAudioOutput = new QAudioOutput(format, NULL);
qAudioOutput->setBufferSize(8 * 8000);

Sento eco e rumore ma forse perchè faccio partire client e server su stesso pc.
 

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!