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\test\test_audio_record_16k\libspeex1\include  
  2. LIBS += -LC:\work\test\test_audio_record_16k\libspeex1 -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

posted @ 2016-12-09 23:30  findumars  Views(1130)  Comments(0Edit  收藏  举报