數據壓縮實驗六 MPEG音頻壓縮編碼

一、實驗原理

1. MPEG-1聲音的主要性能
  輸入爲PCM信號,採樣率爲32,44.1或48kHz,輸出爲 32kbps到384kbps。

2. MPEG音頻編碼主要流程
三個獨立的壓縮層次
  Layer1:編碼器最簡單,384kbps(4:1, 用於小型數字盒帶DCC,Compact Cassette)
  Layer2:編碼器複雜程度中等,256kbps~192kbps(6: 1~8:1, 用於DAB、CD-I和VCD)
  Layer3:編碼器最爲複雜,64kbps,用於ISDN,網絡 音頻。

  MPEG音頻編碼爲同時獲得較高的時域精準度與頻域精準度,對信息分兩條線即時域和頻域分別處理,在綜合獲得最終結果。通過子帶分析濾波器組使信號具有高的時間 分辨率,確保在短暫衝擊信號情況下,編碼 的聲音信號具有足夠高的質量; 使信號通過FFT運算具有高的頻率分辨率,因爲掩蔽閾值是從功率譜密度推出來的。流程圖如下:
這裏寫圖片描述

  聲音壓縮算法屬於感知編碼,可以確立心理聲學特性的模型來取消更 多的冗餘數據。
3.心理聲學模型 :
1.聽覺系統中存在一個聽覺閾值電平,低於這個電平的聲 音信號就聽不到 。聽覺閾值的大小隨聲音頻率的改變而改變,一個人是否聽到聲音取決於聲音的頻率,以及聲音 的幅度是否高於這種頻率下的聽覺閾值 。
2.聽覺掩蔽特性。即聽覺閾值電平是自適應的,會隨聽到的不同頻率聲音而發生變化 。

4.頻域掩蔽域隨聲壓級變化曲線:
這裏寫圖片描述

5.32個子帶濾波器組:
  通過子帶分析濾波器組使信號具有高的時間分辨率,確保在短暫衝擊信號情況下,編碼的聲音信號具有足夠高的質量。將PCM樣本變換到32個子帶的頻域信號:如果輸入的採樣頻率爲48kHz ,那麼子帶的頻率寬度爲48/ (2*32 )=0.75Hz
該多相濾波器組爲如下圖:
這裏寫圖片描述

6.比例因子的取值和編碼:
  對各個子帶每12個樣點進行一次比例因子計算。先定出12個 樣點中絕對值的最大值。查比例因子表中比這個最大值大的 最小值作爲比例因子。用6比特表示。
  第2層的一幀對應36個子帶樣值,是第1層的三倍,原 則上要傳三個比例因子。爲了降低比例因子的傳輸碼率, 採用了利用人耳時域掩蔽特性的編碼策略:
  每幀中每個子帶的三個比例因子被一起考慮,劃分成 特定的幾種模式。根據這些模式,1個、2個或3個比例因 子和比例因子選擇信息(每子帶2比特)一起被傳送。如 果一個比例因子和下一個只有很小的差別,就只傳送大 的一個,這種情況對於穩態信號經常出現。
  使用這一算法後,和第1層相比,第2層傳輸的比例因 子平均減少了2個,即傳輸碼率由22.5Kb/s降低到了 7.5Kb/s。

7.比特分配及編碼:
  在調整到固定的碼率之前先確定可用於樣值編碼的有效比特數。這個數值取決於比例因子、比例因子選擇信息、比特分配信息 以及輔助數據所需比特數 。

比特分配的過程 :
1、對每個子帶計算掩蔽-噪聲比MNR,MNR = SNR –SMR (dB)
2、對最低MNR的子帶分配比特,使獲益最大的子帶的量化級別增加一級
3、重新計算分配了更多比特子帶的MNR
循環,直到沒有比特可用。使整幀和每個子帶的總噪聲—掩蔽比最小。第1層一幀用4比特給每個子帶的比特分配信 息編碼;而第2層只在低頻段用4比特,高頻 段則用2比特。

