[transmute pitch] make and implement crate
This commit is contained in:
parent
4c3e4d42de
commit
29cd40ac12
2 changed files with 123 additions and 0 deletions
15
crates/transmute_pitch/Cargo.toml
Normal file
15
crates/transmute_pitch/Cargo.toml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
[package]
|
||||||
|
name = "transmute_pitch"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
baseplug = { git = "https://github.com/wrl/baseplug.git", rev = "9cec68f31cca9c0c7a1448379f75d92bbbc782a8" }
|
||||||
|
serde = "1.0.126"
|
||||||
|
log = "0.4.14"
|
||||||
|
ringbuf = "0.2.5"
|
||||||
|
|
||||||
|
utils = { path = "../utils" }
|
108
crates/transmute_pitch/src/lib.rs
Normal file
108
crates/transmute_pitch/src/lib.rs
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
#![feature(generic_associated_types)]
|
||||||
|
|
||||||
|
use baseplug::{event::Data, Event, Plugin, ProcessContext};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use utils::pitch::*;
|
||||||
|
|
||||||
|
const BUFFER_LEN: usize = 2 << 9;
|
||||||
|
|
||||||
|
baseplug::model! {
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
struct TransmutePitchModel {
|
||||||
|
#[model(min = 0.0, max = 1.0)]
|
||||||
|
#[parameter(name = "passthrough")]
|
||||||
|
passthrough: f32,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TransmutePitchModel {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { passthrough: 1.0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TransmutePitch {
|
||||||
|
detector_thread: pitch_detection::PitchDetectorThread<BUFFER_LEN>,
|
||||||
|
last_note: Option<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Plugin for TransmutePitch {
|
||||||
|
const NAME: &'static str = "transmute pitch";
|
||||||
|
const PRODUCT: &'static str = "transmute pitch";
|
||||||
|
const VENDOR: &'static str = "unnieversal";
|
||||||
|
|
||||||
|
const INPUT_CHANNELS: usize = 1;
|
||||||
|
const OUTPUT_CHANNELS: usize = 1;
|
||||||
|
|
||||||
|
type Model = TransmutePitchModel;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn new(_sample_rate: f32, _model: &TransmutePitchModel) -> Self {
|
||||||
|
let detector_thread = pitch_detection::PitchDetectorThread::<BUFFER_LEN>::new();
|
||||||
|
Self {
|
||||||
|
detector_thread,
|
||||||
|
last_note: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn process(&mut self, model: &TransmutePitchModelProcess, ctx: &mut ProcessContext<Self>) {
|
||||||
|
let input = &ctx.inputs[0].buffers;
|
||||||
|
let output = &mut ctx.outputs[0].buffers;
|
||||||
|
let enqueue_midi = &mut ctx.enqueue_event;
|
||||||
|
|
||||||
|
for i in 0..ctx.nframes {
|
||||||
|
output[0][i] = model.passthrough[i] * input[0][i];
|
||||||
|
output[1][i] = model.passthrough[i] * input[1][i];
|
||||||
|
|
||||||
|
// pass input to pitch detector
|
||||||
|
self.detector_thread
|
||||||
|
.write(input[0][i], 0.0, ctx.sample_rate as u32);
|
||||||
|
|
||||||
|
// Try to get a processed buffer from the processor thread
|
||||||
|
match self.detector_thread.try_get_pitch() {
|
||||||
|
Some((Some(pitch), _)) => {
|
||||||
|
let note = pitch_to_midi_note(pitch);
|
||||||
|
|
||||||
|
// If note changed
|
||||||
|
if self.last_note != Some(note) {
|
||||||
|
// Send note off for last note
|
||||||
|
if let Some(last_note) = self.last_note {
|
||||||
|
let note_off = Event::<TransmutePitch> {
|
||||||
|
frame: i,
|
||||||
|
data: Data::Midi([0x80, last_note, 0]),
|
||||||
|
};
|
||||||
|
enqueue_midi(note_off);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send note on for the new one
|
||||||
|
let note_on = Event::<TransmutePitch> {
|
||||||
|
frame: i,
|
||||||
|
data: Data::Midi([0x90, note, 64]),
|
||||||
|
};
|
||||||
|
enqueue_midi(note_on);
|
||||||
|
|
||||||
|
// Update note
|
||||||
|
self.last_note = Some(note);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some((None, _)) => {
|
||||||
|
if let Some(last_note) = self.last_note {
|
||||||
|
let note_off = Event::<TransmutePitch> {
|
||||||
|
frame: i,
|
||||||
|
data: Data::Midi([0x80, last_note, 0]),
|
||||||
|
};
|
||||||
|
enqueue_midi(note_off);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.last_note = None;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
baseplug::vst2!(TransmutePitch, b"trpi");
|
Loading…
Reference in a new issue