ここではWAVファイル内の音声データを再生したり、逆に音声データをWAVファイルに記録する方法について学びましょう。
前回の「音を眺める(グラフ化)」の内容と併せて活用すれば、音声データについて多角的に理解することができます。
また、音声データの再生・録音にはスピーカーやマイクといった、コンピューターと接続可能なデバイスが必要になります。自身の開発環境に合ったデバイスを用意してください。本記事の内容を理解すればパソコンにこだわらずとも、ラズパイやArduinoのようなマイコンボードとセンサーを組み合わせて、自作のオーディオデバイスを作れるかもしれません。
音を再生する
まずは音声データを再生する方法について学びます。
スピーカーなどの外部デバイスを使用する場合、音声データの読み込みはwaveモジュールがおすすめです。
グラフ化したりデータ分析したりするときは数値データに変換して扱うことが多い音声データですが、デバイスとの間でデータの授受をする際はバイナリ形式である場合がほとんどです。
waveモジュールは読み込み終わると既にバイナリ形式になっているため、複雑なデータ変換を必要としません。
PythonにはPyAudioという音声の再生、録音に特化したモジュールがあるので、下記のソースコードを実行する前にインストールしておきましょう。
# 音声を再生する
import wave
import pyaudio
# wavファイルのパス
INPUT_FILENAME = "input.wav"
CHUNK = 1024
# WAVファイルからデータを読み込む。
with wave.open(INPUT_FILENAME, "rb") as wf:
fs = wf.getframerate() # 標本化周波数(サンプリングレート)
ch = wf.getnchannels() # チャネル数(モノラル:1、ステレオ:2)
byte_depth = wf.getsampwidth() # 量子化精度[byte]
# pyaudioのインスタンスを作成
p = pyaudio.PyAudio()
# ストリームを開く
stream = p.open(format=p.get_format_from_width(byte_depth),
channels=ch,
rate=fs,
output=True)
# 音声を再生する
data = wf.readframes(CHUNK)
while data:
stream.write(data)
data = wf.readframes(CHUNK)
# ストリームを終了する
stream.stop_stream()
stream.close()
# pyaudioを終了する
p.terminate()
音を録音する
次に音声データを録音する方法についても学びます。
「音の再生」のときと同様、こちらも音声データの書き込みには「waveモジュール」、録音には「PyAudioモジュール」を使用していきます。
ソースコード内に変数名が大文字で定義されている項目は、「音声データを読み込む、書き込む」の内容の復習になりますので、思い出しながら読み進めてください。
# 音声を録音する
import pyaudio
import wave
OUTPUT_FILENAME = "record.wav"
CHUNK = 1024 # デバイスから取得する1回分のデータ量
FORMAT = pyaudio.paInt16 # 量子化精度
CHANNELS = 2 # チャネル数
RATE = 44100 # 標本化周波数(サンプリングレート)
RECORD_SECONDS = 5 # 録音時間[s]
# pyaudioのインスタンスを作成
p = pyaudio.PyAudio()
# ストリームを開く
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
# 音声を録音する
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
# ストリームを停止する
stream.stop_stream()
stream.close()
p.terminate()
with wave.open(OUTPUT_FILENAME, "wb") as wf:
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
コメント