Check and Windows preview / check (patina) (push) Successful in 2m20s
Check and Windows preview / check (rivet) (push) Successful in 1m38s
Check and Windows preview / previews (push) Successful in 1m6s
Check and Windows preview / windows (push) Successful in 1m50s
Independent plugin release / publish (push) Successful in 8s
Independent plugin release / plan (push) Successful in 7s
Independent plugin release / build (push) Successful in 2m21s
153 lines
4.7 KiB
Rust
153 lines
4.7 KiB
Rust
use rivet_core::*;
|
|
fn held() -> Phrase {
|
|
Phrase {
|
|
length: PPQ,
|
|
notes: vec![
|
|
Note {
|
|
start: 0,
|
|
duration: PPQ / 2,
|
|
pitch: 60,
|
|
velocity: 90,
|
|
..Default::default()
|
|
},
|
|
Note {
|
|
start: PPQ / 2,
|
|
duration: PPQ / 2,
|
|
pitch: 60,
|
|
velocity: 70,
|
|
..Default::default()
|
|
},
|
|
],
|
|
}
|
|
}
|
|
#[test]
|
|
fn role_handoffs_preserve_event_identity_and_respect_locks() {
|
|
let mut source = demo_motif();
|
|
source.notes[1].pitch_locked = true;
|
|
source.notes[0].locked = true;
|
|
for mode in RoleMode::ALL {
|
|
let mut s = PerformanceSettings {
|
|
mode,
|
|
..Default::default()
|
|
};
|
|
s.voices[0].transpose = -12;
|
|
s.voices[1].transpose = 12;
|
|
s.voices[0].velocity = 50;
|
|
s.voices[1].velocity = 50;
|
|
let p = Performance::compile(&source, &s, 140., false).unwrap();
|
|
let on: Vec<_> = p
|
|
.events
|
|
.iter()
|
|
.filter(|e| e.message.kind == MessageKind::On && !e.next_cycle)
|
|
.collect();
|
|
assert_eq!(on.len(), source.notes.len());
|
|
for (i, n) in source.notes.iter().enumerate() {
|
|
let role = mode.role(i, n);
|
|
let actual = on.iter().find(|e| e.tick == n.start as i32).unwrap();
|
|
assert_eq!(actual.message.channel, s.voices[role].channel);
|
|
assert_eq!(
|
|
actual.message.key,
|
|
if n.keeps_pitch() {
|
|
n.pitch
|
|
} else {
|
|
(n.pitch as i16 + s.voices[role].transpose as i16) as u8
|
|
}
|
|
);
|
|
}
|
|
assert_eq!(on[0].message.value, 90);
|
|
}
|
|
}
|
|
#[test]
|
|
fn controller_interpolation_and_validation_are_explicit() {
|
|
let mut curve = ControllerCurve::default();
|
|
assert_eq!(curve.value_at(500), 64);
|
|
curve.shape(2);
|
|
assert_eq!(curve.value_at(500), 127);
|
|
assert_eq!(curve.value_at(1000), 0);
|
|
curve.cc = 64;
|
|
assert!(curve.validate().is_err());
|
|
let mut s = PerformanceSettings::default();
|
|
s.voices[0].controller.enabled = true;
|
|
s.voices[0].controller.cc = 20;
|
|
let p = Performance::compile(&held(), &s, 120., false).unwrap();
|
|
assert!(p
|
|
.events
|
|
.iter()
|
|
.any(|e| e.message.kind == MessageKind::Control
|
|
&& e.message.key == 20
|
|
&& e.message.value == 127));
|
|
s.voices[0].controller.points[1].position = 0;
|
|
assert!(s.validate().is_err());
|
|
}
|
|
#[test]
|
|
fn attack_compensation_warms_up_once_and_wraps_without_cutting_the_next_note() {
|
|
let mut s = PerformanceSettings::default();
|
|
s.voices[0].attack_ms = 100;
|
|
let performance = Performance::compile(&held(), &s, 120., true).unwrap();
|
|
assert_eq!(performance.lead_in, 192);
|
|
assert!(performance
|
|
.events
|
|
.iter()
|
|
.any(|e| e.tick == -192 && e.message.kind == MessageKind::On && !e.next_cycle));
|
|
let mut player = PerformancePlayer::default();
|
|
player.set_sample_rate(8000.).unwrap();
|
|
player.set_looping(true);
|
|
player.play(performance.clip().unwrap());
|
|
let mut ons = Vec::new();
|
|
for frame in 0..4802 {
|
|
let (_, events) = player.next_frame(120.);
|
|
for e in events.events[..events.len].iter().flatten() {
|
|
if e.kind == MessageKind::On {
|
|
ons.push(frame);
|
|
}
|
|
}
|
|
}
|
|
assert_eq!(ons.len(), 3);
|
|
assert_eq!(ons[0], 0);
|
|
assert!((ons[2] as i32 - 4000).abs() <= 1);
|
|
assert!(player
|
|
.current_messages()
|
|
.events
|
|
.iter()
|
|
.flatten()
|
|
.any(|e| e.kind == MessageKind::On && e.key == 60));
|
|
player.set_looping(false);
|
|
player.play(performance.clip().unwrap());
|
|
let mut count = 0;
|
|
while player.is_playing() {
|
|
let (_, events) = player.next_frame(120.);
|
|
count += events
|
|
.events
|
|
.iter()
|
|
.flatten()
|
|
.filter(|e| e.kind == MessageKind::On)
|
|
.count();
|
|
}
|
|
assert_eq!(count, 2);
|
|
}
|
|
#[test]
|
|
fn public_clip_validation_rejects_bad_roles_and_dense_events() {
|
|
let mut p =
|
|
Performance::compile(&held(), &PerformanceSettings::default(), 120., false).unwrap();
|
|
p.events[0].role = 9;
|
|
assert!(p.clip().is_err());
|
|
let event = TimedMessage {
|
|
tick: 0,
|
|
role: 0,
|
|
message: MidiMessage {
|
|
kind: MessageKind::On,
|
|
channel: 0,
|
|
key: 60,
|
|
value: 90,
|
|
rest: 0,
|
|
},
|
|
next_cycle: false,
|
|
};
|
|
let p = Performance {
|
|
length: PPQ,
|
|
lead_in: 0,
|
|
events: vec![event; 17],
|
|
};
|
|
assert!(p.clip().is_err());
|
|
}
|