久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2652|回復: 0
打印 上一主題 下一主題
收起左側

PCM數據以WAVE格式存到SD卡,程序源碼

[復制鏈接]
跳轉到指定樓層
樓主
ID:254724 發表于 2020-5-28 10:34 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
電話錄音采用什么文件格式?
小靈呼電話錄音系統LV包括呼叫中心系統的錄音功能均采用WAV格式作為文件存儲,其實WAV格式也分2、4倍壓縮率及線性無壓縮之分,參見電話錄音壓縮率說明,我們可以看到a率、u率、adpcm、8位pcm,16位pcm均可采用WAV格式存儲,可見采用WAV格式存儲并不一定很占空間,它還是可以采用壓縮格式的。
電話錄音采用WAV有什么好處?
WAV是Windows世界里最通用最流行的語音壓縮存儲格式,采用此格式存放錄音文件,可以被大多數播放軟件播放,而不局限于通過小靈呼軟件界面播放。
WAV文件格式介紹
文件是Windows標準的文件格式,WAV文件作為多媒體中使用的聲波文件格式之一,它是以RIFF格式為標準的。RIFF是英文Resource Interchange FileFormat的縮寫,每個WAV文件的頭四個字節便是“RIFF”。WAV文件由文件頭和數據體兩大部分組成。其中文件頭又分為RIFF/WAV文件標識段和聲音數據格式說明段兩部分。WAV文件各部分內容及格式見附表。常見的聲音文件主要有兩種,分別對應于單聲道(11.025KHz采樣率、8Bit的采樣值)和雙聲道(44.1KHz采樣率、16Bit的采樣值)。采樣率是指:聲音信號在“模→數”轉換過程中單位時間內采樣的次數。采樣值是指每一次采樣周期內聲音模擬信號的積分值。對于單聲道聲音文件,采樣數據為八位的短整數(short int 00H-FFH); 而對于雙聲道立體聲聲音文件,每次采樣數據為一個16位的整數(int),高八位和低八位分別代表左右兩個聲道。WAV文件數據塊包含以脈沖編碼調制(PCM)格式表示的樣本。WAV文件是由樣本組織而成的。在單聲道WAV文件中,聲道0代表左聲道,聲道1代表右聲道。在多聲道WAV文件中,樣本是交替出現的。
WAV文件格式說明表
文件頭
偏移地址
字節數
數據類型
內 容
00
H
4
char
"RIFF"標志
04
H
4
long
int 文件長度
08
H
4
char
"WAV"標志
0C
H
4
char
"fmt"標志
10
H
4


過渡字節(不定)
14
H
2
int
格式類別(10HPCM形式的聲音數據)
16
H
2
int
單聲道為1,雙聲道為2通道數
18
H
2
int
采樣率(每秒樣本數),表示每個通道的播放速度
1C
H
4
long
波形音頻數據傳送速率,其值為通道數×每秒數據位數×每樣 本的數據位數/8。播放軟件利用此值可以估計緩沖區的大小
22
H
2


每樣本的數據位數,表示每個聲道中各個樣本的數據位數。如果有多 個聲道,對每個聲道而言,樣本大小都一樣。 24H 4 char 數據標記符"data28H 4 long int 語音數據的長度
PCM數據的存放方式:
樣本1  樣本2
8位單聲道 0聲道 0聲道
8位立體聲 0聲道(左) 1聲道(右) 0聲道(左) 1聲道(右)
16位單聲道 0聲道低字節 0聲道高字節 0聲道低字節 0聲道高字節
16位立體聲 0聲道(左)低字節 0聲道(左)高字節 1聲道(右)低字節 1聲道(右)高字節
PCM數據的存放方式:
WAV文件的每個樣本值包含在一個整數i中,i的長度為容納指定樣本長度所需 的最小字節數。首先存儲低有效字節,表示樣本幅度的位放在i的高有效位上, 剩下的位置為0,這樣8位和16位的PCM波形樣本的數據格式如下所示。
樣本大小
數據格式
最大值
最小值
8PCM
unsigned int
225
0
16PCM
int
327
67
多媒體技術近年來發展很快,較好品質的聲卡可以提供16位的立體聲及44KHZ的播放錄制能力,它不僅可以提供原音逼真的取樣,其合成的音質也十分理想,有的聲卡還加入了數字信號處理器,可編程控制的DSP具有強大的運算能力,它可以用來作聲音信息的壓縮和一些特殊效果的處理。具有此功能的聲卡提供的WAV文件提供的語音信息可以滿足語音特征識別的要求。
RIFF概念
在Windows環境下,大部分的多媒體文件都依循著一種結構來存放信息,這種結構稱為"資源互換文件格式"(Resources lnterchange File Format),簡稱RIFF。例如聲音的WAV文件、視頻的AV1文件等等均是由此結構衍生出來的。RIFF可以看做是一種樹狀結構,其基本構成單位為chunk,猶如樹狀結構中的節點,每個chunk由"辨別碼"、"數據大小"及"數據"所組成。
塊的標志符(4BYTES)
數據大小 (4BYTES)
數據
                               圖一、 塊的結構示意圖
