0

My need is to play an audio file and have its contents on a 8x8 matrix in equalizer aspect as done in Piccolo quite like spectrum analyzer adapted for BeagleBone or RaspberryPI. This doesn't need the ambiant analysis from microphone : just visualisation when playing music on the same board.

Adafruit made a library that made the leds matrix control easy, what is missing is mostly the audio analysis down to a matrix for each audio chunk.

Languages maybe C or C++, but would be best if it's in Python code.For this there are good libraries like Timeside and aubio but I couldn't found out how to fill the leds matrix the same way as in Piccolo, even though I've tested some examples.

dlewin
  • 1,673
  • 1
  • 19
  • 37
  • You don't say what hardware you're using; the piccolo is an arduino, but if you want to program the display in Python, you need something like a Raspberry Pi. Adafruit have a tutorial for driving their i2c LED matrix displays from the R-Pi: https://learn.adafruit.com/matrix-7-segment-led-backpack-with-the-raspberry-pi – dpwe Jun 30 '14 at 17:41
  • Edited in that sense, thanks. The BeagleBackpack lib from Adafruit is only to drive the matrix, which is ok. The missing part is about the audio analyzer to drive these leds – dlewin Jul 02 '14 at 09:09

1 Answers1

2

To get a crude 8-band, 8-level ongoing spectral estimate (in Python, using numpy):

import numpy as np

fftsize = 4096  # about 100ms at 44 kHz; each bin will be ~ 10 Hz
# Band edges to define 8 octave-wide ranges in the FFT output
binedges = [8, 16, 32, 64, 128, 256, 512, 1024, 2048]
nbins = len(binedges)-1
# offsets to get our 48 dB range onto something useful, per band
offsets = [4, 4, 4, 4, 6, 8, 10, 12]
# largest value in ledval
nleds = 8
# scaling of LEDs per doubling in amplitude
ledsPerDoubling = 1.0
# initial value of per-band energy history
binval = 0.001 * np.ones(nbins, np.float)
newbinval = np.zeros(nbins, np.float)
# How rapidly the displays decay after a peak (depends on how often we're called)
decayConst = 0.9

if not_done:
    # somehow tap into the most recent 30-100ms of audio.  
    # Assume we get 44 kHz mono back
    waveform = get_latest_waveform()
    # find spectrum
    spectrum = np.abs(np.fft.rfft(waveform[:fftsize]))
    # gather into octave bands
    for i in range(nbins-1):
        newbinval[i] = np.mean(spectrum[binedges[i]:binedges[i+1]])
    # Peak smoothing - decay slowly after large values
    binval = np.maximum(newbinval, decayConst*binval)
    # Quantize into values 0..8 as the number of leds to light in each column
    ledval = np.round(np.maximum(0, np.minimum(nleds, 
                                               ledsPerDoubling * np.log2(binval) 
                                               + offsets)))
    # Now illuminate ledval[i] LEDs in column i (0..7) ...

Apart from grabbing the latest (4096 points of) waveform, this should give you the idea.

dpwe
  • 728
  • 5
  • 5