日曜日, 4月 15, 2007

python wav output

num2snd(python)を書き直して、ちょっと使いやすくした。

サンプリングレートとか長さを変えられるようにした。グローバル変数を使うのはあんましよくない的な文章を読んだのもある。prepare_list()関数をなくして、変数名、関数名の記法を統一。だいぶすっきりしたけど、何かまだスパゲッティな感じ。最近やっとコーディングの仕方がわかってきた気がする。今まではパズル感覚で適当に組み替えてただけ。

使うときは例えばこのコードをsinewave.pyと名前を付けて同じ階層に移動し、

python

と入力して対話モードにする。

>>>import sinewave

とし、

>>>sinewave.sineWave('test.wav', 2000, 44100, 1)

とすればサンプリングレート44100Hz、高さ2000Hz、1秒のサイン波が録音されたtest.wavというwavファイルが生成される。


import wave, math

def waveInit(fileName, sampFreq):
file = wave.open(fileName, 'w')
file.setnchannels(1)
file.setsampwidth(2)
file.setframerate(sampFreq)
file.setcomptype('NONE', 'not compressed')
return file

def waveWrite(out, samples):
out.writeframesraw(samples)
out.close()

def sineWave(fileName, freq, sampFreq, length):
out = waveInit(fileName, sampFreq)
samples = range(sampFreq * length)
a = math.pi * 2.0 * float(freq) / float(sampFreq)
for i in range(sampFreq * length):
samples[i] = int(math.sin(a * float(i)) * 30000.0)
waveWrite(out, samples)

3 件のコメント:

yosuke hayashi さんのコメント...

別の環境でやったらエラーになった。wave.pyのwriteframesrawに渡す引数のせいみたい。もーよくわからん。

TypeError: argument 1 must be string or read-only buffer, not list

yosuke hayashi さんのコメント...

これはできた。

yosuke hayashi さんのコメント...

samples = range(int(sampFreq * length))
とすると音の長さを0.2秒とか小数点でも指定できるようになる。前のだとできなくはないけど警告される。

あと、for文の中に
env = (sampFreq * float(length) - i) / sampFreq * float(length)
samples[i] = int(math.sin(a * float(i)) * env * 30000.0)
を入れてあげるとエンヴェロープがかかるみたい。なるほどね。単純に周波数を右肩下がりにしてるだけ。

んで、for文はfor i in range(len(samples)):
としたら若干スマートかな。