Skip to content

Commit

Permalink
fix stereo visualization
Browse files Browse the repository at this point in the history
  • Loading branch information
rbn42 committed Sep 24, 2017
1 parent d657298 commit 3126aa4
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 50 deletions.
16 changes: 4 additions & 12 deletions panon/visualizer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from .. import config
from .fallback import VisualizerCairo
from .opengl import VisualizerGL
from .source import Source
from .spectrum import Spectrum
from queue import Queue
from threading import Thread
Expand All @@ -23,20 +22,13 @@ def tick(self):
def destory(self):
self.stop_gen_data = True

def __init__(self, background_color, fps=60, channel_count=2, sample_rate=44100, padding=4, use_opengl=False):
def __init__(self, background_color, fps=60, padding=4, use_opengl=False):
super(Visualizer, self).__init__()
self.sample_rate = sample_rate
self.background_color = helper.color(background_color)
self.data_queue = Queue(3)

self.padding = padding
self.fps = fps
self.channel_count = channel_count
self.sample_rate = sample_rate
self.sample = Source(channel_count, sample_rate)
buffer_size = sample_rate // fps * channel_count
self.spectrum = Spectrum(
self.sample, buffer_size, config.visualizer_decay)
self.spectrum = Spectrum(fps, config.visualizer_decay)
GObject.timeout_add(1000 // fps, self.tick)

self.use_opengl = use_opengl
Expand Down Expand Up @@ -67,11 +59,11 @@ def do_button_release_event(self, widget, event=None):
if event and event.button == 1:
if not self.stop:
self.da.stop()
self.sample.stop()
self.spectrum.stop()
self.stop = True
else:
self.stop = False
self.sample.start()
self.spectrum.start()
self.da.start()
return True
else:
Expand Down
18 changes: 11 additions & 7 deletions panon/visualizer/fallback.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ def do_draw_cb(self, widget, cr):
if self.empty:
return
bins = self.getData()
assert bins.shape[0]==2
x, y = self.padding, self.padding
w, h = w - 2 * self.padding, h - 2 * self.padding

Expand All @@ -77,14 +78,17 @@ def do_draw_cb(self, widget, cr):
cr.set_source(source)
cr.set_operator(cairo.OPERATOR_SOURCE)
cr.move_to(x + 0, y + h / 2) # middle left
width = 2 * w / len(bins)
for i in range(len(bins) // 2):
height = rel * h * bins[i]
width = w / bins.shape[1]
for i in range(bins.shape[1]):
height = rel * h * bins[0,i]
cr.line_to(x + i * width, y + h / 2 - height / 2)
cr.line_to(x + w, y + h / 2) # middle right
for i in range(len(bins) // 2, len(bins)):
freq = len(bins) - i
height = rel * h * bins[i]
cr.line_to(x + freq * width, y + h / 2 + height / 2)
cr.close_path()

cr.move_to(x + 0, y + h / 2) # middle left
for i in range(bins.shape[1]):
height = rel * h * bins[1,i]
cr.line_to(x + i * width, y + h / 2 + height / 2)
cr.line_to(x + w, y + h / 2) # middle right
cr.close_path()
cr.fill()
75 changes: 44 additions & 31 deletions panon/visualizer/spectrum.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,57 @@
import numpy as np
from .source import Source


class Spectrum:
def __init__(self, sample, buffer_size, decay):
self.sample = sample

def __init__(self, fps, decay, channel_count=2, sample_rate=44100,):
self.sample = Source(channel_count, sample_rate)
self.decay = decay
self.history = np.zeros(buffer_size * 8, dtype='int16')
self.history_index = 0

buffer_size = sample_rate // fps
self.buffer_size = buffer_size

self.history = np.zeros(
(channel_count, buffer_size * 8), dtype='int16')
self.history_index = 0

self.min_sample = 10
self.max_sample = self.min_sample

def stop(self):
self.sample.stop()

def start(self):
self.sample.start()

def updateHistory(self):

data = self.sample.read()
data = np.fromstring(data, 'int16')
assert len(data) < len(self.history)
if self.history_index + len(data) > len(self.history):
self.history[self.history_index:] = data[:len(
self.history) - self.history_index]
self.history[:self.history_index + len(data) - len(
self.history)] = data[len(self.history) - self.history_index:]
self.history_index -= len(self.history)

len_data = len(data) // self.history.shape[0]

len_history = self.history.shape[1]
index = self.history_index
assert len_data < len_history

data = data.reshape((len_data, self.history.shape[0]))
data = np.rollaxis(data, 1)

if index + len_data > len_history:
self.history[:, index:] = data[:, :len_history - index]
self.history[:, :index + len_data -
len_history] = data[:, len_history - index:]
self.history_index -= len_history
else:
self.history[self.history_index:self.history_index +
len(data)] = data
self.history_index += len(data)
self.history[:, index:index + len_data] = data
self.history_index += len_data

data_history = np.concatenate([
self.history[self.history_index:],
self.history[:self.history_index],
])
self.history[:, self.history_index:],
self.history[:, :self.history_index],
], axis=1)

return data_history

def getData(self):
Expand All @@ -40,21 +61,13 @@ def getData(self):

def fun(start, end, rel):
size = self.buffer_size
if rel > 20:
start, end = int(start), int(end)
rel = int(rel)
d = data_history[-size * rel:].reshape((rel, size))
d = np.mean(d, axis=0)
else:
start = int(start * rel)
end = int(end * rel)
size = int(size * rel)
d = data_history[-size:]
start = int(start * rel)
end = int(end * rel)
size = int(size * rel)
d = data_history[:, -size:]

fft = np.absolute(np.fft.rfft(d, n=size))
end = min(len(fft) // 2, end)
fft_freq.insert(0, fft[start:end])
fft_freq.append(fft[len(fft) - end:len(fft) - start])
fft_freq.insert(0, fft[:, start:end])

# higher resolution and latency for lower frequency
fun(110, 150, 2)
Expand All @@ -64,7 +77,7 @@ def fun(start, end, rel):
fun(10, 30, 6)
fun(0, 10, 8)

fft = np.concatenate(fft_freq)
fft = np.concatenate(fft_freq, axis=1)

exp = 2
retain = (1 - self.decay)**exp
Expand Down

0 comments on commit 3126aa4

Please sign in to comment.