LoginSignup
4

More than 3 years have passed since last update.

posted at

updated at

【DockerのUbuntuコンテナ + Python】 乃木坂46の曲をsin波で生成して出力

この記事はアドベントカレンダー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

流れたわーい!

参考文献

間違えてたらコメントよろしくお願いします🙇‍♂️

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
What you can do with signing up
4