辨別碼由4個ASCII碼所構成,數據大小則標示出緊跟其后數據的長度(單位為Byte),而數據大小本身也用掉4個Byte,所以事實上一個chunk的長度為數據大小加8。一般而言,chunk本身并不允許內部再包含chunk,但有兩種例外,分別為以"RIFF"及"L1ST"為辨別碼的chunk。而針對此兩種chunk,RIFF又從原先的"數據"中切出4個Byte。 此4個Byte稱為"格式辨別碼",然而RIFF又規定文件中僅能有一個以"RIFF"為辨別碼的chunk。
RIFF/LIST標志符
數據1大小
數據1
格式/列表類型
數據
                               圖二、RIFF/LIST塊結構
只要依循此一結構的文件,我們均稱之為RIFF檔。此種結構提供了一種系統化的分類。如果和MS一DOS文件系統作比較,"RIFF"chunk就好比是一臺硬盤的根目錄,其格式辨別碼便是此硬盤的邏輯代碼(C:或D:),而"L1ST"chunk即為其下的子目錄,其他的chunk則為一般的文件。至于在RIFF文件的處理方面,微軟提供了相關的函數。視窗下的各種多媒體文件格式就如同在磁盤機下規定僅能放怎樣的目錄,而在該目錄下僅能放何種數據。
WAV文件格式
WAVE文件是非常簡單的一種RIFF文件,它的格式類型為"WAVE"。RIFF塊包含兩個子塊,這兩個子塊的ID分別是"fmt"和"data",其中"fmt"子塊由結構PCMWAVEFORMAT所組成,其子塊的大小就是sizeofof(PCMWAVEFORMAT),數據組成就是PCMWAVEFORMAT結構中的數據。
標志符(RIFF)
數據大小
格式類型("WAVE")
"fmt"
Sizeof(PCMWAVEFORMAT)
PCMWAVEFORMAT
"data"
聲音數據大小
聲音數據
                                                      圖三、WAVE文件結構
PCMWAVEFORMAT結構定義如下:
Typedef struct
{
     WAVEFORMAT wf;        /波形格式;
     WORD wBitsPerSample;    //WAVE文件的采樣大小;
} PCMWAVEFORMAT;

//WAVEFORMAT結構定義如下:
typedef struct
{
     WORD wFormatag;        //編碼格式,包括WAVE_FORMAT_PCM,WAVEFORMAT_ADPCM等
     WORD nChannls;        //聲道數,單聲道為1,雙聲道為2;
     DWORD nSamplesPerSec;    //采樣頻率;
     DWORD nAvgBytesperSec;    //每秒的數據量;
      WORD nBlockAlign;        //塊對齊;
} WAVEFORMAT;
"data"子塊包含WAVE文件的數字化波形聲音數據,其存放格式依賴于"fmt"子塊中wFormatTag成員指定的格式種類,在多聲道WAVE文件中,樣本是交替出現的。如16bit的單聲道WAVE文件和雙聲道WAVE文件的數據采樣格式分別如圖四所示:
16位單聲道:
采樣一
采樣二
……
低字節
高字節
低字節
高字節
……





16位雙聲道:
采樣一
……
左聲道
右聲道
……
低字節
高字節
低字節
高字節
……





                             圖四、WAVE文件數據采樣格式
WAV文件格式實例分析:


