test: qualify internal devices across DSP, persistence and GUI workflows
This commit is contained in:
parent
f6dcf207ce
commit
e76552e8dd
7 changed files with 389 additions and 8 deletions
|
|
@ -712,6 +712,41 @@ int main(int argc, char **argv)
|
|||
CHECK(!canvas->select_at(-20,-20) && canvas->selected_node() == SIZE_MAX);
|
||||
window.do_callback();
|
||||
}
|
||||
// Internal devices must work without plugin fixture environment variables.
|
||||
for (unsigned int instrument=0;instrument<2;++instrument) {
|
||||
reset(); MainWindow window(false,""); window.show();
|
||||
CHECK(window.create_track(true)==XTC_OK);
|
||||
auto *sequence=timeline(&window); auto *canvas=graph_canvas(&window);
|
||||
uint64_t track=sequence->selected_track();
|
||||
auto *selector=sequence->instrument_choice(track); CHECK(selector);
|
||||
selector->value(static_cast<int>(instrument+1));selector->do_callback();
|
||||
xtc_plugin_spec spec{};
|
||||
CHECK(xtc_project_get_instrument(sequence->project(),track,&spec)==XTC_OK && spec.index==instrument);
|
||||
CHECK(window.undo()==XTC_OK && window.undo(true)==XTC_OK);
|
||||
xtc_connection_info wire{};
|
||||
CHECK(xtc_graph_get_connection(xtc_project_graph(sequence->project()),0,&wire)==XTC_OK);
|
||||
unsigned int effect=instrument+2;size_t id=SIZE_MAX;
|
||||
CHECK(window.insert_plugin(wire,XTC_BUILTIN_PATH,effect,&id)==XTC_OK);
|
||||
CHECK(canvas->select_node(id));
|
||||
CHECK(window.set_plugin_control(id,2,.75f)==XTC_OK);
|
||||
CHECK(window.set_plugin_automation(id,{960,2,0,.4f},false)==XTC_OK);
|
||||
CHECK(window.undo()==XTC_OK && window.undo(true)==XTC_OK);
|
||||
CHECK(xtc_graph_get_plugin(xtc_project_graph(sequence->project()),id,&spec)==XTC_OK);
|
||||
CHECK(spec.index==effect && spec.values[2]==.75f && spec.point_count==1);
|
||||
xtc_plugin_details details{};xtc_plugin_spec edited{};
|
||||
CHECK(xtc_plugin_describe(&spec,48000,&details)==XTC_OK);
|
||||
Fl::add_timeout(.05,[](void *) {press(find(Fl::first_window(),"Apply"));});
|
||||
CHECK(xtc_edit_plugin(spec,details,edited) && edited.index==effect);
|
||||
CHECK(window.save_project("/tmp/xtc-internal-gui.xtc")==XTC_OK);
|
||||
CHECK(window.new_project()==XTC_OK && window.open_project("/tmp/xtc-internal-gui.xtc")==XTC_OK);
|
||||
CHECK(xtc_project_get_instrument(sequence->project(),track,&spec)==XTC_OK && spec.index==instrument);
|
||||
CHECK(xtc_graph_get_plugin(xtc_project_graph(sequence->project()),id,&spec)==XTC_OK && spec.index==effect && spec.point_count==1);
|
||||
size_t added=SIZE_MAX;CHECK(window.add_plugin(XTC_BUILTIN_PATH,effect,&added)==XTC_OK);
|
||||
CHECK(added!=id);CHECK(window.undo()==XTC_OK);
|
||||
const xtc_project *before=sequence->project();reserve_result=XTC_ERR_OUT_OF_MEMORY;
|
||||
CHECK(window.add_plugin(XTC_BUILTIN_PATH,effect)==XTC_ERR_OUT_OF_MEMORY && sequence->project()==before);
|
||||
reserve_result=XTC_OK;unlink("/tmp/xtc-internal-gui.xtc");window.do_callback();
|
||||
}
|
||||
if (const char *module = std::getenv("XTC_TEST_PLUGIN")) {
|
||||
reset();
|
||||
MainWindow window(false,"");
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include "xtc/xtc_realtime.h"
|
||||
#include "xtc/xtc_native.h"
|
||||
#include "xtc/xtc_control.h"
|
||||
#include "xtc/xtc_plugin.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -152,8 +153,29 @@ static void history_reservations(void)
|
|||
xtc_project_destroy(snapshot); xtc_project_destroy(project); xtc_history_destroy(history);
|
||||
}
|
||||
|
||||
static void builtin_failures(void)
|
||||
{
|
||||
unsigned int id;
|
||||
for(id=0;id<4;++id) {
|
||||
int failure, succeeded=0; xtc_plugin_spec spec;
|
||||
assert(xtc_plugin_probe(XTC_BUILTIN_PATH,id,48000,&spec)==XTC_OK);
|
||||
for(failure=0;failure<16;++failure) {
|
||||
xtc_plugin *plugin=NULL; xtc_result result; float in[256]={0},out[256];
|
||||
fail_after=failure;result=xtc_plugin_create(&spec,48000,256,&plugin);fail_after=-1;
|
||||
if(result!=XTC_OK) {assert(result==XTC_ERR_OUT_OF_MEMORY && !plugin);continue;}
|
||||
processing=1;
|
||||
if(id<2) {xtc_midi_event event={0,XTC_MIDI_NOTE_ON,0,60,100};
|
||||
assert(xtc_plugin_process_midi(plugin,&event,1,out,256)==XTC_OK);
|
||||
} else assert(xtc_plugin_process(plugin,in,out,256)==XTC_OK);
|
||||
processing=0;xtc_plugin_destroy(plugin);succeeded=1;break;
|
||||
}
|
||||
assert(succeeded);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
builtin_failures();
|
||||
graph_limits();
|
||||
history_reservations();
|
||||
xtc_native_descriptor descriptor = {XTC_NATIVE_ABI_VERSION, sizeof(descriptor),
|
||||
|
|
|
|||
|
|
@ -53,21 +53,101 @@ static void automation(void)
|
|||
for(i=0;i<128;++i) assert(fabsf(out[i]-(i<100 ? 1-(float)i/100 : 0))<1e-6f);
|
||||
xtc_plugin_destroy(p);
|
||||
}
|
||||
static void roundtrip(void)
|
||||
static void roundtrip(unsigned int instrument, unsigned int effect)
|
||||
{
|
||||
xtc_project *p=NULL,*q=NULL; xtc_plugin_spec s,t; uint64_t track; size_t id; xtc_graph *g=NULL;
|
||||
xtc_plugin *a=NULL,*b=NULL; float input[256]={0},x[256],y[256]; size_t k;
|
||||
char path[]="/tmp/xtc-builtin-XXXXXX"; int fd=mkstemp(path); assert(fd>=0); close(fd);
|
||||
assert(xtc_project_create(&p)==XTC_OK); assert(xtc_project_create(&q)==XTC_OK);
|
||||
assert(xtc_project_add_track(p,"Keys",&track)==XTC_OK);
|
||||
assert(xtc_plugin_probe(XTC_BUILTIN_PATH,0,48000,&s)==XTC_OK);
|
||||
assert(xtc_plugin_probe(XTC_BUILTIN_PATH,instrument,48000,&s)==XTC_OK);
|
||||
assert(xtc_project_set_instrument(p,track,&s)==XTC_OK);
|
||||
assert(xtc_plugin_probe(XTC_BUILTIN_PATH,2,48000,&s)==XTC_OK); s.values[0]=250;
|
||||
assert(xtc_plugin_probe(XTC_BUILTIN_PATH,effect,48000,&s)==XTC_OK);
|
||||
s.point_count=2; s.points[0]=(xtc_plugin_point){0,2,0,.1f}; s.points[1]=(xtc_plugin_point){960,2,0,.6f};
|
||||
assert(xtc_graph_clone(xtc_project_graph(p),&g)==XTC_OK);
|
||||
assert(xtc_graph_add_plugin(g,&s,&id)==XTC_OK); assert(xtc_project_set_graph(p,g)==XTC_OK);xtc_graph_destroy(g);
|
||||
assert(xtc_project_save(p,path)==XTC_OK); assert(xtc_project_load(q,path)==XTC_OK);
|
||||
assert(xtc_graph_get_plugin(xtc_project_graph(q),id,&t)==XTC_OK); assert(t.values[0]==250 && t.point_count==2);
|
||||
assert(xtc_project_get_instrument(q,track,&t)==XTC_OK && t.index==0 && t.format==XTC_PLUGIN_BUILTIN);
|
||||
assert(xtc_graph_get_plugin(xtc_project_graph(q),id,&t)==XTC_OK); assert(!memcmp(&s,&t,sizeof(s)));
|
||||
assert(xtc_plugin_create(&s,48000,256,&a)==XTC_OK && xtc_plugin_create(&t,48000,256,&b)==XTC_OK);
|
||||
for(k=0;k<256;++k) {
|
||||
input[0]=k==0 ? 1 : 0;
|
||||
assert(xtc_plugin_process(a,input,x,256)==XTC_OK && xtc_plugin_process(b,input,y,256)==XTC_OK);
|
||||
assert(!memcmp(x,y,sizeof(x)));
|
||||
}
|
||||
xtc_plugin_destroy(a);xtc_plugin_destroy(b);
|
||||
assert(xtc_project_get_instrument(q,track,&t)==XTC_OK && t.index==instrument && t.format==XTC_PLUGIN_BUILTIN);
|
||||
assert(xtc_project_get_instrument(p,track,&s)==XTC_OK);
|
||||
assert(xtc_plugin_create(&s,48000,256,&a)==XTC_OK && xtc_plugin_create(&t,48000,256,&b)==XTC_OK);
|
||||
{ xtc_midi_event e={19,XTC_MIDI_NOTE_ON,0,60,100};
|
||||
assert(xtc_plugin_process_midi(a,&e,1,x,256)==XTC_OK && xtc_plugin_process_midi(b,&e,1,y,256)==XTC_OK);
|
||||
assert(!memcmp(x,y,sizeof(x))); }
|
||||
xtc_plugin_destroy(a);xtc_plugin_destroy(b);
|
||||
/* Corrupt a serialized identity, retaining a valid destination project. */
|
||||
{ FILE *file=fopen(path,"r+"); char data[32768]; size_t n; char *label;
|
||||
assert(file);n=fread(data,1,sizeof(data)-1,file);data[n]=0;
|
||||
label=strstr(data,effect==2 ? "44656c6179" : "526576657262");
|
||||
/* Names are hex encoded; module corruption is independent of name codec. */
|
||||
(void)label; label=strstr(data,"2f7874632f696e7465726e616c");
|
||||
assert(label);label[0]='3';rewind(file);assert(fwrite(data,1,n,file)==n);fclose(file);
|
||||
assert(xtc_project_load(q,path)!=XTC_OK);
|
||||
assert(xtc_project_get_instrument(q,track,&t)==XTC_OK && t.index==instrument); }
|
||||
xtc_project_destroy(p);xtc_project_destroy(q);unlink(path);
|
||||
}
|
||||
int main(void) {automation();roundtrip();effects(2);effects(3);synth(0);synth(1);puts("Built-in devices passed.");return 0;}
|
||||
static void synth_partition(unsigned int id)
|
||||
{
|
||||
xtc_plugin_spec s; xtc_plugin *a=NULL,*b=NULL; float x[256],y[256]; size_t i,k;
|
||||
xtc_midi_event events[40];
|
||||
assert(xtc_plugin_probe(XTC_BUILTIN_PATH,id,48000,&s)==XTC_OK);
|
||||
assert(xtc_plugin_create(&s,48000,256,&a)==XTC_OK && xtc_plugin_create(&s,48000,256,&b)==XTC_OK);
|
||||
/* Exhaust voices, repeat a key, sustain its note-off, then release pedal. */
|
||||
for(i=0;i<36;++i) events[i]=(xtc_midi_event){(unsigned int)i,XTC_MIDI_NOTE_ON,0,40+(unsigned int)i,100};
|
||||
events[36]=(xtc_midi_event){40,XTC_MIDI_NOTE_ON,0,60,80};
|
||||
events[37]=(xtc_midi_event){50,XTC_MIDI_CONTROL,0,64,127};
|
||||
events[38]=(xtc_midi_event){60,XTC_MIDI_NOTE_OFF,0,60,0};
|
||||
events[39]=(xtc_midi_event){80,XTC_MIDI_CONTROL,0,64,0};
|
||||
assert(xtc_plugin_process_midi(a,events,40,x,256)==XTC_OK);
|
||||
assert(xtc_plugin_process_midi(b,events,40,y,128)==XTC_OK);
|
||||
assert(xtc_plugin_process_midi(b,NULL,0,y+128,128)==XTC_OK);
|
||||
assert(!memcmp(x,y,sizeof(x)));
|
||||
for(k=0;k<100;++k) {
|
||||
assert(xtc_plugin_process_midi(a,NULL,0,x,256)==XTC_OK);
|
||||
assert(xtc_plugin_process_midi(b,NULL,0,y,128)==XTC_OK);
|
||||
assert(xtc_plugin_process_midi(b,NULL,0,y+128,128)==XTC_OK);
|
||||
for(i=0;i<256;++i) assert(isfinite(x[i]) && x[i]==y[i]);
|
||||
}
|
||||
events[0]=(xtc_midi_event){0,XTC_MIDI_ALL_OFF,0,0,0};
|
||||
assert(xtc_plugin_process_midi(a,events,1,x,256)==XTC_OK);
|
||||
for(i=0;i<256;++i) assert(x[i]==0);
|
||||
xtc_plugin_destroy(a);xtc_plugin_destroy(b);
|
||||
}
|
||||
static void transport(unsigned int id)
|
||||
{
|
||||
xtc_project *project=NULL;xtc_midi_plan *plan=NULL,*fresh=NULL;xtc_plugin_spec spec;
|
||||
uint64_t track,clip,note;float x[256],y[256];size_t k;
|
||||
assert(xtc_project_create(&project)==XTC_OK);
|
||||
assert(xtc_project_add_track(project,"Transport",&track)==XTC_OK);
|
||||
assert(xtc_project_add_midi_clip(project,track,0,3840,&clip)==XTC_OK);
|
||||
assert(xtc_project_add_note(project,clip,0,1920,60,100,0,¬e)==XTC_OK);
|
||||
assert(xtc_plugin_probe(XTC_BUILTIN_PATH,id,48000,&spec)==XTC_OK);
|
||||
assert(xtc_project_set_instrument(project,track,&spec)==XTC_OK);
|
||||
assert(xtc_midi_plan_create(project,48000,&plan)==XTC_OK);
|
||||
assert(xtc_midi_plan_create(project,48000,&fresh)==XTC_OK);
|
||||
assert(xtc_midi_plan_render(plan,0,NULL,0,x,256)==XTC_OK);
|
||||
/* Discontinuity chases with a fresh envelope, identical to a fresh plan. */
|
||||
assert(xtc_midi_plan_render(plan,1000,NULL,0,x,256)==XTC_OK);
|
||||
assert(xtc_midi_plan_render(fresh,1000,NULL,0,y,256)==XTC_OK);
|
||||
assert(!memcmp(x,y,sizeof(x)));
|
||||
xtc_midi_plan_panic(plan,1256);
|
||||
for(k=0;k<200;++k)assert(xtc_midi_plan_render(plan,1256+k*256,NULL,0,x,256)==XTC_OK);
|
||||
for(k=0;k<256;++k)assert(fabsf(x[k])<1e-5f);
|
||||
xtc_midi_plan_reset(plan);
|
||||
assert(xtc_midi_plan_render(plan,0,NULL,0,x,256)==XTC_OK);
|
||||
xtc_midi_plan_reset(fresh);
|
||||
assert(xtc_midi_plan_render(fresh,0,NULL,0,y,256)==XTC_OK);
|
||||
assert(!memcmp(x,y,sizeof(x)));
|
||||
xtc_midi_plan_destroy(plan);xtc_midi_plan_destroy(fresh);xtc_project_destroy(project);
|
||||
}
|
||||
int main(void) {
|
||||
transport(0);transport(1);automation();roundtrip(0,2);roundtrip(1,3);effects(2);effects(3);synth(0);synth(1);
|
||||
synth_partition(0);synth_partition(1);puts("Built-in devices passed.");return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue