手習ひデジタル信号処理(128) Scilab、音源(救急車)、ドップラー効果、距離減衰有

Joseph Halfmoon

信号波形を処理した結果をグラフで見るのも良いのですが「実体験」したいです。それには音にして耳で聞くという方法もありかと。音声データの入出力は第96回第97回で練習済。今回は処理対象の「音源」として救急車のピーポー音(サイレン)を作製してみましたぞ。一応、ドップラー効果あり、距離減衰あり。なんちゃってだけど。

※「手習ひデジタル信号処理」投稿順 Indexはこちら

※Windows11上のScilab6.1.1およびScilab上のツールボックスを使用させていただいております。

救急車のピーポー音

「ドップラー効果」の例として、必ずあげられる救急車のピーポー音(サイレン)です。調べてみると、960Hzと770Hz、各0.6秒ごとの繰り返しだそうです。そして法令により『車両の前方20m、高さ1mの位置において90dB以上120dB以下』と規定されているみたいです。かなりデカイ音量デス。

そのような大音量を発生するのもはばかられる(手元のパソコンじゃ無理っす)ので、波形の最大振幅を±1.0とした信号として

    • 前方50m にいる救急車がピーポーと鳴らしながら
    • 時速60km/hの速度で
    • 静止した観察者に向かって突進してきてその脇をすり抜ける

様子を後で掲げるScilabプログラムで模擬した音が以下であります。

雰囲気でてますかねえ?

観察者位置を「すり抜ける」ところがイマイチなんでありますが、上記波形のFFT結果は以下のようです。近づくところと遠ざかるところで周波数が変わるので合計4周波数が見えてます。ssAmbFFT60

ピーポー音のスクリプト

基本的には「いつもの」正弦波生成と同じなのですが、

    1. 音源が観察者方向に向かってくる速度 vs [km/h]
    2. 観察者の速度 v0 [km/h]
    3. 音源と観察者間の距離 [m]

という3つのパラメータが追加されています。なお音源の進行が観察者方向であるときプラス。観察者が音源に向かって対向方向に進んでいるならマイナスです。ドップラー効果を計算するには大気中の音速が必要ですが、気温15℃、標準大気圧のときの値をキメウチで参照してます。また波形の振幅は距離1mのところでサチル設定で、その時の最大振幅を1.0としてあります。

// Sound Source: Ambulance
// Fs: sampling frequency [Hz]
// nSample: number of samples
// vs: sound source speed[km/h]
// v0: observer speed[km/h]
// dist: initial distance between source and observer [m]
// NOTE: Sound Level will be saturated under 1 [m]
function y=ssAmbulance(Fs, nSample, vs, v0, dist)
    T06 = int(0.6 * Fs);
    vsM = vs * 10^3 / 3600;
    v0M = v0 * 10^3 / 3600;
    AIR15=340.7;
    dopplerAIR15=(AIR15-v0M)/(AIR15-vsM);
    fqH = 960 * dopplerAIR15;
    fqL = 770 * dopplerAIR15;
    mag = 1.0;
    cnt = 0;
    flag = %T;
    for idx = 1:nSample
        timeNow = idx/Fs;
        distNow = dist - (vsM-v0M)*timeNow;
        if flag & (distNow < 0) then
            dopplerAIR15=(AIR15+v0M)/(AIR15+vsM);
            fqH = 960 * dopplerAIR15;
            fqL = 770 * dopplerAIR15;
            flag = %F;
        end
        if abs(distNow) < 1 then
            distNow = 1;
        end;
        magNow = mag / abs(distNow);
        cnt = cnt + 1;
        if cnt > T06 then
            cnt = 1 - T06;
        end;
        if cnt < 0 then
            fq=fqH;
        else
            fq=fqL;
        end;
        y(idx) = magNow * sin(2*%pi*fq*(idx/Fs));
    end;
endfunction
波形の生成

さきほどのサンプル音声を生成するときのスクリプトが以下に。

Fs=22050;
y=ssAmbulance(Fs, Fs*6, 60, 0, 50);
playsnd(y, Fs);
savewave("ssAmbulance.wav", y, Fs);

なお playsnd()関数で、生成したばかりの波形を音にして聞くことができます。また、savewave()関数でファイル出力しています。

音源が動かず、観察者も動かず、音源距離1mのときの様子を聞くためには以下のようにします。

y0=ssAmbulance(Fs, Fs*6, 0, 0, 1);
playsnd(y0, Fs);
clf;
plotFFT2(Fs, y0', 1);

上記のFFTの結果が以下に。ドップラー効果の影響が無いので周波数のピークは2つだけです。ssAmbFFT0

mapsound()関数を使うと、スペクトログラムを生成することができます。操作はこんな感じ。

clf;
mapsound(y0, 0.04, 1500, Fs);

実際に見えるスペクトログラムが以下に。ssAmbMapSound0

まあ、雰囲気は出た、というところ。いいのかそれで。

手習ひデジタル信号処理(127) Scilab、filter関数で時間波形をBPフィルタ へ戻る

手習ひデジタル信号処理(129) Scilab、音源(救急車)の周波数を求めてみる、その1 へ進む