¿Cómo ajusto automáticamente el volumen de acuerdo con el sonido que me rodea?

8

Vivo al lado de un gran camino. Tener la ventana abierta por la noche es benditamente fresco y, intermitentemente, muy ruidoso. ¿Cómo podría ajustar el volumen automáticamente, según la entrada de micrófono incorporada? Si configuro el volumen para que pueda escuchar el discurso en una película mientras pasa un automóvil, será muy fuerte en otras ocasiones, y se siente muy desagradable con las personas cercanas (afuera y vecinos).

Mi sistema es Debian Buster, aunque probablemente pueda obtener una solución genérica para trabajar. Si no hay un paquete disponible que haga esto, un comando para extraer el volumen del micrófono predeterminado ya sería útil para escribir esto.

Luc
fuente
1
Puede usarlo soxpara calcular el volumen medio (IIRC hay otra pregunta sobre stackexchange sobre esto) y pacmdpara cambiar el volumen de Pulseaudio.
dirkt
1
@dirkt Gracias por los consejos! Encontré esta pregunta, intentaré implementarla mañana e informar (tal vez pueda responder mi propia pregunta): superuser.com/questions/306701/…
Luc

Respuestas:

2

Hice un script de Python para hacer el trabajo. Otro problema es que el micrófono de mi computadora portátil, por supuesto, también recogerá sus propios altavoces. Creo que 'cancelación de eco' podría ser lo que estoy buscando, pero no tengo idea de cómo implementarlo yo mismo. Sin embargo, el uso de un micrófono externo podría funcionar.

Es python 2 debido a la python-alsaaudiodependencia, desafortunadamente.

#!/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
Luc
fuente
1
Pulseaudio puede hacer cancelaciones de eco hasta cierto punto, ver, por ejemplo, aquí y aquí , google para más. Si desea hacerlo usted mismo, debe restar la señal de salida de la señal de entrada, con retraso de tiempo y con la amplitud correcta. Encontrar esos dos parámetros automáticamente es la parte divertida. :-) ("correlación" de Google)
dirkt
@dirkt Gracias de nuevo! Sin embargo, Pulseaudio no parece funcionar muy bien; especialmente a niveles de volumen más altos (> 50%) simplemente se descompone, se detecta y sigue subiendo. Solo tendré que ir a buscar un micrófono, no es que sean caros de todos modos :)
Luc