周囲の音に応じて自動的に音量を調整するにはどうすればよいですか?


8

私は大きな道路の隣に住んでいます。夜間に窓を開けることは幸いにも涼しく、断続的に非常に騒々しいです。内蔵マイク入力に基づいて、音量を自動的に調整するにはどうすればよいですか?車の通行中に映画のスピーチが聞こえるように音量を設定すると、それ以外のときは音量が大きくなり、近くの人(外や隣人)に非常に不快に感じます。

私のシステムはDebian Busterですが、おそらく汎用的なソリューションが機能します。これを行うパッケージが利用できない場合、デフォルトのマイクからラウドネスを抽出するコマンドは、これをスクリプト化するのにすでに役立ちます。


1
を使用soxして、平均ラウドネスを計算し(IIRCこれについてstackexchangeで他の質問があります)、pacmdPulseaudioの音量を変更できます。
Dirkt 2017

1
@dirktポインタをありがとう!私は(たぶん私は自分の質問に答えることができます)私はそれを明日とレポートバックを実装しようとするでしょう、この質問を見つけました:superuser.com/questions/306701/...
リュック

回答:


2

仕事をするためのPythonスクリプトを作成しました。残りの問題は、もちろん私のラップトップのマイクが自分のスピーカーも拾うことです。私が探しているのは「エコーキャンセレーション」かもしれないと思いますが、それを自分で実装する方法はわかりません。ただし、外部マイクを使用することもできます。

python-alsaaudio残念ながら、依存関係があるためpython 2 です。

#!/usr/bin/env python

''' For noise cancellation:
$ pactl load-module module-echo-cancel
$ PULSE_PROP="filter.want=echo-cancel" ./this-script.py
'''

''' SETTINGS (you might want to keep presets for music and speech) '''
smoothing = 15 # Over how many samples should we compute?
step_size = 1 # maximum volume adjustment in percent points
# scale_xxx = (n, level) # At mic level n, scale to level% audio volume
scale_min = (4, 39)
scale_max = (19, 53)

''' CREDITS
https://stackoverflow.com/a/1937058
How get sound input from microphone in python, and process it on the fly?
Answer by jbochi

https://stackoverflow.com/a/10739764
How to programmatically change volume in Ubuntu
Answer by mata
'''

import alsaaudio, audioop, sys, os

bucket = [None for i in range(smoothing)]

inp = alsaaudio.PCM(alsaaudio.PCM_CAPTURE)

inp.setchannels(1)
inp.setrate(8000)
inp.setformat(alsaaudio.PCM_FORMAT_S16_LE)

inp.setperiodsize(200)

print('Setting volume to minimum ({}%)'.format(scale_min[1]))
os.system('pactl set-sink-volume 0 {}%'.format(scale_min[1]))

i = 1
last_volume = scale_min[1]
while True:
    l, data = inp.read()
    if l:
        val = audioop.max(data, 2)
        bucket[i % smoothing] = val

        if i % smoothing == 0:
            m = min(bucket)
            miclvl = float(m) / 50.0

            if miclvl < scale_min[0]:
                scale = scale_min[1]
            elif miclvl > scale_max[0]:
                scale = scale_max[1]
            else:
                miclvl_range = scale_max[0] - scale_min[0]
                level_range = scale_max[1] - scale_min[1]
                scale = (miclvl - scale_min[0]) / miclvl_range * level_range + scale_min[1]

            scale = int(round(scale))
            step = max(min(scale - last_volume, step_size), -step_size)

            if step != 0:
                last_volume += step
                step = '+' + str(step) if step > 0 else str(step)
                os.system('pactl set-sink-volume 0 {}%'.format(step))

            miclvl = round(miclvl, 1)
            miclvlpacing = ' ' * (4 - len(str(miclvl)))
            stepspacing = ' ' * (2 - len(str(step)))
            sys.stdout.write('mic lvl {}{}  ideal scale {}%  adjust {}{}  now {}  '.format(
                miclvl, miclvlpacing, str(scale), step, stepspacing, last_volume))
            print(int(round(last_volume - scale_min[1])) * 'x')

        i += 1

1
Pulseaudioはある程度エコーキャンセレーションを行うことができます。たとえば、こちらこちらをご覧ください。それを自分で行いたい場合は、入力信号から出力信号を時間遅延させて適切な振幅で差し引く必要があります。これらの2つのパラメーターを自動的に見つけるのは楽しい部分です。:
dirkt

@dirktありがとうございます!ただし、Pulseaudioはうまく機能しないようです。特に高い音量レベル(> 50%)では、故障して、それ自体を検出し、上昇し続けます。私はただマイクを持って行かなければならないだろう、とにかく彼らが高価であるようではない:)
Luc
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.