Accueil » 1er Partie – Détecter le frappement de main avec le microphone

1er Partie – Détecter le frappement de main avec le microphone

On souhaite programmer le robot MR25 pour détecter un frappement de main en utilisant le microphone.

👏👏👏

Voici un exemple de programme pour détecter le frappement de main :

-> la led rouge s’allume lors d’une détection de frappement de main

import subprocess
import numpy as np
import MR25, time

# Paramètres
DEVICE = "hw:0,0"
RATE = 48000
CHANNELS = 1
CHUNK = 1024

# Seuil de détection
THRESHOLD = 0.01

cmd = [
"arecord",
"-D", DEVICE,
"-f", "S16_LE",
"-r", str(RATE),
"-c", str(CHANNELS),
"-t", "raw",
"-"
]

print("Écoute du microphone...")
print("Frappez dans vos mains pour tester.")
print("Ctrl+C pour arrêter.\n")

process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL
)

try:
while True:
data = process.stdout.read(CHUNK * 2)

if len(data) != CHUNK * 2:
break

# Conversion des échantillons 16 bits
audio = np.frombuffer(data, dtype=np.int16)

# Normalisation entre -1 et +1
audio = audio.astype(np.float32) / 32768.0

# Calcul RMS
volume = np.sqrt(np.mean(audio ** 2))

# Affichage du niveau
bar = int(volume * 50)
print(
f"\rVolume : {volume:.3f} "
f"[{'#' * bar:<50}]",
end="",
flush=True
)

# Détection
if volume > THRESHOLD:
print("\n>>> FRAPPEMENT DETECTE ! <<<")
MR25.ledRGB("100") # allumer led rouge
time.sleep(1)
MR25.ledRGB("000") # eteindre led rouge

except KeyboardInterrupt:
print("\n\nArrêt.")

finally:
process.terminate()

Algorithme

  1. Acquisition audio
    • 1
      arecord

      capture le microphone à 48 kHz, en mono, avec des échantillons

      1
      16 bits

      .

    • Les données sont lues par blocs de 1024 échantillons.
  2. Conversion des données
    • Les octets reçus sont convertis en entiers
      1
      int16

      .

    • Ils sont ensuite normalisés entre
      1
      -1

      et

      1
      +1

      :

  3. Calcul du niveau sonore
    • Le programme calcule la valeur RMS (Root Mean Square) du bloc.
  4. Comparaison avec un seuil
    • Le niveau calculé est comparé à
      1
      THRESHOLD
  5. Action
    • La LED rouge du robot
      1
      MR25

      s’allume.

Détection de plusieurs frappements de main

👏👏👏

Voici un autre exemple de programme pour détecter plusieurs frappement de main :

  • 1 frappement de main -> LED ROUGE
  • 2 frappements de main -> LED VERTE
  • 3 frappements de main -> LED BLEU 
import subprocess
import numpy as np
import MR25
import time

DEVICE = "hw:0,0"
RATE = 48000
CHANNELS = 1
CHUNK = 1024

THRESHOLD = 0.01

# Temps minimum entre deux frappes
DEBOUNCE_TIME = 0.20

# Temps maximum pour regrouper les frappes
GROUP_TIMEOUT = 0.80

cmd = [
"arecord",
"-D", DEVICE,
"-f", "S16_LE",
"-r", str(RATE),
"-c", str(CHANNELS),
"-t", "raw",
"-"
]

process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL
)

nombre_frappes = 0
derniere_frappe = 0
dernier_signal = 0

print("Écoute du microphone...")
print("1 frappe = LED rouge")
print("3 frappes = LED verte")
print("Ctrl+C pour arrêter.\n")

try:
while True:

data = process.stdout.read(CHUNK * 2)

if len(data) != CHUNK * 2:
break

audio = np.frombuffer(data, dtype=np.int16)
audio = audio.astype(np.float32) / 32768.0

volume = np.sqrt(np.mean(audio ** 2))

maintenant = time.time()

# Affichage du volume
bar = min(50, int(volume * 50))

print(
f"\rVolume : {volume:.3f} "
f"[{'#' * bar:<50}] "
f"Frappes : {nombre_frappes}",
end="",
flush=True
)

# Détection d'une frappe
if volume > THRESHOLD:

# Évite de compter plusieurs fois la même frappe
if maintenant - derniere_frappe > DEBOUNCE_TIME:

nombre_frappes += 1
derniere_frappe = maintenant

print(f"\n>>> Frappe {nombre_frappes}")

# Si le délai entre les frappes est dépassé,
# on analyse le nombre de frappes
if (
nombre_frappes > 0
and maintenant - derniere_frappe > GROUP_TIMEOUT
):

if nombre_frappes == 1:
print(">>> 1 FRAPPE : LED ROUGE")
MR25.ledRGB("100")
time.sleep(0.5)
MR25.ledRGB("000")

elif nombre_frappes == 2:
print(">>> 2 FRAPPES : LED VERTE")
MR25.ledRGB("010")
time.sleep(0.5)
MR25.ledRGB("000")

elif nombre_frappes == 3:
print(">>> 3 FRAPPES : LED BLEU")
MR25.ledRGB("001")
time.sleep(0.5)
MR25.ledRGB("000")

else:
print(f">>> {nombre_frappes} frappes : aucune action")

# Réinitialisation
nombre_frappes = 0

except KeyboardInterrupt:
print("\n\nArrêt.")

finally:
process.terminate()

Fin du tuto !