【轉】Python處理wave檔案

來源:互聯網
上載者:User

標籤:數組   tps   電腦   其他   mst   sof   cloud   ali   ibm   

#本文PDF版下載

Python解析Wav檔案並繪製波形的方法

#本文代碼下載

Wav波形繪圖代碼

#本文執行個體音頻檔案night.wav下載

音頻檔案下載 (石進-夜的鋼琴曲)

前言

在現在繁忙的生活中,我們經常會聽些歌來放鬆一下自己,我們經常會從各種播放軟體中聽自己喜歡的歌,並且往往我們會下載一部分歌曲,而現在音訊種類也相當繁多,像是Wav,Mp3,FLAC,AAC等等很多格式,最近由於需要做一個能夠分析Wav格式音訊波形來取得一些資料比如擷取人錄音時是否說完等等用途.本周先對解析Wav並用Python繪製其波形進行了一些探索.

 

Wav檔案格式

我們先來看看wikipedia上對於wav音頻格式的解釋:

「Waveform Audio File Format(WAVE,又或者是因為副檔名而被福士所知的WAV),是微軟與IBM公司所開發在個人電腦儲存音頻流的編碼格式,在Windows平台的應用軟體受到廣泛的支援,地位上類似於麥金塔電腦裡的AIFF.此格式屬於資源交換檔案格式(RIFF)的應用之一,通常會將採用脈衝編碼調製的音頻資儲存在區塊中。也是其音樂發燒友中常用的指定規格之一.由於此音頻格式未經過壓縮,所以在音質方面不會出現失真的情況,但檔案的體積因而在眾多音頻格式中較為大.」

我們可以看到上面提到了兩個個關鍵詞RIFF和脈衝編碼調製.所以我們接下來先解釋一下 RIFF「資源交換檔案格式」是什麼.

 RIFF格式

我們同樣的來看一下wikipedia對RIFF的解釋
「 Resource Interchange File Format(簡稱RIFF),資源分頁檔格式,是一種按照標記區Block Storage資料(tagged chunks)的通用檔案儲存體格式,多用於儲存音頻、視頻等多媒體資料.Microsoft在windows下的AVI、ANI 、WAV等都是基於RIFF實現的.

RIFF是由Microsoft和IBM於1991年,在windows 3.1中引入的,作為windows 3.1預設的多媒體檔案格式。RIFF是參考Interchange File Format來的,二者主要的區別是位元組序大端、小端的問題.在基於IBM的80x86系列主機下,RIFF的位元組序是小端的;而在IFF原有的格式中是按照大端儲存整型資料的.」

RIFF是由chunk構成的,chunk是RIFF組成的基本單位,每個CHUNK可看作存貯了視頻的一幀資料或者是音訊一幀資料,所以下面我們來討論一下chunk的結構是怎麼樣的.

CHUNK的結構

CHUNK總共由三個部分組成:

  • FOURCC   使用4位元組的ASIIC字元標識類型
  • SIZE            資料的大小
  • DATA          用於存放資料

結構如下:

           CHUNK的結構

  • CHUNK在一般情況下不能嵌套,但是當CHUNK的FOURCC為“RIFF”或者是“LIST”的時候可以嵌套資料.
  • “RIFF”的第一個CHUNK的FOURCC一定是“RIFF”,所以LIST為FOURCC的一定是子CHUNK及SUBCHUNK.

下面是一個包含了子CHUNK的結構:

 

       包含了SUBCHUNK的結構

  •  “RIFF”的CHUNK在DATA地區的前四個位元組稱為“Form Type”記錄了資料的類型,比如我們的wav檔案的Form Type就是“WAV”

Form Type結構如下:

 

      包含了Form Type的結構 

  • 同樣的FOURCC為LIST的 SUBCHUNK 的DATA地區也包含了LIST Type,用於表示LIST中資料區域格式
脈衝編碼調製(PCM)

我們先來看看百度百科對它的解釋:
「PCM 脈衝編碼調製是Pulse Code Modulation的縮寫,脈衝編碼調製是數字通訊的編碼方式之一.主要過程是將話音、映像等類比訊號每隔一定時間進行取樣,使其離散化,同時將抽樣值按分層單位四捨五入取整量化,同時將抽樣值按一組二進位碼來表示抽樣脈衝的幅值.」
我們從上面的介紹可以理解為:
通過三個過程-抽樣、量化和編碼講音訊類比訊號轉化為數字訊號.

抽樣

抽樣是由於類比訊號是連續的,通過一定頻率對類比訊號進行取樣,近似得到,如下面的圖中灰色框中就是取了一定頻率進行抽樣的:

                           抽樣過程

  • 抽樣是要將類比訊號以其訊號頻寬2倍以上的頻率提取樣值,變為在時間軸上*離散*的抽樣訊號,就可獲得能取代原來連續音頻訊號的抽樣訊號.對一個正弦訊號進行抽樣獲得的抽樣訊號是一個脈衝幅度調製(PAM)訊號,之後對抽樣訊號進行檢波和平滑濾波,即可還原出原來的類比訊號.
量化

抽樣訊號離散的類比訊號,其取樣的值在一定的取值範圍內,由無限多種值可能性存在.為了實現以數字碼錶示樣值,我們採用“四捨五入”的方法把樣值分級“取整”,使一定取值範圍內的樣值由無限多個值變為有限個值.

編碼

量化後的抽樣訊號在一定的取值範圍內僅有有限個可取的樣值,且訊號正、負幅度分布的對稱性使正、負樣值的個數相等,正、負向的量化級對稱分布

WAV檔案的CHUNK資訊

WAVE檔案是由若干個CHUNK組成的.按照檔案中CHUNK的出現順序分別為:RIFF Chunk, Format Chunk, Fact Chunk, Data Chunk,其中的Fact CHUNK為非必要部分,結構具體如所示:

 

              WAV檔案標頭檔的CHUNK組成

RIFF是頭CHUNK,而Format CHUNK裡面記錄了WAV的各種參數資訊,詳細參數資訊如下:

  • FormatTag            音頻資料的編碼方式,其中PCM方式為1
  • Channels               聲道數,單聲道為1,雙聲道為2
  • SamplesPerSec    採樣率(每秒樣本數)
  • BytesPerSec*        音頻資料傳送速率
  • BlockAlign*           每次採樣的大小
  • BitsPerSample*    每個聲道的採樣精度

而FACT CHUNK的作用是因為有些並沒有使用PCM格式,所以需要一個FACT CHUNK記錄資料解壓縮資料大小.
最後的DATA塊中裝的是真正的聲音資料.一般按照WAVE_FORMAT_PCM的資料格式存貯,即脈衝編碼調製PCM.

WAV的DATA部分

DATA塊內的資訊是根據format chunk內的資訊而決定的.由量化位元/聲道數/採樣率共同決定,為四種情況下DATA地區儲存資訊的格式:

                               DATA CHUNK的格式

Python讀取WAV檔案的資訊

在python中,我們可以直接通過許多音訊庫對wav檔案進行操作,比如內建的標準庫wave庫,還有如eyeD3,PyAudio,Audacity等等.我們先不介紹這種方式,我們先通過傳統的檔案操作以二進位的形式讀取Wav檔案,來分析一下它的標頭檔來驗證一下我們前面有關CHUNK所學的知識.通過二進位操作音頻檔案並取得前四個位元組的代碼如下:(我們的測試音頻是night.wav,已放在github中,通過我的部落格園右上方的綠色表徵圖可以連結到我的github介面,找到lab102下的w8目錄即可擷取該資源,或者找到本文部落格園最上方資源):

#讀取wav前四個位元組內容  -xlxwfile = open("night.wav", "rb")s = file.read(4)print(s)

程式運行:

 

我們可以看到最前面的位元組和我們認為的沒錯,是RIFF,那我們來讀取44個位元組來看看其中的資訊是怎麼樣的:

#讀取wav前44個位元組內容  -xlxwfile = open("night.wav", "rb")s = file.read(44)print(s)

程式運行:

我們可以看到RIFF後面的字串為WAVE的Form Type,以及fmt,data這幾個FOURCC,而其他用十六進位表示的就是資料大小/資料了.所以我們通過二進位讀取的WAV檔案的資訊和我們前面學習的CHUNK中的內容是一致的.

用Wave庫提取wav檔案資訊

在我們前面中的介紹可以知道wav檔案的儲存方式,並且能夠簡單的提取其中的資訊了,而我們知道wav檔案最重要的就是聲音資訊的存貯,這一部分我們也可以通過對CHUNK的DATA 進行分析,不過我們在python中有更加簡單的獲得聲音的方式,那就是利用python內建的wave庫,我們下面就來介紹一下wave庫的一些方法,為後文做鋪墊.

  • 首先引入wave庫
import wave
  •  open()

開啟一個音效檔,使用方法wave.open(音效檔地址,模式)
其中音效檔地址就是wav檔案位置,模式和檔案讀寫差不多,如“wb”-唯寫;“rb”-唯讀方式 b代表以二進位模式開啟.

  • close()

