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-alsaaudio
dependencia, 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
sox
para calcular el volumen medio (IIRC hay otra pregunta sobre stackexchange sobre esto) ypacmd
para cambiar el volumen de Pulseaudio.