code.py
1 # SPDX-FileCopyrightText: 2019 Carter Nelson for Adafruit Industries 2 # 3 # SPDX-License-Identifier: MIT 4 5 import time 6 import array 7 import board 8 import audiobusio 9 import simpleio 10 import neopixel 11 12 #---| User Configuration |--------------------------- 13 SAMPLERATE = 16000 14 SAMPLES = 1024 15 THRESHOLD = 100 16 MIN_DELTAS = 5 17 DELAY = 0.2 18 19 FREQ_LOW = 520 20 FREQ_HIGH = 990 21 COLORS = ( 22 (0xFF, 0x00, 0x00) , # pixel 0 23 (0xFF, 0x71, 0x00) , # pixel 1 24 (0xFF, 0xE2, 0x00) , # pixel 2 25 (0xAA, 0xFF, 0x00) , # pixel 3 26 (0x38, 0xFF, 0x00) , # pixel 4 27 (0x00, 0xFF, 0x38) , # pixel 5 28 (0x00, 0xFF, 0xA9) , # pixel 6 29 (0x00, 0xE2, 0xFF) , # pixel 7 30 (0x00, 0x71, 0xFF) , # pixel 8 31 (0x00, 0x00, 0xFF) , # pixel 9 32 ) 33 #---------------------------------------------------- 34 35 # Create a buffer to record into 36 samples = array.array('H', [0] * SAMPLES) 37 38 # Setup the mic input 39 mic = audiobusio.PDMIn(board.MICROPHONE_CLOCK, 40 board.MICROPHONE_DATA, 41 sample_rate=SAMPLERATE, 42 bit_depth=16) 43 44 # Setup NeoPixels 45 pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, auto_write=False) 46 47 while True: 48 # Get raw mic data 49 mic.record(samples, SAMPLES) 50 51 # Compute DC offset (mean) and threshold level 52 mean = int(sum(samples) / len(samples) + 0.5) 53 threshold = mean + THRESHOLD 54 55 # Compute deltas between mean crossing points 56 # (this bit by Dan Halbert) 57 deltas = [] 58 last_xing_point = None 59 crossed_threshold = False 60 for i in range(SAMPLES-1): 61 sample = samples[i] 62 if sample > threshold: 63 crossed_threshold = True 64 if crossed_threshold and sample < mean: 65 if last_xing_point: 66 deltas.append(i - last_xing_point) 67 last_xing_point = i 68 crossed_threshold = False 69 70 # Try again if not enough deltas 71 if len(deltas) < MIN_DELTAS: 72 continue 73 74 # Average the deltas 75 mean = sum(deltas) / len(deltas) 76 77 # Compute frequency 78 freq = SAMPLERATE / mean 79 80 print("crossings: {} mean: {} freq: {} ".format(len(deltas), mean, freq)) 81 82 # Show on NeoPixels 83 pixels.fill(0) 84 pixel = round(simpleio.map_range(freq, FREQ_LOW, FREQ_HIGH, 0, 9)) 85 pixels[pixel] = COLORS[pixel] 86 pixels.show() 87 88 time.sleep(DELAY)