目次
python3/pyaudioをwindows10にインストール
pythonで音階を鳴らしてみたくなって、pyaudioをインストールしようとしました。
pip install pyaudioではエラーになる
ところが
pip install pyaudio
ではインストールできません。
ERROR: Failed building wheel for pyaudio
どうやら、VisualStudioのBuildToolでコンパイルエラーがでています。
エラーの原因は。
fatal error C1083: include ファイルを開けません。'portaudio.h':No such file or directory
なるほど・・ですね。
portaudio.hというのは、pythonパッケージにはなくて、完全に独立したCライブラリのようです。
Linuxなら、pipのオプションでなんとかなるらしいですし、Windowsでも、Python3.6以下ならいけるという情報もありますが、それだけのために、Pythonのバージョンを落とすのも、Linuxを使うのもめんどくさいので、別の方法を試すことにしました。
ビルド済のWindowsバイナリでインストール
ありがたいことに、こちらでPyAudioのWindowsバイナリを提供いただいています。
https://www.lfd.uci.edu/~gohlke/pythonlibs/#pyaudio
あくまで「Unofficial Windows Binaries」ですけど、個人で使う分には問題ありません。
ここから、windowsとPythonにバージョンにあったものを選びます。
今回は、windowsの64ビット版+Python3.9の仮想環境なので。
をダウンロードします。
そしてダウンロードしたフォルダをカレントフォルダにして以下を実行します。
すると、あっさりインストールできます。
Processing c:\users\tadas\downloads\pyaudio-0.2.11-cp39-cp39m-win_amd64.whl
Installing collected packages: PyAudio
Successfully installed PyAudio-0.2.11
pyaudioで音階を鳴らすサンプル
軽く音階の音を出してみます。
PyAudioで音階を表現するには、周波数を求める必要があります。
A(ラ)の周波数が440Hzとして、これに2の十二乗根を掛け合わせていけば、半音ずつずらした音階の周波数が計算できます。
ループを回して、ちょうどA(ラ)にあたるところで、2の0乗・・つまり1になるようにすればいいわけです。
音階の周波数を求めるサンプルソース
プログラムにすると、こんな感じですかね。
a_hz = 440 names = ("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B") res = [] for n in range(0, 13): hz = a_hz * 2 ** ((n - 9) / 12) name = names[n % 12] print(name, ";", hz)
これを実行すると。
C ; 261.6255653005986
C# ; 277.1826309768721
D ; 293.6647679174076
D# ; 311.1269837220809
E ; 329.6275569128699
F ; 349.2282314330039
F# ; 369.9944227116344
G ; 391.99543598174927
G# ; 415.3046975799451
A ; 440.0
A# ; 466.1637615180899
B ; 493.8833012561241
C ; 523.2511306011972
こんな感じになります。
いけてるっぽいので、音をだしてみます。
ドレミを鳴らすクラスのサンプルソース
ドレミファソラシド・・にしてみます。
まずは、クラス化して、使いやすくしてみました。
numpyも必要なので、まだの場合は
pip install numpy
で追加してください。
Audioクラスです。
import pyaudio as pa import numpy as np class Audio: def __init__(self, bpm=30): self.audio = pa.PyAudio() self.a_hz = 440 self.smpl_rate = 44100 self.bpm = bpm self.code_names = ( "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B") self.stream = self.audio.open( format=pa.paFloat32, channels=1, rate=self.smpl_rate, frames_per_buffer=1024, output=True) def __tone(self, hz, note, gain=1.0): slen = int(note * self.smpl_rate) t = float(hz) * np.pi * 2 / self.smpl_rate return np.sin(np.arange(slen) * t) * gain # 音符 def make_note(self): self.note1 = 60 / (self.bpm * 4) notes = [] notes.append(self.note1) notes.append(self.note1 / 2) notes.append(self.note1 / 4) notes.append(self.note1 / 8) return notes # 音階 def make_scale(self): res = {} octave = -1 for n in range(0, 13): hz = self.a_hz * 2 ** ((n - 9) / 12) if (n % 12) == 0: octave += 1 name = self.code_names[n % 12] + str(octave) res[name] = hz return res def play(self, hz, note, gain=1.0): self.stream.write(self.__tone(hz, note, gain).astype(np.float32).tostring())
補足しておきます。
クラスのソースコードの補足説明
クラスを初期化するときのパラメータ「bmp」は、音の長さです。
Beat Per Minuteなので、1分間あたりのビート数です。
デフォルトは30で、かなりゆっくりにしてます。
数字を大きくすると速くなります。
サンプリングレート( self.smpl_rate)は44100にしてます。
これは、1秒間で44100個のデータを再生デバイスに送る・・という意味で、CDのサンプリングレートにあたります。
とりあえず。
- 音階(スケール)の辞書を作成(make_scale)
- 音符のリストを生成(make?note)
して、それを使って「play」する・・という感じです。
音階は、C、Dなどに、オクターブの0、1をつける形で「C0」「C1」のように名前をつけて辞書化します。
音符は
- 0: 全音符
- 1:二分音符
- 2:四分音符
- 3:八分音符
の4種類を用意します。
クラスを使って音をならすサンプルソース
使い方のサンプルです。
a = Audio() scales = a.make_scale() notes = a.make_note() a.play(scales["C0"], notes[0]) a.play(scales["D0"], notes[0]) a.play(scales["E0"], notes[0]) a.play(scales["F0"], notes[0]) a.play(scales["G0"], notes[0]) a.play(scales["A0"], notes[0]) a.play(scales["B0"], notes[0]) a.play(scales["C1"], notes[0])
ちゃんとインストールできていれば、これで全音符で「ド・レ・ミ・ファ・ソ・ラ・シ・ド」となるはずです。
とりあえず、鳴ればOK。
今回はこんなところです。
ではでは。