0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
00000000H
00000010H
00000020H
00000030H
00000040H
52  49  46  46  0A 06 01 00 57 41 56 45 66 6D 74 20
12 00 00 00 01 00 02 00 44 AC 00 00 10 B1 02 00
04 00 10 00 00 00 66 61 63 74 04 00 00 00 76 41
00 00 64 61 74 61 D8 05 01 00 00 00 00 00 FF FF
00 00 FE FF FE FF  00 00 00 00 FE FF FE FF 00 00


偏移地址
字節數
數據類型
內容






文件頭
00H
4
char
“RIFF”;   RIFF標志
04H
4
long int
0x00 01 06 0A(注意數據存儲順序);   文件長度
08H
4
char
“WAVE”;   WAVE標志
0CH
4
char
“fmt ”;   fmt標志,最后一位為空
10H
4
long int
0x12;   sizeof(PCMWAVEFORMAT)
14H
2
int
1(WAVE_FORMAT_PCM); 格式類別,1表示為PCM形式的聲音數據
16H
2
int
2; 通道數,單聲道為1,雙聲道為2
18H
2
int
44100; 采樣頻率(每秒樣本數)
1CH
4
long int
0x10B10000;   每秒數據量;其值為通道數×每秒數據位數×每樣本的數據位數/8。播放軟件利用此值可以估計緩沖區的大小。
20H
2
int
數據塊的調整數(按字節算的),其值為通道數×每樣本的數據位值/8。播放軟件需要一次處理多個該值大小的字節數據,以便將其值用于緩沖區的調整。
22H
2


每樣本的數據位數,表示每個聲道中各個樣本的數據位數。如果有多個聲道,對每個聲道而言,樣本大小都一樣。
50H
4
char
“data”;   數據標記符
54H
4
long int
0x00 01 05 D8;   語音數據大小
在Windows環境下,大部分的多媒體文件都依循著一種結構來存放信息,這種結構稱為"資源互換文件格式"(Resources lnterchange File Format),簡稱RIFF。例如聲音的WAV文件、視頻的AVI文件等等均是由此結構衍生出來的。RIFF可以看做是一種樹狀結構,其基本構成單位為chunk,猶如樹狀結構中的節點,每個chunk由"辨別碼"、"數據大小"及"數據"所組成。
  辨別碼由4個ASCII碼所構成,數據大小則標示出緊跟其后數據的長度(單位為Byte),而數據大小本身也用掉4個Byte,所以事實上一個chunk的長度為數據大小加8。一般而言,chunk本身并不允許內部再包含chunk,但有兩種例外,分別為以"RIFF"及"LIST"為辨別碼的chunk。而針對此兩種chunk,RIFF又從原先的"數據"中切出4個Byte。 此4個Byte稱為"格式辨別碼",然而RIFF又規定文件中僅能有一個以"RIFF"為辨別碼的chunk。
  只要依循此一結構的文件,我們均稱之為RIFF檔。此種結構提供了一種系統化的分類。如果和MS一DOS文件系統作比較,"RIFF"chunk就好比是一臺硬盤的根目錄,其格式辨別碼便是此硬盤的邏輯代碼(C:或D:),而"LIST"chunk即為其下的子目錄,其他的chunk則為一般的文件。至于在RIFF文件的處理方面,微軟提供了相關的函數。視窗下的各種多媒體文件格式就如同在磁盤機下規定僅能放怎樣的目錄,而在該目錄下僅能放何種數據。
  WAV為WAVEFORM(波形)的縮寫。在聲音文件的結構中,"RIFF"的格式辨別碼為"WAVE"。整個文件由兩個chunk所組成:辨別碼"fmt "(注意,后面有一個空格)及"data"。
  在"fmt "的chunk下包含了一個PCMWAVEFORMAT數據結構,其定義如下:
  typedef struct pcmwaveformat - tag {
  WAVEFORMAT wf ;
  WORD wBitsPerSample;
  } PCMWAVEFORMAT;
  typedef struct waveformat - tag {
  WORD wFormatTag ;
  WORD nChannels;
  DWORD nSamplesPerSec;
  DWORD nAvgBytesperSec;
  WORD nBlockAlign;
  } WAVEFORMAT;
  其意義分別為:
  wFormatTag:記錄著此聲音的格式代號,例如WAVE_FORMAT_PCM,WAVE_F0RAM_ADPCM等等。
  nChannels:記錄聲音的頻道數。
  nSamp1esPerSec:記錄每秒取樣數。
  nAvgBytesPerSec:記錄每秒的數據量。
  nBlockA1ign:記錄區塊的對齊單位。
  wBitsPerSample:記錄每個取樣所需的位元數。
  "data"Chunk包含真正的聲音數據。Window目前僅提供WAVE_FORMAT_PCM一種數據格式,所代表的意義是脈派編碼調變(Pu1se Code Modulation)。針對此格式,Windows定義了在"data"的chunk中數據的存放情形,圖2中列出了四種不同頻道數及取樣所需的位元數以及位元位置的安排。
  "RIFF" 頻道0 頻道0 頻道0 頻道0
  xxxx nChannels=1,wBitsPerSample=8
  "WAVE" 頻0(左) 頻道1(右) 頻道0(左) 頻道1 (右)
  "fmt "
  nChannels=2,wBitsPerSample=8
  sizeof(PCMWAVEFORMAT)
  struct of PCMWAVEFORMAT 頻道0(低位) 頻道0(高位) 頻道0(低位)頻道0(高位)
  "data" nChannels=1,wBitsPerSample=16
  xxxx 頻道0(低位) 頻道0(高位) 頻道0(低位)頻道0(高位)
  (低位) (高位) (低位) (高位)
  wave form data
  nChannels=2,wBitsPerSample=16
  圖1 WAV文件結構 圖2 PCM文件中位元安排方式
  第一排表示單聲道8位元,第二排表示雙聲道8位元,第三排表示單聲道16位元,第四排表示雙聲道16位元。8位元代表音量大小由8個位元所表示,16位元則代表音量大小由16個位元所表示。理論上8位元可以表示0~255,16位元可表示0~65536,不過windows卻定16位元其值的范圍從-32168~32167。此外尚有一點要注意的是,0并不一定代表無聲,而是由中間的數值來決定,也就是在8位元時為128,16位元時為0才是無聲。所以,若程序設計時需放入無聲的數據,糯特別注意聲音格式是16或是8位元,以放入適當的值。
