<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 聲音的輸入輸出 在本章我們將學習如何讀寫WAV文件,如何利用聲卡實時地進行聲音的輸入輸出。標準的Python已經支持WAV文件的讀寫,而實時的聲音輸入輸出需要安裝pyAudio([http://people.csail.mit.edu/hubert/pyaudio](http://people.csail.mit.edu/hubert/pyaudio))。最后我們還將看看如何使用pyMedia([http://pymedia.org](http://pymedia.org))進行Mp3的解碼和播放。 掌握了上面的基礎知識之后,就可以做許多有趣的聲效處理的算法實驗了。聲效處理方面的內容將在以后的章節詳細介紹。 ## 讀寫Wave文件 WAV是Microsoft開發的一種聲音文件格式,雖然它支持多種壓縮格式,不過它通常被用來保存未壓縮的聲音數據(PCM脈沖編碼調制)。WAV有三個重要的參數:聲道數、取樣頻率和量化位數。 * 聲道數:可以是單聲道或者是雙聲道 * 采樣頻率:一秒內對聲音信號的采集次數,常用的有8kHz, 16kHz, 32kHz, 48kHz, 11.025kHz, 22.05kHz, 44.1kHz * 量化位數:用多少bit表達一次采樣所采集的數據,通常有8bit、16bit、24bit和32bit等幾種 例如CD中所儲存的聲音信號是雙聲道、44.1kHz、16bit。 如果你需要自己錄制和編輯聲音文件,推薦使用Audacity([http://audacity.sourceforge.net](http://audacity.sourceforge.net)),它是一款開源的、跨平臺、多聲道的錄音編輯軟件。在我的工作中經常使用Audacity進行聲音信號的錄制,然后再輸出成WAV文件供Python程序處理。 ### 讀Wave文件 下面讓我們來看看如何在Python中讀寫聲音文件: ``` # -*- coding: utf-8 -*- import wave import pylab as pl import numpy as np # 打開WAV文檔 f = wave.open(r"c:\WINDOWS\Media\ding.wav", "rb") # 讀取格式信息 # (nchannels, sampwidth, framerate, nframes, comptype, compname) params = f.getparams() nchannels, sampwidth, framerate, nframes = params[:4] # 讀取波形數據 str_data = f.readframes(nframes) f.close() #將波形數據轉換為數組 wave_data = np.fromstring(str_data, dtype=np.short) wave_data.shape = -1, 2 wave_data = wave_data.T time = np.arange(0, nframes) * (1.0 / framerate) # 繪制波形 pl.subplot(211) pl.plot(time, wave_data[0]) pl.subplot(212) pl.plot(time, wave_data[1], c="g") pl.xlabel("time (seconds)") pl.show() ``` ![](https://box.kancloud.cn/2016-03-19_56ed1bafe0283.png) WindowsXP的經典"叮"聲的波形 首先載入Python的標準處理WAV文件的模塊,然后調用wave.open打開wav文件,注意需要使用"rb"(二進制模式)打開文件: ``` import wave f = wave.open(r"c:\WINDOWS\Media\ding.wav", "rb") ``` open返回一個的是一個Wave_read類的實例,通過調用它的方法讀取WAV文件的格式和數據: * getparams:一次性返回所有的WAV文件的格式信息,它返回的是一個組元(tuple):聲道數, 量化位數(byte單位), 采樣頻率, 采樣點數, 壓縮類型, 壓縮類型的描述。wave模塊只支持非壓縮的數據,因此可以忽略最后兩個信息: ``` params = f.getparams() nchannels, sampwidth, framerate, nframes = params[:4] ``` * getnchannels, getsampwidth, getframerate, getnframes等方法可以單獨返回WAV文件的特定的信息。 * readframes:讀取聲音數據,傳遞一個參數指定需要讀取的長度(以取樣點為單位),readframes返回的是二進制數據(一大堆bytes),在Python中用字符串表示二進制數據: ``` str_data = f.readframes(nframes) ``` 接下來需要根據聲道數和量化單位,將讀取的二進制數據轉換為一個可以計算的數組: ``` wave_data = np.fromstring(str_data, dtype=np.short) ``` 通過fromstring函數將字符串轉換為數組,通過其參數dtype指定轉換后的數據格式,由于我們的聲音格式是以兩個字節表示一個取樣值,因此采用short數據類型轉換。現在我們得到的wave_data是一個一維的short類型的數組,但是因為我們的聲音文件是雙聲道的,因此它由左右兩個聲道的取樣交替構成:LRLRLRLR....LR(L表示左聲道的取樣值,R表示右聲道取樣值)。修改wave_data的sharp之后: ``` wave_data.shape = -1, 2 ``` 將其轉置得到: ``` wave_data = wave_data.T ``` 整個轉換過程如下圖所示: 最后通過取樣點數和取樣頻率計算出每個取樣的時間: ``` time = np.arange(0, nframes) * (1.0 / framerate) ``` ### 寫Wave文件 寫WAV文件的方法和讀類似: ``` # -*- coding: utf-8 -*- import wave import numpy as np import scipy.signal as signal framerate = 44100 time = 10 # 產生10秒44.1kHz的100Hz - 1kHz的頻率掃描波 t = np.arange(0, time, 1.0/framerate) wave_data = signal.chirp(t, 100, time, 1000, method='linear') * 10000 wave_data = wave_data.astype(np.short) # 打開WAV文檔 f = wave.open(r"sweep.wav", "wb") # 配置聲道數、量化位數和取樣頻率 f.setnchannels(1) f.setsampwidth(2) f.setframerate(framerate) # 將wav_data轉換為二進制數據寫入文件 f.writeframes(wave_data.tostring()) f.close() ``` 10-12行通過調用scipy.signal庫中的chrip函數,產生長度為10秒、取樣頻率為44.1kHz、100Hz到1kHz的頻率掃描波。由于chrip函數返回的數組為float64型,需要調用數組的astype方法將其轉換為short型。 18-20行分別設置輸出WAV文件的聲道數、量化位數和取樣頻率,當然也可以調用文件對象的setparams方法一次性配置所有的參數。最后21行調用文件的writeframes方法,將數組的內部的二進制數據寫入文件。writeframes方法會自動的更新WAV文件頭中的長度信息(nframes),保證其和真正的數據數量一致。 ## 用pyAudio播放和錄音 通過上一節介紹的讀寫聲音文件的方法,我們可以離線處理已經錄制好的聲音。不過更酷的是我們可以通過pyAudio庫從聲卡讀取聲音數據,處理之后再寫回聲卡,這樣就可以在電腦上實時地輸入、處理和輸出聲音數據。想象一下,我們可以做一個小程序,讀取麥克風的數據;加上回聲并和WAV文件中的數據進行混合;最后從聲卡輸出。這不就是一個Karaoke的原型么。 pyAudio是開源聲音庫PortAudio( [http://www.portaudio.com](http://www.portaudio.com) )的Python綁定,目前它只支持阻塞式的輸入輸出模式。所謂阻塞式就是需要用戶的程序主動地去讀寫輸入輸出流。雖然阻塞式在功能上有所局限,但是由于編程比較簡單,非常適合一些處理聲音的腳本程序開發。 ### 播放 下面先來看看如何用pyAudio播放聲音。 ``` # -*- coding: utf-8 -*- import pyaudio import wave chunk = 1024 wf = wave.open(r"c:\WINDOWS\Media\ding.wav", 'rb') p = pyaudio.PyAudio() # 打開聲音輸出流 stream = p.open(format = p.get_format_from_width(wf.getsampwidth()), channels = wf.getnchannels(), rate = wf.getframerate(), output = True) # 寫聲音輸出流進行播放 while True: data = wf.readframes(chunk) if data == "": break stream.write(data) stream.close() p.terminate() ``` 這段程序首先根據WAV文件的量化格式、聲道數和取樣頻率,分別配置open函數的各個參數,然后循環從WAV文件讀取數據,寫入用open函數打開的聲音輸出流。我們看到17-20行的while循環沒有任何等待的代碼。因為pyAudio使用阻塞模式,因此當底層的輸出數據緩存沒有空間保存數據時,stream.write會阻塞用戶程序,直到stream.write能將數據寫入輸出緩存。 PyAudio類的open函數有許多參數: * **rate** - 取樣頻率 * **channels** - 聲道數 * **format** - 取樣值的量化格式 (paFloat32, paInt32, paInt24, paInt16, paInt8 ...)。在上面的例子中,使用get_format_from_width方法將wf.sampwidth()的返回值2轉換為paInt16 * **input** - 輸入流標志,如果為True的話則開啟輸入流 * **output** - 輸出流標志,如果為True的話則開啟輸出流 * **input_device_index** - 輸入流所使用的設備的編號,如果不指定的話,則使用系統的缺省設備 * **output_device_index** - 輸出流所使用的設備的編號,如果不指定的話,則使用系統的缺省設備 * **frames_per_buffer** - 底層的緩存的塊的大小,底層的緩存由N個同樣大小的塊組成 * **start** - 指定是否立即開啟輸入輸出流,缺省值為True ### 錄音 從聲卡讀取數據和寫入數據一樣簡單,下面我們用一個簡單的聲音監測小程序來展示一下如何用pyAudio讀取聲音數據。 ``` # -*- coding: utf-8 -*- from pyaudio import PyAudio, paInt16 import numpy as np from datetime import datetime import wave # 將data中的數據保存到名為filename的WAV文件中 def save_wave_file(filename, data): wf = wave.open(filename, 'wb') wf.setnchannels(1) wf.setsampwidth(2) wf.setframerate(SAMPLING_RATE) wf.writeframes("".join(data)) wf.close() NUM_SAMPLES = 2000 # pyAudio內部緩存的塊的大小 SAMPLING_RATE = 8000 # 取樣頻率 LEVEL = 1500 # 聲音保存的閾值 COUNT_NUM = 20 # NUM_SAMPLES個取樣之內出現COUNT_NUM個大于LEVEL的取樣則記錄聲音 SAVE_LENGTH = 8 # 聲音記錄的最小長度:SAVE_LENGTH * NUM_SAMPLES 個取樣 # 開啟聲音輸入 pa = PyAudio() stream = pa.open(format=paInt16, channels=1, rate=SAMPLING_RATE, input=True, frames_per_buffer=NUM_SAMPLES) save_count = 0 save_buffer = [] while True: # 讀入NUM_SAMPLES個取樣 string_audio_data = stream.read(NUM_SAMPLES) # 將讀入的數據轉換為數組 audio_data = np.fromstring(string_audio_data, dtype=np.short) # 計算大于LEVEL的取樣的個數 large_sample_count = np.sum( audio_data > LEVEL ) print np.max(audio_data) # 如果個數大于COUNT_NUM,則至少保存SAVE_LENGTH個塊 if large_sample_count > COUNT_NUM: save_count = SAVE_LENGTH else: save_count -= 1 if save_count < 0: save_count = 0 if save_count > 0: # 將要保存的數據存放到save_buffer中 save_buffer.append( string_audio_data ) else: # 將save_buffer中的數據寫入WAV文件,WAV文件的文件名是保存的時刻 if len(save_buffer) > 0: filename = datetime.now().strftime("%Y-%m-%d_%H_%M_%S") + ".wav" save_wave_file(filename, save_buffer) save_buffer = [] print filename, "saved" ``` 此程序一開頭是一系列的全局變量,用來配置錄音的一些參數:以SAMPLING_RATE為采樣頻率,每次讀入一塊有NUM_SAMPLES個采樣的數據塊,當讀入的采樣數據中有COUNT_NUM個值大于LEVEL的取樣的時候,將數據保存進WAV文件,一旦開始保存數據,所保存的數據長度最短為SAVE_LENGTH個塊。WAV文件以保存時的時刻作為文件名。 從聲卡讀入的數據和從WAV文件讀入的類似,都是二進制數據,由于我們用paInt16格式(16bit的short類型)保存采樣值,因此將它自己轉換為dtype為np.short的數組。 ## 用pyMedia播放Mp3
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看