Phase 16: persist sample-timed effect automation and add expressive MIDI controls
This commit is contained in:
parent
f72314b5a3
commit
7fac0a4f6a
23 changed files with 374 additions and 39 deletions
|
|
@ -476,10 +476,15 @@ int main(int argc, char **argv)
|
|||
const xtc_project *before = sequence->project();
|
||||
CHECK(window.add_plugin("/absent/plugin.so",0) == XTC_ERR_NOT_FOUND && sequence->project() == before);
|
||||
CHECK(window.add_plugin(module,2) == XTC_ERR_UNSUPPORTED && sequence->project() == before);
|
||||
xtc_plugin_point point{960,spec.ports[0],0,.25f};
|
||||
CHECK(window.set_plugin_automation(id,point) == XTC_OK);
|
||||
CHECK(window.set_plugin_automation(id,point,true) == XTC_OK);
|
||||
CHECK(window.undo(false) == XTC_OK);
|
||||
CHECK(window.save_project("/tmp/xtc-gui-plugin-test.xtc") == XTC_OK);
|
||||
CHECK(window.new_project() == XTC_OK);
|
||||
CHECK(window.open_project("/tmp/xtc-gui-plugin-test.xtc") == XTC_OK);
|
||||
CHECK(xtc_graph_get_plugin(xtc_project_graph(sequence->project()),id,&spec) == XTC_OK && spec.values[0] == .5f);
|
||||
CHECK(spec.point_count == 1 && spec.points[0].tick == 960 && spec.points[0].value == .25f);
|
||||
xtc_project *missing = nullptr; xtc_graph *graph = nullptr; size_t absent;
|
||||
CHECK(xtc_project_create(&missing) == XTC_OK);
|
||||
CHECK(xtc_graph_create(8,&graph) == XTC_OK);
|
||||
|
|
|
|||
|
|
@ -133,6 +133,41 @@ int main(int argc, char **argv)
|
|||
for (i = 0; i < 17; ++i) assert(data[i] == 1);
|
||||
xtc_plugin_destroy(p); p = NULL;
|
||||
graph_roundtrip(&s);
|
||||
s.point_count = 2;
|
||||
s.points[0] = (xtc_plugin_point){0,s.ports[0],0,.5f};
|
||||
s.points[1] = (xtc_plugin_point){1,s.ports[0],0,2};
|
||||
graph_roundtrip(&s);
|
||||
{
|
||||
xtc_graph *g = NULL; xtc_realtime *rt = NULL; size_t id;
|
||||
float in[1] = {1}, out[1];
|
||||
assert(xtc_graph_create(8,&g) == XTC_OK && xtc_graph_add_plugin(g,&s,&id) == XTC_OK);
|
||||
assert(xtc_realtime_create(48000,31,&rt) == XTC_OK);
|
||||
assert(xtc_realtime_position(rt,25) == XTC_OK && xtc_realtime_submit(rt,g) == XTC_OK);
|
||||
audio = 1; assert(xtc_realtime_process(rt,in,out,1) == XTC_OK && out[0] == 2); audio = 0;
|
||||
xtc_realtime_collect(rt);
|
||||
assert(xtc_realtime_submit(rt,g) == XTC_OK);
|
||||
audio = 1; assert(xtc_realtime_process(rt,in,out,1) == XTC_OK && out[0] == 2); audio = 0;
|
||||
xtc_realtime_collect(rt);
|
||||
xtc_realtime_destroy(rt); xtc_graph_destroy(g);
|
||||
}
|
||||
{
|
||||
float whole[31], split[31], in[31]; xtc_plugin *other = NULL;
|
||||
for (i = 0; i < 31; ++i) in[i] = 1;
|
||||
assert(xtc_plugin_create(&s,48000,31,&p) == XTC_OK);
|
||||
assert(xtc_plugin_create(&s,48000,31,&other) == XTC_OK);
|
||||
audio = 1;
|
||||
assert(xtc_plugin_process_at(p,in,whole,31,0) == XTC_OK);
|
||||
assert(xtc_plugin_process_at(other,in,split,7,0) == XTC_OK);
|
||||
assert(xtc_plugin_process_at(other,in+7,split+7,24,7) == XTC_OK);
|
||||
audio = 0;
|
||||
for (i = 0; i < 31; ++i) {
|
||||
assert(whole[i] == split[i]);
|
||||
assert(fabsf(whole[i]-(i < 25 ? .5f+1.5f*(float)i/25 : 2)) < .000001f);
|
||||
}
|
||||
assert(xtc_plugin_process_at(other,in,split,1,25) == XTC_OK && split[0] == 2);
|
||||
xtc_plugin_destroy(p); xtc_plugin_destroy(other); p = NULL;
|
||||
}
|
||||
s.point_count = 0;
|
||||
s.values[0] = 3; assert(xtc_plugin_create(&s,48000,17,&p) == XTC_ERR_UNSUPPORTED && !p);
|
||||
assert(xtc_plugin_probe(argv[1],1,48000,&s) == XTC_OK && !s.inputs);
|
||||
graph_roundtrip(&s);
|
||||
|
|
|
|||
38
tests/unit/test_control.c
Normal file
38
tests/unit/test_control.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#include "xtc/xtc_midi.h"
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
int main(void)
|
||||
{
|
||||
xtc_project *project = NULL; xtc_midi_plan *a = NULL, *b = NULL;
|
||||
float whole[400], split[400]; size_t i, j, cursor = 0;
|
||||
xtc_midi_event decoded;
|
||||
const unsigned char cc[] = {0xb2,7,0};
|
||||
xtc_midi_event events[] = {
|
||||
{0,XTC_MIDI_NOTE_ON,2,69,127}, {3,XTC_MIDI_CONTROL,2,64,127},
|
||||
{5,XTC_MIDI_NOTE_OFF,2,69,0}, {9,XTC_MIDI_NOTE_ON,2,69,127},
|
||||
{10,XTC_MIDI_CONTROL,2,7,0}, {11,XTC_MIDI_CONTROL,2,10,127},
|
||||
{260,XTC_MIDI_NOTE_OFF,2,69,0}, {270,XTC_MIDI_CONTROL,2,64,0}};
|
||||
assert(xtc_midi_decode(cc,3,10,&decoded) == XTC_OK && decoded.type == XTC_MIDI_CONTROL && decoded.pitch == 7);
|
||||
assert(xtc_project_create(&project) == XTC_OK);
|
||||
assert(xtc_midi_plan_create(project,48000,&a) == XTC_OK);
|
||||
assert(xtc_midi_plan_create(project,48000,&b) == XTC_OK);
|
||||
assert(xtc_midi_plan_render(a,0,events,8,whole,400) == XTC_OK);
|
||||
while (cursor < 400) {
|
||||
xtc_midi_event local[8]; size_t count = 0, n = 13;
|
||||
if (n > 400-cursor) n = 400-cursor;
|
||||
for (j = 0; j < 8; ++j) if (events[j].offset >= cursor && events[j].offset < cursor+n) {
|
||||
local[count] = events[j]; local[count++].offset -= (unsigned int)cursor;
|
||||
}
|
||||
assert(xtc_midi_plan_render(b,cursor,local,count,split+cursor,n) == XTC_OK); cursor += n;
|
||||
}
|
||||
for (i = 0; i < 400; ++i) assert(whole[i] == split[i]);
|
||||
assert(whole[6] != 0); /* Sustain retains the released note. */
|
||||
for (i = 250; i < 400; ++i) assert(whole[i] == 0); /* CC7 ramp reaches zero in 240 samples. */
|
||||
xtc_midi_plan_reset(a);
|
||||
assert(xtc_midi_plan_render(a,400,NULL,0,whole,400) == XTC_OK);
|
||||
for (i = 0; i < 400; ++i) assert(whole[i] == 0);
|
||||
xtc_midi_plan_destroy(a); xtc_midi_plan_destroy(b); xtc_project_destroy(project);
|
||||
puts("Sample-timed CC7/CC10/sustain, retrigger, note-off and block partition checks passed.");
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue