音頻處理 (一) 音頻文件

音頻文件算法

   音頻文件是對聲音進行數字轉換以後存放的數據文件,瞭解音頻數據必須先知道幾個重要概念。ide

1. 採樣:對聲音信息錄入時,行進的最小操做單位,通常一次採樣具備左右2個聲道,每一個聲道用1或2個字節來存儲;this

這樣採樣的量化位數是8位,或16位(樣本位寬),量化位數越高聲音音質越好;就像11位電話號碼錶示的號碼比7位要多得多;編碼

2. 採樣頻率:每秒採樣次數,單位Hz,通常的音頻文件有11.025kHz22.05kHz44.10kHz等;顯然,這種模-數信息的轉換,每秒採樣次數越多,聲音就越精確;spa

3. 碼率:每秒編碼的bit數,單位是kb/s;計算方式:位寬×聲道數×採樣頻率;(單位是bit不是字節)指針

4. 聲道數,固定值爲1-單聲道,或者2-雙聲道,雙聲道時,每一個採樣樣本中包含左聲道、右聲道的音頻數據,所以二者的數據是交錯排列的;code

 

 (一)Wave 格式orm

    WAVE是微軟開發的聲音文件格式,用於保存Windows平臺的音頻信息資源,文件後綴名*.wav;支持多種壓縮算法、多種音頻位數、採樣頻率和聲道;blog

    標準的wav文件採用44.1kHz採樣頻率,16位量化位數,聲音文件質量幾與CD至關;Wave格式不對源數據作任何處理,若是源數據是無損的,編碼後的Wav文件也是無損的;若是源數據是有損的,編碼後的Wav文件也是有損的;資源

1. Wave文件的構成:

RIFF 標 志 4B "RIFF"
數據大小 4B -
格式 4B "WAVE"
fmt 標誌 4B "fmt "
結構體大小 4B 16/18
結構體 16B/18B  
data 標誌 4B "data"
聲音數據大小 4B -
data -

 

 

 

 

 

 

 

 

 

 

 

 

 

2. Wave文件的詳細結構:

// RIFF 標準媒體流文件頭
struct Riff_Header {
char szRiffId[4]; // 'R','I','F','F' DWORD dwRiffSize; // Size, 除了這 8 個字節以外,文件剩餘大小,等於文件總字節數-8 char szRiffFormat[4]; // 'W','A','V','E' }; struct Fmt_Block { char szFmtId[4]; // 'f', 'm', 't',' ' DWORD dwFmtSize; // Size 爲 16 或 18 WORD wFormatTag; // 編碼方式,通常爲 0x0001 WORD wChannels; // 聲道數 1--單聲道 2--雙聲道 DWORD dwSamplesPerSec; // 採樣頻率 /Hz DWORD dwAvgBytesPerSec; // 每秒字節數 WORD wBlockAlign; // 數據塊對齊單位(每一個採樣須要的字節數) WORD wBitsPerSample; // 每一個採樣須要的 bit // WORD wBits; // 可能有可能沒有,由dwFmtSize字段決定 }; //Fact_Block 塊,有些 wav 文件中沒有 struct Fact_Block { char szFactId[4]; // 'f','a','c','t' DWORD dwFactSize; // }; //數據塊 struct Data_Block { char szDataId[4]; //'d','a,','t','a' DWORD dwDataSize; // 音頻數據大小 //data ... };

 說明:

(1)  RIFF塊裏面的 dwRiffSize 表示的是整個文件除開頭8個字節以外的大小0x24 0xCD 0x01 0x00,即 118,052 Byte,經過文件屬性查得文件大小是118,060Byte;

(2)  dwFmtSize 0x10 0x00 0x00 0x00,即爲16;fmt塊的剩餘部分是一個波形信息結構,是微軟定義的:

/*
 *  extended waveform format structure used for all non-PCM formats. this
 *  structure is common to all non-PCM formats.
 */
typedef struct tWAVEFORMATEX
{
    WORD        wFormatTag;         /* format type */
    WORD        nChannels;          /* number of channels (i.e. mono, stereo...) */
    DWORD       nSamplesPerSec;     /* sample rate */
    DWORD       nAvgBytesPerSec;    /* for buffer estimation */
    WORD        nBlockAlign;        /* block size of data */
    WORD        wBitsPerSample;     /* number of bits per sample of mono data */
    WORD        cbSize;             /* the count in bytes of the size of */
                                                                                      /* extra information (after cbSize) */
} WAVEFORMATEX, *PWAVEFORMATEX, NEAR *NPWAVEFORMATEX, FAR *LPWAVEFORMATEX;
WAVEFORMATEX

(3)  Data塊:dwDataSize表示音頻數據的大小,0x00 0x01 0xCD 0x00,即118,016,略小於118,052,說明文件末有部分無效數據

 一個示例:

//
// 讀取Wav文件頭,並驗證文件格式
// 成功返回文件句柄,並重定位文件指針到數據區
// 失敗返回NULL
//
HANDLE ReadHeader(char* path)
{
    HANDLE hFile = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);

    if (hFile == INVALID_HANDLE_VALUE)
    {
        printf("Unable to Open File!");
        return NULL;
    }
    char buffer[512];
    DWORD readByte;
    if (ReadFile(hFile, buffer, sizeof(buffer), &readByte, NULL))
    {
        Riff_Header header;
        Fmt_Block fmt;
        Data_Block data;
        memcpy(&header, buffer, sizeof(Riff_Header));
        if (strncmp(header.szRiffId, "RIFF", 4) != 0) {CloseHandle(hFile); return NULL;}

        memcpy(&fmt, buffer + sizeof(Riff_Header), sizeof(Fmt_Block));
        if (strncmp(fmt.szFmtId, "fmt ", 4) != 0) {CloseHandle(hFile);return NULL;}

        memcpy(&data, buffer + sizeof(Riff_Header)+fmt.dwFmtSize+8, sizeof(Data_Block));
        if (strncmp(data.szDataId, "data", 4) != 0) {CloseHandle(hFile);return NULL;}

        memcpy(&wfx, &fmt.wFormatTag, sizeof(WAVEFORMATEX) - 2);
        wfx.cbSize = 0;

        // 重定位文件指針,到數據起始位置
        int headSize = sizeof(Riff_Header) + fmt.dwFmtSize + 8 + sizeof(Data_Block);
headSize = (headSize/8 + (headSize%8?1:0))*8; SetFilePointer(hFile,
headSize, 0, FILE_BEGIN); return hFile; } return NULL; }

說明:1. 這裏沒有考慮fact結構存在的狀況;2. 調用ReadHeader()以後wfx結構同時也填充完畢,能夠用於打開音頻設備,進行wav音頻播放;

其調用以下:

#include "stdafx.h"
#include <Windows.h>
#include <mmsystem.h>
#include "WavStruct.h"

#pragma comment(lib, "winmm.lib")

const char testWave = "C:/Windows/Media/Ring02.wav"; WAVEFORMATEX wfx;
int main(int argc, char* argv[]) { HANDLE hFile = ReadHeader((char*)testWave); if (hFile == NULL) return 0; CloseHandle(hFile); return 0; }

結果:

 

 (二) MP3格式

     MP3格式(待續 ...)

相關文章
相關標籤/搜索