add midi function
This commit is contained in:
parent
5fb6af0aa4
commit
3c559bd689
@ -17,6 +17,7 @@ from flandre.nodes.Muxer import Muxer
|
||||
from flandre.nodes.Robot import Robot
|
||||
from flandre.nodes.ImageFFMPEG import ImageFFMPEG
|
||||
from flandre.nodes.ImageQt import ImageQt
|
||||
from flandre.nodes.Midi import Midi
|
||||
from flandre.utils.Msg import KillMsg
|
||||
from flandre.config import CONFIG_FOLDER
|
||||
|
||||
@ -31,6 +32,7 @@ class LaunchComponent(Enum):
|
||||
Beamformer = Beamformer
|
||||
ImageFFMPEG = ImageFFMPEG
|
||||
ImageQt = ImageQt
|
||||
Midi = Midi
|
||||
|
||||
|
||||
def launch(arg: dict[LaunchComponent, dict]):
|
||||
|
||||
@ -40,7 +40,7 @@ class Beamformer(Node):
|
||||
.call(cp.asarray, order='C')
|
||||
.argrelextrema()
|
||||
.conv_guass(b=arg.beta * 0.01)
|
||||
.crop(arg.t_start, arg.t_end)
|
||||
.crop_center(arg.t_start, arg.t_end)
|
||||
.rotate90()
|
||||
.cpu()
|
||||
)
|
||||
|
||||
@ -345,12 +345,25 @@ class Adv(QMainWindow, Ui_MainWindow):
|
||||
elif isinstance(msg, ImageArgMsg):
|
||||
self.arg = msg
|
||||
self.arg.sender = 'ui'
|
||||
|
||||
self.s_t_start.setValue(msg.t_start)
|
||||
self.s_t_end.setValue(msg.t_end)
|
||||
self.s_f_rows.setValue(msg.f_rows)
|
||||
self.s_v2.setValue(msg.v2)
|
||||
self.s_dct_center.setValue(msg.dct_center)
|
||||
self.s_dct_bandwidth.setValue(msg.dct_bandwidth)
|
||||
self.s_beta.setValue(msg.beta)
|
||||
|
||||
self.sp_crop_center.setValue(msg.t_start)
|
||||
self.sp_crop_width.setValue(msg.t_end)
|
||||
self.sp_f_rows.setValue(msg.f_rows)
|
||||
self.sp_v2.setValue(msg.v2)
|
||||
self.sp_dct_center.setValue(msg.dct_center)
|
||||
self.sp_dct_bandwidth.setValue(msg.dct_bandwidth)
|
||||
self.sp_beta.setValue(msg.beta)
|
||||
|
||||
|
||||
|
||||
elif isinstance(msg, MoveAxisMsg):
|
||||
match msg.axis:
|
||||
case 'S':
|
||||
@ -376,11 +389,19 @@ class Adv(QMainWindow, Ui_MainWindow):
|
||||
elif isinstance(msg, SetSeqMetaMsg):
|
||||
self.seq_meta = RfSequenceMeta.from_name(msg.name)
|
||||
mmax_shape0 = max(self.seq_meta.shape)
|
||||
|
||||
self.s_t_start.setMaximum(mmax_shape0)
|
||||
self.s_t_end.setMaximum(mmax_shape0)
|
||||
self.s_dct_center.setMaximum(mmax_shape0)
|
||||
self.s_dct_bandwidth.setMaximum(mmax_shape0)
|
||||
self.s_f_rows.setMaximum(mmax_shape0)
|
||||
|
||||
self.sp_crop_center.setMaximum(mmax_shape0)
|
||||
self.sp_crop_width.setMaximum(mmax_shape0)
|
||||
self.sp_dct_center.setMaximum(mmax_shape0)
|
||||
self.sp_dct_bandwidth.setMaximum(mmax_shape0)
|
||||
self.sp_f_rows.setMaximum(mmax_shape0)
|
||||
|
||||
elif isinstance(msg, DeviceConnectedMsg):
|
||||
if msg.value:
|
||||
self.set_device_connection(LinkStatus.GREEN)
|
||||
@ -456,6 +477,24 @@ class Adv(QMainWindow, Ui_MainWindow):
|
||||
if self.cb_bscan.sender() is None:
|
||||
self.p.send(SetWindowVisibleMsg('ui', 'bscan', v == 2))
|
||||
|
||||
@pyqtSlot(int)
|
||||
def on_sp_crop_center_valueChanged(self, v):
|
||||
if self.sp_crop_center.sender() is None:
|
||||
self.arg.t_start = v
|
||||
self.p.send(self.arg)
|
||||
|
||||
@pyqtSlot(int)
|
||||
def on_sp_crop_width_valueChanged(self, v):
|
||||
if self.sp_crop_width.sender() is None:
|
||||
self.arg.t_end = v
|
||||
self.p.send(self.arg)
|
||||
|
||||
@pyqtSlot(int)
|
||||
def on_sp_v2_valueChanged(self, v):
|
||||
if self.sp_v2.sender() is None:
|
||||
self.arg.v2 = v
|
||||
self.p.send(self.arg)
|
||||
|
||||
@pyqtSlot(int)
|
||||
def on_s_beta_valueChanged(self, v):
|
||||
if self.s_beta.sender() is None:
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import logging
|
||||
from threading import Thread
|
||||
from unittest import case
|
||||
|
||||
import mido
|
||||
import zmq
|
||||
@ -7,12 +8,15 @@ from mido import Message
|
||||
from mido.backends.rtmidi import Input, Output
|
||||
|
||||
from flandre.nodes.Node import Node
|
||||
from flandre.utils.Msg import KillMsg, MidiMsg, Msg, ImageArgMsg
|
||||
from flandre.utils.Msg import KillMsg, MidiMsg, Msg, ImageArgMsg, SetSeqMetaMsg, SetSidMsg
|
||||
from flandre.utils.RfMeta import RfSequenceMeta
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Midi(Node):
|
||||
topics = [ImageArgMsg, SetSeqMetaMsg]
|
||||
|
||||
def __init__(self, level=logging.INFO):
|
||||
super(Midi, self).__init__(level=level)
|
||||
self.m_input: Input = None
|
||||
@ -20,6 +24,15 @@ class Midi(Node):
|
||||
self.do_loop = True
|
||||
self.t_midi_event_loop: Thread = None
|
||||
self.isa: zmq.Socket = None
|
||||
self.arg = ImageArgMsg('midi', 0)
|
||||
|
||||
self.m_t_start = 100
|
||||
self.m_t_end = 100
|
||||
self.m_dct_center = 100
|
||||
self.m_dct_bandwidth = 100
|
||||
self.m_f_rows = 100
|
||||
self.last_pitch: dict[int, int] = dict()
|
||||
self.sid = 0
|
||||
|
||||
def custom_setup(self):
|
||||
self.isa = self.c.ctx.socket(zmq.PUSH)
|
||||
@ -33,16 +46,32 @@ class Midi(Node):
|
||||
def midi_event_loop(self):
|
||||
while self.do_loop:
|
||||
midi_msg: Message = self.m_input.receive()
|
||||
# print(midi_msg)
|
||||
print(midi_msg)
|
||||
d = midi_msg.dict()
|
||||
match d['type']:
|
||||
case 'pitchwheel':
|
||||
channel = d['channel']
|
||||
# 0-127
|
||||
pitch = int(d['pitch'] / 128) + 64
|
||||
if channel not in self.last_pitch:
|
||||
self.last_pitch[channel] = pitch
|
||||
elif abs(pitch - self.last_pitch[channel]) > 5:
|
||||
pass
|
||||
else:
|
||||
self.last_pitch[channel] = pitch
|
||||
# pitch_p = int(pitch / 127)
|
||||
self.isa.send(MidiMsg(type='pitchwheel', channel=channel, pitch=pitch).encode_msg())
|
||||
|
||||
case 'control_change':
|
||||
for i in range(16, 24):
|
||||
if i in [d['control'], d['value']]:
|
||||
if 1 in [d['control'], d['value']]:
|
||||
self.isa.send(MidiMsg(type='control_change', value=1, control=i - 16).encode_msg())
|
||||
else:
|
||||
self.isa.send(MidiMsg(type='control_change', value=-1, control=i - 16).encode_msg())
|
||||
case 'note_on':
|
||||
self.isa.send(MidiMsg(type='note_on', note=d['note'], velocity=d['velocity']).encode_msg())
|
||||
case 'note_off':
|
||||
self.isa.send(MidiMsg(type='note_off', note=d['note'], velocity=d['velocity']).encode_msg())
|
||||
def loop(self):
|
||||
isb = self.c.ctx.socket(zmq.PULL)
|
||||
isb.connect("inproc://midi")
|
||||
@ -50,16 +79,42 @@ class Midi(Node):
|
||||
while True:
|
||||
p = dict(self.c.poller.poll())
|
||||
if isb in p:
|
||||
msg = Msg.decode_msg(isb.recv())
|
||||
msg: MidiMsg = Msg.decode_msg(isb.recv())
|
||||
match msg.type:
|
||||
case 'pitchwheel':
|
||||
match msg.channel:
|
||||
case 0:
|
||||
self.arg.v2 = int(100 + 6000 * (msg.pitch / 127))
|
||||
# print(msg.pitch)
|
||||
self.send(ImageArgMsg('midi', 0, msg.pitch * 3))
|
||||
self.send(self.arg)
|
||||
case 'control_change':
|
||||
match msg.control:
|
||||
case 0:
|
||||
self.arg.t_start = sorted((1, self.arg.t_start + msg.value * 10, self.m_t_start))[1]
|
||||
case 1:
|
||||
self.arg.t_end = sorted((1, self.arg.t_end + msg.value * 10, self.m_t_end))[1]
|
||||
case 2:
|
||||
self.arg.v2 = sorted((500, self.arg.v2 + msg.value * 10, 7000))[1]
|
||||
case 'note_on':
|
||||
self.sid += 1
|
||||
self.send(SetSidMsg(self.sid))
|
||||
|
||||
self.send(self.arg)
|
||||
if self.c.sub in p:
|
||||
msg = self.recv()
|
||||
if isinstance(msg, KillMsg):
|
||||
if msg.name == '':
|
||||
self.do_loop = False
|
||||
return
|
||||
elif isinstance(msg, ImageArgMsg):
|
||||
if msg.sender != 'midi':
|
||||
self.arg = msg
|
||||
self.arg.sender = 'midi'
|
||||
elif isinstance(msg, SetSeqMetaMsg):
|
||||
seq_meta = RfSequenceMeta.from_name(msg.name)
|
||||
mmax_shape0 = max(seq_meta.shape)
|
||||
self.m_t_start = mmax_shape0
|
||||
self.m_t_end = mmax_shape0
|
||||
self.m_dct_center = mmax_shape0
|
||||
self.m_dct_bandwidth = mmax_shape0
|
||||
self.m_f_rows = mmax_shape0
|
||||
|
||||
@ -485,9 +485,9 @@ class Ui_MainWindow(object):
|
||||
self.label_7 = QtWidgets.QLabel(parent=self.centralwidget)
|
||||
self.label_7.setObjectName("label_7")
|
||||
self.gridLayout_5.addWidget(self.label_7, 6, 0, 1, 1)
|
||||
self.spinBox = QtWidgets.QSpinBox(parent=self.centralwidget)
|
||||
self.spinBox.setObjectName("spinBox")
|
||||
self.gridLayout_5.addWidget(self.spinBox, 4, 2, 1, 1)
|
||||
self.sp_crop_width = QtWidgets.QSpinBox(parent=self.centralwidget)
|
||||
self.sp_crop_width.setObjectName("sp_crop_width")
|
||||
self.gridLayout_5.addWidget(self.sp_crop_width, 4, 2, 1, 1)
|
||||
spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding)
|
||||
self.gridLayout_5.addItem(spacerItem2, 10, 1, 1, 1)
|
||||
self.s_t_end = QJumpSlider(parent=self.centralwidget)
|
||||
@ -496,9 +496,9 @@ class Ui_MainWindow(object):
|
||||
self.s_t_end.setOrientation(QtCore.Qt.Orientation.Horizontal)
|
||||
self.s_t_end.setObjectName("s_t_end")
|
||||
self.gridLayout_5.addWidget(self.s_t_end, 4, 1, 1, 1)
|
||||
self.spinBox_7 = QtWidgets.QSpinBox(parent=self.centralwidget)
|
||||
self.spinBox_7.setObjectName("spinBox_7")
|
||||
self.gridLayout_5.addWidget(self.spinBox_7, 7, 2, 1, 1)
|
||||
self.sp_dct_bandwidth = QtWidgets.QSpinBox(parent=self.centralwidget)
|
||||
self.sp_dct_bandwidth.setObjectName("sp_dct_bandwidth")
|
||||
self.gridLayout_5.addWidget(self.sp_dct_bandwidth, 7, 2, 1, 1)
|
||||
self.label_5 = QtWidgets.QLabel(parent=self.centralwidget)
|
||||
self.label_5.setObjectName("label_5")
|
||||
self.gridLayout_5.addWidget(self.label_5, 4, 0, 1, 1)
|
||||
@ -518,15 +518,17 @@ class Ui_MainWindow(object):
|
||||
self.label_6 = QtWidgets.QLabel(parent=self.centralwidget)
|
||||
self.label_6.setObjectName("label_6")
|
||||
self.gridLayout_5.addWidget(self.label_6, 5, 0, 1, 1)
|
||||
self.spinBox_2 = QtWidgets.QSpinBox(parent=self.centralwidget)
|
||||
self.spinBox_2.setObjectName("spinBox_2")
|
||||
self.gridLayout_5.addWidget(self.spinBox_2, 5, 2, 1, 1)
|
||||
self.spinBox_3 = QtWidgets.QSpinBox(parent=self.centralwidget)
|
||||
self.spinBox_3.setObjectName("spinBox_3")
|
||||
self.gridLayout_5.addWidget(self.spinBox_3, 6, 2, 1, 1)
|
||||
self.spinBox_13 = QtWidgets.QSpinBox(parent=self.centralwidget)
|
||||
self.spinBox_13.setObjectName("spinBox_13")
|
||||
self.gridLayout_5.addWidget(self.spinBox_13, 8, 2, 1, 1)
|
||||
self.sp_v2 = QtWidgets.QSpinBox(parent=self.centralwidget)
|
||||
self.sp_v2.setMinimum(500)
|
||||
self.sp_v2.setMaximum(7000)
|
||||
self.sp_v2.setObjectName("sp_v2")
|
||||
self.gridLayout_5.addWidget(self.sp_v2, 5, 2, 1, 1)
|
||||
self.sp_dct_center = QtWidgets.QSpinBox(parent=self.centralwidget)
|
||||
self.sp_dct_center.setObjectName("sp_dct_center")
|
||||
self.gridLayout_5.addWidget(self.sp_dct_center, 6, 2, 1, 1)
|
||||
self.sp_f_rows = QtWidgets.QSpinBox(parent=self.centralwidget)
|
||||
self.sp_f_rows.setObjectName("sp_f_rows")
|
||||
self.gridLayout_5.addWidget(self.sp_f_rows, 8, 2, 1, 1)
|
||||
self.s_f_rows = QtWidgets.QSlider(parent=self.centralwidget)
|
||||
self.s_f_rows.setMinimum(500)
|
||||
self.s_f_rows.setMaximum(7000)
|
||||
@ -538,7 +540,7 @@ class Ui_MainWindow(object):
|
||||
self.s_dct_bandwidth.setObjectName("s_dct_bandwidth")
|
||||
self.gridLayout_5.addWidget(self.s_dct_bandwidth, 7, 1, 1, 1)
|
||||
self.s_v2 = QtWidgets.QSlider(parent=self.centralwidget)
|
||||
self.s_v2.setMinimum(1)
|
||||
self.s_v2.setMinimum(500)
|
||||
self.s_v2.setMaximum(7000)
|
||||
self.s_v2.setProperty("value", 5900)
|
||||
self.s_v2.setOrientation(QtCore.Qt.Orientation.Horizontal)
|
||||
@ -556,9 +558,9 @@ class Ui_MainWindow(object):
|
||||
self.label_2.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.gridLayout_5.addWidget(self.label_2, 0, 0, 1, 3)
|
||||
self.spinBox_12 = QtWidgets.QSpinBox(parent=self.centralwidget)
|
||||
self.spinBox_12.setObjectName("spinBox_12")
|
||||
self.gridLayout_5.addWidget(self.spinBox_12, 3, 2, 1, 1)
|
||||
self.sp_crop_center = QtWidgets.QSpinBox(parent=self.centralwidget)
|
||||
self.sp_crop_center.setObjectName("sp_crop_center")
|
||||
self.gridLayout_5.addWidget(self.sp_crop_center, 3, 2, 1, 1)
|
||||
self.s_beta = QtWidgets.QSlider(parent=self.centralwidget)
|
||||
self.s_beta.setMinimum(1)
|
||||
self.s_beta.setMaximum(30)
|
||||
@ -569,9 +571,9 @@ class Ui_MainWindow(object):
|
||||
self.label_35 = QtWidgets.QLabel(parent=self.centralwidget)
|
||||
self.label_35.setObjectName("label_35")
|
||||
self.gridLayout_5.addWidget(self.label_35, 9, 0, 1, 1)
|
||||
self.spinBox_14 = QtWidgets.QSpinBox(parent=self.centralwidget)
|
||||
self.spinBox_14.setObjectName("spinBox_14")
|
||||
self.gridLayout_5.addWidget(self.spinBox_14, 9, 2, 1, 1)
|
||||
self.sp_beta = QtWidgets.QSpinBox(parent=self.centralwidget)
|
||||
self.sp_beta.setObjectName("sp_beta")
|
||||
self.gridLayout_5.addWidget(self.sp_beta, 9, 2, 1, 1)
|
||||
self.gridLayout.addLayout(self.gridLayout_5, 3, 0, 1, 1)
|
||||
self.gridLayout.setRowStretch(0, 1)
|
||||
MainWindow.setCentralWidget(self.centralwidget)
|
||||
|
||||
@ -910,7 +910,7 @@ border-radius: 7px;
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QSpinBox" name="spinBox"/>
|
||||
<widget class="QSpinBox" name="sp_crop_width"/>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<spacer name="verticalSpacer_2">
|
||||
@ -939,7 +939,7 @@ border-radius: 7px;
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="2">
|
||||
<widget class="QSpinBox" name="spinBox_7"/>
|
||||
<widget class="QSpinBox" name="sp_dct_bandwidth"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
@ -977,13 +977,20 @@ border-radius: 7px;
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QSpinBox" name="spinBox_2"/>
|
||||
<widget class="QSpinBox" name="sp_v2">
|
||||
<property name="minimum">
|
||||
<number>500</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>7000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<widget class="QSpinBox" name="spinBox_3"/>
|
||||
<widget class="QSpinBox" name="sp_dct_center"/>
|
||||
</item>
|
||||
<item row="8" column="2">
|
||||
<widget class="QSpinBox" name="spinBox_13"/>
|
||||
<widget class="QSpinBox" name="sp_f_rows"/>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QSlider" name="s_f_rows">
|
||||
@ -1008,7 +1015,7 @@ border-radius: 7px;
|
||||
<item row="5" column="1">
|
||||
<widget class="QSlider" name="s_v2">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
<number>500</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>7000</number>
|
||||
@ -1045,7 +1052,7 @@ border-radius: 7px;
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QSpinBox" name="spinBox_12"/>
|
||||
<widget class="QSpinBox" name="sp_crop_center"/>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QSlider" name="s_beta">
|
||||
@ -1071,7 +1078,7 @@ border-radius: 7px;
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="2">
|
||||
<widget class="QSpinBox" name="spinBox_14"/>
|
||||
<widget class="QSpinBox" name="sp_beta"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
|
||||
@ -403,8 +403,12 @@ class DeviceZero(Msg):
|
||||
@dataclasses.dataclass
|
||||
class MidiMsg(Msg):
|
||||
type: str
|
||||
channel: int
|
||||
pitch: int
|
||||
channel: int = None
|
||||
pitch: int = None
|
||||
control: int = None
|
||||
value: int = None
|
||||
velocity: int = None
|
||||
note: int = None
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
|
||||
@ -210,6 +210,11 @@ class RfMat:
|
||||
def crop(self, t_start: int, t_end: int):
|
||||
return self.copy(self.m[:, t_start:t_end])
|
||||
|
||||
def crop_center(self, center: float, width: float):
|
||||
mmin = max(0, int(center - width / 2))
|
||||
mmax = min(self.duration, int(center + width / 2))
|
||||
return self.crop(mmin, mmax)
|
||||
|
||||
def watermark(self, watermark=None):
|
||||
assert self.m.dtype == np.uint8
|
||||
canvas = np.zeros(self.m.shape, dtype=np.uint8)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user