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


    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
     
    1. INCLUDEPATH += C:work est est_audio_record_16klibspeex1include  
    2. LIBS += -LC:work est est_audio_record_16klibspeex1 -llibspeex  

    audio_read.h

    [cpp] view plain copy
     
    1. #ifndef AUDIO_READ_H  
    2. #define AUDIO_READ_H  
    3.   
    4. #include "world.h"  
    5.   
    6. class Audio_Read : public QObject  
    7. {  
    8.     Q_OBJECT  
    9. public:  
    10.     Audio_Read();  
    11. signals:  
    12.     /********************************************************************* 
    13.     *                           发送网络帧 
    14.     *参数:frame:发送的报文 
    15.     **********************************************************************/  
    16.   
    17.     void sig_net_tx_frame(QByteArray frame);  
    18.   
    19. public slots:  
    20.     void readMore();  
    21.   
    22. private:  
    23.   
    24.     QAudioInput* audio_in; // class member.  
    25.     QIODevice *myBuffer_in;  
    26.   
    27.     //SPEEX相关全局变量  
    28.     SpeexBits bits_enc;  
    29.     void *Enc_State;  
    30.   
    31.     short input_frame[SPEEX_FRAME_BYTE / 2];            //speex压缩输入存储区  
    32.     short input_frame0[SPEEX_FRAME_BYTE / 2];            //speex压缩输入存储区  
    33.     char cbits[SPEEX_FRAME_BYTE];                       //压缩后数据存储区  
    34.     char buf[SPEEX_FRAME_BYTE];                         //读取声卡存储区  
    35.   
    36. };  
    37.   
    38. #endif // AUDIO_READ_H  

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

    [cpp] view plain copy
     
    1. #include "audio_read.h"  
    2.   
    3. Audio_Read::Audio_Read()  
    4. {  
    5.     //speex编码初始化  
    6.     speex_bits_init(&bits_enc);  
    7.     Enc_State = speex_encoder_init(&speex_wb_mode);  
    8.     //Enc_State = speex_encoder_init(&speex_nb_mode);  
    9.     //设置压缩质量  
    10.     int tmp = SPEEX_QUALITY;  
    11.     speex_encoder_ctl(Enc_State,SPEEX_SET_QUALITY,&tmp);  
    12.   
    13.     //声卡采样格式  
    14.     QAudioFormat format;  
    15.     // set up the format you want, eg.  
    16.     format.setSampleRate(16000);  
    17.     format.setChannelCount(1);  
    18.     format.setSampleSize(16);  
    19.     format.setCodec("audio/pcm");  
    20.     format.setByteOrder(QAudioFormat::LittleEndian);  
    21.     //format.setByteOrder(QAudioFormat::BigEndian);  
    22.     format.setSampleType(QAudioFormat::UnSignedInt);  
    23.     //format.setSampleType(QAudioFormat::SignedInt);  
    24.     QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice();  
    25.     if (!info.isFormatSupported(format)) {  
    26.        qWarning()<<"default format not supported try to use nearest";  
    27.        format = info.nearestFormat(format);  
    28.     }  
    29.     audio_in = new QAudioInput(format, this);  
    30.     myBuffer_in = audio_in->start();  
    31.     connect(myBuffer_in, SIGNAL(readyRead()), SLOT(readMore()));  
    32.     // Records audio for 3000ms  
    33.     qDebug() <<"record begin!" << endl;  
    34. }  
    35.   
    36. void Audio_Read::readMore()  
    37. {  
    38.     char bytes[800] = {0};  
    39.     int i = 0;  
    40.     float input_frame1[320];  
    41.     QByteArray frame;  
    42.   
    43.     int nbytes = 0;  
    44.     short num = 0;  
    45.   
    46.     if (!audio_in)  
    47.         return;  
    48.   
    49.     QByteArray m_buffer(2048,0);  
    50.     qint64 len = audio_in->bytesReady();  
    51.     qDebug() << "len1 = " << len;  
    52.     qint64 l = myBuffer_in->read(m_buffer.data(), len);  
    53.     qDebug() << "len2 = " << l;  
    54.   
    55.     if (len > 640)  
    56.     {  
    57.         return;  
    58.     }  
    59.   
    60.     frame.clear();  
    61.   
    62.     //将读取的数据转换成speex识别的格式  
    63.     //大端  
    64.     for (i = 0;i < 320;i++)  
    65.     {  
    66.         num = (uint8_t)m_buffer[2 * i] | ((uint8_t)m_buffer[2 * i + 1] << 8);  
    67.         input_frame1[i] = num;  
    68.     }  
    69. //    //小端  
    70. //    for (i = 0;i < SPEEX_FRAME_BYTE / 2;i++)  
    71. //    {  
    72. //        input_frame1[i] = m_buffer[2 * i + 1] | ((short)(m_buffer[2 * i]) << 8);  
    73. //    }  
    74.   
    75. //    //大端  
    76. //    for (i = 0;i < 160;i++)  
    77. //    {  
    78. //        num = (uint8_t)m_buffer[2 * i] | (((uint8_t)m_buffer[2 * i + 1]) << 8);  
    79. //        input_frame1[i] = num;  
    80. //        //num = m_buffer[2 * i] | ((short)(m_buffer[2 * i + 1]) << 8);  
    81. //        //qDebug() << "float in" << num << input_frame1[i];  
    82. //    }  
    83.     //压缩数据  
    84.     speex_bits_reset(&bits_enc);  
    85.     speex_encode(Enc_State,input_frame1,&bits_enc);  
    86.     nbytes = speex_bits_write(&bits_enc,bytes,800);  
    87.     qDebug() << "nbytes = " << nbytes;  
    88.     frame.append(bytes,nbytes);  
    89.   
    90. //    //大端  
    91. //    for (i = 0;i < 160;i++)  
    92. //    {  
    93. //        num = (uint8_t)m_buffer[2 * i + 320] | (((uint8_t)m_buffer[2 * i + 1 + 320]) << 8);  
    94. //        input_frame1[i] = num;  
    95. //    }  
    96. //    //压缩数据  
    97. //    speex_bits_reset(&bits_enc);  
    98. //    speex_encode(Enc_State,input_frame1,&bits_enc);  
    99. //    nbytes = speex_bits_write(&bits_enc,bytes,800);  
    100. //    qDebug() << "nbytes = " << nbytes;  
    101. //    frame.append(bytes,nbytes);  
    102.   
    103.     //发送  
    104. //    frame.append(bytes,nbytes);  
    105. //    frame.clear();  
    106. //    frame.append(m_buffer.data(),len);  
    107.     if (Server_Ip != QHostAddress("0"))  
    108.     {  
    109.         sig_net_tx_frame(frame);  
    110.     }  
    111. }  

    audio_write.h

    [cpp] view plain copy
     
    1. #ifndef AUDIO_WRITE_H  
    2. #define AUDIO_WRITE_H  
    3.   
    4. #include "world.h"  
    5.   
    6. class Audio_Write : public QObject  
    7. {  
    8.     Q_OBJECT  
    9. public:  
    10.     Audio_Write();  
    11.   
    12. signals:  
    13.   
    14. public slots:  
    15.     void finishedPlaying(QAudio::State state);  
    16.   
    17.     /********************************************************************* 
    18.     *                           网络接收数据包 
    19.     *参数:data:接收的数据 
    20.     **********************************************************************/  
    21.   
    22.     void slot_net_rx(QByteArray data);  
    23.   
    24.     void update2();  
    25.   
    26. private:  
    27.   
    28.     QAudioOutput* audio_out; // class member.  
    29.     QIODevice *myBuffer_out;  
    30.   
    31.     QByteArray Buffer_Play;  
    32.   
    33.     //SPEEX相关全局变量  
    34.     SpeexBits bits_dec;  
    35.     void *Dec_State;  
    36.   
    37.     short output_frame[SPEEX_FRAME_BYTE / 2];           //speex解压输出存储区  
    38.   
    39. };  
    40.   
    41. #endif // AUDIO_WRITE_H  

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

    [cpp] view plain copy
     
    1. #include "audio_write.h"  
    2.   
    3. Audio_Write::Audio_Write()  
    4. {  
    5.     //speex初始化  
    6.     speex_bits_init(&bits_dec);  
    7.     Dec_State = speex_decoder_init(&speex_wb_mode);  
    8.     //Dec_State = speex_decoder_init(&speex_nb_mode);  
    9.   
    10.     QAudioFormat format;  
    11.     // set up the format you want, eg.  
    12.     format.setSampleRate(16000);  
    13.     format.setChannelCount(1);  
    14.     format.setSampleSize(16);  
    15.     format.setCodec("audio/pcm");  
    16.     format.setByteOrder(QAudioFormat::LittleEndian);  
    17.     //format.setByteOrder(QAudioFormat::BigEndian);  
    18.     format.setSampleType(QAudioFormat::UnSignedInt);  
    19.     //format.setSampleType(QAudioFormat::SignedInt);  
    20.     QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice();  
    21.     if (!info.isFormatSupported(format)) {  
    22.        qWarning()<<"default format not supported try to use nearest";  
    23.        format = info.nearestFormat(format);  
    24.     }  
    25.   
    26.     audio_out = new QAudioOutput(format, this);  
    27.     connect(audio_out,SIGNAL(stateChanged(QAudio::State)),SLOT(finishedPlaying(QAudio::State)));  
    28.     myBuffer_out = audio_out->start();  
    29.     qDebug() <<"play begin!" << endl;  
    30.   
    31.     QTimer *timer2 = new QTimer(this);  
    32.     connect(timer2, SIGNAL(timeout()), this, SLOT(update2()));  
    33.     //timer2->start(10 * INTERVAL);  
    34.     //timer2->start(5);  
    35. }  
    36.   
    37. void Audio_Write::finishedPlaying(QAudio::State state)  
    38.  {  
    39. //   if(state == QAudio::IdleState) {  
    40. //     audio_out->stop();  
    41. //     inputFile.close();  
    42. //     delete audio_out;  
    43. //   }  
    44.    qDebug() << "play end!" << endl;  
    45.  }  
    46.   
    47. /********************************************************************* 
    48. *                               网络接收数据包 
    49. *参数:data:接收的数据 
    50. **********************************************************************/  
    51.   
    52. void Audio_Write::slot_net_rx(QByteArray data)  
    53. {  
    54.     char bytes[800] = {0};  
    55.     int i = 0;  
    56.     float output_frame1[320] = {0};  
    57.     char buf[800] = {0};  
    58.   
    59.     //memcpy(bytes,data.data(),data.length());  
    60.   
    61.     qDebug() << "lenght!!!!!!!!!!!!!!" << data.length();  
    62.   
    63.     memcpy(bytes,data.data(),data.length());  
    64.     //解压缩数据106 62  
    65.     //speex_bits_reset(&bits_dec);  
    66.     speex_bits_read_from(&bits_dec,bytes,data.length());  
    67.     int error = speex_decode(Dec_State,&bits_dec,output_frame1);  
    68.     //qDebug() << "error1 = !!!!!!!!!!!!!!" << error;  
    69.   
    70.     //将解压后数据转换为声卡识别格式  
    71.     //大端  
    72.     short num = 0;  
    73.     for (i = 0;i < 320;i++)  
    74.     {  
    75.         num = output_frame1[i];  
    76.         buf[2 * i] = num;  
    77.         buf[2 * i + 1] = num >> 8;  
    78.         //qDebug() << "float out" << num << output_frame1[i];  
    79.     }  
    80.   
    81. //    memcpy(bytes,data.data() + data.length() / 2,data.length() / 2);  
    82. //    //解压缩数据  
    83. //    //speex_bits_reset(&bits_dec);  
    84. //    speex_bits_read_from(&bits_dec,bytes,data.length() / 2);  
    85. //    error = speex_decode(Dec_State,&bits_dec,output_frame1);  
    86. //    qDebug() << "error2 = !!!!!!!!!!!!!!" << error;  
    87.   
    88. //    //将解压后数据转换为声卡识别格式  
    89. //    //大端  
    90. //    for (i = 0;i < 160;i++)  
    91. //    {  
    92. //        num = output_frame1[i];  
    93. //        buf[2 * i + 320] = num;  
    94. //        buf[2 * i + 1 + 320] = num >> 8;  
    95. //    }  
    96. //    //小端  
    97. //    for (i = 0;i < SPEEX_FRAME_BYTE / 2;i++)  
    98. //    {  
    99. //        buf[2 * i + 1] = (int)(output_frame1[i]) & 0x00ff;  
    100. //        buf[2 * i] = (int)(output_frame1[i]) >> 8;  
    101. //    }  
    102.   
    103.     //qDebug() << "size!!!" << myBuffer_out->size();  
    104.     //if (audio_out->state() == QAudio::IdleState)  
    105.     //{  
    106.         qDebug() << "播放";  
    107.         myBuffer_out->write(buf,640);  
    108.         //Buffer_Play.append(buf,640);  
    109.         //myBuffer_out->write(data);  
    110. //    }  
    111. //    else  
    112. //    {  
    113. //        qDebug() << "忙碌";  
    114. //    }  
    115. }  
    116.   
    117. void Audio_Write::update2()  
    118. {  
    119.     char bytes[800] = {0};  
    120.     int i = 0;  
    121.     QByteArray frame;  
    122.   
    123.     //short input_short[L_FRAME] = {0};  
    124.     int j = 0;  
    125.   
    126.     //检查是否有剩余空间  
    127.     qDebug() << "aaaaaaaaa222222222222222:" << audio_out->bytesFree()  
    128.              << audio_out->periodSize() << Buffer_Play.length();  
    129.     if (audio_out && audio_out->state() != QAudio::StoppedState) {  
    130.         int chunks = audio_out->bytesFree()/audio_out->periodSize();  
    131.         while (chunks)  
    132.         {  
    133.             if (Buffer_Play.length() >= audio_out->periodSize())  
    134.             {  
    135.                 myBuffer_out->write(Buffer_Play.data(),audio_out->periodSize());  
    136.                 Buffer_Play = Buffer_Play.mid(audio_out->periodSize());  
    137.             }  
    138.             else  
    139.             {  
    140.                 myBuffer_out->write(Buffer_Play);  
    141.                 Buffer_Play.clear();  
    142.                 break;  
    143.             }  
    144.   
    145.             --chunks;  
    146.         }  
    147.     }  
    148.   
    149.   
    150.   
    151. //    if (Count * L_FRAME_COMPRESSED * INTERVAL > file_all.length())  
    152. //    {  
    153. //        return;  
    154. //    }  
    155.   
    156. //    //发送  
    157. //    frame.append(file_all.data() + Count * L_FRAME_COMPRESSED * INTERVAL,L_FRAME_COMPRESSED * INTERVAL);  
    158. //    Count++;  
    159. //    slot_net_rx(frame);  
    160. }  

    http://blog.csdn.net/jdh99/article/details/39525911

  • 相关阅读:
    Ghost Button制作教程及设计趋势分析
    onhashchange事件--司徒正美
    window.location.hash属性介绍
    优质UI的7条准则(一)
    当在浏览器地址栏输入一个网址的时候,究竟发生了什么?
    全球最快的JS模板引擎
    眨眼登录表单
    DIV+CSS规范命名
    es6--export,import
    es6--class
  • 原文地址:https://www.cnblogs.com/findumars/p/6152817.html
Copyright © 2020-2023  润新知