PyAudioの基本メモ2 音声入出力
PyAudioの基本メモ1の続きです。
今回はPyAudioの基本的な使い方を書きます。
ほとんどPyAudio: PortAudio v19 Python Bindingsの例題のままです。
音声の出力
import pyaudio import wave CHUNK = 1024 filename="好きなwavファイル" wf = wave.open(filename, 'rb') p = pyaudio.PyAudio() stream = p.open(format=p.get_format_from_width(wf.getsampwidth()), channels=wf.getnchannels(), rate=wf.getframerate(), output=True) """ format : ストリームを読み書きするときのデータ型 channels: ステレオかモノラルかの選択 1でモノラル 2でステレオ rate : サンプル周波数 output : 出力モード """ # 1024個読み取り data = wf.readframes(CHUNK) while data != '': stream.write(data) # ストリームへの書き込み(バイナリ) data = wf.readframes(CHUNK) # ファイルから1024個*2個の stream.stop_stream() stream.close() p.terminate()
これで好きなwavファイルを再生できる
音声の入力
import pyaudio import wave CHUNK = 1024 FORMAT = pyaudio.paInt16 # int16型 CHANNELS = 2 # ステレオ RATE = 44100 # 441.kHz RECORD_SECONDS = 5 # 5秒録音 WAVE_OUTPUT_FILENAME = "output.wav" p = pyaudio.PyAudio() stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=CHUNK) print("* recording") frames = [] for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)): data = stream.read(CHUNK) frames.append(data) print("* done recording") stream.stop_stream() stream.close() p.terminate() wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb') wf.setnchannels(CHANNELS) wf.setsampwidth(p.get_sample_size(FORMAT)) wf.setframerate(RATE) wf.writeframes(b''.join(frames)) wf.close()
frames_per_bufferがよくわからん
とりあえず1024にしておけば大丈夫そう
リアルタイムで音声入出力
マイク入力した音声をリアルタイムでスピーカーから出力します。
マイクはOSで設定したデフォルト、スピーカーもOSで設定したデフォルトの機器を使います。
※注意! イヤホンをしていないとハウリングして耳がキィーンとします。
# -*- coding:utf-8 -*- import pyaudio CHUNK=1024 RATE=44100 p=pyaudio.PyAudio() stream=p.open( format = pyaudio.paInt16, channels = 1, rate = RATE, frames_per_buffer = CHUNK, input = True, output = True) # inputとoutputを同時にTrueにする while stream.is_active(): input = stream.read(CHUNK) output = stream.write(input) stream.stop_stream() stream.close() p.terminate() print "Stop Streaming"
リアルタイムで音声加工
マイク入力した音声をリアルタイムで加工して出力します。
# -*- coding:utf-8 -*- import pyaudio CHUNK=1024*2 RATE=44100 p=pyaudio.PyAudio() stream=p.open( format = pyaudio.paInt16, channels = 1, rate = RATE, frames_per_buffer = CHUNK, input = True, output = True) # inputとoutputを同時にTrueにする def audio_trans(input): # なんかしらの処理 return ret while stream.is_active(): input = stream.read(CHUNK) input = audio_trans(input) output = stream.write(input) stream.stop_stream() stream.close() p.terminate() print "Stop Streaming"
加工する場合はCHUNKを2倍の2048にして少し処理を遅くしました。
なぜならばまず、アウトプットする時のストリームへの書き込みに必要となる時間がCHUNK=1024とすると
(書き込みに必要な時間)=CHUNK/RATE=0.023[sec] でした。
timeモジュールで測定してみましたが確かにそのくらいの時間のようです。
ストリームから音声を読み取る時間と入力音声を加工する処理の時間の合計が、書き込みに必要な時間より遅いと
音声出力中→→→終了 | 空白の時間 | 音声出力...→→ |
読み取り→→→→加工 | 処理中......... | 書き込み |
↑
ここで空白の時間(音声が出ない→声が途切れて聞こえる)
という現象が起こりました。(わかりにく)
この空白の時間が人間が感じ取れないほど短い時間(またサンプル周期よりも小さい時間)であればプツプツ音は出ないようです。
また読み込みよりも書き込みのほうが圧倒的に時間がかかるようなのでCHUNKを大きくしても書き込み時間だけを気にしていれば平気そうです。
このため、CHUNKを2倍にして書き込みに必要な時間を 0.046[sec]としました。
読み取り時間+処理時間 がテキトーに処理を書いた(ピッチ抽出など)ときおよそ 0.03[sec]程度だったのでこれで空白の時間はなくなりました
が、入力から出力の遅れ時間は当たり前のごとく増えました。
適宜CHUNK幅を調整して遅れさせてください。