LoginSignup
8
4

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-12-12

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

流れたわーい!

参考文献

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

8
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
8
4