98 lines
9.4 KiB
C
98 lines
9.4 KiB
C
#define _POSIX_C_SOURCE 200809L
|
|
#include "xtc/xtc_sample.h"
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
#include <float.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
int main(void)
|
|
{
|
|
char root[]="/tmp/xtc-sample-test-XXXXXX",path[256];float values[]={0,.25f,-.5f,.75f,0,0,.5f,-.25f};
|
|
xtc_recorder *rec=NULL;xtc_sample *s=NULL,*sentinel=NULL;xtc_sample_stats stats;size_t frames;unsigned int rate;float v=123;
|
|
assert(mkdtemp(root));snprintf(path,sizeof(path),"%s/source.wav",root);
|
|
assert(xtc_recorder_create(path,8000,8,&rec)==XTC_OK);xtc_recorder_push(rec,values,8);assert(xtc_recorder_finish(rec)==XTC_OK);xtc_recorder_destroy(rec);
|
|
assert(xtc_sample_load(path,&s)==XTC_OK && xtc_sample_info(s,&rate,&frames)==XTC_OK && rate==8000 && frames==8);
|
|
assert(xtc_sample_analyze(s,0,8,&stats)==XTC_OK && stats.minimum==-.5f && stats.maximum==.75f && stats.mean==.09375);
|
|
assert(fabs(stats.rms-sqrt(1.1875/8))<.000001);
|
|
assert(xtc_sample_read(s,8,&v)==XTC_ERR_INVALID_ARGUMENT && v==123);
|
|
assert(xtc_sample_read(s,2,&v)==XTC_OK && v==-.5f);
|
|
assert(xtc_sample_analyze(s,2,2,&stats)==XTC_ERR_INVALID_ARGUMENT);
|
|
assert(xtc_sample_load("/missing/xtc.wav",&sentinel)==XTC_ERR_IO && sentinel==NULL);
|
|
{xtc_project *p=NULL;uint64_t t,c;xtc_clip_info clip;assert(xtc_project_create(&p)==XTC_OK && xtc_project_add_track(p,"Audio",&t)==XTC_OK);
|
|
assert(xtc_project_add_clip(p,t,"Audio",10,960,&c)==XTC_OK && xtc_project_set_clip_asset(p,c,path)==XTC_OK);
|
|
assert(xtc_project_trim_source_frames(p,c,48000,1000,2000)==XTC_OK);
|
|
assert(xtc_project_find_clip(p,c,&clip)==XTC_OK && clip.start_tick==50 && clip.offset_tick==40 && clip.length_tick==40);
|
|
assert(xtc_project_trim_source_frames(p,c,48000,1001,1002)==XTC_ERR_INVALID_ARGUMENT);
|
|
assert(xtc_project_find_clip(p,c,&clip)==XTC_OK && clip.offset_tick==40 && clip.length_tick==40);
|
|
xtc_project_destroy(p);}
|
|
{char copy[256];xtc_sample *q=NULL;snprintf(copy,sizeof(copy),"%s/copy.wav",root);
|
|
assert(xtc_sample_write(s,1,7,copy)==XTC_OK && xtc_sample_write(s,1,7,copy)==XTC_ERR_IO);
|
|
assert(xtc_sample_load(copy,&q)==XTC_OK && xtc_sample_info(q,&rate,&frames)==XTC_OK && frames==6 && rate==8000);
|
|
for(size_t j=0;j<6;++j){assert(xtc_sample_read(q,j,&v)==XTC_OK && v==values[j+1]);}
|
|
xtc_sample_destroy(q);assert(unlink(copy)==0);assert(xtc_sample_write(s,0,8,"relative.wav")==XTC_ERR_INVALID_ARGUMENT);}
|
|
{xtc_sample *q=NULL,*twice=NULL;assert(xtc_sample_process(s,1,7,XTC_SAMPLE_REVERSE,0,&q)==XTC_OK);
|
|
for(size_t j=0;j<8;++j){assert(xtc_sample_read(q,j,&v)==XTC_OK && v==(j>=1&&j<7 ? values[7-j] : values[j]));}
|
|
assert(xtc_sample_process(q,1,7,XTC_SAMPLE_REVERSE,0,&twice)==XTC_OK);
|
|
for(size_t j=0;j<8;++j){assert(xtc_sample_read(twice,j,&v)==XTC_OK && v==values[j]);}
|
|
xtc_sample_destroy(q);xtc_sample_destroy(twice);}
|
|
{xtc_sample *q=NULL,*twice=NULL;assert(xtc_sample_process(s,1,7,XTC_SAMPLE_INVERT,0,&q)==XTC_OK);
|
|
for(size_t j=0;j<8;++j){assert(xtc_sample_read(q,j,&v)==XTC_OK && v==(j>=1&&j<7 ? -values[j] : values[j]));}
|
|
assert(xtc_sample_process(q,1,7,XTC_SAMPLE_INVERT,0,&twice)==XTC_OK);
|
|
for(size_t j=0;j<8;++j){assert(xtc_sample_read(twice,j,&v)==XTC_OK && v==values[j]);}
|
|
xtc_sample_destroy(q);xtc_sample_destroy(twice);}
|
|
{xtc_sample *q=NULL;xtc_sample_stats after;assert(xtc_sample_analyze(s,1,7,&stats)==XTC_OK);
|
|
assert(xtc_sample_process(s,1,7,XTC_SAMPLE_REMOVE_DC,0,&q)==XTC_OK);
|
|
assert(xtc_sample_analyze(q,1,7,&after)==XTC_OK && fabs(after.mean)<.000001);
|
|
for(size_t j=0;j<8;++j){assert(xtc_sample_read(q,j,&v)==XTC_OK && fabs(v-(j>=1&&j<7 ? values[j]-stats.mean : values[j]))<.000001);}
|
|
xtc_sample_destroy(q);}
|
|
for(int mode=0;mode<4;++mode){xtc_sample *q=NULL;assert(xtc_sample_process(s,1,7,(xtc_sample_operation)(XTC_SAMPLE_FADE_IN+mode),0,&q)==XTC_OK);
|
|
for(size_t j=0;j<8;++j){double scale=1;if(j>=1&&j<7){scale=(double)(j-1)/5;if(mode==1||mode==3)scale=1-scale;if(mode>=2)scale=sin(scale*1.57079632679489661923);}assert(xtc_sample_read(q,j,&v)==XTC_OK && fabs(v-values[j]*scale)<.000001);}
|
|
xtc_sample_destroy(q);}
|
|
{xtc_sample *q=NULL;assert(xtc_sample_process(s,1,2,XTC_SAMPLE_FADE_IN,0,&q)==XTC_ERR_INVALID_ARGUMENT && q==NULL);}
|
|
{xtc_sample *q=NULL;assert(xtc_sample_process(s,1,7,XTC_SAMPLE_NORMALIZE,.375,&q)==XTC_OK);
|
|
for(size_t j=0;j<8;++j){assert(xtc_sample_read(q,j,&v)==XTC_OK && v==values[j]*(j>=1&&j<7 ? .5f : 1));}xtc_sample_destroy(q);q=NULL;
|
|
assert(xtc_sample_process(s,1,7,XTC_SAMPLE_GAIN,2,&q)==XTC_OK);assert(xtc_sample_read(q,3,&v)==XTC_OK && v==1.5f);xtc_sample_destroy(q);q=NULL;
|
|
assert(xtc_sample_process(s,4,6,XTC_SAMPLE_NORMALIZE,1,&q)==XTC_ERR_INVALID_STATE && q==NULL);
|
|
assert(xtc_sample_process(s,1,7,XTC_SAMPLE_GAIN,NAN,&q)==XTC_ERR_INVALID_ARGUMENT && q==NULL);
|
|
assert(xtc_sample_process(s,1,7,XTC_SAMPLE_GAIN,17,&q)==XTC_ERR_INVALID_ARGUMENT && q==NULL);}
|
|
{size_t b=999,e=999;assert(xtc_sample_audible_bounds(s,0,8,.25,0,&b,&e)==XTC_OK && b==2 && e==7);
|
|
assert(xtc_sample_audible_bounds(s,0,8,.25,2,&b,&e)==XTC_OK && b==0 && e==8);
|
|
b=e=999;assert(xtc_sample_audible_bounds(s,4,6,0,0,&b,&e)==XTC_ERR_NOT_FOUND && b==999 && e==999);
|
|
assert(xtc_sample_audible_bounds(s,0,8,NAN,0,&b,&e)==XTC_ERR_INVALID_ARGUMENT && b==999);}
|
|
{size_t crossing=999;assert(xtc_sample_zero_crossing(s,1,1,&crossing)==XTC_OK && crossing==0);
|
|
assert(xtc_sample_zero_crossing(s,6,0,&crossing)==XTC_ERR_NOT_FOUND && crossing==0);
|
|
assert(xtc_sample_zero_crossing(s,6,1,&crossing)==XTC_OK && crossing==5);
|
|
assert(xtc_sample_zero_crossing(s,8,1,&crossing)==XTC_OK && crossing==7);
|
|
assert(xtc_sample_zero_crossing(s,0,65537,&crossing)==XTC_ERR_INVALID_ARGUMENT && crossing==7);}
|
|
{size_t positions[128]={999},count=999;assert(xtc_sample_transients(s,0,8,.4,1,positions,128,&count)==XTC_OK && count==2 && positions[0]==2 && positions[1]==6);
|
|
count=999;positions[0]=999;assert(xtc_sample_transients(s,0,8,.4,1,positions,1,&count)==XTC_ERR_CAPACITY && count==999 && positions[0]==999);
|
|
assert(xtc_sample_transients(s,0,8,.4,5,positions,128,&count)==XTC_OK && count==1 && positions[0]==2);}
|
|
{xtc_project *p=NULL,*q=NULL;xtc_audio_plan *a=NULL,*b=NULL;uint64_t t,c;float before[128],after[128];size_t cuts[]={0,4,8},made=999,tracks=0,clips=0;char song[256];
|
|
assert(xtc_project_create(&p)==XTC_OK && xtc_project_add_track(p,"Audio",&t)==XTC_OK && xtc_project_import_audio(p,t,path,10,&c)==XTC_OK);
|
|
assert(xtc_audio_plan_create(p,8000,&a)==XTC_OK && xtc_audio_plan_render(a,0,before,128)==XTC_OK);
|
|
assert(xtc_project_slice_source_frames(p,c,8000,cuts,3,&made)==XTC_OK && made==1);
|
|
assert(xtc_audio_plan_create(p,8000,&b)==XTC_OK && xtc_audio_plan_render(b,0,after,128)==XTC_OK && !memcmp(before,after,sizeof(before)));
|
|
snprintf(song,sizeof(song),"%s/slices.xtc",root);assert(xtc_project_save(p,song)==XTC_OK && xtc_project_create(&q)==XTC_OK && xtc_project_load(q,song)==XTC_OK);
|
|
assert(xtc_project_get_counts(q,&tracks,&clips)==XTC_OK && clips==2);assert(unlink(song)==0);
|
|
xtc_audio_plan_destroy(a);xtc_audio_plan_destroy(b);xtc_project_destroy(p);xtc_project_destroy(q);}
|
|
{xtc_project *p=NULL;uint64_t t,c,extra;size_t cuts[]={1000,2000},made=999,tracks,clips;
|
|
assert(xtc_project_create(&p)==XTC_OK && xtc_project_add_track(p,"Full",&t)==XTC_OK && xtc_project_add_clip(p,t,"Source",0,960,&c)==XTC_OK && xtc_project_set_clip_asset(p,c,path)==XTC_OK);
|
|
for(size_t j=1;j<XTC_PROJECT_MAX_CLIPS-1;++j)assert(xtc_project_add_clip(p,t,"Fill",10000,960,&extra)==XTC_OK);
|
|
assert(xtc_project_slice_source_frames(p,c,48000,cuts,2,&made)==XTC_ERR_CAPACITY && made==999);
|
|
assert(xtc_project_get_counts(p,&tracks,&clips)==XTC_OK && clips==XTC_PROJECT_MAX_CLIPS-1);
|
|
assert(xtc_project_add_clip(p,t,"Probe",10000,960,&extra)==XTC_OK && extra==XTC_PROJECT_MAX_CLIPS-1);xtc_project_destroy(p);}
|
|
{char big[256];unsigned char header[44];uint32_t count=(XTC_SAMPLE_MAX_FRAMES+1U)*4U;FILE *input=fopen(path,"rb"),*output;xtc_sample *q=NULL;
|
|
assert(input && fread(header,1,44,input)==44 && fclose(input)==0);snprintf(big,sizeof(big),"%s/large.wav",root);
|
|
for(unsigned int j=0;j<4;++j){header[4+j]=(unsigned char)((count+36U)>>(j*8));header[40+j]=(unsigned char)(count>>(j*8));}
|
|
output=fopen(big,"wb");assert(output && fwrite(header,1,44,output)==44 && fflush(output)==0 && ftruncate(fileno(output),(off_t)count+44)==0 && fclose(output)==0);
|
|
assert(xtc_sample_load(big,&q)==XTC_ERR_CAPACITY && q==NULL);assert(unlink(big)==0);}
|
|
{char edge[256];float large=FLT_MAX;xtc_sample *q=NULL,*result=NULL;snprintf(edge,sizeof(edge),"%s/edge.wav",root);
|
|
assert(xtc_recorder_create(edge,8000,1,&rec)==XTC_OK);xtc_recorder_push(rec,&large,1);assert(xtc_recorder_finish(rec)==XTC_OK);xtc_recorder_destroy(rec);
|
|
assert(xtc_sample_load(edge,&q)==XTC_OK && xtc_sample_process(q,0,1,XTC_SAMPLE_GAIN,2,&result)==XTC_ERR_CAPACITY && result==NULL);
|
|
assert(xtc_sample_read(q,0,&v)==XTC_OK && v==FLT_MAX);xtc_sample_destroy(q);assert(unlink(edge)==0);
|
|
large=.001f;assert(xtc_recorder_create(edge,8000,1,&rec)==XTC_OK);xtc_recorder_push(rec,&large,1);assert(xtc_recorder_finish(rec)==XTC_OK);xtc_recorder_destroy(rec);
|
|
assert(xtc_sample_load(edge,&q)==XTC_OK && xtc_sample_process(q,0,1,XTC_SAMPLE_NORMALIZE,1,&result)==XTC_ERR_CAPACITY && result==NULL);xtc_sample_destroy(q);assert(unlink(edge)==0);}
|
|
xtc_sample_destroy(s);assert(unlink(path)==0 && rmdir(root)==0);puts("Sample editor core tests passed.");return 0;
|
|
}
|