Back to: Multiplier Event Luxembourg
import array
import audiobusio
import board
import math
import time
from adafruit_circuitplayground import cp
# Define color of the peak pixel.
PEAK_COLOR = (80, 0, 255)
# Exponential scaling factor.
# Should probably be in range -10 .. 10 to be reasonable.
# CURVE is used to make
# - the readings more or less sensitive and
# - the display more or less jumpy.
CURVE = 10
SCALE_EXPONENT = math.pow(10, CURVE * -0.1)
# Define the number of samples that should be read at once.
NUM_SAMPLES = 160
# Return a normalized root mean square (RMS) average.
# Calculate the RMS value to measure the average loudness of a sound waveform.
def normalized_rms(samples):
mean = sum(samples) / len(samples)
return math.sqrt(sum((sample - mean) * (sample - mean) for sample in samples) / len(samples))
# Configure the microphone object and the samples variable.
mic = audiobusio.PDMIn(board.MICROPHONE_CLOCK, board.MICROPHONE_DATA, sample_rate = 16000, bit_depth = 16)
samples = array.array('H', [0] * NUM_SAMPLES)
# Initialize the mic object. Assume that it is quiet when started.
mic.record(samples, len(samples))
# Set the lowest expected level, plus a slight increase.
input_floor = normalized_rms(samples) + 10
# OR
# Use a fixed floor
#input_floor = 50
# Lower sensitivity number means more sensitive; more NeoPixels will light up with less sound.
# If the meter seems too sensitive, the sensitivity number can be adjusted.
sensitivity = 500
input_ceiling = input_floor + sensitivity
peak = 0
# Loop forever
while True:
# Sound samples are taken by the mic object.
mic.record(samples, len(samples))
# Use the normalized RMS to calculate the average of a set of samples, namely the magnitude of this set of samples.
magnitude = normalized_rms(samples)
# Compute scaled logarithmic reading in the range 0 to 10,
# as 10 NeoPixels are built into the Circuit Playground Express board.
constrain = max(input_floor, min(magnitude, input_ceiling))
scale = math.pow((constrain - input_floor) / (input_ceiling - input_floor), SCALE_EXPONENT) * 10
# The pixels below the scaled and interpolated magnitude are lit up.
cp.pixels.fill((0, 0, 0))
for p in range(10):
if p < scale:
cp.pixels[p] = (200, p * (255 // 10), 0)
# Light up the peak pixel and animate it slowly dropping.
if scale >= peak:
peak = min(scale, 9)
elif peak > 0:
peak = peak - 1
if peak > 0:
cp.pixels[int(peak)] = PEAK_COLOR
# Depending on the switch, write to
# * the serial console (if True, i.e. left), or to
# * the CircuitPython storage (if False, i.e. right).
if cp.switch:
print("The magnitude of the set of samples is", magnitude)
print( (magnitude, ) )
else:
f = open("magnitude.csv", "a")
f.write(repr(magnitude) + "\n")
f.close()
import storage
from adafruit_circuitplayground import cp
storage.remount("/", readonly=cp.switch)
