この記事はアドベントカレンダー12日目の記事です。
乃木坂46の曲の中で一番好きな「きっかけ」という曲を、sin波で生成してwav形式で出力します。
環境構築
開発環境
- MacBookPro 10.14.5
- Docker fo Mac 2.1.0.3
ホストの環境構築
pulseaudioの準備
$ brew install pulseaudio
$ pulseaudio --load=module-native-protocol-tcp --exit-idle-time=-1 --daemon
Dockerの環境構築
Dockerのコンテナで処理した音をホストPCから出力できるように環境を構築します。
Dockerfile
FROM ubuntu
LABEL maintainer="nyax"
RUN apt-get update && apt-get install -y \
wget \
vim \
pulseaudio \
python-pip
RUN pip install --upgrade \
numpy \
matplotlib \
scipy
イメージのビルド
$ docker build -t nogi .
コンテナ起動
$ docker run -it -e PULSE_SERVER=docker.for.mac.localhost -v ~/.config/pulse:/root/.config/pulse nogi bash
準備
$ apt-get install python-tk
いろいろ出てくる、住んでる場所とか答えます。
日本語文字化け対応
$ apt-get install locales locales-all
$ export LANG=en_US.UTF-8
テスト
実際に音声を再生できるかテスト
$ wget http://www.name-of-this-site.org/coding/wave/txt2wav/la.wav
$ paplay la.wav
「ラ♪」って音が鳴ったら、Docker for mac のコンテナ内の処理で出た音をmacで聞くことに成功。
実践
音階の周波数
音階周波数に詳しく書いてあります。
音階 | 周波数(Hz) | 今回使用 | 補足事項 | |
---|---|---|---|---|
ド | C5 | 523.251 | ||
レ♭ | C#5 | 554.365 | ||
レ | D5 | 587.330 | ||
ミ♭ | D#5 | 622.254 | ◯ | ミとして扱う |
ミ | E5 | 659.255 | ||
ファ | F5 | 698.456 | ◯ | |
ソ♭ | F#5 | 739.989 | ||
ソ | G5 | 783.991 | ◯ | |
ラ♭ | G#5 | 830.609 | ◯ | ラとして扱う |
ラ | A5 | 880.000 | ||
シ♭ | A#5 | 932.328 | ◯ | シとして扱う |
シ | B5 | 987.767 | ||
ド | C6 | 1046.502 | ◯ |
波形の生成
数値計算ライブラリを使って波形を生成しsin波(正弦波)を作ります。
以下の式を用いて生成します。
\begin{equation}
n=t \times f_s (t:再生時間、f_s:サンプリング周波数)
\end{equation}
sinの式に書き換えると以下のようになります。
\begin{equation}
sin(n)=A sin( \frac{2 \pi f_0 n}{f_s})
\end{equation}
nogi.py
# -*- coding: utf-8 -*-
import pylab
import scipy.io.wavfile
import functools
import numpy as np
def sin (x, f0, fs):
return np.sin(2 * np.pi * f0 * x / fs)
def generate (sec, freq, rate):
f = np.vectorize(lambda x: sin(x, freq, rate))
return f(np.arange(0, sec * rate))
def main():
#音階
scale = {
'sleep':0.0,
'do':523.251, 'le':587.330, 'mi':622.254,'fa':698.456,
'so':783.991, 'la': 830.609, 'ci':932.328,'do_':1046.502
}
#メロディー
score = [
('mi', 0.25),('fa', 0.25),('so', 0.25),('la',0.25),('ci',0.5),
('sleep', 0.05),
('mi', 0.25),('fa', 0.25),('so', 0.25),('la',0.25),('ci',0.5),
('ci', 0.5),('mi', 0.4),
('le', 0.3),('mi',1.0),
('sleep', 0.05),
('do_',1.0),
('sleep', 0.05),
('do_',0.25),('la',0.25),('la',0.25),('la',0.5)
]
rate = 16000
y = np.empty(0)
for f, t in score:
y = np.append(y, generate(t, scale[f], rate))
scipy.io.wavfile.write('kikkake.wav', rate, y)
if __name__ == '__main__':
main()
実行する
$ python nogi.py
生成したwavファイルの再生
$ paplay kikkake.wav
流れたわーい!
参考文献
- Dockerコンテナで文字化けが発生した場合の直し方
- Dockerで音を鳴らす
- Docker for mac のコンテナ内の処理で出た音をmacで聞く
- Python で音楽を作って楽しもう
- [python] sin波の音をWAV形式で出力する
間違えてたらコメントよろしくお願いします🙇♂️