xtc/tests/unit/test_creative.c

103 lines
7.3 KiB
C
Raw Permalink Normal View History

#define _POSIX_C_SOURCE 200809L
#include "xtc/xtc_plugin.h"
#include "xtc/xtc_tempo.h"
#include "xtc/xtc_editing.h"
#include "xtc/xtc_audio.h"
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
static void tap_tests(void)
{
xtc_tap_tempo s={0},before;unsigned int tempo=999;
assert(xtc_tap_tempo_push(&s,0,&tempo)==XTC_ERR_NOT_FOUND && tempo==999);
assert(xtc_tap_tempo_push(&s,.5,&tempo)==XTC_OK && tempo==120000);
before=s;assert(xtc_tap_tempo_push(&s,.55,&tempo)==XTC_ERR_INVALID_ARGUMENT && !memcmp(&s,&before,sizeof(s)) && tempo==120000);
assert(xtc_tap_tempo_push(&s,NAN,&tempo)==XTC_ERR_INVALID_ARGUMENT && !memcmp(&s,&before,sizeof(s)));
assert(xtc_tap_tempo_push(&s,.4,&tempo)==XTC_ERR_INVALID_ARGUMENT && !memcmp(&s,&before,sizeof(s)));
assert(xtc_tap_tempo_push(&s,1,&tempo)==XTC_OK && xtc_tap_tempo_push(&s,1.5,&tempo)==XTC_OK && xtc_tap_tempo_push(&s,2,&tempo)==XTC_OK);
assert(xtc_tap_tempo_push(&s,2.25,&tempo)==XTC_OK && tempo==137143);
assert(xtc_tap_tempo_push(&s,10,&tempo)==XTC_ERR_NOT_FOUND && tempo==137143 && !s.count);
assert(xtc_tap_tempo_push(&s,10.25,&tempo)==XTC_OK && tempo==240000);
xtc_tap_tempo_reset(&s);assert(!s.started && !s.count);
}
static void crossfade_tests(void)
{
xtc_project *p=NULL;xtc_recorder *rec=NULL;xtc_audio_plan *plan=NULL;uint64_t track,a,b;xtc_clip_info left,right,before;
char wave[]="/tmp/xtc-crossfade-XXXXXX";int fd=mkstemp(wave);float ones[1000],output[32];assert(fd>=0);close(fd);unlink(wave);
for(size_t i=0;i<1000;++i)ones[i]=1;
assert(xtc_recorder_create(wave,8000,8000,&rec)==XTC_OK);
for(size_t i=0;i<8;++i)xtc_recorder_push(rec,ones,1000);
assert(xtc_recorder_finish(rec)==XTC_OK);xtc_recorder_destroy(rec);
assert(xtc_project_create(&p)==XTC_OK && xtc_project_add_track(p,"Audio",&track)==XTC_OK);
assert(xtc_project_add_clip(p,track,"Left",0,1920,&a)==XTC_OK && xtc_project_add_clip(p,track,"Right",960,1920,&b)==XTC_OK);
assert(xtc_project_set_clip_asset(p,a,wave)==XTC_OK && xtc_project_set_clip_asset(p,b,wave)==XTC_OK);
assert(xtc_project_set_clip_audio(p,a,1,16,0)==XTC_OK && xtc_project_set_clip_audio(p,b,1,0,16)==XTC_OK);
assert(xtc_project_crossfade(p,b,a)==XTC_OK && xtc_project_find_clip(p,a,&left)==XTC_OK && xtc_project_find_clip(p,b,&right)==XTC_OK);
assert(left.fade_in_tick==16 && left.fade_out_tick==960 && right.fade_in_tick==960 && right.fade_out_tick==16);
assert(xtc_audio_plan_create(p,8000,&plan)==XTC_OK && xtc_audio_plan_set_fade_frames(plan,0)==XTC_OK && xtc_audio_plan_render(plan,4000,output,32)==XTC_OK);
for(size_t i=0;i<32;++i)assert(fabsf(output[i]-.99975f)<.00001f);
xtc_audio_plan_destroy(plan);before=left;
assert(xtc_project_crossfade(p,a,a)==XTC_ERR_INVALID_ARGUMENT && xtc_project_find_clip(p,a,&left)==XTC_OK && !memcmp(&before,&left,sizeof(left)));
assert(xtc_project_edit_clip(p,b,track,1920,1920,0)==XTC_OK && xtc_project_crossfade(p,a,b)==XTC_ERR_INVALID_ARGUMENT);
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();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);
assert(xtc_track_chain_duplicate(&c,0,&out)==XTC_OK && out.count==2 && out.output_gain==.8f);
assert(!memcmp(out.slots,out.slots+1,sizeof(out.slots[0])));
out.slots[1].plugin.values[0]=10;assert(c.slots[0].plugin.values[0]!=10 && out.slots[0].plugin.values[0]!=10);
assert(xtc_track_chain_duplicate(&out,1,&out)==XTC_OK && out.count==3 && out.slots[2].plugin.values[0]==10);
c=out;assert(xtc_track_chain_duplicate(&out,3,&out)==XTC_ERR_INVALID_ARGUMENT && !memcmp(&c,&out,sizeof(c)));
for(size_t i=3;i<XTC_TRACK_INSERTS;++i)out.slots[i]=out.slots[0];
out.count=XTC_TRACK_INSERTS;c=out;
assert(xtc_track_chain_duplicate(&out,0,&out)==XTC_ERR_CAPACITY && !memcmp(&c,&out,sizeof(c)));
for(unsigned int preset=0;preset<3;++preset) {
xtc_graph *g=NULL;xtc_plan *plan=NULL;float input[512]={1},output[512];double energy=0;
assert(xtc_track_chain_template_name(preset) && xtc_track_chain_template(preset,135000,&c)==XTC_OK && xtc_track_chain_validate(&c)==XTC_OK);
assert(c.slots[0].plugin.tempo==135000 && xtc_track_chain_graph(&c,&g)==XTC_OK && xtc_graph_compile(g,8000,512,&plan)==XTC_OK);
assert(xtc_plan_process(plan,input,output,512)==XTC_OK);
for(size_t i=0;i<512;++i){assert(isfinite(output[i]));energy+=output[i]*output[i];}assert(energy>0);
xtc_plan_destroy(plan);xtc_graph_destroy(g);
}
out=c;assert(!xtc_track_chain_template_name(3) && xtc_track_chain_template(3,120000,&c)==XTC_ERR_INVALID_ARGUMENT && !memcmp(&out,&c,sizeof(c)));
assert(xtc_track_chain_template(1,120000,&c)==XTC_OK);
assert(xtc_track_chain_bulk(&c,XTC_CHAIN_BYPASS_ALL,&c)==XTC_OK && !c.slots[0].enabled && !c.slots[1].enabled && c.output_gain==.8f);
assert(xtc_track_chain_bulk(&c,XTC_CHAIN_ENABLE_ALL,&c)==XTC_OK && c.slots[0].enabled && c.slots[1].enabled);
out=c;assert(xtc_track_chain_bulk(&c,(xtc_chain_action)99,&c)==XTC_ERR_INVALID_ARGUMENT && !memcmp(&c,&out,sizeof(c)));
assert(xtc_track_chain_bulk(&c,XTC_CHAIN_CLEAR,&c)==XTC_OK && c.count==0 && c.output_gain==.8f && !c.slots[0].plugin.path[0]);
puts("Creative editing core checks passed.");return 0;
}