feat(midi): strum chords with preserved note ends and undo (phase 99)

This commit is contained in:
Johannes Findeisen 2026-11-06 02:16:46 +01:00
commit bd0a63c06d
17 changed files with 172 additions and 5 deletions

View file

@ -45,9 +45,35 @@ static void crossfade_tests(void)
assert(xtc_project_find_clip(p,a,&left)==XTC_OK && !memcmp(&before,&left,sizeof(left)));
xtc_project_destroy(p);unlink(wave);
}
static void strum_tests(void)
{
xtc_project *p=NULL,*down=NULL;uint64_t t,c,n,solo,audio;xtc_note_info before[5],after;
unsigned int pitches[]={67,60,64,72,48};
assert(xtc_project_create(&p)==XTC_OK && xtc_project_add_track(p,"Chords",&t)==XTC_OK);
assert(xtc_project_add_midi_clip(p,t,0,1920,&c)==XTC_OK);
for(size_t i=0;i<5;++i){
assert(xtc_project_add_note(p,c,i==3 ? 480 : 0,200,pitches[i],100,i==4 ? 1 : 0,&n)==XTC_OK);
assert(xtc_project_get_note(p,i,before+i)==XTC_OK);
}
assert(xtc_project_clone(p,&down)==XTC_OK);
assert(xtc_project_strum(p,&c,1,200,0)==XTC_ERR_INVALID_ARGUMENT);
for(size_t i=0;i<5;++i){assert(xtc_project_get_note(p,i,&after)==XTC_OK && !memcmp(&after,before+i,sizeof(after)));}
assert(xtc_project_strum(p,&c,1,0,0)==XTC_ERR_INVALID_ARGUMENT && xtc_project_strum(p,&c,1,20,2)==XTC_ERR_INVALID_ARGUMENT);
assert(xtc_project_strum(p,&c,1,20,0)==XTC_OK && xtc_project_strum(down,&c,1,20,1)==XTC_OK);
for(size_t i=0;i<5;++i){
uint64_t up[]={40,0,20,480,0},descending[]={0,40,20,480,0};
assert(xtc_project_get_note(p,i,&after)==XTC_OK && after.start_tick==up[i] && after.start_tick+after.length_tick==before[i].start_tick+200 && after.id==before[i].id && after.pitch==pitches[i] && after.velocity==100 && after.channel==before[i].channel);
assert(xtc_project_get_note(down,i,&after)==XTC_OK && after.start_tick==descending[i]);
}
assert(xtc_project_add_midi_clip(p,t,3840,1920,&solo)==XTC_OK && xtc_project_add_note(p,solo,0,100,60,100,0,&n)==XTC_OK);
assert(xtc_project_strum(p,&solo,1,20,0)==XTC_ERR_NOT_FOUND);
assert(xtc_project_add_clip(p,t,"Audio",7680,1920,&audio)==XTC_OK);
{uint64_t ids[]={c,audio};assert(xtc_project_strum(p,ids,2,20,0)==XTC_ERR_INVALID_STATE);}
xtc_project_destroy(p);xtc_project_destroy(down);
}
int main(void)
{
tap_tests();crossfade_tests();
tap_tests();crossfade_tests();strum_tests();
xtc_track_chain c={0},out={0};
c.output_gain=.8f;c.count=1;c.slots[0].enabled=1;c.slots[0].wet=.4f;
assert(xtc_plugin_probe_format(XTC_PLUGIN_BUILTIN,XTC_BUILTIN_PATH,2,48000,&c.slots[0].plugin)==XTC_OK);