Skip to content

Commit

Permalink
add meters to bridge qt
Browse files Browse the repository at this point in the history
  • Loading branch information
dctucker committed Mar 29, 2024
1 parent 9bc1826 commit 62cb8b4
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 16 deletions.
1 change: 1 addition & 0 deletions bridge/bridge.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ def check_connections(client, port):
last_attempt = now
if capture.ok:
x = capture.listen()
capture.sync()

if control.ok:
control.listen()
Expand Down
52 changes: 52 additions & 0 deletions bridge/capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,55 @@
from view import log
from bindings.capmix import capmix, Type

import pyaudio
import numpy as np
import math

def addr_channel(addr):
return ((addr & 0x0f00) >> 8) + 1

def addr_monitor(addr):
return ((addr & 0x0f000) >> 12)

class Meter:
def __init__(self, size=10):
self.index = 0
self.values = [-132 for x in range(0, size)]
self.size = size

def average(self):
return np.mean(self.values)

def append(self, value):
self.values[self.index] = value
self.index += 1
if self.index >= self.size:
self.index = 0

class Capture:
def __init__(self, name='STUDIO-CAPTURE MIDI 2'):
capmix.set_model(4)
self.name = name
self.ok = False

self.rmsdb = [-132 for x in range(18)]
self.meters = [Meter() for x in range(18)]

def sync(self):
for i in range(16):
self.model.meters[i] = self.meters[i].average()

def get_callback(self):
def audio_callback(in_data, frame_count, time_info, status_flags):
frame = np.frombuffer(in_data, dtype=np.float32)
channels = [frame[idx::18] for idx in range(18)]
rms = [ np.sqrt(np.mean(np.absolute(c)**2)) for c in channels ]
self.rmsdb = [ int(20 * math.log10(abs(x))) for x in rms ]
for i in range(18):
self.meters[i].append(self.rmsdb[i])
return (None, pyaudio.paContinue)
return audio_callback

def listener(self, event):
value = event.value()
self.model.set_cache(event.addr, value)
Expand Down Expand Up @@ -44,15 +81,30 @@ def listener(self, event):

log("addr=%x=%s type=%s v=%s" % (event.addr, addr, event.type_name(), value))

#def find_card(self):
# card_name = "STUDIOCAPTURE"
# with open("/proc/asound/cards",'r') as file:
# for line in file.readlines():
# if card_name in line:
# return True
# return False

def connect(self):
self.ok = capmix.connect(self.listener)
if not self.ok:
log("Unable to connect to STUDIO-CAPTURE")
return False

self.pa = pyaudio.PyAudio()
names = [ self.pa.get_device_info_by_index(i)['name'].split(':')[0] for i in range(self.pa.get_device_count())]
idx = names.index('STUDIO-CAPTURE')
self.dev = self.pa.open(rate=96000, input_device_index=idx, format=pyaudio.paFloat32, channels=18, input=True, stream_callback=self.get_callback())

self.view.dim(False)
sleep(1)
self.get_mixer_data()
self.ok = True

return True

def disconnect(self):
Expand Down
18 changes: 12 additions & 6 deletions bridge/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,26 @@ def __init__(self, create=True):
#self.solos = { (ch+1): { mon: 0 for mon in self.monitors } for ch in range(0, self.num_channels) }
#self.pans = { (ch+1): Value.parse(Type.Pan, "C") for ch in range(0, 16) }

span = len(self.monitors) * self.num_channels
n_controls = 6
size = n_controls * span

shm_path = 'pimix'
if create:
create = not exists('/dev/shm/' + shm_path)
if create:
shm = shared_memory.SharedMemory(shm_path, create=True, size=16*self.num_channels)
shm = shared_memory.SharedMemory(shm_path, create=True, size=size)
else:
shm = shared_memory.SharedMemory(shm_path, create=False)
unregister(shm._name, 'shared_memory')

self.data = np.ndarray(shape=(16,4,4), dtype=np.int8, buffer=shm.buf)
self.stereo = ShmStereoLink( np.ndarray(shape=(16,4), dtype=np.int8, buffer=shm.buf[0:]) )
self.mutes = ShmChannels( np.ndarray(shape=(16,4), dtype=np.int8, buffer=shm.buf[64:]) )
self.solos = ShmChannels( np.ndarray(shape=(16,4), dtype=np.int8, buffer=shm.buf[128:]) )
self.pans = ShmChannels( np.ndarray(shape=(16,4), dtype=np.int8, buffer=shm.buf[192:]) )
self.data = np.ndarray(shape=(self.num_channels,len(self.monitors),n_controls), dtype=np.int8, buffer=shm.buf)
self.stereo = ShmStereoLink( np.ndarray(shape=(16,4), dtype=np.int8, buffer=shm.buf[0*span:]) )
self.mutes = ShmChannels( np.ndarray(shape=(16,4), dtype=np.int8, buffer=shm.buf[1*span:]) )
self.solos = ShmChannels( np.ndarray(shape=(16,4), dtype=np.int8, buffer=shm.buf[2*span:]) )
self.pans = ShmChannels( np.ndarray(shape=(16,4), dtype=np.int8, buffer=shm.buf[3*span:]) )
self.volume = ShmChannels( np.ndarray(shape=(16,4), dtype=np.int8, buffer=shm.buf[4*span:]) )
self.meters = np.ndarray(shape=(16,), dtype=np.float32, buffer=shm.buf[5*span:])
self.shm = shm

