Comment régler automatiquement le volume en fonction du son autour de moi?

8

J'habite à côté d'une grande route. La fenêtre ouverte la nuit est heureusement cool et, par intermittence, très bruyante. Comment puis-je régler le volume automatiquement, en fonction de l'entrée microphone intégrée? Si je règle le volume de manière à pouvoir entendre la parole dans un film pendant le passage d'une voiture, il sera très bruyant à d'autres moments, et il se sent très désagréable pour les personnes à proximité (extérieur et voisins).

Mon système est Debian Buster, bien que je puisse probablement faire fonctionner une solution générique. Si aucun package n'est disponible pour cela, une commande pour extraire le volume du microphone par défaut serait déjà utile pour l'écrire.

Luc
la source
1
Vous pouvez utiliser soxpour calculer le volume moyen (IIRC il y a d'autres questions sur stackexchange à ce sujet), et pacmdpour changer le volume de Pulseaudio.
dirkt
1
@dirkt Merci pour les pointeurs! J'ai trouvé cette question, je vais essayer de l'implémenter demain et de faire un rapport (peut-être que je peux répondre à ma propre question): superuser.com/questions/306701/…
Luc

Réponses:

2

J'ai créé un script Python pour faire le travail. Un problème restant est que le microphone de mon ordinateur portable captera également ses propres haut-parleurs. Je pense que «l'annulation d'écho» pourrait être ce que je recherche, mais je ne sais pas comment l'implémenter moi-même. L'utilisation d'un microphone externe peut cependant fonctionner.

C'est python 2 en raison de la python-alsaaudiodépendance, malheureusement.

#!/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
la source
1
Pulseaudio peut faire une annulation d'écho dans une certaine mesure, voir par exemple ici et ici , google pour plus. Si vous voulez le faire vous-même, vous devez soustraire le signal de sortie du signal d'entrée, temporisé et avec la bonne amplitude. Trouver ces deux paramètres automatiquement est la partie amusante. :-) (Google "corrélation")
dirkt
@dirkt Merci encore! Cependant, Pulseaudio ne semble pas très bien fonctionner; en particulier à des niveaux de volume plus élevés (> 50%), il se décompose, se détecte et continue d'augmenter. Je vais juste devoir aller chercher un micro, ce n'est pas comme s'ils étaient chers de toute façon :)
Luc