总结网上的G711编解码, 将其一直到andorid系统上去, 通过jni的来进行G711和PCM 的互转, 由于对于这两种格式没有深入的了解,, 所以如果想深入的了解他们可以百度, 在这里只是实现这样的功能罢了.
g711.c 包含编码和解码的方法
//http://www.easydarwin.org/article/Streaming/38.html 参考文章 //https://github.com/EasyDarwin/EasyAACEncoder/blob/master/g711.cpp //http://www.oschina.net/code/snippet_1173523_38946 //http://blog.csdn.net/rightorwrong/article/details/4209467 PCM 2 G711 G711 2 PCM unsigned char encode(short pcm); short decode(unsigned char alaw); /** 个人理解 * bitsize 应该为16, pBuffer(pcm数据) 两个char 合成一个 short ,长度自然就是原来的一半(nBufferSize/2), * 通过编码后short类型的数据变为char类型,让后复制给pCodecBits */ int g711_encode(unsigned char* pCodecBits, const char* pBuffer, int nBufferSize) { short* buffer = (short*)pBuffer; int i; for(i=0; i<nBufferSize/2; i++) { pCodecBits[i] = encode(buffer[i]); } return nBufferSize/2; } /** 个人理解 * bitsize 应该为16, pcm 数组的宽度变为原来两倍(short *out_data = (short*)pRawData;), * 通过对pBuffer(g711数据)中char解码转为两个字节的short ,后复制给out_data数组, 在使用的时候又转为char类型, 则 解码后的数据就是原来的两倍(nBufferSize*2) */ int g711_decode(char* pRawData, const unsigned char* pBuffer, int nBufferSize) { short *out_data = (short*)pRawData; int i; for(i=0; i<nBufferSize; i++) { out_data[i] = decode(pBuffer[i]); } return nBufferSize*2; } #define MAX 32635 unsigned char encode(short pcm) { int sign = (pcm & 0x8000) >> 8; if (sign != 0) pcm = -pcm; if (pcm > MAX) pcm = MAX; int exponent = 7; int expMask; for (expMask = 0x4000; (pcm & expMask) == 0 && exponent>0; exponent--, expMask >>= 1) { } int mantissa = (pcm >> ((exponent == 0) ? 4 : (exponent + 3))) & 0x0f; unsigned char alaw = (unsigned char)(sign | exponent << 4 | mantissa); return (unsigned char)(alaw^0xD5); } short decode(unsigned char alaw) { alaw ^= 0xD5; int sign = alaw & 0x80; int exponent = (alaw & 0x70) >> 4; int data = alaw & 0x0f; data <<= 4; data += 8; if (exponent != 0) data += 0x100; if (exponent > 1) data <<= (exponent - 1); return (short)(sign == 0 ? data : -data); }
G711 -> PCM
JNIEXPORT void JNICALL Java_com_ff_aacdemo_jni_G711Coder_g711Topcm (JNIEnv *env, jobject obj){ FILE* fpOut = fopen("/storage/emulated/0/t/pcm_to_g711.pcm", "wb"); FILE* fpIn = fopen("/storage/emulated/0/t/pcm_to_g711.g711", "rb");//g711格式文件在最后会给出连接 int g711_BufferSize = 1024; char g711_Buffer[g711_BufferSize]; int len; while((len = fread(g711_Buffer, 1, g711_BufferSize, fpIn)) > 0){ LOGD("g711topcm length = %d", len); char pcmBuffer[len]; int pcmbufsize = g711_decode(pcmBuffer, g711_Buffer, len); fwrite(pcmBuffer, 1, pcmbufsize, fpOut); } LOGD("g711topcm end"); fclose(fpIn); fclose(fpOut); }
PCM -> G711
JNIEXPORT void JNICALL Java_com_ff_aacdemo_jni_G711Coder_pcmTog711 (JNIEnv *env, jobject obj){ FILE* fpIn = fopen("/storage/emulated/0/t/pcm_to_g711.pcm", "rb"); FILE* fpOut = fopen("/storage/emulated/0/t/pcm_to_g711.g711", "wb"); LOGD("pcmTog711 1"); int pcm_BufferSize = 1024; char pcm_Buffer[pcm_BufferSize]; int len; while((len = fread(pcm_Buffer, 1, pcm_BufferSize, fpIn)) > 0){ LOGD("pcmTog711 length = %d", len); char g711Buffer[len]; int g711BufSize = g711_encode(g711Buffer, pcm_Buffer, len); fwrite(g711Buffer, 1, g711BufSize, fpOut); } LOGD("pcmTog711 end"); fclose(fpIn); fclose(fpOut); }
虽然能够实现他们的相互转换, 可是,不怎么好找到播放器播放, 效果始终没有验证, 在下一章中, 将总结将 G711 转换为 AAC , AAC这种格式将能够使用常规的播放器进行播放
g711文件 http://download.csdn.net/detail/yuanzhenhai/2693878