關閉音效檔

  • getparams()

擷取wav檔案的參數(以tuple形式輸出),依次為(聲道數,採樣精度,採樣率,幀數,......)
如為本文例子night.wav的getparams()的資訊:

 

  • readframes()

得到每一幀的聲音資料,返回的值是位元據,在python中用字串表示位元據,如,所以我們後面要進行轉化.
得到的night.wav的前10幀的資料如所示:

 

上面就基本上是wave庫的常用方法了.下面會對此進行應用了.

 

繪製WAV檔案的波形

我們經常在許多聲音軟體,比如CoolEdit,Audition等軟體中能看到音效檔的波形,所以我們在這裡利用Python以及前面介紹的wave庫,輔以numpy,Matplotlib來嘗試繪製night.wav檔案的波形.
下面我們來簡單講述一下繪製波形的步驟:(以night.wav為例子)

  1. 通過wav庫獲得night.wav的標頭檔中的資訊,如採樣率/聲道數等等.
  2. 提取出DATA地區的資訊,用numpy將string格式資料轉化為數組
  3. 通過判定聲道數將DATA地區資料進行處理(對數組矩陣進行轉換)
  4. 得到每個繪製點的時間(x座標)
  5. 用matplotlib庫提供的方法繪製出波形圖

我們來對這些步驟中的一些部分詳細說一下:

對DATA地區的處理

因為night.wav是一個雙聲道的WAV 檔案,我們從上文對DATA地區格式的介紹可以知道儲存形式是左聲道/右聲道的形式存貯資料,所以在這裡我們要對提取出的資料進行處理,這裡numpy庫為我們提供了很好的解決方案,我們主要用到了改變形狀的Shape方法以及T轉置方法,我們在這裡來舉一個例子:
我們建立一個數組[1,2,3,4,5,6,7,8]裡面有8個元素,這時候根據我們的分離方法,應該分為左聲道[1,3,5,7]和右[2,4,6,8],我們可以通過shape先改變矩陣的形狀使資料變為兩列分別為左右聲道,再通過轉置得到最終資料,我們的例子可以用如所示理解:

 

            將資料分為左右聲道的例子

繪製波形圖的matplotlib庫

這裡我們要繪出波形,所以用matplotlib庫大大減少我們的繪圖難度,我們主要用到plt.subplot和plt.plot這兩個方法,所以我們對這兩個方法進行解釋.

  •  plt.subplot()

這是用於matplotlib繪製多個子圖的方法,因為我們這裡音頻檔案要分為兩個部分(左聲道/右聲道)
即分成2X1的形式,所以我們的第一個繪圖和第二個繪圖分別用
plt.subplot(211)和plt.subplot(212)來表示,如所示:

                  matplotlib子圖

  • plt.plot

plt.plot()是用於繪製線條的方法,我們用到了其中的三個參數
(X座標,y座標,顏色)
就能用plot畫出最終的波形圖了

  • 其他的方法這裡就不介紹了,但是matplotlib的繪圖功能相當強大.

 

繪製night.wav波形的代碼

用於繪製出wav檔案波形的代碼如下(這裡我們還是以night.wav作為例子)

#wave data   -xlxw#importimport wave as weimport numpy as npimport matplotlib.pyplot as pltdef wavread(path):    wavfile =  we.open(path,"rb")    params = wavfile.getparams()    framesra,frameswav= params[2],params[3]    datawav = wavfile.readframes(frameswav)    wavfile.close()    datause = np.fromstring(datawav,dtype = np.short)    datause.shape = -1,2    datause = datause.T    time = np.arange(0, frameswav) * (1.0/framesra)    return datause,timedef main():    path = input("The Path is:")    wavdata,wavtime = wavread(path)    plt.title("Night.wav‘s Frames")    plt.subplot(211)    plt.plot(wavtime, wavdata[0],color = ‘green‘)    plt.subplot(212)    plt.plot(wavtime, wavdata[1])    plt.show()    main()

程式繪製出的波形圖的:

 

                     night.wav音效檔的雙聲道波形

總結&拓展

在本周我學到了wav檔案的存貯格式以及怎麼用python讀取wav檔案資訊並且繪製出波形圖.其中在繪製了波形圖後,我們可以對波形多透露出的資訊進行分析,比如:

  • 得到聲音的特徵
  • 分析錄音時被錄音者是否停止說話

等等用途,可以用於許多方面,如聲音識別,斷句(音頻分割)等等許多的情境.這裡在以後我也會繼續進行探索.

【轉】Python處理wave檔案

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.