今天给大家讲说一个新的东西,使用QT实现音频通信的功能,挺起来是不是很高大上啊,哈哈,实际上我们只是使用一些接口做一些简单的工作而已,并不是让你写一个传输协议和采集音频信息,好了,那我们就来说一说关于在QT中是实现音频通信的具体过程吧!
首先我们要是用到是UDP的通信协议和关于音频信息的采集类和标准的输入输出设别的类,那么我们分别是下面的几个类:
QUdpSocket:在QT用用于udp通信的类
QAudioInput:音频采集的类
QIODevice:标准输入输出设备
QAudioOutput:数据音频的类
音频采集端口
上边的用到的类中分别用到了网络模块和多媒体模块所以在工程文件中需要加入对网络和多媒体的支持(*.pro文件):
1 QT += multimedia 2 QT += network
首先我们在音频的采集端口需要设置音频采集的格式和传输的数据包的类型,使用QAudioInput的对象按指定的格式去采集音频数据,代码提供如下:
1 MainWindow::MainWindow(QWidget *parent) : 2 QWidget(parent), 3 ui(new Ui::MainWindow) 4 { 5 ui->setupUi(this); 6 //设置声音格式 7 QAudioFormat format; 8 format.setSampleRate (8000); //设置采样频率 9 format.setChannelCount (1); //设置通道计数 10 format.setSampleSize (16); //设置样本大小,一般为8或者16 11 format.setCodec ("audio/pcm"); //设置编码格式 12 format.setSampleType (QAudioFormat::SignedInt); //设置采样类型 13 format.setByteOrder (QAudioFormat::LittleEndian); //设置字节序为小端字节序 14 15 input = new QAudioInput(format, this); 16 17 videoWriteSocket = new QUdpSocket(this); 18 }
接下来我们要定义音频信息在网络间传输的数据包格式:
1 //音频传输的数据包格式 2 struct videoPack{ 3 char data[1024]; 4 int lens; 5 };
现在我们将音频数据能够采集出来了,接下来就是将音频的数据写入标准输入设备最后写到广播端口,写入:
1 inputDevice = input->start (); 2 connect (inputDevice, SIGNAL(readyRead()), 3 this, SLOT(onReadyRead()));
1 void MainWindow::onReadyRead () 2 { 3 qDebug() << "send audioinput...."; 4 videoPack vp; 5 memset (&vp, 0, sizeof(vp)); 6 //读取音频数据 7 vp.lens = inputDevice->read (vp.data, 1024); 8 videoWriteSocket->writeDatagram((const char*)&vp, 9 sizeof(vp), 10 QHostAddress("224.0.0.0"), 11 10000); 12 }
好了,通过上边的步骤,那么你就能够将音频数据将它按指定的格式写入广播端口了,接下来就只需要在读取端口读取我们的音频信息就可以了。
音频读取端口
首先我们要在读取端口这边设置和音频采集端口的音频采集格式和传输的数据包类型严格的一致,不然的话你是不能处理音频信息的。
好了,接下来我们就来看一看如何使用udp的端口读取音频信息吧,代码如下:
1 MainWindow::MainWindow(QWidget *parent) : 2 QWidget(parent), 3 ui(new Ui::MainWindow) 4 { 5 ui->setupUi(this); 6 //窗口udp的套接字对象 7 videoReadSocket = new QUdpSocket(this); 8 //绑定到广播端口 9 videoReadSocket->bind (QHostAddress::AnyIPv4, 10000, 10 QUdpSocket::ShareAddress 11 | QUdpSocket::ReuseAddressHint); 12 //加入广播组 13 videoReadSocket->joinMulticastGroup (QHostAddress("224.0.0.0")); 14 //如果有套接字动作将会触发readyRead信号,我们将读取音频信息 15 connect(videoReadSocket, SIGNAL(readyRead()), 16 this, SLOT(readyReadSlot())); 17 //设置声音格式 18 QAudioFormat format; 19 format.setSampleRate (8000); //设置采样频率 20 format.setChannelCount (1); //设置通道计数 21 format.setSampleSize (16); //设置样本大小,一般为8或者16 22 format.setCodec ("audio/pcm"); //设置编码格式 23 format.setSampleType (QAudioFormat::SignedInt); //设置采样类型 24 format.setByteOrder (QAudioFormat::LittleEndian); //设置字节序为小端字节序 25 output = new QAudioOutput(format, this); 26 27 //开启读取音频数据的接口 28 outputDevice = output->start (); 29 }
那好我们再来看一看在readyReadSlot的槽函数的处理代码吧
1 void MainWindow::readyReadSlot () 2 { 3 qDebug() << "video reveiver..."; 4 videoPack vp; 5 memset (&vp, 0, sizeof(vp)); 6 videoReadSocket->readDatagram ((char*)&vp, sizeof(vp)); 7 outputDevice->write (vp.data, vp.lens); 8 }
经过上边一系列过程,那么我们可以试一试,是不是已经可以接受到音频的信息了呢,另外说一句,在构造函数的中用到的对象,我都将他声明在了这个类的声明中,以私有成员的形式出现在了类中,我就不予给出了,大家自己在头文件中加入相应的声明就行了。