ガレスタさんのDIY日記

電子回路、Web、組み込み、自作エフェクターを語るblog

Python:ステレオwavファイルをLRに分ける

基礎編です。



信号処理をやって行くにあたりまずは入力となるwavファイルについて知っておく必要がある。
フォーマットに関してはここを読んでほしい
http://sky.geocities.jp/kmaedam/directx9/waveform.html

まあ簡単に言えばヘッダー情報の後はLRLRLRと信号が並んでいる感じ。
I2Sデータもそうだが基本的に信号処理ルーチンを組むならこういったデータを整列して*1いく必要がある。


というわけで2チャンネルのwavファイルを用意してコードを書いてみた
wave_lr.py

import wave
import matplotlib.pyplot as plt
import audio_func as af
import scipy

wf = wave.open("GS03.wav", "r")
af.printWaveInfo(wf)  # デバッグ用
data = wf.readframes(wf.getnframes())
num_data = scipy.fromstring(data,dtype = "int16")

if(wf.getnchannels() == 2):
    left = num_data[::2]
    right= num_data[1::2]

    #スライスの説明
    #a[1,2,3,4,5]ていうリストがあったとして
    #a[::2]  -> 1,3,5
    #a[1::2] -> 2,4

# left channel
plt.subplot(2, 1, 1)
plt.plot(left,label="left")
plt.legend()

# right channel
plt.subplot(2, 1, 2)
plt.plot(right,label="right")
plt.legend()
plt.show()

audio_func.py

def printWaveInfo(wf):
    """WAVEファイルの情報を取得"""
    print("チャンネル数 : "+ str(wf.getnchannels()))
    print("サンプル幅 : "+ str(wf.getsampwidth()))
    print("サンプルレート : "+ str(wf.getframerate()))
    print("フレーム数 : "+ str(wf.getnframes()))
    print("総パラメータ(一括表示用) : "+ str(wf.getparams()))
    print("再生時間 : "+ str(float(wf.getnframes()) / wf.getframerate()))

結果がこんな感じ
もともとモノラルなギターを左右に振ってるだけなので同じ波形が出てくる
f:id:gsmcustomeffects:20180730073550p:plain

コンソール画面

チャンネル数 : 2
サンプル幅 : 2
サンプルレート : 44100
フレーム数 : 196475
総パラメータ(一括表示用) : _wave_params(nchannels=2, sampwidth=2, framerate=44100, nframes=196475, comptype='NONE', compname='not compressed')
再生時間 : 4.455215419501134

補足

フレーム数 : 196475と出ているがこれはwavとしてのフレームのためLR合わせたときのもの

num_data = scipy.fromstring(wf.readframes(wf.getnframes()),dtype = "int16") / 32768.0

とした場合二倍の392950がサイズとなる
f:id:gsmcustomeffects:20180731013557p:plain

上記の例ではこれを分解してるので
Lのサイズ->196475
Rのサイズ->196475

*1:interleaveを外す、解くとか言われてる