Created
April 2, 2020 15:50
-
-
Save benevpi/5d65b399ac6adb020a363d0e17a1cbf7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Waterfall FFT demo adapted from | |
https://teaandtechtime.com/fft-circuitpython-library/ | |
to work with ulab on Adafruit CLUE""" | |
import array | |
import board | |
import audiobusio | |
import displayio | |
import ulab | |
import ulab.extras | |
import ulab.vector | |
display = board.DISPLAY | |
# Create a heatmap color palette | |
palette = displayio.Palette(52) | |
for i, pi in enumerate((0xff0000, 0xff0a00, 0xff1400, 0xff1e00, | |
0xff2800, 0xff3200, 0xff3c00, 0xff4600, | |
0xff5000, 0xff5a00, 0xff6400, 0xff6e00, | |
0xff7800, 0xff8200, 0xff8c00, 0xff9600, | |
0xffa000, 0xffaa00, 0xffb400, 0xffbe00, | |
0xffc800, 0xffd200, 0xffdc00, 0xffe600, | |
0xfff000, 0xfffa00, 0xfdff00, 0xd7ff00, | |
0xb0ff00, 0x8aff00, 0x65ff00, 0x3eff00, | |
0x17ff00, 0x00ff10, 0x00ff36, 0x00ff5c, | |
0x00ff83, 0x00ffa8, 0x00ffd0, 0x00fff4, | |
0x00a4ff, 0x0094ff, 0x0084ff, 0x0074ff, | |
0x0064ff, 0x0054ff, 0x0044ff, 0x0032ff, | |
0x0022ff, 0x0012ff, 0x0002ff, 0x0000ff)): | |
palette[51-i] = pi | |
class RollingGraph(displayio.TileGrid): | |
def __init__(self, scale=2): | |
# Create a bitmap with heatmap colors | |
self.bitmap = displayio.Bitmap(display.width//scale, | |
display.height//scale, len(palette)) | |
super().__init__(self.bitmap, pixel_shader=palette) | |
self.scroll_offset = 0 | |
def show(self, data): | |
y = self.scroll_offset | |
bitmap = self.bitmap | |
board.DISPLAY.auto_refresh = False | |
offset = max(0, (bitmap.width-len(data))//2) | |
for x in range(min(bitmap.width, len(data))): | |
bitmap[x+offset, y] = int(data[x]) | |
board.DISPLAY.auto_refresh = True | |
self.scroll_offset = (y + 1) % self.bitmap.height | |
class LineGraph(displayio.TileGrid): | |
def __init__(self, scale=2): | |
# Create a bitmap with heatmap colors | |
self.bitmap = displayio.Bitmap(display.width//scale, | |
display.height//scale, len(palette)) | |
super().__init__(self.bitmap, pixel_shader=palette) | |
self.scroll_colour = 10 | |
def show(self, data): | |
bitmap = self.bitmap | |
board.DISPLAY.auto_refresh = False | |
#offset = max(0, (bitmap.width-len(data))//2) | |
#for x in range(min(bitmap.width, len(data))): | |
# bitmap[x+offset, y] = int(data[x]) | |
for x in range(min(bitmap.width, len(data))): | |
for y in range(bitmap.height): | |
if data[x] < y: pass#bitmap[x,y] = 100 | |
else: bitmap[x,y] = self.scroll_colour | |
board.DISPLAY.auto_refresh = True | |
self.scroll_colour = self.scroll_colour + 1 | |
if self.scroll_colour > 50 : self.scroll_colour = 1 | |
#self.scroll_offset = (y + 1) % self.bitmap.height | |
group = displayio.Group(scale=3) | |
graph = LineGraph(3) | |
fft_size = 256 | |
# Add the TileGrid to the Group | |
group.append(graph) | |
# Add the Group to the Display | |
display.show(group) | |
# instantiate board mic | |
mic = audiobusio.PDMIn(board.MICROPHONE_CLOCK, board.MICROPHONE_DATA, | |
sample_rate=16000, bit_depth=16) | |
#use some extra sample to account for the mic startup | |
samples_bit = array.array('H', [0] * (fft_size+3)) | |
#this gets 256 samples at a rate of 16000Hz | |
#and the sprectrogram returns 256 data points. | |
#each'bit' of the spectrogram should then be 16000/256 hz. = 62.5Hz | |
# hang on, does that make any sense? | |
# shouldn't each bit be 1/16000hz? | |
#fuck it, brute force. 440=index 6 | |
# 880 = index 13 | |
# 1320 - index 20 | |
# 220 = between 2 and three | |
#what if I change the sample rate? | |
# Main Loop | |
def main(): | |
max_all = 10 | |
while True: | |
mic.record(samples_bit, len(samples_bit)) | |
samples = ulab.array(samples_bit[3:]) | |
#print(len(samples)) | |
spectrogram1 = ulab.extras.spectrogram(samples) | |
# spectrum() is always nonnegative, but add a tiny value | |
# to change any zeros to nonzero numbers | |
spectrogram1 = ulab.vector.log(spectrogram1 + 1e-7) | |
#print(len(spectrogram1)) | |
spectrogram1 = spectrogram1[1:(fft_size//2)-1] | |
min_curr = ulab.numerical.min(spectrogram1)[0] | |
max_curr = ulab.numerical.max(spectrogram1)[0] | |
index=0 | |
for item in spectrogram1: | |
if item == max_curr: | |
print(index) | |
index=index+1 | |
if max_curr > max_all: | |
max_all = max_curr | |
else: | |
max_curr = max_curr-1 | |
#print(min_curr, max_all) | |
min_curr = max(min_curr, 3) | |
# Plot FFT | |
data = (spectrogram1 - min_curr) * (51. / (max_all - min_curr)) | |
# This clamps any negative numbers to zero | |
data = data * ulab.array((data > 0)) | |
graph.show(data) | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment