Source code for BiblioPixelAnimations.cube.spectrum

from bibliopixel.animation.cube import Cube
from bibliopixel.util import log
from bibliopixel.layout import matrix
from . system_eq import EQ


[docs]class BaseSpectrumDraw: def __init__(self, frame): self.frame = frame self.width = frame.x self.height = frame.y self.height_map = [((i * (self.height - 1)) // (1023)) for i in range(1024)] self.width_map = [((i * (self.width - 1)) // (1023)) for i in range(1024)]
[docs] def draw(self, data): raise NotImplementedError("Cannot call draw on the base class.")
[docs] def draw_bar(self, x, y, w, h, c, fill=True): if w > 1: if fill: self.frame.fill_rect(x, y, w, h, c) else: self.frame.draw_rect(x, y, w, h, c) else: self.frame._draw_fast_vline(x, y, h, c)
[docs] def color_map(self, width, offset=0): return [self.palette((((i * (255)) // (width - 1)) + offset) % 256) for i in range(width)]
[docs]class PeakLineGraph(BaseSpectrumDraw): def __init__(self, frame): super().__init__(frame) self.peak_dots = True self.peaks = [0] * self.width
[docs] def draw(self, data, amt=1): chan = len(data) bar_w = int(self.width // chan) pos = (self.width - (bar_w * chan)) // 2 color_list = self.color_map(chan) count = 0 for level in data: c = color_list[count] h = self.height_map[level] if h: self.draw_bar(pos, self.height - h, bar_w, h, c, fill=True) if self.peak_dots: if self.peaks[count] > 0 and self.peaks[count] > h: for i in range(bar_w): self.frame.set(pos + i, self.height - self.peaks[count], c) if h >= self.peaks[count]: self.peaks[count] = h else: self.peaks[count] -= 1 if self.peaks[count] < 0: self.peaks[count] = 0 pos += bar_w count += 1
[docs]class BasicLineGraph(PeakLineGraph): def __init__(self, frame): super().__init__(frame) self.peak_dots = False
[docs]class Spread(BaseSpectrumDraw): def __init__(self, frame): super().__init__(frame) self.center_line = self.height // 2 self.offset = 0 self.color_offset = 0 self.inverse = False self.scroll = False
[docs] def draw(self, data, amt=1): chan = len(data) color_list = self.color_map(chan, self.color_offset) bar_w = int(self.width // chan) pos = (self.width - (bar_w * chan)) // 2 for i in range(chan): h = self.height_map[data[(i + self.offset) % len(data)]] c = color_list[i] if self.inverse: self.draw_bar(pos, 0, bar_w, self.center_line - h, c) self.draw_bar(pos, self.center_line + h, bar_w, self.height - h, c) else: if h: self.draw_bar(pos, self.center_line - h, bar_w, h, c) self.draw_bar(pos, self.center_line, bar_w, h, c) pos += bar_w if self.scroll: self.offset += amt self.color_offset += amt
[docs]class ScrollSpread(Spread): def __init__(self, frame): super().__init__(frame) self.scroll = True
[docs]class InverseSpread(Spread): def __init__(self, frame): super().__init__(frame) self.inverse = True
[docs]class InverseScrollSpread(Spread): def __init__(self, frame): super().__init__(frame) self.scroll = True self.inverse = True
DEFAULT_VIS_LIST = [ Spread, ScrollSpread, InverseSpread, InverseScrollSpread, PeakLineGraph, BasicLineGraph ]
[docs]class FrameDraw(object): def __init__(self, anim): self.x = anim.x self.y = anim.y self.frame = [[(0, 0, 0)] * anim.x] * anim.y
[docs] def set(self, x, y, color): self.frame[y][x] = color
[docs] def draw_rect(self, x, y, w, h, color): matrix.draw_rect(self.set, x, y, w, h, color)
[docs] def fill_rect(self, x, y, w, h, color): matrix.fill_rect(self.set, x, y, w, h, color)
def _draw_fast_vline(self, x, y, h, color): matrix._draw_fast_vline(self.set, x, y, h, color)
[docs]class Spectrum(Cube): def __init__(self, layout, vis_list=None, steps_per_vis=None, bins=64, max_freq=4000, log_scale=True, auto_gain=False, gain=3, **kwds): super().__init__(layout, **kwds) self.source = EQ(bins=bins, max_freq=max_freq, log_scale=log_scale, auto_gain=auto_gain, gain=gain) self.x, self.y, self.z = layout.x, layout.y, layout.z self.frames = [[[(0, 0, 0)] * self.x] * self.y] * self.z self.frame = FrameDraw(self) self.draw_obj = None self.steps_per_vis = steps_per_vis self.vis_dict = {} for v in DEFAULT_VIS_LIST: self.vis_dict[v.__name__] = v(self.frame) self.vis_list = vis_list if not self.vis_list: self.vis_list = [v.__name__ for v in DEFAULT_VIS_LIST] self.cur_vis = len(self.vis_list) self.next_draw_obj()
[docs] def pre_run(self): self._step = 0 self.source.start()
def _exit(self, type, value, traceback): self.source.stop()
[docs] def next_draw_obj(self): self.cur_vis += 1 if self.cur_vis >= len(self.vis_list): self.cur_vis = 0 if self.draw_obj: del self.draw_obj name = self.vis_list[self.cur_vis] log.debug("Loading {}".format(name)) self.draw_obj = self.vis_dict[name]
[docs] def step(self, amt=1): assert self.draw_obj, "No loaded visualizers!" self.layout.all_off() data = self.source.get_audio_data() self.draw_obj.draw(data, amt) print(self.frame.frame) self.frames[0] = self.frame.frame[:] for z in range(1): for y in range(self.y): for x in range(self.x): self.layout.set(x, y, z, self.frames[z][y][x]) if self.steps_per_vis: self._step += 1 if self._step % self.steps_per_vis == 0: self.next_draw_obj()