from array import array
from math import log
from time import monotonic
from supervisor import reload
import board
from audiobusio import PDMIn
from busio import I2C
import adafruit_is31fl3741
from adafruit_is31fl3741 import PREFER_BUFFER
from adafruit_is31fl3741.adafruit_rgbmatrixqt import Adafruit_RGBMatrixQT
from rainbowio import colorwheel
from ulab import numpy as np
from ulab.scipy.signal import spectrogram

i2c=I2C(board.SCL,board.SDA,frequency=1000000)

is31 = Adafruit_RGBMatrixQT(i2c, allocate=PREFER_BUFFER)

is31.set_led_scaling(0x19)
is31.global_current=0x03
is31.enable=True

heatmap=[0xb000ff,0xa600ff,0x9b00ff,0x8f00ff,0x8200ff,
 0x7400ff,0x6500ff,0x5200ff,0x3900ff,0x0003ff,
 0x00a6ff,0x00b7ff,0x0066ff,0x007eff,0x0093ff,
 0x00e0ff,0x00e6fd,0x00ecf6,0x00f2ea,0x00f6d7,
 0x00ff16,0xaaff00,0xb8ff00,0xc5ff00,0xffab00,
 0xedff00,0xf5eb00,0xfcd600,0xffc100,0xff0000,
 0xff9500,0xff7c00,0xff6100,0xff4100,0xff0000,
 0xff0000,0xff0000]

fft_size=64
mic=audiobusio.PDMIn(board.D8,board.D9,sample_rate=16000,bit_depth=16)

samples_bit=array.array('H',[0]*(fft_size+3))

def waves(data,y):
    offset=max(0,(13-len(data))//2)
    
    for x in range(min(13, len(data))):
        is31.pixel(x+offset,y,heatmap[int(data[x])])
        
def main():
    max_all=10
    scroll_offset=0
    y=scroll_offset
    
    while True:
        mic.record(samples_bit,len(samples_bit))
        samples=np.array(samples_bit[3:])
        
        spectrogram1=spectrogram(samples)
        spectrogram1=np.log(spectrogram1 + 1e-7)
        spectrogram1=spectrogram1[1:(fft_size//2)-1]
        
        min_curr=np.min(spectrogram1)
        max_curr=np.max(spectrogram1)
        
        if max_curr>max_all:
            max_all=max_curr
        else:
            max_curr=max_curr-1
        min_curr=max(min_curr,3)
        
        data=(spectrogram1-min_curr)*(51./(max_all-mi_curr))
        
        data=data*np.array((data>0))
        
        y=scroll_offset
        
        waves(data,y)
        scroll_offset=(y+1)%9
        is31.show()
        
main()