8.子帶樣值的量化和編碼:
(1)輸入以12個樣本爲一組,每組樣本經過時間-頻率變換 之後進行一次比特分配並記錄一個比例因子(scale factor)
(2)比特分配信息告訴解碼器每個樣本由幾位表示,比例因子用6比特表示,解碼器使用這個6比特的比例因子乘逆量化器的每個輸出樣本值,以恢復被量化的子帶 值。比例因子的作用是充分利用量化器的量化範圍, 通過比特分配和比例因子相配合,可以表示動態範圍超過120dB的樣本。
(3)第2層中,量化級別的數目隨子帶的不同而不同,但量化等級仍然覆蓋了3~65535的範圍,同時子帶不被分配給比特的概率增加了,沒有分配給比特的子帶就不被量化。低頻段的量化等級有15級,中頻段7級,高頻段只有3級。

二、關鍵代碼分析

實驗流程一再原理部分中說明,下面直接分析關鍵代碼。

#ifdef NEWENCODE
    sf_transmission_pattern (scalar, scfsi, &frame);
    main_bit_allocation_new (smr, scfsi, bit_alloc, &adb, &frame, &glopts);
    //main_bit_allocation (smr, scfsi, bit_alloc, &adb, &frame, &glopts);

    if (error_protection)
      CRC_calc (&frame, bit_alloc, scfsi, &crc);

    write_header (&frame, &bs);
    //encode_info (&frame, &bs);
    if (error_protection)
      putbits (&bs, crc, 16);
    write_bit_alloc (bit_alloc, &frame, &bs);
    //encode_bit_alloc (bit_alloc, &frame, &bs);
    write_scalefactors(bit_alloc, scfsi, scalar, &frame, &bs);
    //encode_scale (bit_alloc, scfsi, scalar, &frame, &bs);
    subband_quantization_new (scalar, *sb_sample, j_scale, *j_sample, bit_alloc,
                  *subband, &frame);
    //subband_quantization (scalar, *sb_sample, j_scale, *j_sample, bit_alloc,
    //    *subband, &frame);
    write_samples_new(*subband, bit_alloc, &frame, &bs);
    //sample_encoding (*subband, bit_alloc, &frame, &bs);
#else
/*add by Alfred*/
if(frameNum==200)
{
    int k,t,i;
    fprintf(result,"採樣率=%.1f khz\n",s_freq[header.version][header.sampling_frequency]);
    fprintf(result,"目標碼率=%d kbps\n", bitrate[header.version][header.bitrate_index]);
    fprintf(result,"第%d幀\n",frameNum);
    fprintf(result,"可用比特數=%d\n",adb);
    fprintf(result,"比例因子:\n");
    for(k=0;k<nch;k++)
    {
        fprintf(result,"聲道[%d]\n",k);
        for(i=0;i<frame.sblimit;i++)
        {
            fprintf(result,"子帶[%d]:",i);
            for(t=0;t<3;t++)
            {
                fprintf(result,"%d\t",scalar[k][t][i]);
            }
            fprintf(result,"\n");
        }
    }

}
/*end by Alfred*/
    transmission_pattern (scalar, scfsi, &frame);
    main_bit_allocation (smr, scfsi, bit_alloc, &adb, &frame, &glopts);
/*add by Alfred*/
if(frameNum==200)
{
    int k,i;
    fprintf(result,"比特分配:\n");
    for(k=0;k<nch;k++)
    {
        fprintf(result,"聲道[%d]\n",k);
        for(i=0;i<frame.sblimit;i++)
        {
            fprintf(result,"子帶[%d]:%d\n",i,bit_alloc[k][i]);

        }
    }
}
/*end by Alfred*/
    if (error_protection)
      CRC_calc (&frame, bit_alloc, scfsi, &crc);
    encode_info (&frame, &bs);
    if (error_protection)
      encode_CRC (crc, &bs);
    encode_bit_alloc (bit_alloc, &frame, &bs);
    encode_scale (bit_alloc, scfsi, scalar, &frame, &bs);
    subband_quantization (scalar, *sb_sample, j_scale, *j_sample, bit_alloc,
              *subband, &frame);
    sample_encoding (*subband, bit_alloc, &frame, &bs);

#endif

三、實驗結果

輸出一個“.txt”文件。
這裏寫圖片描述
這裏寫圖片描述這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章