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  
10  #---| User Configuration |---------------------------
11  SAMPLERATE = 16000
12  SAMPLES = 1024
13  THRESHOLD = 100
14  MIN_DELTAS = 5
15  DELAY = 0.2
16  
17  #        octave = 1    2    3    4    5     6     7     8
18  NOTES = { "C" : (33,  65, 131, 262, 523, 1047, 2093, 4186),
19            "D" : (37,  73, 147, 294, 587, 1175, 2349, 4699),
20            "E" : (41,  82, 165, 330, 659, 1319, 2637, 5274),
21            "F" : (44,  87, 175, 349, 698, 1397, 2794, 5588),
22            "G" : (49,  98, 196, 392, 785, 1568, 3136, 6272),
23            "A" : (55, 110, 220, 440, 880, 1760, 3520, 7040),
24            "B" : (62, 123, 247, 494, 988, 1976, 3951, 7902)}
25  #----------------------------------------------------
26  
27  # Create a buffer to record into
28  samples = array.array('H', [0] * SAMPLES)
29  
30  # Setup the mic input
31  mic = audiobusio.PDMIn(board.MICROPHONE_CLOCK,
32                         board.MICROPHONE_DATA,
33                         sample_rate=SAMPLERATE,
34                         bit_depth=16)
35  
36  while True:
37      # Get raw mic data
38      mic.record(samples, SAMPLES)
39  
40      # Compute DC offset (mean) and threshold level
41      mean = int(sum(samples) / len(samples) + 0.5)
42      threshold = mean + THRESHOLD
43  
44      # Compute deltas between mean crossing points
45      # (this bit by Dan Halbert)
46      deltas = []
47      last_xing_point = None
48      crossed_threshold = False
49      for i in range(SAMPLES-1):
50          sample = samples[i]
51          if sample > threshold:
52              crossed_threshold = True
53          if crossed_threshold and sample < mean:
54              if last_xing_point:
55                  deltas.append(i - last_xing_point)
56              last_xing_point = i
57              crossed_threshold = False
58  
59      # Try again if not enough deltas
60      if len(deltas) < MIN_DELTAS:
61          continue
62  
63      # Average the deltas
64      mean = sum(deltas) / len(deltas)
65  
66      # Compute frequency
67      freq = SAMPLERATE / mean
68  
69      print("crossings: {}  mean: {}  freq: {} ".format(len(deltas), mean, freq))
70  
71      # Find corresponding note
72      for note in NOTES:
73          for octave, note_freq in enumerate(NOTES[note]):
74              if note_freq * 0.97 <= freq <= note_freq * 1.03:
75                  print("-"*10)
76                  print("NOTE = {}{}".format(note, octave + 1))
77                  print("-"*10)
78  
79      time.sleep(DELAY)