您的位置:首页 > 理论基础 > 计算机网络

qt中采用宽带speex进行网络语音通话实验程序

2016-12-09 23:30 405 查看
qt中采用宽带speex进行网络语音通话实验程序

本文博客链接:http://blog.csdn.NET/jdh99,作者:jdh,转载请注明.

环境:

主机:WIN8

开发环境:Qt5 3.1.2

speex版本:1.0.5

说明:

本程序采样频率为16KHz,量化位数为16位,则码率为256kbps。

speex采用窄带压缩,质量10,压缩比率为106/640,则压缩后的码率为42.4kbps。

测试程序实现网络语音通讯的功能。

源码:

pro文件加载库文件

[cpp] view plain copy

INCLUDEPATH += C:\work\test\test_audio_record_16k\libspeex1\include

LIBS += -LC:\work\test\test_audio_record_16k\libspeex1 -llibspeex

audio_read.h

[cpp] view plain copy

#ifndef AUDIO_READ_H

#define AUDIO_READ_H

#include "world.h"

class Audio_Read : public QObject

{

Q_OBJECT

public:

Audio_Read();

signals:

/*********************************************************************

* 发送网络帧

*参数:frame:发送的报文

**********************************************************************/

void sig_net_tx_frame(QByteArray frame);

public slots:

void readMore();

private:

QAudioInput* audio_in; // class member.

QIODevice *myBuffer_in;

//SPEEX相关全局变量

SpeexBits bits_enc;

void *Enc_State;

short input_frame[SPEEX_FRAME_BYTE / 2]; //speex压缩输入存储区

short input_frame0[SPEEX_FRAME_BYTE / 2]; //speex压缩输入存储区

char cbits[SPEEX_FRAME_BYTE]; //压缩后数据存储区

char buf[SPEEX_FRAME_BYTE]; //读取声卡存储区

};

#endif // AUDIO_READ_H

audio_read.cpp 读取声卡,并压缩传输

[cpp] view plain copy

#include "audio_read.h"

Audio_Read::Audio_Read()

{

//speex编码初始化

speex_bits_init(&bits_enc);

Enc_State = speex_encoder_init(&speex_wb_mode);

//Enc_State = speex_encoder_init(&speex_nb_mode);

//设置压缩质量

int tmp = SPEEX_QUALITY;

speex_encoder_ctl(Enc_State,SPEEX_SET_QUALITY,&tmp);

//声卡采样格式

QAudioFormat format;

// set up the format you want, eg.

format.setSampleRate(16000);

format.setChannelCount(1);

format.setSampleSize(16);

format.setCodec("audio/pcm");

format.setByteOrder(QAudioFormat::LittleEndian);

//format.setByteOrder(QAudioFormat::BigEndian);

format.setSampleType(QAudioFormat::UnSignedInt);

//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);

}

audio_in = new QAudioInput(format, this);

myBuffer_in = audio_in->start();

connect(myBuffer_in, SIGNAL(readyRead()), SLOT(readMore()));

// Records audio for 3000ms

qDebug() <<"record begin!" << endl;

}

void Audio_Read::readMore()

{

char bytes[800] = {0};

int i = 0;

float input_frame1[320];

QByteArray frame;

int nbytes = 0;

short num = 0;

if (!audio_in)

return;

QByteArray m_buffer(2048,0);

qint64 len = audio_in->bytesReady();

qDebug() << "len1 = " << len;

qint64 l = myBuffer_in->read(m_buffer.data(), len);

qDebug() << "len2 = " << l;

if (len > 640)

{

return;

}

frame.clear();

//将读取的数据转换成speex识别的格式

//大端

for (i = 0;i < 320;i++)

{

num = (uint8_t)m_buffer[2 * i] | ((uint8_t)m_buffer[2 * i + 1] << 8);

input_frame1[i] = num;

}

// //小端

// for (i = 0;i < SPEEX_FRAME_BYTE / 2;i++)

// {

// input_frame1[i] = m_buffer[2 * i + 1] | ((short)(m_buffer[2 * i]) << 8);

// }

// //大端

// for (i = 0;i < 160;i++)

// {

// num = (uint8_t)m_buffer[2 * i] | (((uint8_t)m_buffer[2 * i + 1]) << 8);

// input_frame1[i] = num;

// //num = m_buffer[2 * i] | ((short)(m_buffer[2 * i + 1]) << 8);

// //qDebug() << "float in" << num << input_frame1[i];

// }

//压缩数据

speex_bits_reset(&bits_enc);

speex_encode(Enc_State,input_frame1,&bits_enc);

nbytes = speex_bits_write(&bits_enc,bytes,800);

qDebug() << "nbytes = " << nbytes;

frame.append(bytes,nbytes);

// //大端

// for (i = 0;i < 160;i++)

// {

// num = (uint8_t)m_buffer[2 * i + 320] | (((uint8_t)m_buffer[2 * i + 1 + 320]) << 8);

// input_frame1[i] = num;

// }

// //压缩数据

// speex_bits_reset(&bits_enc);

// speex_encode(Enc_State,input_frame1,&bits_enc);

// nbytes = speex_bits_write(&bits_enc,bytes,800);

// qDebug() << "nbytes = " << nbytes;

// frame.append(bytes,nbytes);

//发送

// frame.append(bytes,nbytes);

// frame.clear();

// frame.append(m_buffer.data(),len);

if (Server_Ip != QHostAddress("0"))

{

sig_net_tx_frame(frame);

}

}

audio_write.h

[cpp] view plain copy

#ifndef AUDIO_WRITE_H

#define AUDIO_WRITE_H

#include "world.h"

