G711編解碼(G711與PCM型別互轉)【轉】
阿新 • • 發佈:2019-01-31
總結網上的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);
- }
jni中實現編解碼,只貼出主要程式碼
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