标签:style blog http color io os ar strong for
qt中采用G.729A进行网络语音通话实验程序
本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.
环境:
主机:WIN8
开发环境:Qt5 3.1.2
说明:
G.729是电话带宽的语音信号编码的标准,G.729A是它的简化版本。
本程序采样频率为8KHz,量化位数为16位,则码率为128kbps。
G.729A压缩比率为1/16,则压缩后的码率为8kbps。
本测试程序实现网络语音通讯的功能。
源码:
pro文件加载库文件
LIBS += -LC:\mnt\test_audio_record -lva_g729a
audio_read.h
#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(); void update(); private: QAudioInput* audio_in; // class member. QIODevice *myBuffer_in; QByteArray file_all; int Count; QByteArray buffer_tx; int first; }; #endif // AUDIO_READ_H
audio_read.cpp 读取声卡,并压缩传输
#include "audio_read.h" #define INTERVAL 4 Audio_Read::Audio_Read() { //初始化编码器 va_g729a_init_encoder(); //声卡采样格式 QAudioFormat format; // set up the format you want, eg. format.setSampleRate(8000); 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!" << format.sampleSize(); QFile file("22.raw"); if (!file.open(QIODevice::ReadOnly)) { qDebug() << "error!!!!!!!!!"; return; } file_all = file.readAll(); Count = 0; qDebug() << "hahahahaha" << file_all.length() << (int)file_all[0] <<(int)file_all[1] << (int)file_all[2]; QTimer *timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(update())); //timer->start(10 * INTERVAL); //timer->start(5); first = 0; } void Audio_Read::readMore() { char bytes[800] = {0}; int i = 0; QByteArray frame; short input_short[L_FRAME] = {0}; int j = 0; if (!audio_in) { qDebug() << "error1111111111111111111"; 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 != 0) { qDebug() << "error2222222222222222222"; return; } // if (first < 30) // { // first++; // if (first >= 100) // { // first = 100; // } // return; // } // qDebug() << "ggggggggggggggggg"; buffer_tx.append(m_buffer.data(),l); // for (i = 0;i < 640 / (L_FRAME * 2);i++) // { // for (j = 0;j < L_FRAME;j++) // { // input_short[j] = m_buffer[2 * j + i * L_FRAME * 2] | // ((short)(m_buffer[2 * j + 1 + i * L_FRAME * 2]) << 8); // } // va_g729a_encoder(input_short, (unsigned char *)bytes); // frame.append(bytes,L_FRAME_COMPRESSED); // } // if (Server_Ip == QHostAddress("0")) // { // return; // } qDebug() << "length--------------------" << buffer_tx.length(); short num = 0; for (i = 0;i < buffer_tx.length() / (L_FRAME * 2);i++) { for (j = 0;j < L_FRAME;j++) { input_short[j] = (uint8_t)buffer_tx[2 * j + i * L_FRAME * 2] | (((uint8_t)buffer_tx[2 * j + 1 + i * L_FRAME * 2]) << 8); num = buffer_tx[2 * j + i * L_FRAME * 2] | ((buffer_tx[2 * j + 1 + i * L_FRAME * 2]) << 8); qDebug() << "---------!!!!!------------" << num << input_short[j]; } va_g729a_encoder(input_short, (unsigned char *)bytes); frame.append(bytes,L_FRAME_COMPRESSED); } buffer_tx.clear(); //发送 if (Server_Ip != QHostAddress("0")) { //frame.clear(); //frame.append(m_buffer.data(), len); sig_net_tx_frame(frame); } } void Audio_Read::update() { char bytes[800] = {0}; int i = 0; QByteArray frame; short input_short[L_FRAME] = {0}; int j = 0; if (Count * L_FRAME_COMPRESSED * INTERVAL > file_all.length()) { return; } //发送 if (Server_Ip != QHostAddress("0")) { frame.append(file_all.data() + Count * L_FRAME_COMPRESSED * INTERVAL,L_FRAME_COMPRESSED * INTERVAL); Count++; 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_OBJECT public: Audio_Write(); signals: public slots: void finishedPlaying(QAudio::State state); /********************************************************************* * 网络接收数据包 *参数:data:接收的数据 **********************************************************************/ void slot_net_rx(QByteArray data); void update(); void update2(); private: QAudioOutput* audio_out; // class member. QIODevice *myBuffer_out; QByteArray Buffer_Play; QByteArray file_all; int Count; }; #endif // AUDIO_WRITE_H
audio_write.cpp 接收语音数据,并解码播放
#include "audio_write.h" #define INTERVAL 4 Audio_Write::Audio_Write() { //初始化解码器 va_g729a_init_decoder(); QAudioFormat format; // set up the format you want, eg. format.setSampleRate(8000); 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::defaultOutputDevice(); if (!info.isFormatSupported(format)) { qWarning()<<"111default 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 *timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(update())); //timer->start(10); QFile file("22.raw"); if (!file.open(QIODevice::ReadOnly)) { qDebug() << "error!!!!!!!!!"; return; } file_all = file.readAll(); Count = 0; qDebug() << "hahahahaha" << file_all.length() << (int)file_all[0] <<(int)file_all[1] << (int)file_all[2]; QTimer *timer2 = new QTimer(this); connect(timer2, SIGNAL(timeout()), this, SLOT(update2())); //timer2->start(10 * INTERVAL); timer2->start(5); } void Audio_Write::update() { if (Buffer_Play.length() > 0) { if (Buffer_Play.length() % (L_FRAME * 2) != 0) { Buffer_Play.clear(); return; } myBuffer_out->write(Buffer_Play.data(),L_FRAME * 2); Buffer_Play = Buffer_Play.mid(L_FRAME * 2); qDebug() << "gogogogo111111111111"; } 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); } void Audio_Write::finishedPlaying(QAudio::State state) { // if(state == QAudio::IdleState) { // audio_out->stop(); // inputFile.close(); // delete audio_out; // } qDebug() << "play end!" << endl; // if(state == QAudio::IdleState) // { // if (Buffer_Play.length() != 0) // { // myBuffer_out->write(Buffer_Play); // Buffer_Play.clear(); // } // } } /********************************************************************* * 网络接收数据包 *参数:data:接收的数据 **********************************************************************/ void Audio_Write::slot_net_rx(QByteArray data) { char bytes[800] = {0}; int i = 0; short output_short[L_FRAME] = {0}; int j = 0; QByteArray frame; //memcpy(bytes,data.data(),data.length()); qDebug() << "lenght!!!!!!!!!!!!!!" << data.length(); for (i = 0;i < data.length() / L_FRAME_COMPRESSED;i++) { va_g729a_decoder((unsigned char*)data.data() + i * L_FRAME_COMPRESSED, output_short, 0); for (j = 0;j < L_FRAME;j++) { bytes[j * 2] = output_short[j]; bytes[j * 2 + 1] = output_short[j] >> 8; } frame.append(bytes,L_FRAME * 2); } // int k = 0; // for (i = 0;i < data.length() / L_FRAME_COMPRESSED;i++) // { // va_g729a_decoder((unsigned char*)data.data() + i * L_FRAME_COMPRESSED, output_short, 0); // for (j = 0;j < L_FRAME;j++) // { // bytes[k++] = output_short[j]; // bytes[k++] = output_short[j] >> 8; // } // } //qDebug() << "size!!!" << myBuffer_out->size(); //if (audio_out->state() == QAudio::IdleState) //{ qDebug() << "播放"; //myBuffer_out->write(frame); // if (audio_out->state() == QAudio::IdleState) // { // myBuffer_out->write(frame); // Buffer_Play.clear(); // } // else // { Buffer_Play.append(frame); //} qDebug() << "gogogogo2222222"; //myBuffer_out->write(data); //myBuffer_out->write(bytes,k); // } // else // { // qDebug() << "忙碌"; // } }
va_g729a.h 注意函数前加extern "C"
/*--------------------------------------------------------------------------------* * * * This material is trade secret owned by VoiceAge Corporation * * and is strictly confidential and shall remain as such. * * * * Copyright ?1995-2001 VoiceAge Corporation. All Rights Reserved. No part of * * this material may be reproduced, stored in a retrieval system, or transmitted, * * in any form or by any means, including, but not limited to, photocopying, * * electronic, mechanical, recording, or otherwise, without the prior written * * permission of VoiceAge Corporation. * * * * This material is subject to continuous developments and improvements. All * * warranties implied or expressed, including but not limited to implied * * warranties of merchantability, or fitness for purpose, are excluded. * * * * ACELP and VoiceAge are registered trademark and trademark of VoiceAge * * Corporation in Canada and / or other countries. Any unauthorized use is * * strictly prohibited. * * * *--------------------------------------------------------------------------------* * * * VoiceAge Corporation * * 750, Chemin Lucerne * * Suite 250 * * Ville Mont-Royal (Quebec) * * Canada, H3R 2H6 * * * * Tel. (514) 737-4940, fax. (514) 908-2037 * * * *--------------------------------------------------------------------------------* * *--------------------------------------------------------------------------------* * va_g729a.h * * ~~~~~~~~~~~~~~~~~~ * *--------------------------------------------------------------------------------* va_g729a API functions prototypes and constants */ #define L_FRAME_COMPRESSED 10 #define L_FRAME 80 extern "C" void va_g729a_init_encoder(); extern "C" void va_g729a_encoder(short *speech, unsigned char *bitstream); extern "C" void va_g729a_init_decoder(); extern "C" void va_g729a_decoder(unsigned char *bitstream, short *synth_short, int bfi);
标签:style blog http color io os ar strong for
原文地址:http://blog.csdn.net/jdh99/article/details/39525451