class Audio_Write : public QObject

{

Q_OBJECT

public:

Audio_Write();

signals:

public slots:

void finishedPlaying(QAudio::State state);

/*********************************************************************

* 网络接收数据包

*参数:data:接收的数据

**********************************************************************/

void slot_net_rx(QByteArray data);

void update2();

private:

QAudioOutput* audio_out; // class member.

QIODevice *myBuffer_out;

QByteArray Buffer_Play;

//SPEEX相关全局变量

SpeexBits bits_dec;

void *Dec_State;

short output_frame[SPEEX_FRAME_BYTE / 2]; //speex解压输出存储区

};

#endif // AUDIO_WRITE_H

audio_write.cpp 接收语音数据,并解码播放

[cpp] view plain copy

#include "audio_write.h"

Audio_Write::Audio_Write()

{

//speex初始化

speex_bits_init(&bits_dec);

Dec_State = speex_decoder_init(&speex_wb_mode);

//Dec_State = speex_decoder_init(&speex_nb_mode);

QAudioFormat format;

// set up the format you want, eg.

format.setSampleRate(16000);

format.setChannelCount(1);

format.setSampleSize(16);

format.setCodec("audio/pcm");

format.setByteOrder(QAudioFormat::LittleEndian);

//format.setByteOrder(QAudioFormat::BigEndian);

format.setSampleType(QAudioFormat::UnSignedInt);

//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);

}

audio_out = new QAudioOutput(format, this);

connect(audio_out,SIGNAL(stateChanged(QAudio::State)),SLOT(finishedPlaying(QAudio::State)));

myBuffer_out = audio_out->start();

qDebug() <<"play begin!" << endl;

QTimer *timer2 = new QTimer(this);

connect(timer2, SIGNAL(timeout()), this, SLOT(update2()));

//timer2->start(10 * INTERVAL);

//timer2->start(5);

}

void Audio_Write::finishedPlaying(QAudio::State state)

{

// if(state == QAudio::IdleState) {

// audio_out->stop();

// inputFile.close();

// delete audio_out;

// }

qDebug() << "play end!" << endl;

}

/*********************************************************************

* 网络接收数据包

*参数:data:接收的数据

**********************************************************************/

void Audio_Write::slot_net_rx(QByteArray data)

{

char bytes[800] = {0};

int i = 0;

float output_frame1[320] = {0};

char buf[800] = {0};

//memcpy(bytes,data.data(),data.length());

qDebug() << "lenght!!!!!!!!!!!!!!" << data.length();

memcpy(bytes,data.data(),data.length());

//解压缩数据106 62

//speex_bits_reset(&bits_dec);

speex_bits_read_from(&bits_dec,bytes,data.length());

int error = speex_decode(Dec_State,&bits_dec,output_frame1);

//qDebug() << "error1 = !!!!!!!!!!!!!!" << error;

//将解压后数据转换为声卡识别格式

//大端

short num = 0;

for (i = 0;i < 320;i++)

{

num = output_frame1[i];

buf[2 * i] = num;

buf[2 * i + 1] = num >> 8;

//qDebug() << "float out" << num << output_frame1[i];

}

// memcpy(bytes,data.data() + data.length() / 2,data.length() / 2);

// //解压缩数据

// //speex_bits_reset(&bits_dec);

// speex_bits_read_from(&bits_dec,bytes,data.length() / 2);

// error = speex_decode(Dec_State,&bits_dec,output_frame1);

// qDebug() << "error2 = !!!!!!!!!!!!!!" << error;

// //将解压后数据转换为声卡识别格式

// //大端

// for (i = 0;i < 160;i++)

// {

// num = output_frame1[i];

// buf[2 * i + 320] = num;

// buf[2 * i + 1 + 320] = num >> 8;

// }

// //小端

// for (i = 0;i < SPEEX_FRAME_BYTE / 2;i++)

// {

// buf[2 * i + 1] = (int)(output_frame1[i]) & 0x00ff;

// buf[2 * i] = (int)(output_frame1[i]) >> 8;

// }

//qDebug() << "size!!!" << myBuffer_out->size();

//if (audio_out->state() == QAudio::IdleState)

//{

qDebug() << "播放";

myBuffer_out->write(buf,640);

//Buffer_Play.append(buf,640);

//myBuffer_out->write(data);

// }

// else

// {

// qDebug() << "忙碌";

// }

}

void Audio_Write::update2()

{

char bytes[800] = {0};

int i = 0;

QByteArray frame;

//short input_short[L_FRAME] = {0};

int j = 0;

//检查是否有剩余空间

qDebug() << "aaaaaaaaa222222222222222:" << audio_out->bytesFree()

<< audio_out->periodSize() << Buffer_Play.length();

if (audio_out && audio_out->state() != QAudio::StoppedState) {

int chunks = audio_out->bytesFree()/audio_out->periodSize();

while (chunks)

{

if (Buffer_Play.length() >= audio_out->periodSize())

{

myBuffer_out->write(Buffer_Play.data(),audio_out->periodSize());

Buffer_Play = Buffer_Play.mid(audio_out->periodSize());

}

else

{

myBuffer_out->write(Buffer_Play);

Buffer_Play.clear();

break;

}

--chunks;

}

}

// if (Count * L_FRAME_COMPRESSED * INTERVAL > file_all.length())

// {

// return;

// }

// //发送

// frame.append(file_all.data() + Count * L_FRAME_COMPRESSED * INTERVAL,L_FRAME_COMPRESSED * INTERVAL);

// Count++;

// slot_net_rx(frame);

}
http://blog.csdn.net/jdh99/article/details/39525911
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: