LoginSignup
1
2

More than 1 year has passed since last update.

Python3 で 騒音計を作ろう

Last updated at Posted at 2023-03-25

Python3 で 騒音計を作ろう

音楽を聴いていたら、隣家から苦情

自分が音楽を聞く自由と、近隣の方々が静かに暮らす自由を両立させたい

壁に遮音材と吸音材を貼ったところ、苦情の内容が
「音が漏れている」という表現から「重低音が聞こえる」に変わった。

よっしゃ重低音対策しちゃうぞ

音漏れは60dBぐらいから聞こえる

重低音は40dBぐらいでも聞こえることが有る
というのを突き止めた。(長男が詳しかった)

床を通じて隣に伝わっているので、床とスピーカの間に遮音材を敷いた上で、さらに対策を行う。

重低音の部分の音量を把握したい

全域の音量の算出は、サンプルがネットに見つかった。

https://hotsmmrblog.com/noise-level-measurement_with_raspberry_pi_and_usb_mic/
ラズパイとUSBマイクを用いたデシベル計算、騒音測定器の作成【Python + pyaudio】

重低音部分はサンプルコードが見つからず。

Facebookで質問してみた

ローパスフィルタというものを使えば、高音部分を消してくれるらしい、との回答を頂いた。(丹野さんに感謝)

ローパスフィルタ(英語: Low-pass filter: LPF、低域通過濾波器)とは、フィルタの一種で、なんらかの信号のうち、遮断周波数より低い周波数の成分はほとんど減衰させず、遮断周波数より高い周波数の成分を逓減させるフィルタである。

方針

1秒間、録音
そのデシベル数を算出(全域)
録音内容をローパスフィルタにかける
そのデシベル数を算出(重低音)
以上を無限ループさせる

全域の処理(抜粋)

        stream = p.open(format = FORMAT,
                        channels = CHANNELS,
                        rate = SAMPLING_RATE,
                        input = True,
                        frames_per_buffer = CHUNK,
                        input_device_index = INPUT_DEVICE_INDEX
                )

        # get specified range of data. size of data equals (CHUNK * (SAMPLING_RATE / CHUNK) * RECORD_SECONDS)
        data = np.empty(0)
        for i in range(0, int(SAMPLING_RATE / CHUNK * RECORD_SECONDS)):
            elm = stream.read(CHUNK, exception_on_overflow = False)
            elm = np.frombuffer(elm, dtype="int16")/float((np.power(2,16)/2)-1)
            data = np.hstack([data, elm])
        # calc RMS
        rms = np.sqrt(np.mean([elm * elm for elm in data]))
        # RMS to db
        db = to_db(rms, 20e-6)
        stream.close()

ローパスフィルタ

    import numpy as np
    from scipy.signal import butter, lfilter, freqz
    import matplotlib.pyplot as plt

    def butter_lowpass(cutoff, fs, order=5):
        nyq = 0.5 * fs
        normal_cutoff = cutoff / nyq
        b, a = butter(order, normal_cutoff, btype='low', analog=False)
        return b, a

    def butter_lowpass_filter(data, cutoff, fs, order=5):
        b, a = butter_lowpass(cutoff, fs, order=order)
        y = lfilter(b, a, data)
        return y

    # Setting standard filter requirements.
    order = 6
    fs = SAMPLING_RATE
    cutoff = 100.0          # 100Hz以下が重低音ということで、ここは 100.0

    b, a = butter_lowpass(cutoff, fs, order)

これを組合せて、全域・重低音のdB算出

いい感じに妥当な数字が出た。

RasPi.jpg

動作イメージ

大きさに応じて色付けして、隣家に聞こえるレベルを赤表示にした。

Sample01.jpg

ダウンロード・入手したい人向けの情報

https://tanaka-cs.co.jp/NoiseMeter.html
ここで販売しています。(誰も買わないけど)

https://github.com/hidemune/sound-level-meter
ここでテストコードを公開しています。

ダイナミックマイクとコンデンサマイク

コンデンサマイクは、重低音のノイズが乗る?
(中華の安価なもの)

ダイナミックマイクのほうがノイズが少ない?
(Shureの高価なものと中華の安価なもの両方)

上記の原因として考えられるものは何だろう。。?

コンデンサーマイクとダイナミックマイクのおおまかな特徴

ダイナミックマイク:電源不必要、丈夫で比較的湿度に強い、感度が低い、⇒比較的安価

コンデンサーマイク:電源必要、振動や湿気に特に弱い、感度が高い、⇒比較的高価

電源部分がノイズの原因になりやすい?
感度の問題は、音漏れの閾値が妥当ならあまり問題はないかも

とりあえず、苦情は来なくなったので成功

おめでとう〜 ぱちぱち

以上です。最後まで読んでいただき、ありがとうございました。

1
2
1

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
1
2