はじめに
この記事は @ShijiMi-Soup 様の pythonで音を鳴らす方法を詳しめに解説 を参考にしつつ外部ライブラリ、つまりnumpy
やpyaudio
を用いないで音を鳴らすことに成功したので共有する記事です。環境や宗教上の理由で外部のライブラリ(pip
でインストールするようなもの)を用いることが出来ない場合などにご活用ください。
本家様の記事は音ってなんだ的な所から解説していますが、そのような解説は本家様の記事に任せて、この記事では実装例と相違点について取り上げようと思います。それでは参りましょう。
環境
Python 3.9.0
音を鳴らす機構はそれぞれの環境に依存するので後々解説します。
プログラムの実装
まずはプログラムを見ていただきます。
import wave
import struct
import math
import os
def arrange(start, end):
l = []
x = start
while(x < end):
l.append(x)
x += 1.0
return l
def mul(x, l):
return [x * e for e in l]
def div(x, l):
return [(lambda a, b: a / b if b != 0 else 0)(e, x) for e in l]
def sin(l):
return [math.sin(e) for e in l]
sec = 1.0 #1秒
note_hz = 440 #ラの音の周波数
sample_hz = 44100 #サンプリング周波数
t = arrange(0, sample_hz * sec)
wv = sin(div(sample_hz, mul(2 * math.pi * note_hz, t)))
max_num = 32767.0 / max(wv)
wv16 = [int(x * max_num) for x in wv]
bi_wv = struct.pack("h" * len(wv16), *wv16)
name_file = "sound.wav"
file = wave.open(name_file, mode='wb')
param = (1,2,sample_hz,len(bi_wv),'NONE','not compressed')
file.setparams(param)
file.writeframes(bi_wv)
file.close()
if os.name == "nt":
import winsound
winsound.PlaySound(name_file, winsound.SND_FILENAME)
以降は解説です。
外部ライブラリに頼らないとどうなるか
外部ライブラリに頼らないとどうなるかという話ですが、まずはnumpy
から、元の記事を見ていただければ何となくわかると思いますが、音声ファイルはたくさんの数値の集まりで出来ています、配列ですね。numpy
では便利な関数や配列クラスを定義されています。例えばarrange
関数を使えば浮動小数点数を含む数列を生成できたり、配列に対して掛け算や割り算を行うことが出来ます。それがnumpy
の素晴らしい所なのですが今回はその恩恵にあずかることはできないので自前で実装します。それがソースコード上部の関数群です。
# 始まりと終わりを指定して等差数列の生成する関数
def arrange(start, end):
l = []
x = start
while(x < end):
l.append(x)
x += 1.0
return l
# リスト型に対して掛け算を行う関数
def mul(x, l):
return [x * e for e in l]
# リスト型に対して割り算を行う関数
def div(x, l):
return [(lambda a, b: a / b if b != 0 else 0)(e, x) for e in l]
# リスト型に対してそれぞれの値を`math.sin`関数に入れる関数
def sin(l):
return [math.sin(e) for e in l]
若干お行儀悪い気がしますが許してください。
次にpyaudio
が使えないとという話ですが、何らかの音声再生機能をかわりに選ばなくてはいけません。実装例ではwindows環境向けに記述されています。
if os.name == "nt":
import winsound
winsound.PlaySound(name_file, winsound.SND_FILENAME)
ここはPythonで鳴らすことを考えずwav
ファイルをコマンドから再生することを考えましょうか。例えばpaplay
がインストールされている環境ならこのように記述することが出来ます。
import subprocess
subprocess.run(["paplay", name_file])
使えるかはターミナルでpaplay --version
と入力してみてください。
他にもMacならafplay
というコマンドが使えるはずなのでそれを使います。
import subprocess
subprocess.run(["afplay", name_file])
音声再生はこのようにします。これで大抵のデスクトップ環境はカバーできるのでは?と思うのですが、何か良いwav
の再生方法があったらコメントで共有してくれると助かります。
おわりに
今回は以上です。ショートな記事でしたが忘備録としてまとめられる程度には自分の中でまとまったので記事に起こしました。役に立つことがあれば幸いです。
ここまで読んでくださってありがとうございました。次は何しようかな…思いついたらまたやるのでもしよろしかったら次も読んでくださるとありがたいです。