Sonomètre visuel - Niveau avancé
Ce projet reprend les éléments décrits sur cette page d'Adafruit :
https://learn.adafruit.com/adafruit-circuit-playground-express/playground-sound-meter
Utilisez le microphone de votre carte cpx pour mesurer les niveaux sonores et les visualiser à l'aide des LEDs RVB.
Le programme échantillonne l'audio pendant un court instant et calcule l'énergie dans l'échantillon (correspondant au volume) à l'aide d'un calcul (fonction normalized_rms). Vous pouvez essayer de varier la taille de l'échantillon si vous le souhaitez.
Le programme prend un échantillon lorsqu'il commence à régler un niveau sonore "silencieux". Si cela ne vous convient pas, définissez input_floor
comme un nombre fixe. Si le compteur semble trop sensible, essayez de changer input_ceiling = input_floor + 500
en input_ceiling = input_floor + 2000
ou plus. Ou aller dans l'autre sens.
La fonction log_scale()
fait varier le nombre de NeoPixels éclairés de manière exponentielle, car les niveaux sonores peuvent varier d'un facteur 10 entre le niveau le plus fort et celui le plus faible. Essayez de modifier la façon dont elle est calculée pour voir ce qui se passe.
Méthode : Le programme
# The MIT License (MIT)
#
# Copyright (c) 2017 Dan Halbert for Adafruit Industries
# Copyright (c) 2017 Kattni Rembor, Tony DiCola for Adafruit Industries
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import array
import math
import audiobusio
import board
import neopixel
# facteur d'echelle exponentielle.
# Les valeurs raisonables devraient être entre -10 et 10
CURVE = 2
SCALE_EXPONENT = math.pow(10, CURVE * -0.1)
PEAK_COLOR = (100, 0, 255)
NUM_PIXELS = 10
# Nombre d'echantillons à lire d'un coup
NUM_SAMPLES = 160
# contraint les valeurs dans un intervalle entre floor et ceilling
def constrain(value, floor, ceiling):
return max(floor, min(value, ceiling))
# equivalent de la fonction range_map déjà rencontrée mais en echelle exponentielle
def log_scale(input_value, input_min, input_max, output_min, output_max):
normalized_input_value = (input_value - input_min) / \
(input_max - input_min)
return output_min + \
math.pow(normalized_input_value, SCALE_EXPONENT) \
* (output_max - output_min)
def normalized_rms(values):
minbuf = int(mean(values))
samples_sum = sum(
float(sample - minbuf) * (sample - minbuf)
for sample in values
)
return math.sqrt(samples_sum / len(values))
def mean(values):
return sum(values) / len(values)
def volume_color(volume):
return 200, volume * (255 // NUM_PIXELS), 0
# Programme principal
# initialise les leds neopixels
pixels = neopixel.NeoPixel(board.NEOPIXEL, NUM_PIXELS,
brightness=0.1, auto_write=False)
pixels.fill(0)
pixels.show()
mic = audiobusio.PDMIn(board.MICROPHONE_CLOCK, board.MICROPHONE_DATA,
sample_rate=16000, bit_depth=16)
# Calibration du niveau de silence sur un échantillon au démarrage
samples = array.array('H', [0] * NUM_SAMPLES)
mic.record(samples, len(samples))
# définit le niveau minimum
input_floor = normalized_rms(samples) + 10
# OU utiliser une valeur fixée
# input_floor = 50
# You might want to print the input_floor to help adjust other values.
# print(input_floor)
# sensibilité: moins -> augmente le nb de pixels
input_ceiling = input_floor + 500
peak = 0
while True:
mic.record(samples, len(samples))
magnitude = normalized_rms(samples)
# You might want to print this to see the values.
# print(magnitude)
# Calcule l'échelle logarithmique de 0 à NUM_PIXELS
c = log_scale(constrain(magnitude, input_floor, input_ceiling),
input_floor, input_ceiling, 0, NUM_PIXELS)
# allume les LEDs
pixels.fill(0)
for i in range(NUM_PIXELS):
if i < c:
pixels[i] = volume_color(i)
if c >= peak:
peak = min(c, NUM_PIXELS - 1)
elif peak > 0:
peak = peak - 1
if peak > 0:
pixels[int(peak)] = PEAK_COLOR
pixels.show()