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)