This commit is contained in:
2026-04-20 13:19:15 +03:00
parent 1cc59d5408
commit ad8910ea19
9 changed files with 1333 additions and 449 deletions

View File

@@ -1,35 +1,98 @@
use engine::Engine;
use lv2::prelude::*;
use std::sync::Arc;
use engine::{oscillator::WavetableBank, synth::Synth};
use lv2::lv2_urid::LV2Map;
use lv2::{lv2_atom, prelude::*};
use params::ParamStore;
#[derive(URIDCollection)]
struct TenkoUrids {
atom: AtomURIDCollection,
midi: MidiURIDCollection,
units: UnitURIDCollection,
}
#[derive(FeatureCollection)]
struct InitFeatures<'a> {
map: LV2Map<'a>,
}
#[derive(PortCollection)]
struct Ports {
midi_in: InputPort<AtomPort>,
out_l: OutputPort<Audio>,
out_r: OutputPort<Audio>,
}
#[uri("https://git.yokai.digital/deadYokai/tenko")]
struct TenkoLv2 {
engine: Engine,
synth: Synth,
urids: TenkoUrids,
host_bpm: f32,
}
impl Plugin for TenkoLv2 {
type Ports = Ports;
type InitFeatures = ();
type InitFeatures = InitFeatures<'static>;
type AudioFeatures = ();
fn new(info: &PluginInfo, _features: &mut ()) -> Option<Self> {
fn new(info: &PluginInfo, features: &mut InitFeatures<'static>) -> Option<Self> {
let urids = TenkoUrids::from_map(&features.map)?;
let params = ParamStore::new();
let engine = Engine::new(params, info.sample_rate() as f32);
Some(Self { engine })
let bank = Arc::new(WavetableBank::new());
let synth = Synth::new(info.sample_rate() as f32, params, bank);
Some(Self {
synth,
urids,
host_bpm: 120.0,
})
}
fn run(&mut self, ports: &mut Ports, _: &mut (), _: u32) {
for s in ports.out_l.iter_mut() {
*s = 0.0;
fn run(&mut self, ports: &mut Ports, _features: &mut (), _count: u32) {
if let Some(seq) = ports
.midi_in
.read(self.urids.atom.sequence, self.urids.units.beat)
{
for (_, atom) in seq {
if let Some(raw) = atom.read(self.urids.midi.raw, ()) {
self.dispatch_midi(raw);
} else if let Some((_header, reader)) = atom.read(self.urids.atom.object, ()) {
self.handle_time_position(reader);
}
}
}
for s in ports.out_r.iter_mut() {
*s = 0.0;
for (l, r) in ports.out_l.iter_mut().zip(ports.out_r.iter_mut()) {
let (sl, sr) = self.synth.process(self.host_bpm);
*l = sl;
*r = sr;
}
}
}
impl TenkoLv2 {
#[inline]
fn dispatch_midi(&mut self, raw: &[u8]) {
if raw.len() < 3 {
return;
}
let note = raw[1];
let vel = raw[2];
match raw[0] & 0xF0 {
0x90 if vel > 0 => self.synth.note_on(note, vel),
0x90 | 0x80 => self.synth.note_off(note),
_ => {}
}
}
#[inline]
fn handle_time_position(&mut self, reader: lv2_atom::object::ObjectReader) {
for (_, atom) in reader {
if let Some(bpm) = atom.read(self.urids.atom.float, ())
&& bpm > 0.0
{
self.host_bpm = bpm;
}
}
}
}