G711编解码(G711与PCM类型互转)【转】

news/2024/11/29 11:49:06/

来自:http://blog.csdn.net/qq_24551315/article/details/51134689

总结网上的G711编解码, 将其一直到andorid系统上去, 通过jni的来进行G711和PCM 的互转,  由于对于这两种格式没有深入的了解,, 所以如果想深入的了解他们可以百度, 在这里只是实现这样的功能罢了.

g711.c 包含编码和解码的方法

[html]  view plain copy
在CODE上查看代码片 派生到我的代码片
  1. //http://www.easydarwin.org/article/Streaming/38.html               参考文章  
  2. //https://github.com/EasyDarwin/EasyAACEncoder/blob/master/g711.cpp  
  3. //http://www.oschina.net/code/snippet_1173523_38946  
  4. //http://blog.csdn.net/rightorwrong/article/details/4209467  PCM 2 G711  G711 2 PCM   
  5.   
  6. unsigned char encode(short pcm);  
  7. short decode(unsigned char alaw);  
  8.   
  9. /** 个人理解  
  10.  * bitsize 应该为16, pBuffer(pcm数据) 两个char 合成一个 short ,长度自然就是原来的一半(nBufferSize/2),  
  11.  * 通过编码后short类型的数据变为char类型,让后复制给pCodecBits  
  12.  */  
  13. int g711_encode(unsigned char* pCodecBits, const char* pBuffer, int nBufferSize)  
  14. {  
  15.     short* buffer = (short*)pBuffer;  
  16.     int i;  
  17.     for(i=0; i<nBufferSize/2; i++)  
  18.     {  
  19.         pCodecBits[i] = encode(buffer[i]);  
  20.     }  
  21.   
  22.     return nBufferSize/2;  
  23. }  
  24.   
  25. /** 个人理解  
  26.  * bitsize 应该为16, pcm 数组的宽度变为原来两倍(short *out_data = (short*)pRawData;),  
  27.  * 通过对pBuffer(g711数据)中char解码转为两个字节的short ,后复制给out_data数组, 在使用的时候又转为char类型, 则 解码后的数据就是原来的两倍(nBufferSize*2)  
  28.  */  
  29. int g711_decode(char* pRawData, const unsigned char* pBuffer, int nBufferSize)  
  30. {  
  31.     short *out_data = (short*)pRawData;  
  32.     int i;  
  33.     for(i=0; i<nBufferSize; i++)  
  34.     {  
  35.         out_data[i] = decode(pBuffer[i]);  
  36.     }  
  37.   
  38.     return nBufferSize*2;  
  39. }  
  40.   
  41. #define MAX 32635  
  42. unsigned char encode(short pcm)  
  43. {  
  44.     int sign = (pcm & 0x8000) >> 8;  
  45.     if (sign != 0)  
  46.         pcm = -pcm;  
  47.     if (pcm > MAX) pcm = MAX;  
  48.     int exponent = 7;  
  49.     int expMask;  
  50.     for (expMask = 0x4000; (pcm & expMask) == 0  
  51.         && exponent>0; exponent--, expMask >>= 1) { }  
  52.     int mantissa = (pcm >> ((exponent == 0) ? 4 : (exponent + 3))) & 0x0f;  
  53.     unsigned char alaw = (unsigned char)(sign | exponent << 4 | mantissa);  
  54.     return (unsigned char)(alaw^0xD5);  
  55. }  
  56.   
  57. short decode(unsigned char alaw)  
  58. {  
  59.     alaw ^= 0xD5;  
  60.     int sign = alaw & 0x80;  
  61.     int exponent = (alaw & 0x70) >> 4;  
  62.     int data = alaw & 0x0f;  
  63.     data <<= 4;  
  64.     data += 8;  
  65.     if (exponent != 0)  
  66.         data += 0x100;  
  67.     if (exponent > 1)  
  68.         data <<= (exponent - 1);  
  69.   
  70.     return (short)(sign == 0 ? data : -data);  
  71. }  

jni中实现编解码,只贴出主要代码

G711 -> PCM

[html]  view plain copy
在CODE上查看代码片 派生到我的代码片
  1. JNIEXPORT void JNICALL Java_com_ff_aacdemo_jni_G711Coder_g711Topcm  
  2.   (JNIEnv *env, jobject obj){  
  3.     FILE* fpOut = fopen("/storage/emulated/0/t/pcm_to_g711.pcm", "wb");  
  4.     FILE* fpIn = fopen("/storage/emulated/0/t/pcm_to_g711.g711", "rb");//g711格式文件在最后会给出连接  
  5.   
  6.     int g711_BufferSize = 1024;  
  7.     char g711_Buffer[g711_BufferSize];  
  8.   
  9.     int len;  
  10.     while((len = fread(g711_Buffer, 1, g711_BufferSize, fpIn)) > 0){  
  11.         LOGD("g711topcm length = %d", len);  
  12.         char pcmBuffer[len];  
  13.         int pcmbufsize = g711_decode(pcmBuffer, g711_Buffer, len);  
  14.         fwrite(pcmBuffer, 1, pcmbufsize, fpOut);  
  15.     }  
  16.     LOGD("g711topcm end");  
  17.     fclose(fpIn);  
  18.     fclose(fpOut);  
  19. }  