WAV文件信息的具體應用
  WAV文件中包括了對原始聲音的高速率采樣,并且以WAVE_PCM_FORMAT脈派編碼調變格式,我們可以在VISUAL C++程序中實現,在讀出WAVEHDR文件頭之后,下面就是原始聲音的高速率采樣信息,我們可以對它作多方面的信息處理。
波形顯示。
  我們可以以時域-幅度的方式顯示出原始聲音的波形,這是最簡單同時也是最直接的信息處理方式。在時域范圍內,我們可以觀察該信號波形是否連續,中間是否有跳變等。
頻譜顯示
  我們可以以頻域-幅度的方式顯示出原始聲音的頻譜,在對原始信號經過FFT變換之后,可以得到該信號的頻譜,進而得到該信號的能量集中帶,分布特征,譜對稱系數等等。
用于語音信號識別
  講話者的個體識別是語音信號處理的一個重要內容,但它的一個前提條件是必須提供語音信號的數字波形,通常的方法是將原始的語音信號進行放大、抗混疊濾波、A/D采樣、數值編碼,最終得到語音信號的數字波形,通常多采用硬件處理,費時費力,如果我們借助非常成熟的聲卡技術,將WAV文件打開,就非常方便地得到語音信號的數字波形,為下一步進行語音信號識別提供良好的前端預處理。

