音訊編解碼·實戰篇(1)WAV轉至AAC(AAC編碼)

鍾超發表於2012-04-07

音訊編解碼·實戰篇(1)WAV轉至AAC(AAC編碼)

  • 作者:柳大·Poechant
  • 部落格:blog.csdn.net/poechant
  • 郵箱:zhongchao.ustc@gmail.com
  • 日期:April 7th, 2012

這裡利用FAAC來實現AAC編碼。另外,WAV的資料段是PCM,程式碼會出現很多PCM縮寫。

1 下載安裝 FAAC

這裡的安裝過程是在 Mac 和 Linux 上實現的,Windows可以類似參考。

wget http://downloads.sourceforge.net/faac/faac-1.28.tar.gz
tar zxvf faac-1.28.tar.gz
cd faac-1.28
./configure
make
sudo make install

如果才用預設的 configure 中的 prefix path,那麼安裝後的 lib 和 .h 檔案分別在/usr/local/lib/usr/local/include,後面編譯的時候會用到。

2 FAAC API

2.1 Open FAAC engine

Prototype:

faacEncHandle faacEncOpen               // 返回一個FAAC的handle
(                   
    unsigned long   nSampleRate,        // 取樣率,單位是bps
    unsigned long   nChannels,          // 聲道,1為單聲道,2為雙聲道
    unsigned long   &nInputSamples,     // 傳引用,得到每次呼叫編碼時所應接收的原始資料長度
    unsigned long   &nMaxOutputBytes    // 傳引用,得到每次呼叫編碼時生成的AAC資料的最大長度
);

2.2 Get/Set encoding configuration

Prototype:

獲取編碼器的配置:

faacEncConfigurationPtr faacEncGetCurrentConfiguration // 得到指向當前編碼器配置的指標
(
    faacEncHandle hEncoder  // FAAC的handle
);

設定編碼器的配置:

int FAACAPI faacEncSetConfiguration
(
    faacDecHandle hDecoder,         // 此前得到的FAAC的handle
    faacEncConfigurationPtr config  // FAAC編碼器的配置
);

2.3 Encode

Prototype:

int faacEncEncode
(
    faacEncHandle hEncoder,     // FAAC的handle
    short *inputBuffer,         // WAV原始資料
    unsigned int samplesInput,  // 呼叫faacEncOpen時得到的nInputSamples值
    unsigned char *outputBuffer,// 至少具有呼叫faacEncOpen時得到的nMaxOutputBytes位元組長度的緩衝區
    unsigned int bufferSize     // outputBuffer緩衝區的實際大小
);

2.4 Close FAAC engine

Prototype

void faacEncClose
(
    faacEncHandle hEncoder  // 此前得到的FAAC handle
);

3 流程

3.1 做什麼準備?

取樣率,聲道數(雙聲道還是單聲道?),還有你的WAV的單個樣本是8位的還是16位的?

3.2 開啟FAAC編碼器,做編碼前的準備

  1. 呼叫faacEncOpen開啟FAAC編碼器後,得到了單次輸入樣本數nInputSamples和輸出資料最大位元組數nMaxOutputBytes
  2. 根據nInputSamplesnMaxOutputBytes,分別為WAV資料和將要得到的AAC資料建立緩衝區;
  3. 呼叫faacEncGetCurrentConfiguration獲取當前配置,修改完配置後,呼叫faacEncSetConfiguration設定新配置。

3.3 開始編碼

呼叫faacEncEncode,該準備的剛才都準備好了,很簡單。

3.4 善後

關閉編碼器,另外別忘了釋放緩衝區,如果使用了檔案流,也別忘記了關閉。

4 測試程式

4.1 完整程式碼

WAV格式音訊檔案/home/michael/Development/testspace/in.wav轉至AAC格式檔案/home/michael/Development/testspace/out.aac

#include <faac.h>
#include <stdio.h>

typedef unsigned long   ULONG;
typedef unsigned int    UINT;
typedef unsigned char   BYTE;
typedef char            _TCHAR;

int main(int argc, _TCHAR* argv[])
{
    ULONG nSampleRate = 11025;  // 取樣率
    UINT nChannels = 1;         // 聲道數
    UINT nPCMBitSize = 16;      // 單樣本位數
    ULONG nInputSamples = 0;
    ULONG nMaxOutputBytes = 0;

    int nRet;
    faacEncHandle hEncoder;
    faacEncConfigurationPtr pConfiguration; 

    int nBytesRead;
    int nPCMBufferSize;
    BYTE* pbPCMBuffer;
    BYTE* pbAACBuffer;

    FILE* fpIn; // WAV file for input
    FILE* fpOut; // AAC file for output

    fpIn = fopen("/home/michael/Development/testspace/in.wav", "rb");
    fpOut = fopen("/home/michael/Development/testspace/out.aac", "wb");

    // (1) Open FAAC engine
    hEncoder = faacEncOpen(nSampleRate, nChannels, &nInputSamples, &nMaxOutputBytes);
    if(hEncoder == NULL)
    {
        printf("[ERROR] Failed to call faacEncOpen()\n");
        return -1;
    }

    nPCMBufferSize = nInputSamples * nPCMBitSize / 8;
    pbPCMBuffer = new BYTE [nPCMBufferSize];
    pbAACBuffer = new BYTE [nMaxOutputBytes];

    // (2.1) Get current encoding configuration
    pConfiguration = faacEncGetCurrentConfiguration(hEncoder);
    pConfiguration->inputFormat = FAAC_INPUT_16BIT;

    // (2.2) Set encoding configuration
    nRet = faacEncSetConfiguration(hEncoder, pConfiguration);

    for(int i = 0; 1; i++)
    {
        // 讀入的實際位元組數,最大不會超過nPCMBufferSize,一般只有讀到檔案尾時才不是這個值
        nBytesRead = fread(pbPCMBuffer, 1, nPCMBufferSize, fpIn);

        // 輸入樣本數,用實際讀入位元組數計算,一般只有讀到檔案尾時才不是nPCMBufferSize/(nPCMBitSize/8);
        nInputSamples = nBytesRead / (nPCMBitSize / 8);

        // (3) Encode
        nRet = faacEncEncode(
        hEncoder, (int*) pbPCMBuffer, nInputSamples, pbAACBuffer, nMaxOutputBytes);

        fwrite(pbAACBuffer, 1, nRet, fpOut);

        printf("%d: faacEncEncode returns %d\n", i, nRet);

        if(nBytesRead <= 0)
        {
            break;
        }
    }

    /*
    while(1)
    {
        // (3) Flushing
        nRet = faacEncEncode(
        hEncoder, (int*) pbPCMBuffer, 0, pbAACBuffer, nMaxOutputBytes);

        if(nRet <= 0)
        {
            break;
        }
    }
    */

    // (4) Close FAAC engine
    nRet = faacEncClose(hEncoder);

    delete[] pbPCMBuffer;
    delete[] pbAACBuffer;
    fclose(fpIn);
    fclose(fpOut);

    //getchar();

    return 0;
}

4.2 編譯執行

將上述程式碼儲存為“wav2aac.cpp”檔案,然後編譯:

g++ wav2aac.cpp -o wav2aac -L/usr/local/lib -lfaac -I/usr/local/include

執行:

./wav2aac

然後就生成了out.aac檔案了,聽聽看吧!~

5 Reference

  1. AudioCoding.com - FAAC
  2. Dogfoot – 재밌는 개발

-

轉載請註明來自柳大的CSDN部落格:blog.csdn.net/poechant

-

相關文章