1. 程式人生 > >介紹幾個python的音訊處理庫

介紹幾個python的音訊處理庫

 圖 3比如我的機器的地址就是 192.168.152.130。然後將這個ip地址填入 圖2 的Host Name 一欄,注意預設埠為22,不要去改它,然後點選open,就會彈出一個登陸介面,接著輸入你在linux
下登陸的使用者名稱和密碼就可以ssh連上linux啦。http://www.infoworld.com/article/2617683/linux/linux-moving-files-between-unix-and-windows-systems.html這篇文章介紹了
幾種在unix與windows之間傳遞檔案的方法。我只講第一種,使用putty的pscp的secure copy(安全拷貝)。你安裝了putty之後,會自帶一個叫 pscp.exe的可執行檔案,將其目錄加入windows
環境變數。然後 cmd執行命令 pscp myfile.txt 
[email protected]
:/home/shs 即可以把你的檔案 myfile.txt 複製到 linux 下的 /home/shs 目錄下了。解釋一下,你在執行的時候需要把shs 換成你的使用者名稱,@後面跟你的linux ip地址, /home/shs 是你要把檔案移動的位置。執行完之後,檔案就會成功拷貝過去了。其他方法不講了,有興趣可以自行搜尋,或者看我上面說的那篇文章。   回到正題,eyeD3 命令列講完之後,再來說下如何在Python中使用。還是看官方給的例子吧:
複製程式碼
 1 import eyed3
 2 
 3 audiofile = eyed3.load("song.mp3
") 4 audiofile.tag.artist = u"Nobunny" 5 audiofile.tag.album = u"Love Visions" 6 audiofile.tag.album_artist = u"Various Artists" 7 audiofile.tag.title = u"I Am a Girlfriend" 8 audiofile.tag.track_num = 4 9 10 audiofile.tag.save()
複製程式碼

上面的程式碼,使用 import eyed3 匯入eyeD3 庫,然後使用load方法載入mp3檔案,後面的幾行分別是設定 artist,album等等 ID3 tag ,直接看程式碼就能看出來,就不說了。如果想顯示mp3檔案內部的ID3 tag資訊,直接print 相應的tag就行了,比如 print(audiofile.tag.artist)等等,當然,前提是你的MP3 metadata得儲存了這些資訊。其實還有一些更復雜和高階的用法,我就不講了,大家有興趣直接去官方文件看吧,地址:http://eyed3.nicfit.net/index.html。eyeD3 主要就是處理 MP3檔案的metadata的,至於解析音訊之類的就得用其他的庫了。

二、pydub

  第一個介紹的eyeD3 一般只能處理MP3檔案,功能上相對來說也是比較簡單一點。下面介紹的pydub庫就要強大的多。老規矩,還是
先看一下它的官方介紹:
Manipulate audio with a simple and easy high level interface http://pydub.com  就一句話,簡單,易用的處理音訊
的高度抽象的介面,嘿,這不就是我們要找的麼。github專案地址為:https://github.com/jiaaro/pydub/  有1800多的star,說明這個
庫還是很受歡迎的。安裝直接很簡單,直接 pip install pydub 就可以安裝。但是需要注意的是:

Dependencies

You can open and save WAV files with pure python. For opening and saving non-wav files – like mp3 – you'll need ffmpeg orlibav.

這裡是說python自帶的wave模組只能處理 wav 格式的音訊檔案,如果要想處理類似MP3格式的檔案,就得要裝 ffmpeg或者libav了。

什麼是ffmpeg 呢?

A complete, cross-platform solution to record, convert and stream audio and video. 

ffmpeg 是一個跨平臺的 可以用來 記錄、轉化音訊與視訊的工具,如果你做過數字訊號處理方面的工作,對它應該不陌生。還有一個libav,其實是從ffmpeg分出來的一個分支,功能和 ffmpeg差不多,二者你任選一個下載就可以了。windows下直接選擇可執行檔案安裝即可。

還是看官網的例子來介紹吧。

I:開啟 mp3或者mp4等檔案

可以採用如下的命令:

複製程式碼
 1 from pydub import AudioSegment
 2 
 3 song = AudioSegment.from_wav("never_gonna_give_you_up.wav")
 4 song = AudioSegment.from_mp3("never_gonna_give_you_up.mp3")
 5 
 6 ogg_version = AudioSegment.from_ogg("never_gonna_give_you_up.ogg")
 7 flv_version = AudioSegment.from_flv("never_gonna_give_you_up.flv")
 8 
 9 mp4_version = AudioSegment.from_file("never_gonna_give_you_up.mp4", "mp4")
10 wma_version = AudioSegment.from_file("never_gonna_give_you_up.wma", "wma")
11 aac_version = AudioSegment.from_file("never_gonna_give_you_up.aiff", "aac")
複製程式碼

可以開啟任何 ffmpeg支援的檔案型別,從上面可以看出,主要有 from_filetype()方法,filetype為具體的檔案型別,比如 wav,mp3等

或者通用的 from_file()方法,但是這個方法必須在第二個引數指定開啟檔案的型別,返回的結果都是 AudioSegment物件。

II:切割音訊

1 # pydub does things in milliseconds
2 ten_seconds = 10 * 1000
3 
4 first_10_seconds = song[:ten_seconds]
5 
6 last_5_seconds = song[-5000:]

注意pydub中的標準時間為毫秒,上面的程式碼就得到了音樂的前10秒和後5秒,非常簡單。

III:調整音量

1 # boost volume by 6dB
2 beginning = first_10_seconds + 6
3 
4 # reduce volume by 3dB
5 end = last_5_seconds - 3

+6 就表示將音樂的音量提高6分貝,-3就表示將音樂的音量降低3分貝

IV: 拼接兩段音樂

without_the_middle = beginning + end
without_the_middle.duration_seconds

拼接之後的音樂時長是兩段音樂時長之和,可以通過 .duration_seconds方法來獲取一段音樂的時長。這與使用 len(audio)/1000.0得到的結果是一樣的。

V:將音樂翻轉(reverse)

1 # song is not modified
2 # AudioSegments are immutable
3 backwards = song.reverse()

注意 AudioSegment 物件是不可變的,上面使用reverse 方法不會改變song這個物件,而是會返回一個新的AudioSegment物件,其他的方法也是這樣,需要注意。reverse簡單來說就是 將音樂從尾部向頭部開始逆序播放,我試了一下,發現轉換之後還真的挺有意思的。

VI:crossfade(交叉漸入漸出方法)

1 # 1.5 second crossfade
2 with_style = beginning.append(end, crossfade=1500)

crossfade 就是讓一段音樂平緩地過渡到另一段音樂,上面的crossfade = 1500 表示過渡的時間是1.5秒。

VII:repeat(重複音樂片段)

# repeat the clip twice
do_it_over = with_style * 2

上面的程式碼讓音樂重複播放兩次

VIII:fade in and fade out(逐漸增強與逐漸減弱)

# 2 sec fade in, 3 sec fade out
awesome = do_it_over.fade_in(2000).fade_out(3000)

逐漸增強2秒,逐漸減弱3秒

XI:save(儲存)

awesome.export("mashup.mp3", format="mp3")

awesome.export("mashup.mp3", format="mp3", tags={'artist': 'Various artists', 'album': 'Best of 2011', 'comments': 'This album is awesome!'})

這裡展示了兩種儲存的形式,都是使用export方法,要指定儲存的格式,使用format 引數,但第二種方法多了一個tags引數,其實看一下應該就很容易明白,是儲存 歌曲ID3 tag資訊的。

以上只是pydub 使用方法的初步介紹,還有其他非常多的功能,請自行移步官方API 文件:https://github.com/jiaaro/pydub/blob/master/API.markdown

介紹的非常詳細。

三、PyAudio

又是一個功能強大的處理音訊庫。官方介紹:

PyAudio provides Python bindings for PortAudio, the cross-platform audio I/O library. With PyAudio, you can easily use Python to play and record audio on a variety of platforms. PyAudio is inspired by:

  • pyPortAudio/fastaudio: Python bindings for PortAudio v18 API.
  • tkSnack: cross-platform sound toolkit for Tcl/Tk and Python.

Pyaudio 提供了對於跨平臺的 PortAudio(處理 audio輸入輸出的庫)的繫結,PyAudio可以讓你輕鬆錄製與播放音訊。

廢話不多說,直接看官方文件(https://people.csail.mit.edu/hubert/pyaudio/docs/)提供的一個quick start 的程式碼

複製程式碼
 1 """PyAudio Example: Play a wave file."""
 2 
 3 import pyaudio
 4 import wave
 5 import sys
 6 
 7 CHUNK = 1024
 8 
 9 if len(sys.argv) < 2:
10     print("Plays a wave file.\n\nUsage: %s filename.wav" % sys.argv[0])
11     sys.exit(-1)
12 
13 wf = wave.open(sys.argv[1], 'rb')
14 
15 # instantiate PyAudio (1)
16 p = pyaudio.PyAudio()
17 
18 # open stream (2)
19 stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
20                 channels=wf.getnchannels(),
21                 rate=wf.getframerate(),
22                 output=True)
23 
24 # read data
25 data = wf.readframes(CHUNK)
26 
27 # play stream (3)
28 while len(data) > 0:
29     stream.write(data)
30     data = wf.readframes(CHUNK)
31 
32 # stop stream (4)
33 stream.stop_stream()
34 stream.close()
35 
36 # close PyAudio (5)
37 p.terminate()
複製程式碼

當然,這個提供的是使用命令列引數接收音訊檔案的形式,CHUNK 是一次讀取的音訊byte數量,p = pyaudio.PyAudio()初始化一個

PyAudio物件,然後使用其open方法開啟一個輸入輸出流,這裡指定了output=True說明這是一個輸出流,即我們是往stream中新增data,如果這裡改為 input = True就是變成輸入流了,一般是從裝置的標準 audio device ,對於電腦來說可能就是麥克風了,來讀取音訊data。使用wave開啟一個 .wav 檔案,然後使用 readframes方法每次讀取 CHUNK 這麼多的資料,將資料寫入 stream,直到讀完為止。寫入stream的audio data 就會不斷通過麥克風播放出來了,於是我們就可以聽到音樂了。最後在結束的時候,注意要關閉相應的物件以釋放資源。

還有一種方法是使用callback(回撥函式)函式,程式碼如下:

複製程式碼
 1 """PyAudio Example: Play a wave file (callback version)."""
 2 
 3 import pyaudio
 4 import wave
 5 import time
 6 import sys
 7 
 8 if len(sys.argv) < 2:
 9     print("Plays a wave file.\n\nUsage: %s filename.wav" % sys.argv[0])
10     sys.exit(-1)
11 
12 wf = wave.open(sys.argv[1], 'rb')
13 
14 # instantiate PyAudio (1)
15 p = pyaudio.PyAudio()
16 
17 # define callback (2)
18 def callback(in_data, frame_count, time_info, status):
19     data = wf.readframes(frame_count)
20     return (data, pyaudio.paContinue)
21 
22 # open stream using callback (3)
23 stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
24                 channels=wf.getnchannels(),
25                 rate=wf.getframerate(),
26                 output=True,
27                 stream_callback=callback)
28 
29 # start the stream (4)
30 stream.start_stream()
31 
32 # wait for stream to finish (5)
33 while stream.is_active():
34     time.sleep(0.1)
35 
36 # stop stream (6)
37 stream.stop_stream()
38 stream.close()
39 wf.close()
40 
41 # close PyAudio (7)
42 p.terminate()
複製程式碼

