PI-PO

コンピュータで”ピーポーピーポー”音を作ってみました(前編)


なんのために作るの

救急車が道を走っているときの音知ってますよね。
近づいてくるときは高い音で離れていく時は低くなる。ドップラー効果ですね。
緊急車両でも無茶なスピードは出さずに安全なスピードで走ってます。
もしも救急車が、100km/hで走ったらどんな音になるのだろう?
F1のように300km/hなら・・・。
どんな音になるのか聞いてみたくなって作ってみました。

高い音の発信機

webで音の情報を入手して早速perlで書いてみました。
これは単なるサインウェブゼネレータです。
44.1kHzのサンプリング周期で、970Hzサイン波形の16bitフルスイングデータを吐き出します。
20秒固定として、近づく方向で10秒。遠ざかる方向で10秒にします。
20秒間なので、44100×20回のデータができます。

###########################################
#サウンド1                               #
#                                         #
# Date: 2016.12.26                        #
# Programed: G-yan                        #
###########################################
require "saveWav.pl";

sub makeWaveData {
        $wavSampleRate = 44100;
        $wavDataLength = 0;
        $tMax = $wavSampleRate * 20; #20sec
        $t0 = 2 / $wavSampleRate; #44.1kHz = 2pi[rad]
        $t01 = $t0 * 970; #970Hz
        $t31 = 0;
        $i3 = 32767; #Signed 16bitデータの最大値
        $sw = 1;
        while ($sw) {
                if ($wavDataLength >= $tMax) { #20sec経過
                        $sw = 0;
                        last;
                }
                $t40 = sin(3.14 * $t31);
                $wavData[$wavDataLength++] = int($t40 * $i3);
                $t31 += $t01;
                if ($t31 > 2) { #2Piを超えたら2Piを引く
                        $t31 -= 2;
                }
        }
}

&makeWaveData;
&saveWaveData("s1");

サウンド1

低い音の発信機

これも同じで、周波数が770Hzに変わっただけ。

###########################################
#サウンド2                               #
#                                         #
# Date: 2016.12.26                        #
# Programed: G-yan                        #
###########################################
require "saveWav.pl";

sub makeWaveData {
        $wavSampleRate = 44100;
        $wavDataLength = 0;
        $tMax = $wavSampleRate * 20; #20sec
        $t0 = 2 / $wavSampleRate; #44.1kHz = 2pi[rad]
        $t01 = $t0 * 970; #970Hz
        $t11 = $t0 * 770; #770Hz
        $t31 = 0;
        $i3 = 32767;
        $sw = 1;
        while ($sw) {
                if ($wavDataLength >= $tMax) {
                        $sw = 0;
                        last;
                }
                $t40 = sin(3.14 * $t31);
                $wavData[$wavDataLength++] = int($t40 * $i3);
                $t31 += $t11;
                if ($t31 > 2) {
                        $t31 -= 2;
                }
        }
}

&makeWaveData;
&saveWaveData("s2");

サウンド2

高音と低音の切り替え

650msec周期で、970Hzと770Hzを切り替えます。

###########################################
#サウンド3                               #
#                                         #
# Date: 2016.12.26                        #
# Programed: G-yan                        #
###########################################
require "saveWav.pl";

sub makeWaveData {
        $wavSampleRate = 44100;
        $wavDataLength = 0;
        $tMax = $wavSampleRate * 20; #20sec
        $t0 = 2 / $wavSampleRate; #44.1kHz = 2pi[rad]
        $t01 = $t0 * 970; #970Hz
        $t11 = $t0 * 770; #770Hz
        $t31 = 0;
        $i3 = 32767;
        $i4 = 0;
        $sw = 1;
        while ($sw) {
                if (($i4++ & 0x1) == 0) { #偶数の時は970Hz
                        $t21 = $t01;
                } else { #奇数の時は770Hz
                        $t21 = $t11;
                }
                $i2 = $wavSampleRate * 0.65; #650msec
                for ($i1 = 0; $i1 < $i2; $i1++) {
                        if ($wavDataLength >= $tMax) {
                                $sw = 0;
                                last;
                        }
                        $t40 = sin(3.14 * $t31);
                        $wavData[$wavDataLength++] = int($t40 * $i3);
                        $t31 += $t21;
                        if ($t31 > 2) {
                                $t31 -= 2;
                        }
                }
        }
}

&makeWaveData;
&saveWaveData("s3");

サウンド3

音のビブラート

10Hzの差がある波形を合成してビブラートさせます。

###########################################
#サウンド4                               #
#                                         #
# Date: 2016.12.26                        #
# Programed: G-yan                        #
###########################################
require "saveWav.pl";

sub makeWaveData {
        $wavSampleRate = 44100;
        $wavDataLength = 0;
        $tMax = $wavSampleRate * 20; #20sec
        $t0 = 2 / $wavSampleRate; #44.1kHz = 2pi[rad]
        $t01 = $t0 * 970; #970Hz
        $t02 = $t0 * 960; #960Hz
        $t11 = $t0 * 770; #770Hz
        $t12 = $t0 * 760; #760Hz
        $t31 = 0;
        $t32 = 0;
        $i3 = 32767;
        $i4 = 0;
        $sw = 1;
        while ($sw) {
                if (($i4++ & 0x1) == 0) {
                        $t21 = $t01;
                        $t22 = $t02;
                } else {
                        $t21 = $t11;
                        $t22 = $t12;
                }
                $i2 = $wavSampleRate * 0.65; #650msec
                for ($i1 = 0; $i1 < $i2; $i1++) {
                        if ($wavDataLength >= $tMax) {
                                $sw = 0;
                                last;
                        }
                        $t40 = sin(3.14 * $t31) * 0.7 + sin(3.14 * $t32) * 0.1; #基本波形 70% 合成波形 10%の割合で加算
                        $wavData[$wavDataLength++] = int($t40 * $i3);
                        $t31 += $t21;
                        $t32 += $t22;
                        if ($t31 > 2) {
                                $t31 -= 2;
                        }
                        if ($t32 > 2) {
                                $t32 -= 2;
                        }
                }
        }
}

&makeWaveData;
&saveWaveData("s4");

サウンド4

徐々に音量を大きくする

TM1時間で最大値まで直線的に音量を上げます。
これで音源は作れた感じです。
後編で音源を走らせてみようと思います。

###########################################
#サウンド5                               #
#                                         #
# Date: 2016.12.26                        #
# Programed: G-yan                        #
###########################################
require "saveWav.pl";

use constant PI => 3.14;
use constant TM1 => 0.03; #30msec
use constant S_MAX => 32767;

sub makeWaveData {
        $wavSampleRate = 44100;
        $wavDataLength = 0;
        $tMax = $wavSampleRate * 20; #20sec
        $t0 = 2 / $wavSampleRate; #44.1kHz = 2pi[rad]
        $t01 = $t0 * 970; #970Hz
        $t02 = $t0 * 960; #960Hz
        $t11 = $t0 * 770; #770Hz
        $t12 = $t0 * 760; #760Hz
        $t31 = 0;
        $t32 = 0;
        $i4 = 0;
        $sw = 1;
        while ($sw) {
                if (($i4++ & 0x1) == 0) {
                        $t21 = $t01;
                        $t22 = $t02;
                } else {
                        $t21 = $t11;
                        $t22 = $t12;
                }
                $i2 = $wavSampleRate * 0.65; #650msec
                $i3 = 0;
                for ($i1 = 0; $i1 < $i2; $i1++) {
                        if ($wavDataLength >= $tMax) {
                                $sw = 0;
                                last;
                        }
                        $t40 = sin(PI * $t31) * 0.7 + sin(PI * $t32) * 0.1;
                        $wavData[$wavDataLength++] = int($t40 * $i3);
                        $t31 += $t21;
                        $t32 += $t22;
                        if ($t31 > 2) {
                                $t31 -= 2;
                        }
                        if ($t32 > 2) {
                                $t32 -= 2;
                        }
                        if ($i1 < $wavSampleRate * TM1) { #0からTM1時間まで
                                if ($i3 < S_MAX) { #最大でない
                                        $i3 += (S_MAX / ($wavSampleRate * TM1)); #ボリュームアップ
                                }
                                if ($i3 > S_MAX) {
                                        $i3 = S_MAX;
                                }
                        }
                        if (($i1 + $wavSampleRate * TM1) > $i2) { #設定時間のTM1秒前
                                if ($i3 > 0) {
                                        $i3 -= (S_MAX / ($wavSampleRate * TM1)); #ボリュームダウン
                                }
                                if ($i3 < 0) {
                                        $i3 = 0;
                                }
                        }
                }
        }
}

&makeWaveData;
&saveWaveData("s5");

サウンド5