單片機源程序如下:
  1. #include "wave.h"
  2. char wave_file[]="00_1942.wav";
  3. FIL waveFile;
  4. UINT wave_bw;
  5. u8 wave_top_table[44];
  6. //u32 wave_write_table[1024];

  7. FRESULT wavefileStatus;
  8. void wave_top_init(u8 select,int channels,int sample_rate,unsigned char *table,int num)
  9. {
  10.         WAVE_HEADER   pcmHEADER;  
  11.   WAVE_FMT   pcmFMT;  
  12.   WAVE_DATA   pcmDATA;  
  13.         u16 i,j=0;
  14.         u8 *p;
  15.         u8 CounterTimer=0;
  16.         CounterTimer=select;
  17.         wavefileStatus = f_open(&waveFile,(TCHAR const*)wave_file, FA_OPEN_ALWAYS | FA_WRITE |FA_READ );
  18.           if(FR_OK==wavefileStatus)
  19.           {
  20.                         //WAVE_HEADER
  21.       memcpy(pcmHEADER.fccID,"RIFF",strlen("RIFF"));   
  22.       if(CounterTimer==0)
  23.                         {                        
  24.       pcmHEADER.dwSize=44-8+num;        
  25.                         }
  26.                         else
  27.                         {
  28.                           pcmHEADER.dwSize=num+waveFile.obj.objsize-8;        
  29.                         }
  30.       memcpy(pcmHEADER.fccType,"WAVE",strlen("WAVE"));  
  31.             //WAVE_FMT
  32.             
  33.             memcpy(pcmFMT.fccID,"fmt ",strlen("fmt "));
  34.             pcmFMT.dwSize=16;                              
  35.             pcmFMT.wFormatTag=1;                          
  36.             pcmFMT.wChannels=channels;                     
  37.       pcmFMT.dwSamplesPerSec=sample_rate;           
  38.       pcmFMT.dwAvgBytesPerSec=channels*sample_rate*24/8;  
  39.             pcmFMT.wBlockAlign=1*24/8;            
  40.       pcmFMT.uiBitsPerSample=24;                     
  41.             
  42.       //WAVE_DATA;
  43.       memcpy(pcmDATA.fccID,"data",strlen("data"));  
  44.                         if(CounterTimer==0)
  45.                         {
  46.       pcmDATA.dwSize=num;
  47.                         }
  48.                         else
  49.                         {
  50.                            pcmDATA.dwSize=waveFile.obj.objsize-44+num;
  51.                         }
  52.                         //waveFile.obj.objsize=0;
  53.             j=0;
  54.             p=(u8*)(&pcmHEADER);
  55.             for(i=0;i<sizeof(WAVE_HEADER);i++)
  56.             {
  57.               wave_top_table[j++]=*p;
  58.                     p++;
  59.             }
  60.             p=(u8*)(&pcmFMT);
  61.             for(i=0;i<sizeof(WAVE_FMT);i++)
  62.             {
  63.               wave_top_table[j++]=*p;
  64.                     p++;
  65.             }
  66.             p=(u8*)(&pcmDATA);
  67.             for(i=0;i<sizeof(WAVE_DATA);i++)
  68.             {
  69.               wave_top_table[j++]=*p;
  70.                     p++;
  71.             }  
  72.                         
  73.             f_lseek (&waveFile,0);
  74.             f_write(&waveFile, (const void*)wave_top_table, 44, &wave_bw);
  75.                         f_sync (&waveFile);
  76.                         
  77.       f_lseek (&waveFile,waveFile.obj.objsize);
  78.                         f_write(&waveFile, (const void*)table, num, &wave_bw);
  79.                         f_sync (&waveFile);
  80.             f_close(&waveFile);
  81.         }
  82. }
復制代碼

頭文件51hei提供下載:
PCM轉wave存到sd卡.rar (1.33 KB, 下載次數: 21)

評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 91精品久久久久久综合五月天 | 成人精品一区 | 日韩午夜场 | 一区二区中文字幕 | 狠狠干狠狠操 | 999www视频免费观看 | 国产精品成人一区 | 91av久久久 | 欧美一级欧美三级在线观看 | 91精品国产日韩91久久久久久 | 免费一级大片 | 亚洲国产精品99久久久久久久久 | 精品熟人一区二区三区四区 | 国产综合精品一区二区三区 | 特黄色毛片 | 欧美日韩精品专区 | 一级片av| 亚洲韩国精品 | 男女午夜激情视频 | 玖玖色在线视频 | 区一区二在线观看 | 天天干夜夜拍 | 国产精品久久久久免费 | 亚洲1区 | 看a级黄色毛片 | 毛片国产 | 尤物在线精品视频 | 国内久久| 涩涩视频网站在线观看 | 在线精品观看 | 欧美一级二级三级 | 色婷婷av一区二区三区软件 | 国产成人精品久久二区二区91 | 久久伊人免费视频 | 久久久成人精品 | 少妇一级淫片免费放播放 | 有码在线| 亚洲国产中文字幕 | 久久久久国产一区二区三区 | 男女爱爱网站 | 欧美天堂一区 |