分享

QT实现采集即时音频信号并发送至另一台电脑播放

 QomoIT 2020-06-05

       QT有一个音频信号处理的库,非常强大,可以实现音频采集,设定采集的参数等。本文的程序是在一台电脑中实现采集即时音频信号(电脑连接耳机并且说话),将这个音频信号采集后发送至另一台电脑上,在这一台电脑中连接耳机就可以清晰地听清这个即时语音信号。全程实现的是类似音频通话的功能。

       话不多说,上代码。

       在.pro文件中首先加入下面两个库,否则会造成编译错误:

  1. QT += network
  2. QT += multimedia

       首先是发送端,实现的是语音的采集,以及音频信号的发送:

头文件:

  1. #ifndef MAINWINDOW_H
  2. #define MAINWINDOW_H
  3. #include <QMainWindow>
  4. #include <QtNetwork/QUdpSocket>
  5. #include <QAudio>//一下这五个是QT处理音频的库
  6. #include <QAudioFormat>
  7. #include <QAudioInput>
  8. #include <QAudioOutput>
  9. #include <QIODevice>
  10. using namespace std;
  11. namespace Ui {
  12. class MainWindow;
  13. }
  14. class MainWindow : public QMainWindow
  15. {
  16. Q_OBJECT
  17. public:
  18. explicit MainWindow(QWidget *parent = 0);
  19. ~MainWindow();
  20. private:
  21. Ui::MainWindow *ui;
  22. QUdpSocket *udpSocket;//用于音频信号的发送
  23. QAudioInput *input;
  24. QIODevice *inputDevice;
  25. struct video{
  26. char audiodata[1024];
  27. int lens;
  28. };
  29. private slots:
  30. void onReadyRead();//
  31. };
  32. #endif // MAINWINDOW_H

发送端.cpp文件如下:

 

#include "mainwindow.h"
#include "ui_mainwindow.h"
 
#include <QtNetwork/QUdpSocket>
#include <QDebug>
#include <QHostAddress>
 
 
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
 
    udpSocket= new QUdpSocket(this);
 
    udpSocket->bind(QHostAddress::Any,10004);//绑定10004端口,不绑定也行,因为是发送端不涉及到接收
 
    input = new QAudioInput(format,this);
    inputDevice = input->start();//input开始读入输入的音频信号,写入QIODevice,这里是inputDevice
    connect(inputDevice,SIGNAL(readyRead()),this,SLOT(onReadyRead()));
    //槽函数,当inputDevice收到input写入的音频数据之后,调用onReadyRead函数,发送数据到目标主机上
}
 
MainWindow::~MainWindow()
{
    delete ui;
}
 
void MainWindow::onReadyRead(){
    qDebug()<<"It's sending audio!"<<endl;
    video vp;
    memset(&vp,0,sizeof(vp));
 
    //读取音频
    vp.lens = inputDevice->read(vp.data,1024);//读取音频
    QHostAddress destaddr;
    destaddr.setAddress("192.168.1.104");
    udpSocket->writeDatagram((const char*)&vp,sizeof(vp),destaddr,10004);//将此结构体发送给目标主机,端口是10004,IP是192.168.1.104
}
 

       至此发送端的程序就结束了,只要有音频信号输入就可以调用writedatagram函数发送至目标主机。

       接收端的任务是手写接收网络上发送给他的音频数据包,之后发送给QIODevice进行播放。程序如下:

       头文件:

  1. #ifndef MAINWINDOW_H
  2. #define MAINWINDOW_H
  3. #include <QMainWindow>
  4. #include <QtNetwork/QUdpSocket>
  5. #include <QAudio>
  6. #include <QAudioInput>
  7. #include <QAudioOutput>
  8. #include <QAudioFormat>
  9. #include <QIODevice>
  10. namespace Ui {
  11. class MainWindow;
  12. }
  13. class MainWindow : public QMainWindow
  14. {
  15. Q_OBJECT
  16. public:
  17. explicit MainWindow(QWidget *parent = 0);
  18. ~MainWindow();
  19. private:
  20. Ui::MainWindow *ui;
  21. QUdpSocket *udpsocket;
  22. struct video{
  23. char data[1024];
  24. int lens;
  25. };
  26. QAudioOutput *output;
  27. QIODevice *outputDevice;
  28. private slots:
  29. void readyReadSlot();
  30. };
  31. #endif // MAINWINDOW_H

接收.cpp文件如下:

  1. #include "mainwindow.h"
  2. #include "ui_mainwindow.h"
  3. #include <QHostAddress>
  4. MainWindow::MainWindow(QWidget *parent) :
  5. QMainWindow(parent),
  6. ui(new Ui::MainWindow)
  7. {
  8. ui->setupUi(this);
  9. udpsocket = new QUdpSocket(this);
  10. udpsocket->bind(QHostAddress::Any,10004);
  11. connect(udpsocket,SIGNAL(readyRead()),this,SLOT(readyReadSlot()));//收到网络数据报就开始往outputDevice写入,进行播放
  12. QAudioFormat format;
  13. format.setSampleRate(8000);
  14. format.setChannelCount(1);
  15. format.setSampleSize(16);
  16. format.setCodec("audio/pcm");
  17. format.setSampleType(QAudioFormat::SignedInt);
  18. format.setByteOrder(QAudioFormat::LittleEndian);
  19. output = new QAudioOutput(format,this);
  20. outputDevice = output->start();//开始播放
  21. }
  22. MainWindow::~MainWindow()
  23. {
  24. delete ui;
  25. }
  26. void MainWindow::readyReadSlot(){
  27. while(udpsocket->hasPendingDatagrams()){
  28. QHostAddress senderip;
  29. quint16 senderport;
  30. qDebug()<<"audio is being received..."<<endl;
  31. video vp;
  32. memset(&vp,0,sizeof(vp));
  33. udpsocket->readDatagram((char*)&vp,sizeof(vp),&senderip,&senderport);
  34. outputDevice->write(vp.data,vp.lens);
  35. }
  36. }

       别忘了往.pro文件加上那两行QT库。

        怎么样?运行程序,你在发送端的电脑上面说话,接收端就能听到,延迟不到半秒。这样你就自己实现了语音电话的功能。是不是很酷炫呢?

 https://blog.csdn.net/hanzhen7541/article/details/98794555  这是更新版,更有借鉴价值。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多