1. 程式人生 > >G.711編碼原理及程式碼

G.711編碼原理及程式碼

最近看語音編碼,發現網上大都只給出了G711的程式碼,確沒有介紹原理,儘管很簡單,但直接看程式碼也是有點摸不著。下面找到了原理進行簡要的敘述,並給出了在網上找到的程式碼。

1.介紹:

G.711

也稱為PCM(脈衝編碼調製),是國際電信聯盟訂定出來的一套語音壓縮標準,主要用於電話。它主要用脈衝編碼調製對音訊取樣,取樣率為8k每秒。它利用一個 64Kbps 未壓縮通道傳輸語音訊號。起壓縮率為12即把16位資料壓縮成8位。G.711是主流的波形聲音編解碼器。
   G.711
標準下主要有兩種壓縮演算法。一種是µ-law algorithm (又稱often u-law, ulaw, mu-law),主要運用於北美和日本;另一種是A-law algorithm,主要運用於歐洲和世界其他地區。其中,後者是特別設計用來方便計算機處理的。這兩種演算法都使用一個取樣率為8kHz的輸入來建立64Kbps的數字輸出。G.711採用一種稱為分組丟失隱藏(PLC)的技術來減少丟包帶來的實際影響。有效的訊號頻寬在靜默期間通過語音活動檢測(VAD)這一過程被減小。

2.原理概述:

G.711編碼方式將14bits(採用16bits取樣與儲存)的PCM訊號編碼成8bits的樣本進行傳輸。

原理:取影響較為重要的位編碼成8位(保留重要位),比如下面的資料,前N較具有影響力,(以下2組資料,N=5

0000 0001 1111 1111 (511)

0000 0001 1111 0000 (496)

0001 1111 1111 1111 (8191)

0001 1111 0000 0000 (7936)

3.alaw編碼規則:

取影響最大的5位(1位為強度位,4位樣本位),sign為樣本的符號位,同時編碼後的資料逢偶數為取補數。即^0xD5。編碼表如下,s位符號位正數時s=1。


比如pcm=3210(0000 1100 1000 1010)2

1. int sign = pcm & 0x8000) >> 8;

S=1;

2. 取強度位

0001 10010001010

Xs = 100

3. 取高位樣本

0  0001 10010001010

wxyz = 1001

4. 結合以上數字

s  xxx wxyz

1   100  1001

5. 逢偶位數取補數

1001001

1  0011100

4.ULaw編碼規則:

1.取得範圍值,得到8-bit基本值

2.取得間隔數值size。如圖所示:

3.取得區間基本值rb(ex2015)

4.算出與區間基本值rb的距離d      d = rb - sample

5.依據間距大小size,算出平移量s = d / size

6.與8-bit基本值相加output = b + s

7903

8159

4319

4063

4063

2143

2015

2015

1055

991

991

511

479

479

239

223

223

103

95

95

35

31

31

3

0

1

0

範例 : 2345  => 0x9D

1.取得範圍值

range => 4063~2015

1-1.得到8-bit基本值

b = 0x90

2.取得間隔數值

size = 128

3.取得區間基本值

4063

4063

2143

rb = 4063

4.算出與區間基本值rb的距離d

d = rb – sample = 4063 – 2345 = 1718

5.依據間距大小size,算出平移量

s = d / size = 1718 / 128 = 13.42…  => 13

6.與8-bit基本值相加

output = b + s = 0x90 + 13 = 9D

5.程式碼

//編碼  
int CG711Decoder::G711_EnCode(unsigned char* pCodecBits, const char* pBuffer, int nBufferSize)  
{  
    short* buffer = (short*)pBuffer;  
    for(int i=0; i<nBufferSize/2; i++)  
    {  
        pCodecBits[i] = encode(buffer[i]);  
    }  
  
    return nBufferSize/2;  
}   
  
//解碼  
int CG711Decoder::G711_Decode(char* pRawData, const unsigned char* pBuffer, int nBufferSize)  
{  
    short *out_data = (short*)pRawData;  
    for(int i=0; i<nBufferSize; i++)  
    {  
        out_data[i] = decode(pBuffer[i]);  
    }  
      
    return nBufferSize*2;  
}  
  
#define MAX (32635)  
unsigned char CG711Decoder::encode(short pcm)  
{  
    int sign = (pcm & 0x8000) >> 8;  
    if (sign != 0)  
        pcm = -pcm;  	//最高位,符號位
    if (pcm > MAX) pcm = MAX;  //max=32635
    int exponent = 7;  
    int expMask;  
    for (expMask = 0x4000; (pcm & expMask) == 0  ///bit14->14-7,找到高位元組中第一個不為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);  //11010101
}  
short CG711Decoder::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);  
}  
參考: lITU-TG.711 pdf lWikipedia: G.711 & A-law lWikipedia: Mu-law 詳細PPT下載(分享自網路): http://download.csdn.net/detail/guo8113/8587203

相關推薦

G.711編碼原理程式碼

最近看語音編碼,發現網上大都只給出了G711的程式碼,確沒有介紹原理,儘管很簡單,但直接看程式碼也是有點摸不著。下面找到了原理進行簡要的敘述,並給出了在網上找到的程式碼。 1.介紹: G.711 也稱為PCM(脈衝編碼調製),是國際電信聯盟訂定出來的一套語音壓縮標準,主要

G711編碼原理程式碼

G711編碼的聲音清晰度好,語音自然度高,但壓縮效率低,資料量大常在32Kbps以上。常用於電話語音(推薦使用64Kbps),sampling rate為8K,壓縮率為2,即把S16格式的資料壓縮為8bit,分為a-law和u-law。 a-law也叫g711a,輸

Quoted-Printable編碼原理程式碼實現

這篇文章是我之前在RYTong內部分享的一篇文章,摘取了有用的部分。當時幫助某專案郵件系統解決問題,期間瞭解到Quoted-Printable編碼,在此與大家分享下該編碼的原理和個人版本的程式碼實現。 關於規範 關於Quoted-Printable的

OpenCV(一)——高斯卷積核原理程式碼實現

貼出getGaussianKernel原始碼 在smooth.cpp中 提示:Gaussian核基於 正態分佈函式設計 μ是均值,σ^2是方差 正態函式(即一維Gaussian卷積核)如下 二維卷積核通過對一維積分得到,並且μ = 0 根據如下原始碼可知

batchnorm原理程式碼詳解(筆記2)

Batchnorm原理詳解 前言:Batchnorm是深度網路中經常用到的加速神經網路訓練,加速收斂速度及穩定性的演算法,可以說是目前深度網路必不可少的一部分。 本文旨在用通俗易懂的語言,對深度學習的常用演算法–batchnorm的原理及其程式碼實現做一個詳細的解讀。本文主要包括以下幾個

微信公眾號掃碼登陸原理程式碼實現

1.使用者開啟公眾號點選掃碼功能(注意我們用 scancode_waitmsg這種型別即可)  2.使用者掃描了二維碼會給微信傳送資訊,然後微信把資訊以XML格式傳送給我們的伺服器 3.接收資料,並把資料保存於資料庫或者快取,程式碼如下: $wechatObj = new

蒙特.卡羅方法求解圓周率近似值原理程式碼實現

原理 對於某些不能精確求解的問題,蒙特.卡羅方法是一種非常巧妙的尋找近似解的方法。 以求解圓周率的問題為例,假設有一個單位圓及其外切正方形,我們往正方形內扔飛鏢,當扔的次數足夠多以後,“落在圓內的次數/落在正方形內的次數”這個比值會無限接近“圓的面積/

大資料教程(8.2)wordcount程式原理程式碼實現/執行

        上一篇部落格分享了mapreduce的程式設計思想,本節博主將帶小夥伴們瞭解wordcount程式的原理和程式碼實現/執行細節。通過本節可以對mapreduce程式有一個大概的認識,其實hadoop中的map、reduce程

【機器學習】Apriori演算法——原理程式碼實現(Python版)

Apriopri演算法 Apriori演算法在資料探勘中應用較為廣泛,常用來挖掘屬性與結果之間的相關程度。對於這種尋找資料內部關聯關係的做法,我們稱之為:關聯分析或者關聯規則學習。而Apriori演算法就是其中非常著名的演算法之一。關聯分析,主要是通過演算法在大規模資料集中尋找頻繁項集和關聯規則。

