Up

音ファイル(.wav)の作成と再生

 

音の波をnumpy.ndarray上に作成して、wavファイルとしてscipy.io.wavfile.writeで保存した後、winsound.PlaySoundで音として再生するスクリプト(リスト1)を備忘録として作成した。

再生は別プロセスとして実行して、Enterキーの押下でプロセスを停止してプログラムの終了とした。

音はnumpy.ndarray型のw_valuesに、以下のコードで設定した。

 

    w_values = np.zeros(len(ts))

    for t in range(len(ts)):

        if t < len(ts) / 4:

            w_values[t] = Do.value()

        elif t < 2 * len(ts) / 4:

            w_values[t] = Mi.value()

        elif t < 3 * len(ts) / 4:

            w_values[t] = Sol.value()

        else:

            w_values[t] = (Do.value() + Mi.value() + Sol.value()) / 3

 

DoMiSolはド、ミ、ソの音を生成するオブジェクトでWave型である。Wave型は、次のコードで与えられるクラス型である。

 

class Wave():

    """

            freq: 周波数,  dt: 時間増分(1/sampling rate)

    """

    def __init__(self, freq, dt):

        self.freq = freq

        self.phase = 0.0

        self.dt = dt

    def value(self):

        v = np.sin(2*np.pi * self.phase)

        self.phase += self.freq * self.dt

        if self.phase > 1.0:

            self.phase -= 1.0

        return v

 

配列w_valuesに設定された音は、次のコードによってファイルexample.wavに保存される。

 

from scipy.io.wavfile import write as write_wav

write_wav("example.wav", s_rate, w_values.astype(np.int16))

 

保存したファイルは、次の関数によって再生される。フラッグwinsound.SND_LOOPが指定されているので、ファイルは繰り返し実行される。

 

def mysound(v):

    winsound.PlaySound(v, winsound.SND_ASYNC |

                       winsound.SND_FILENAME | winsound.SND_LOOP)

 

この再生は、次のこーどにより別プロセスとして実行される。

 

    with Pool() as pool:

        print('Playing.')

        pool.map(mysound, ["example.wav"])

        print()

        a = input('Press Enter-key, to exit.')

        pool.terminate()

 

input関数の次のterminate()が実行されると、この別プロセスは終了して、音の再生は終わる。

 

 

リスト1 音ファイルの作成と再生(ScriptFile.zip

from scipy.io.wavfile import write as write_wav

import numpy as np

import copy

import winsound

from time import sleep

from multiprocessing import Pool

 

 

class Wave():

    """

            freq: 周波数,  dt: 時間増分(1/sampling rate)

    """

    def __init__(self, freq, dt):

        self.freq = freq

        self.phase = 0.0

        self.dt = dt

    def value(self):

        v = np.sin(2*np.pi * self.phase)

        self.phase += self.freq * self.dt

        if self.phase > 1.0:

            self.phase -= 1.0

        return v

 

 

#

#         winsound.SND_LOOP: 繰り返し再生

#

def mysound(v):

    winsound.PlaySound(v, winsound.SND_ASYNC |

                       winsound.SND_FILENAME | winsound.SND_LOOP)

   

        

if __name__ == '__main__':

    #     サンプリング周波数

    s_rate = 44100;

    #     音データの長さ(2秒)

    ts = np.linspace(0, 2, s_rate * 2 + 1)

    #     時間増分

    d_t = 1.0 / s_rate

    #     ド(523.251ヘルツ)

    Do = Wave(523.251, d_t)

    #     ミ(659.255ヘルツ)

    Mi = Wave(659.255, d_t)

    #     ソ(783.991ヘルツ)

    Sol = Wave(783.991, d_t)

 

    #

    #    ドー>ミー>ソー>(ド+ミ+ソ)

    #

    w_values = np.zeros(len(ts))

    for t in range(len(ts)):

        if t < len(ts) / 4:

            w_values[t] = Do.value()

        elif t < 2 * len(ts) / 4:

            w_values[t] = Mi.value()

        elif t < 3 * len(ts) / 4:

            w_values[t] = Sol.value()

        else:

            w_values[t] = (Do.value() + Mi.value() + Sol.value()) / 3

              

 

    #

    #       音データの強さの調整

    #

    amplitude = np.iinfo(np.int16).max * 0.5

    max_wave = np.abs(w_values).max()

    w_values = w_values * amplitude / max_wave

    #

    #      numpy.ndarrayのデータをint16型でwavファイルに書き出す

    #

    write_wav("example.wav", s_rate, w_values.astype(np.int16))

 

    #

    #     Enterキーが押されるまで、繰り返し再生になるように

    #     再生を別プロセスとして実行する。

    #

    with Pool() as pool:

        print('Playing.')

        pool.map(mysound, ["example.wav"])

        print()

        a = input('Press Enter-key, to exit.')

        pool.terminate()

 

 

Up