<pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
    <pre id="vvttv"></pre>

      <p id="vvttv"></p>

          <p id="vvttv"></p>

                <p id="vvttv"></p>

                <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                  <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                    <p id="vvttv"></p>

                    聲音的輸入輸出?

                    在本章我們將學習如何讀寫WAV文件,如何利用聲卡實時地進行聲音的輸入輸出。標準的Python已經支持WAV文件的讀寫,而實時的聲音輸入輸出需要安裝pyAudio(http://people.csail.mit.edu/hubert/pyaudio)。最后我們還將看看如何使用pyMedia(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),它是一款開源的、跨平臺、多聲道的錄音編輯軟件。在我的工作中經常使用Audacity進行聲音信號的錄制,然后再輸出成WAV文件供Python程序處理。

                    讀Wave文件?

                    下面讓我們來看看如何在Python中讀寫聲音文件:

                     1
                     2
                     3
                     4
                     5
                     6
                     7
                     8
                     9
                    10
                    11
                    12
                    13
                    14
                    15
                    16
                    17
                    18
                    19
                    20
                    21
                    22
                    23
                    24
                    25
                    26
                    27
                    28
                    29
                    30
                    # -*- 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()
                    
                    _images/wave_pyaudio_01.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文件的方法和讀類似:

                     1
                     2
                     3
                     4
                     5
                     6
                     7
                     8
                     9
                    10
                    11
                    12
                    13
                    14
                    15
                    16
                    17
                    18
                    19
                    20
                    21
                    22
                    23
                    # -*- 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 )的Python綁定,目前它只支持阻塞式的輸入輸出模式。所謂阻塞式就是需要用戶的程序主動地去讀寫輸入輸出流。雖然阻塞式在功能上有所局限,但是由于編程比較簡單,非常適合一些處理聲音的腳本程序開發。

                    播放?

                    下面先來看看如何用pyAudio播放聲音。

                     1
                     2
                     3
                     4
                     5
                     6
                     7
                     8
                     9
                    10
                    11
                    12
                    13
                    14
                    15
                    16
                    17
                    18
                    19
                    20
                    21
                    22
                    23
                    24
                    # -*- 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讀取聲音數據。

                     1
                     2
                     3
                     4
                     5
                     6
                     7
                     8
                     9
                    10
                    11
                    12
                    13
                    14
                    15
                    16
                    17
                    18
                    19
                    20
                    21
                    22
                    23
                    24
                    25
                    26
                    27
                    28
                    29
                    30
                    31
                    32
                    33
                    34
                    35
                    36
                    37
                    38
                    39
                    40
                    41
                    42
                    43
                    44
                    45
                    46
                    47
                    48
                    49
                    50
                    51
                    52
                    53
                    54
                    55
                    56
                    57
                    58
                    59
                    # -*- 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?

                    首頁目錄

                    上一篇文章

                    場景窗口

                    下一篇文章

                    數字信號系統

                      <pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
                      <pre id="vvttv"></pre>

                        <p id="vvttv"></p>

                            <p id="vvttv"></p>

                                  <p id="vvttv"></p>

                                  <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                                    <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                                      <p id="vvttv"></p>

                                      这里只有精品视频