音を再生、録音する

Python

ここでは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))

コメント