OpenCV+OCR 影象處理字元識別原理程式碼

需配置好OpenCV和OCR環境下執行 1、OpenCV簡介 OpenCV的全稱是Open Source Computer Vision Library,是一個跨平臺的計算機視覺庫。 OpenCV用C++語言編寫,它的主要介面也是C++語言,但是依然保留了大量的C語言介

IOS —— App啟動原理程式碼優化

哈嘍,好久不見。最近處於心情低迷期就沒怎麼來更新文章了。 在下也算是個半路出家的程式碼家,從之前的文章更新到現在 依然是還是從基礎學起,萬物歸基礎! 所以從今天起每天回來更新彙報學習成果!!每天 今天主要接觸的是Application相關的知識,包括App啟動原理,以及windos視窗控制以及Appd

tensorflow-deeplab-resnet 原理程式碼詳解

前言: 程式碼的model.py,network.py是建立深度學習網路的部分,這部分程式碼風格與Faster-RCNN_TF那個程式的風格非常相似,也很簡單,不再多做介紹。這裡主要介紹train.py、image_reader.py其他還有inference

java:集合框架(TreeSet保證元素唯一和比較器排序的原理程式碼實現)

* A:案例演示     * TreeSet保證元素唯一和比較器排序的原理及程式碼實現 按照字串長度排序 重寫了Comparator介面中的方法 class CompareByLen implem

(四)DFS檔案操作的原理程式碼實現

1、檔案操作原理 1.1、下載過程 Client向namenode發起Open file 請求。目的是獲取指定檔案的輸入流 namenode收到請求之後,會檢查路徑的合法性,客戶端的操作許可權。如果檢測未通過,則直接報錯返回 Client也會向namenode發起Get

AVL樹的原理程式碼實現

前言: 如果你還沒有學習過二叉查詢樹,那麼請你先去看看二叉查詢樹,因為AVL樹便是從二叉查詢樹進化而來的,不看的話你無法理解AVL樹。 如果你已經學習了二叉查詢樹,你會覺得二叉查詢樹效能在各方面都很好,就只有一丟丟的小毛病,那就是當資料非常坑時,二叉查詢樹退化成了一條

【原創】大資料基礎之Spark(4)RDD原理程式碼解析

一 簡介 spark核心是RDD,官方文件地址:https://spark.apache.org/docs/latest/rdd-programming-guide.html#resilient-distributed-datasets-rdds官方描述如下:重點是可容錯,可並行處理 Spark r

【原創】大資料基礎之Spark(5)Shuffle實現原理程式碼解析

一 簡介 Shuffle,簡而言之,就是對資料進行重新分割槽,其中會涉及大量的網路io和磁碟io,為什麼需要shuffle,以詞頻統計reduceByKey過程為例, serverA:partition1: (hello, 1), (word, 1)serverB:partition2: (hell

JAVA NIO工作原理程式碼示例

簡介:本文主要介紹了JAVA NIO中的Buffer, Channel, Selector的工作原理以及使用它們的若干注意事項,最後是利用它們實現伺服器和客戶端通訊的程式碼例項。 歡迎探討,如有錯誤敬請指正 1. ByteBuffer 1.1直接緩衝區和非直接緩衝區 下面是建立ByteBuffer物件的

SIFT演算法特徵描述子構建---關鍵點定位原理程式碼

0.引言 sift針對區域性特徵進行特徵提取,在尺度空間尋找極值點,提取位置,尺度,旋轉不變數,生成特徵描述子。 總共分四個步驟: step2 關鍵點/極值點提取 2.1 關鍵點位置初步探查 生成DOG金字塔後,要找到DOG空間中的區域

sift演算法特徵描述子構建程式碼實現--梯度直方圖生成原理程式碼

0.引言 sift針對區域性特徵進行特徵提取,在尺度空間尋找極值點,提取位置,尺度,旋轉不變數,生成特徵描述子。 總共分四個步驟: step3 生成梯度直方圖 生成特徵點的梯度資訊,並且確定主方向和輔助主方向的關鍵點。 3.1 梯度計算