3
4

More than 3 years have passed since last update.

[wave.py] Pythonで手っ取り早く音を生成してwav書き出しする

Last updated at Posted at 2021-08-02

使うもの

Python組み込みモジュールのwave.pyを使います。

前提

24bit などを扱うと面倒(*1)なので、ここでは 16bit int, 44.1kHz の音源を作ります。

実装

main.py
import wave
import numpy as np
from random import uniform
from struct import pack

# 保存するwaveファイルのファイル名を指定
filename = './output.wav'

# チャンネル数
n_ch = 2  # 1: mono, 2: stereo

# サンプル幅(ビット深度を8で割った値)
s_width = 2 # 2: 16bit, 3: 24bit, 4: 32bit

# サンプリング周波数
s_rate = 44100  # Hz

# 音源の長さ(ここでは3秒とする)
t_length = 3 # sec

# サンプル数
n_samples = t_length * s_rate


# この後で使う波形を定義しておく
def sin(t, f):
    return np.sin(2*np.pi*f*t)

def tri(t, f):
    u = int(2*f*t + 0.5)
    return (-1)**u * (4*f*t - 2*u)

def sqr(t, f):
    return 1 if 0 <= f*t - int(f*t) < 0.5 else -1

def saw(t, f):
    return 2*f*t - 2*int(f*t + 0.5)

def noise():
    return uniform(-1, 1)


# data_array には1サンプルごとにL, Rの順番で変位の値(int)が入る
# 各要素は -32768~32767 の範囲内に収める必要がある
data_array = []

# 最大振幅
A_max = 32767  # = 0.5 * (2**16) - 1

for i_samples in range(n_samples):
  # 秒単位での時間
  t_i = i_samples / s_rate # sec

  # ここで sin の代わりに saw などを用いると音色が変わる
  L_i = A_max * sin(t_i, 440)
  data_array.append(int(L_i))

  R_i = A_max * sin(t_i, 440)
  data_array.append(int(R_i))


# wav 書き出し
with wave.open(filename, 'w') as wf:
    wf.setnchannels(n_ch)
    wf.setsampwidth(s_width)
    wf.setframerate(s_rate)
    data_binary = pack("h" * n_ch * n_samples, *data_array)
    wf.writeframes(data_binary)

実行

python main.pyと実行すれば output.wav が出てきます。

おわり

色々パラメータを変えて遊んでみて下さい。

参考文献

(*1) Pythonでのwavファイル操作
(*2) pythonのwaveモジュール

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4