不細說了。

下面來看一個使用pyaudio + numpy + pylab 視覺化音訊的程式碼,下面的程式碼開啟電腦的麥克風,然後接受音訊輸入,再以影象的形式展示出來。

複製程式碼
 1 # -*- coding: utf-8 -*-
 2 """
 3 Created on Fri May 12 10:30:00 2017
 4 @author: Lyrichu
 5 @description: show the sound in graphs
 6 """
 7 import pyaudio
 8 import numpy as np
 9 import pylab
10 import time
11 
12 RATE = 44100
13 CHUNK = int(RATE/20) # RATE/number of updates per second
14 
15 def sound_plot(stream):
16     t1 = time.time() # time starting
17     data = np.fromstring(stream.read(CHUNK),dtype = np.int16)
18     pylab.plot(data)
19     pylab.title(i)
20     pylab.grid()
21     pylab.axis([0,len(data),-2**8,2**8])
22     pylab.savefig("sound.png",dpi=50)
23     pylab.show(block = False)
     time.sleep(0.5)
24     pylab.close('all')
25     print("took %.2f ms." % (time.time() - t1)*1000)
26 
27 if __name__ == '__main__':
28     p = pyaudio.PyAudio()
29     stream = p.open(format = pyaudio.paInt16,channels = 1,rate = RATE,
30                     input = True,frames_per_buffer = CHUNK)
31     for i in range(int(20*RATE/CHUNK)): 
32         # for 10 seconds
33         sound_plot(stream)
34     stream.stop_stream()
35     stream.close()
36     p.terminate()
複製程式碼

程式碼應該比較容易理解。得到的大概是像下面這樣的圖形(圖4):

圖 4

需要注意的是,如果不是在互動式命令下執行pylab或者matplotlib的plot命令,其plt.show()函式是一個block函式,這會導致最後的

plt.close('all') 關閉所有的視窗只會在手動關閉了影象之後才會執行,所有我們無法看到連續變化的影象,為了解決這個問題,我們將plt.show()函式block引數設為False,這樣show函式就不是block函數了,可以直接執行plt.close('all')命令,為了不因為影象重新整理太快我們看不清變化,所以使用time.sleep(0.5) 暫停0.5秒。

其實還沒介紹完,還有pygame模組(python的一個做遊戲的模組)以及librosa庫(專業的數字訊號處理庫)等沒有講,等有機會再更吧。敬請關注!