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

来源:互联网 发布:排序算法对比 编辑:程序博客网 时间:2024/06/11 08:28


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文件加载库文件

INCLUDEPATH += C:\work\test\test_audio_record_16k\libspeex1\includeLIBS += -LC:\work\test\test_audio_record_16k\libspeex1 -llibspeex

audio_read.h

#ifndef AUDIO_READ_H#define AUDIO_READ_H#include "world.h"class Audio_Read : public QObject{    Q_OBJECTpublic:    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 读取声卡,并压缩传输

#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

#ifndef AUDIO_WRITE_H#define AUDIO_WRITE_H#include "world.h"class Audio_Write : public QObject{    Q_OBJECTpublic:    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 接收语音数据,并解码播放

#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);}




0 0
原创粉丝点击