如何根据周围的声音自动调节音量?


8

我住在一条大路旁。晚上开着窗户真是凉爽,间歇地,很大声。如何根据内置麦克风输入自动调节音量?如果设置音量以便在汽车经过时能听到电影中的讲话,则其他时间声音会很大,并且对附近的人(外面和邻居)感到非常讨厌。

我的系统是Debian Buster,尽管我可能可以得到一个通用的解决方案。如果没有可用的软件包可以执行此操作,那么从默认麦克风中提取响度的命令将有助于对此进行脚本编写。


1
您可以sox用来计算平均响度(IIRC,关于stackexchange还有其他问题),以及pacmd更改Pulseaudio的音量。
dirkt

1
@dirkt感谢您的指导!我找到了这个问题,明天我将尝试实施并报告(也许我可以回答我自己的问题):superuser.com/questions/306701/…–
Luc

Answers:


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可以在某种程度上进行回声消除,请参见例如此处此处,谷歌以了解更多信息。如果您想自己动手,则必须从输入信号中减去输出信号,该信号经过延时且幅度适当。自动找到这两个参数是很有趣的部分。:
dirkt

@dirkt再次感谢!不过,Pulseaudio的效果似乎不太好;特别是在较高音量(> 50%)时,它会分解,自我检测并不断上升。我只需要去拿麦克风,这并不意味着它们很昂贵:)
Luc
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.