58 votes

Comment obtenir une entrée sonore depuis un microphone en python, et la traiter à la volée ?

Salutations,

J'essaie d'écrire un programme en Python qui imprimerait une chaîne de caractères chaque fois qu'il reçoit une tape dans le microphone. Quand je dis 'tape', je veux dire un bruit fort et soudain ou quelque chose de similaire.

J'ai cherché dans SO et j'ai trouvé ce post : Reconnaître le ton de l'audio

Je pense que la bibliothèque PyAudio répondrait à mes besoins, mais je ne sais pas vraiment comment faire pour que mon programme attende un signal audio (surveillance du microphone en temps réel), et quand j'en ai un, comment le traiter (dois-je utiliser la transformation de Fourier comme il est indiqué dans le post ci-dessus) ?

Merci d'avance pour toute aide que vous pourriez m'apporter.

1 votes

42voto

jbochi Points 12280

Si vous utilisez LINUX, vous pouvez utiliser pyALSAAUDIO . Pour Windows, nous avons PyAudio et il existe également une bibliothèque appelée SoundAnalyse .

J'ai trouvé un exemple pour Linux aquí :

#!/usr/bin/python
## This is an example of a simple sound capture script.
##
## The script opens an ALSA pcm for sound capture. Set
## various attributes of the capture, and reads in a loop,
## Then prints the volume.
##
## To test it out, run it and shout at your microphone:

import alsaaudio, time, audioop

# Open the device in nonblocking capture mode. The last argument could
# just as well have been zero for blocking mode. Then we could have
# left out the sleep call in the bottom of the loop
inp = alsaaudio.PCM(alsaaudio.PCM_CAPTURE,alsaaudio.PCM_NONBLOCK)

# Set attributes: Mono, 8000 Hz, 16 bit little endian samples
inp.setchannels(1)
inp.setrate(8000)
inp.setformat(alsaaudio.PCM_FORMAT_S16_LE)

# The period size controls the internal number of frames per period.
# The significance of this parameter is documented in the ALSA api.
# For our purposes, it is suficcient to know that reads from the device
# will return this many frames. Each frame being 2 bytes long.
# This means that the reads below will return either 320 bytes of data
# or 0 bytes of data. The latter is possible because we are in nonblocking
# mode.
inp.setperiodsize(160)

while True:
    # Read data from device
    l,data = inp.read()
    if l:
        # Return the maximum of the absolute value of all samples in a fragment.
        print audioop.max(data, 2)
    time.sleep(.001)

7voto

Craig McQueen Points 13194

...et quand j'en aurai un, comment le traiter (dois-je utiliser la Transformée de Fourier comme indiqué dans le post ci-dessus) ?

Si vous voulez un "tap", je pense que vous êtes plus intéressé par l'amplitude que par la fréquence. Les transformées de Fourier ne sont donc probablement pas utiles pour votre objectif particulier. Vous voulez probablement faire une mesure courante de l'amplitude à court terme (disons 10 ms) de l'entrée, et détecter quand elle augmente soudainement d'un certain delta. Vous aurez besoin d'ajuster les paramètres de :

  • qu'est-ce que la mesure de l'amplitude "à court terme" ?
  • quelle est l'augmentation du delta que vous recherchez
  • la rapidité avec laquelle le changement de delta doit se produire

Bien que j'aie dit que vous n'étiez pas intéressé par la fréquence, vous devriez peut-être commencer par effectuer un filtrage pour éliminer les composantes de basse et de haute fréquence. Cela pourrait vous aider à éviter certains "faux positifs". Vous pouvez le faire avec un filtre numérique FIR ou IIR ; le filtre de Fourier n'est pas nécessaire.

2 votes

Oui, ce que j'ai fait c'est prendre audioop.max(data,2) et changer sa valeur avec la précédente (de l'itération précédente). De cette façon, je peux détecter s'il y a une augmentation soudaine. Et ça marche bien ! Merci à vous tous ! :-)

6voto

max.haredoom Points 386

Je sais que c'est une vieille question, mais si quelqu'un cherche à nouveau ici... voir https://python-sounddevice.readthedocs.io/en/0.4.1/index.html .

Il y a un bel exemple de "Input to Ouput Pass-Through" ici. https://python-sounddevice.readthedocs.io/en/0.4.1/examples.html#input-to-output-pass-through .

... et beaucoup d'autres exemples également ...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X