self.capture_hash = {}
Expand Down
56 changes: 46 additions & 10 deletions bridge/qt.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,33 @@
class GLWidget(QOpenGLWidget):
def __init__(self, parent=None):
QOpenGLWidget.__init__(self, parent)

self.painter = QPainter()
self.pen_grey = QPen(QColor(192,192,192))
self.pen_black = QPen(QColor(0,0,0))
self.font = QFont('ChicagoFLF', 9)

self.setFixedSize(800,400)
self.glrect = QRect(0,0,800,400)
self.background = QBrush(QColor(1,1,1))
self.foreground = QBrush(QColor(200,200,0))
self.pen_fg = QPen(self.foreground.color())
self.stereo_on = QBrush(QColor(0,200,200))
self.button_on = QBrush(QColor(200,0,0))
self.button_off = QBrush(QColor(50,50,50))
self.pan_brush = QBrush(QColor(224,128,0))
self.pan_pen = QPen(self.pan_brush.color())

self.iteration = 0
self.timer = QTimer(self)
self.timer.timeout.connect(self.timeout)
self.timer.start(16)
self.iteration = 0
self.timer.start(64)

def repaint(self):
self.iteration += 1
painter = QPainter()
painter = self.painter
painter.begin(self)
painter.setFont(self.font)
size = self.glrect
painter.fillRect(QRect(0, 0, size.width(), size.height()), self.background)
width = int(size.width())
Expand All @@ -52,7 +61,7 @@ def repaint(self):
left = ch * col_width
top = row_height

painter.setPen(QPen(QColor(192,192,192)))
painter.setPen(self.pen_grey)
rect = QRect(left, top, col_width * 2, 20)
painter.drawText(rect, Qt.AlignHCenter, labels[ch//2])
top += row_height
Expand All @@ -61,13 +70,13 @@ def repaint(self):
color = self.stereo_on
rect = QRect(left+2*col_spacing, top, col_width * 2 - 2*col_spacing, 20)
painter.fillRect(rect, color)
painter.setPen(QPen(QColor(0,0,0)))
painter.setPen(self.pen_black)
painter.drawText(rect, Qt.AlignHCenter, "%d / %d" % (ch+1, ch+2))
else:
color = self.button_off
rect = QRect(left+2*col_spacing, top, col_width - 2*col_spacing, 20)
painter.fillRect(rect, color)
painter.setPen(QPen(QColor(192,192,192)))
painter.setPen(self.pen_grey)
painter.drawText(rect, Qt.AlignHCenter, "%d" % (ch+1))

left = (ch+1) * col_width
Expand All @@ -85,7 +94,7 @@ def repaint(self):
pan_top = int(top+20-7 - abs(p / math.tan(math.radians(60))))
poly = QPolygon((QPoint(center, top+20), QPoint(center+p, top+20), QPoint(center+p, pan_top)))
painter.setBrush(self.pan_brush)
painter.setPen(QPen(self.pan_brush.color()))
painter.setPen(self.pan_pen)
painter.drawPolygon(poly)
#painter.fillRect(QRect(center, top, p, 20), self.pan_brush)

Expand All @@ -94,14 +103,41 @@ def repaint(self):
color = self.button_on if model.mutes[ch+1][m] > 0 else self.button_off
if model.solos[ch+1][m]:
color = QColor(self.stereo_on)
fg = QColor(0,0,0)
fg = self.pen_black
else:
fg = QColor(0,0,0) if model.mutes[ch+1][m] > 0 else self.foreground.color()
fg = self.pen_black if model.mutes[ch+1][m] > 0 else self.pen_fg
painter.fillRect(QRect(left + col_spacing, top, col_width - col_spacing, 20), color)
painter.setPen(QPen(fg))
painter.setPen(fg)
painter.drawText(center - col_spacing//2, top+15, m.upper())

#painter.fillRect(QRect(0, 0, self.iteration % size.width(), 20), self.foreground)

meter_top = top + row_height
meter_height = size.height() - meter_top
min_db = -60
def bar_gradient(left):
grad = QLinearGradient(
QPoint(left, meter_top),
QPoint(left - col_spacing * 2, meter_top + meter_height)
)
grad.setColorAt(0.125, QColor(255,0,0))
grad.setColorAt(0.25 , QColor(255,255,0))
grad.setColorAt(0.375, QColor(0,255,0))
grad.setColorAt(0.5 , QColor(0,127,0))
grad.setColorAt(0.75 , QColor(0,63,95))
grad.setColorAt(1.0 , QColor(0,0,31))
return grad

for x in range(0, 16):
rms = model.meters[x]
#color = bar_color(rms)
left = x * col_width + col_spacing
top = meter_top + int(meter_height * rms / min_db)
painter.fillRect(QRect(left + col_spacing, top, col_width - col_spacing * 2, meter_height), QBrush(bar_gradient(left)))
painter.setPen(QPen(self.foreground.color()))
painter.drawText(QRect(left, size.height() - 20, col_width, 20), Qt.AlignHCenter, "%d" % rms)
#painter.fillRect(QRect(0, 0, self.iteration % size.width(), 20), self.foreground)

painter.end()

def paintEvent(self, event):
Expand Down

0 comments on commit 62cb8b4

Please sign in to comment.