PCM -> G711

[html]  view plain copy
在CODE上查看代码片 派生到我的代码片
  1. JNIEXPORT void JNICALL Java_com_ff_aacdemo_jni_G711Coder_pcmTog711  
  2.   (JNIEnv *env, jobject obj){  
  3.     FILE* fpIn = fopen("/storage/emulated/0/t/pcm_to_g711.pcm", "rb");  
  4.     FILE* fpOut = fopen("/storage/emulated/0/t/pcm_to_g711.g711", "wb");  
  5.   
  6.     LOGD("pcmTog711 1");  
  7.   
  8.     int pcm_BufferSize = 1024;  
  9.     char pcm_Buffer[pcm_BufferSize];  
  10.   
  11.     int len;  
  12.     while((len = fread(pcm_Buffer, 1, pcm_BufferSize, fpIn)) > 0){  
  13.         LOGD("pcmTog711 length = %d", len);  
  14.         char g711Buffer[len];  
  15.         int  g711BufSize = g711_encode(g711Buffer, pcm_Buffer, len);  
  16.         fwrite(g711Buffer, 1, g711BufSize, fpOut);  
  17.     }  
  18.     LOGD("pcmTog711 end");  
  19.     fclose(fpIn);  
  20.     fclose(fpOut);  
  21. }  

虽然能够实现他们的相互转换, 可是,不怎么好找到播放器播放, 效果始终没有验证, 在下一章中, 将总结将 G711 转换为 AAC , AAC这种格式将能够使用常规的播放器进行播放

g711文件 http://download.csdn.net/detail/yuanzhenhai/2693878


http://www.ppmy.cn/news/224325.html

相关文章

音频格式G711转PCM的代码

今天调试摄像头的音频格式&#xff0c;始终不对。原始音频为8000&#xff0c;16位&#xff0c;帧率50。每帧的数据应该是320字节。 接收到手上&#xff0c;RTP包为171字节&#xff0c;数据为160&#xff0c;只有一半。这是怎么回事&#xff1f;一开始总是认为RTP接收有问题&…

国腾|GM8775C替换TC358775/MIPI转双通道LVDS

1 产品概述 GM8775C 型DSI 转双通道 LVDS 发送器产品主要实现将MIPI DSI 转单/双通道 LVDS 功能&#xff0c;MIPI 支持 1/2/3/4 通道可选&#xff0c;最大支持 4Gbps 速率。LVDS 时钟频率最高154MHz&#xff0c;最大支持视频格式为 FULL HD&#xff08;1920 x 1200&#xf…

MICROCHIP的PIC16F1519-I/PT中英文简略规格书

PIC16(L)F1516/7/8/9通用&#xff0c;带有XLP技术的28/40/44针Flash微控制器 本数据表中包含的设备 •pic16f1516 •pic16f1517 pic16f1518 pic16lf1518 •pic16f1519 高性能的RISC CPU •C编译器优化架构 •只有49指令 •操作速度: - dc - 20 MHz时钟输入 2.5V - dc - 16mhz时…

基于Django Admin+HttpRunner-1.5.6开发简易的接口测试平台

前言 这是一个使用HttpRunner开发接口平台的简单Demo。 新建Django项目 安装依赖包 pip install httprunner1.5.6 -i https://pypi.doubanio.com/simple/ 模型规划 项目Project&#xff1a;包含 名称、创建时间、修改时间测试套件TestSuite&#xff1a;对应HttpRunner的一个…

ITU-T G.781标准解读(二)

同步信号的常见种类 STM-N Synchronous Transport Module level N&#xff0c;同步传输模块n级 STM-N的帧结构设计使得它可以在低速信号支路上均匀、有规律的分布&#xff0c;这就使得它可以很好的满足同步复用与交叉连接的需求&#xff0c;这样的设计也使得可以它可以满足从…

sim868模块

最近使用了SIM868模块做了项目&#xff0c;单片机使用的是STM32F103C8T6&#xff0c;使用串口2与SIM模块通信&#xff0c;实现了打电话、发短信、GPS定位、GPRS发送数据的功能&#xff0c;能够实时定位&#xff0c;1s发送一次定位数据到服务器。 SIM模块代码如下&#xff1a; …

ISO7816 智能卡 接口

原文 1 了解ISO7816接口 一、主要从两个方面来了解 ISO7816触点的电气特性 ISO7816的通讯协议流程 二、电气特性 有三种类型的7816接口 A类7816&#xff1a;工作电压4.5~5.5V B类7816&#xff1a;工作电压2.7~3.3V C类7816&#xff1a;工作电压1.8V &#xff08;供电电压…

写好Java代码的30条经验总结

1、 类名首字母应该大写。字段、方法以及对象&#xff08;句柄&#xff09;的首字母应小写。对于所有标识符&#xff0c;其中包含的所有单词都应紧靠在一起&#xff0c;而且大写中间单词的首字母。例如&#xff1a; ThisIsAClassNamethisIsMethodOrFieldName 若在定义中出现了…