chubakur
chubakur

Reputation: 51

UDP voice chat on Qt

First, I'm trying to send audio data from one process to other via the UDP protocol on localhost.

First, the program reads voice from the microphone and sends it via UDP socket:

#include <QApplication>
#include <QIODevice>
#include <QtMultimediaKit/QAudioOutput>
#include <QtMultimediaKit/QAudioInput>
#include <QtMultimediaKit/QAudioFormat>
#include <QUdpSocket>

int main(int argc, char** argv){
    QApplication app(argc, argv);
    QAudioFormat format;
    format.setSampleRate(128000);
    format.setChannelCount(1);
    format.setSampleSize(16);
    format.setCodec("audio/pcm");
    format.setByteOrder(QAudioFormat::LittleEndian);
    format.setSampleType(QAudioFormat::UnSignedInt);
    QAudioInput* input = new QAudioInput(format);
    QUdpSocket* socket = new QUdpSocket();
    socket->connectToHost("127.0.0.1", 1002);
    input->start(socket);
    return app.exec();
}

I check data sending in by Wireshark, and I think data is sent. So many UDP packages per second on the 1002 port.

The second program should read UDP packages and play it in the output device:

#include "UDPPlayer.h"
#include <QDebug>

UDPPlayer::UDPPlayer(){
    socket = new QUdpSocket();
    socket->bind(1002);
    QAudioFormat format;
    format.setSampleRate(128000);
    format.setChannelCount(1);
    format.setSampleSize(16);
    format.setCodec("audio/pcm");
    format.setByteOrder(QAudioFormat::LittleEndian);
    format.setSampleType(QAudioFormat::UnSignedInt);
    output = new QAudioOutput(format);
    connect(socket, SIGNAL(readyRead()), this, SLOT(playData()));
}

void UDPPlayer::playData(){
    qDebug() << "data";
    output->start(socket);
}

The problem is the following: playData() is never called ("data" is never printed). Does it mean that the socket is never readyRead? But I see these packages by Wireshark. What am I doing wrong?

Upvotes: 1

Views: 4314

Answers (1)

Antonio Dias
Antonio Dias

Reputation: 2881

You need make sure that the format used is supported by the input and output devices.

You also need to create a QIODevice from the output device, in order to write data to it, such data you will get with socket->readDatagram()

And you need to do something like this:

main.cpp:

#include <QApplication>
#include <QIODevice>
#include <QtMultimedia/QAudioOutput>
#include <QtMultimedia/QAudioInput>
#include <QtMultimedia/QAudioFormat>
#include <QUdpSocket>
#include "udpplayer.h"

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

    new UDPPlayer();

    QAudioFormat format;
    format.setSampleRate(128000);
    format.setChannelCount(1);
    format.setSampleSize(16);
    format.setCodec("audio/pcm");
    format.setByteOrder(QAudioFormat::LittleEndian);
    format.setSampleType(QAudioFormat::UnSignedInt);

    //If format isn't supported find the nearest supported
    QAudioDeviceInfo info(QAudioDeviceInfo::defaultInputDevice());
    if (!info.isFormatSupported(format))
        format = info.nearestFormat(format);

    QAudioInput* input = new QAudioInput(format);
    QUdpSocket* socket = new QUdpSocket();
    socket->connectToHost("127.0.0.1", 1002);
    input->start(socket);

    return a.exec();
}

udpplayer.h:

#include <QObject>
#include <QtMultimedia/QAudioOutput>
#include <QtMultimedia/QAudioInput>
#include <QtMultimedia/QAudioFormat>
#include <QUdpSocket>

class UDPPlayer : public QObject
{
    Q_OBJECT
public:
    explicit UDPPlayer(QObject *parent = 0);

private slots:
    void playData();

private:
    QAudioOutput *output;
    QUdpSocket *socket;
    QIODevice *device;
};

udpplayer.cpp:

UDPPlayer::UDPPlayer(QObject *parent) : QObject(parent)
{
    socket = new QUdpSocket();
    socket->bind(1002);
    QAudioFormat format;
    format.setSampleRate(128000);
    format.setChannelCount(1);
    format.setSampleSize(16);
    format.setCodec("audio/pcm");
    format.setByteOrder(QAudioFormat::LittleEndian);
    format.setSampleType(QAudioFormat::UnSignedInt);

    QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
    if (!info.isFormatSupported(format))
        format = info.nearestFormat(format);

    output = new QAudioOutput(format);
    device = output->start();
    connect(socket, SIGNAL(readyRead()), this, SLOT(playData()));
}

void UDPPlayer::playData()
{
    //You need to read datagrams from the udp socket
    while (socket->hasPendingDatagrams())
    {
        QByteArray data;
        data.resize(socket->pendingDatagramSize());
        socket->readDatagram(data.data(), data.size());
        device->write(data.data(), data.size());
    }
}

Upvotes: 2

Related Questions