/* * Copyright (c) 1983-2023 Trevor Wishart and Composers Desktop Project Ltd * http://www.trevorwishart.co.uk * http://www.composersdesktop.com * This file is part of the CDP System. The CDP System is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The CDP System is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the CDP System; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined unix || defined __GNUC__ #define round(x) lround((x)) #endif #ifndef HUGE #define HUGE 3.40282347e+38F #endif char errstr[2400]; int anal_infiles = 1; int sloom = 0; int sloombatch = 0; const char* cdp_version = "7.1.0"; char infilename[1000]; #define BIGGERSIL (8) /* keep only silences which are more than 1/8 length of max silence */ #define RETIME_ENVSIZE (1000) #define RETIME_WINSIZE (20) //CDP LIB REPLACEMENTS static int check_retime_param_validity_and_consistency(dataptr dz); static int setup_retime_application(dataptr dz); static int parse_sloom_data(int argc,char *argv[],char ***cmdline,int *cmdlinecnt,dataptr dz); static int parse_infile_and_check_type(char **cmdline,dataptr dz); static int setup_retime_param_ranges_and_defaults(dataptr dz); static int handle_the_outfile(int *cmdlinecnt,char ***cmdline,dataptr dz); static int setup_and_init_input_param_activity(dataptr dz,int tipc); static int setup_input_param_defaultval_stores(int tipc,aplptr ap); static int establish_application(dataptr dz); static int initialise_vflags(dataptr dz); static int setup_parameter_storage_and_constants(int storage_cnt,dataptr dz); static int initialise_is_int_and_no_brk_constants(int storage_cnt,dataptr dz); static int mark_parameter_types(dataptr dz,aplptr ap); static int assign_file_data_storage(int infilecnt,dataptr dz); static int get_tk_cmdline_word(int *cmdlinecnt,char ***cmdline,char *q); static int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz); static int get_the_mode_from_cmdline(char *str,dataptr dz); static int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt); static int handle_the_special_data(int *cmdlinecnt,char ***cmdline,dataptr dz); static int create_retime_sndbufs(dataptr dz); static int retime(dataptr dz); static int setup_the_special_data_ranges(int mode,int srate,double duration,double nyquist,int wlength,int channels,aplptr ap); static int advance_obuf(int *obufpos,dataptr dz); static int advance_ibuf(int *abs_read_start,int *read_end_in_buf,int *last_time_in_inbuf,int *next_time_in_inbuf, int *min_energy_point,int silcnt,int *silat,dataptr dz); static int find_min_energy_point(int *min_energy_point,int last_time_in_inbuf,int next_time_in_inbuf,int winsize,float *ibuf,float *env,int *pos,dataptr dz); static int read_ideal_data(char *filename,dataptr dz); static int read_retime_data(char *filename,dataptr dz); static int read_retempo_data(char *filename,dataptr dz); static int read_retime_mask(char *filename,dataptr dz); static int ideal_retime(dataptr dz); static int shave(dataptr dz); static int retime_found_peaks(dataptr dz); static int locate_peaks(dataptr dz); static int establish_cuts_array(dataptr dz); static int eliminate_lost_ideal_and_real_events(int *lost,int lostcnt,dataptr dz); static int reposition_peak(dataptr dz); static int repeat_beats(dataptr dz); static int get_initial_silence(int *initial_silence,dataptr dz); static int find_sound_start(dataptr dz); static int read_retime_fnam(char *filename,dataptr dz); static int find_shortest_event(dataptr dz); static int count_events(int paramno,int arrayno,int *eventsegscnt, dataptr dz); static int equalise_event_levels(dataptr dz); static int retempo_events(dataptr dz); static int mask_events(dataptr dz); static int usage22(char *str,char *str2); #define MMin scalefact /* Use 'dz->scalefact' param to store MM */ #define offset chwidth /* use 'dz->chwidth' param to store offset */ /**************************************** MAIN *********************************************/ int main(int argc,char *argv[]) { int exit_status; dataptr dz = NULL; char **cmdline; int cmdlinecnt; //aplptr ap; int is_launched = FALSE; if(argc==2 && (strcmp(argv[1],"--version") == 0)) { fprintf(stdout,"%s\n",cdp_version); fflush(stdout); return 0; } /* CHECK FOR SOUNDLOOM */ if((sloom = sound_loom_in_use(&argc,&argv)) > 1) { sloom = 0; sloombatch = 1; } if(sflinit("cdp")){ sfperror("cdp: initialisation\n"); return(FAILED); } /* SET UP THE PRINCIPLE DATASTRUCTURE */ if((exit_status = establish_datastructure(&dz))<0) { // CDP LIB print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(FAILED); } if(!sloom) { if(argc == 1) { usage1(); return(FAILED); } else if(argc == 2) { usage2(argv[1]); return(FAILED); } else if(argc == 3) { usage22(argv[1],argv[2]); return(FAILED); } } dz->maxmode = 14; if(!sloom) { if((exit_status = make_initial_cmdline_check(&argc,&argv))<0) { // CDP LIB print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(FAILED); } cmdline = argv; cmdlinecnt = argc; if((get_the_process_no(argv[0],dz))<0) return(FAILED); cmdline++; cmdlinecnt--; if((exit_status = get_the_mode_from_cmdline(cmdline[0],dz))<0) { print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(exit_status); } cmdline++; cmdlinecnt--; // setup_particular_application = if((exit_status = setup_retime_application(dz))<0) { print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(FAILED); } if((exit_status = count_and_allocate_for_infiles(cmdlinecnt,cmdline,dz))<0) { // CDP LIB print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(FAILED); } } else { //parse_TK_data() = if((exit_status = parse_sloom_data(argc,argv,&cmdline,&cmdlinecnt,dz))<0) { exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(exit_status); } } //ap = dz->application; // parse_infile_and_hone_type() = if((exit_status = parse_infile_and_check_type(cmdline,dz))<0) { exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(FAILED); } // setup_param_ranges_and_defaults() = if((exit_status = setup_retime_param_ranges_and_defaults(dz))<0) { exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(FAILED); } // open_first_infile CDP LIB strcpy(infilename,cmdline[0]); if((exit_status = open_first_infile(cmdline[0],dz))<0) { print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(FAILED); } cmdlinecnt--; cmdline++; // handle_extra_infiles() : redundant // handle_outfile() = if(dz->mode != 11) { if(dz->mode != 10) { if((exit_status = handle_the_outfile(&cmdlinecnt,&cmdline,dz))<0) { print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(FAILED); } } else if(sloom) { // mode 10, no outfile cmdlinecnt--; // in sloom, always an outfile name in cmdline cmdline++; } } // handle_formants() redundant // handle_formant_quiksearch() redundant if((exit_status = handle_the_special_data(&cmdlinecnt,&cmdline,dz))<0) { print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(FAILED); } if((exit_status = read_parameters_and_flags(&cmdline,&cmdlinecnt,dz))<0) { // CDP LIB print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(FAILED); } // check_param_validity_and_consistency.... if((exit_status = check_retime_param_validity_and_consistency(dz))<0) { print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(FAILED); } is_launched = TRUE; switch(dz->mode) { case(0): dz->bufcnt = 5; break; case(1): dz->bufcnt = 4; break; case(2): case(8): case(10): case(11): dz->bufcnt = 1; break; case(3): case(4): case(5): case(6): dz->bufcnt = 3; break; case(7): dz->bufcnt = 4; break; case(9): dz->bufcnt = 1; break; case(12): case(13): dz->bufcnt = 2; break; } if((dz->sampbuf = (float **)malloc(sizeof(float *) * (dz->bufcnt+1)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY establishing sample buffers.\n"); return(MEMORY_ERROR); } if((dz->sbufptr = (float **)malloc(sizeof(float *) * dz->bufcnt))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY establishing sample buffer pointers.\n"); return(MEMORY_ERROR); } if((exit_status = create_retime_sndbufs(dz))<0) { print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(FAILED); } //param_preprocess() redundant //spec_process_file = switch(dz->mode) { case(0): if((exit_status = retime(dz))<0) { print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(FAILED); } break; case(1): if((exit_status = ideal_retime(dz))<0) { print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(FAILED); } break; case(2): if((exit_status = shave(dz))<0) { print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(FAILED); } break; case(3): case(4): if((exit_status = retime_found_peaks(dz))<0) { print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(FAILED); } break; case(5): case(6): if((exit_status = retempo_events(dz))<0) { print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(FAILED); } break; case(7): if((exit_status = repeat_beats(dz))<0) { print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(FAILED); } break; case(8): if((exit_status = mask_events(dz))<0) { print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(FAILED); } break; case(9): if((exit_status = equalise_event_levels(dz))<0) { print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(FAILED); } break; case(10): if((exit_status = find_shortest_event(dz))<0) { print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(FAILED); } break; case(11): if((exit_status = find_sound_start(dz))<0) { print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(FAILED); } break; case(12): case(13): if((exit_status = reposition_peak(dz))<0) { print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(FAILED); } break; } if((exit_status = complete_output(dz))<0) { // CDP LIB print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(FAILED); } exit_status = print_messages_and_close_sndfiles(FINISHED,is_launched,dz); // CDP LIB free(dz); return(SUCCEEDED); } /********************************************** REPLACED CDP LIB FUNCTIONS **********************************************/ /****************************** SET_PARAM_DATA *********************************/ int set_param_data(aplptr ap, int special_data,int maxparamcnt,int paramcnt,char *paramlist) { ap->special_data = (char)special_data; ap->param_cnt = (char)paramcnt; ap->max_param_cnt = (char)maxparamcnt; if(ap->max_param_cnt>0) { if((ap->param_list = (char *)malloc((size_t)(ap->max_param_cnt+1)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY: for param_list\n"); return(MEMORY_ERROR); } strcpy(ap->param_list,paramlist); } return(FINISHED); } /****************************** SET_VFLGS *********************************/ int set_vflgs (aplptr ap,char *optflags,int optcnt,char *optlist,char *varflags,int vflagcnt, int vparamcnt,char *varlist) { ap->option_cnt = (char) optcnt; /*RWD added cast */ if(optcnt) { if((ap->option_list = (char *)malloc((size_t)(optcnt+1)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY: for option_list\n"); return(MEMORY_ERROR); } strcpy(ap->option_list,optlist); if((ap->option_flags = (char *)malloc((size_t)(optcnt+1)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY: for option_flags\n"); return(MEMORY_ERROR); } strcpy(ap->option_flags,optflags); } ap->vflag_cnt = (char) vflagcnt; ap->variant_param_cnt = (char) vparamcnt; if(vflagcnt) { if((ap->variant_list = (char *)malloc((size_t)(vflagcnt+1)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY: for variant_list\n"); return(MEMORY_ERROR); } strcpy(ap->variant_list,varlist); if((ap->variant_flags = (char *)malloc((size_t)(vflagcnt+1)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY: for variant_flags\n"); return(MEMORY_ERROR); } strcpy(ap->variant_flags,varflags); } return(FINISHED); } /***************************** APPLICATION_INIT **************************/ int application_init(dataptr dz) { int exit_status; int storage_cnt; int tipc, brkcnt; aplptr ap = dz->application; if(ap->vflag_cnt>0) initialise_vflags(dz); tipc = ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt; ap->total_input_param_cnt = (char)tipc; if(tipc>0) { if((exit_status = setup_input_param_range_stores(tipc,ap))<0) return(exit_status); if((exit_status = setup_input_param_defaultval_stores(tipc,ap))<0) return(exit_status); if((exit_status = setup_and_init_input_param_activity(dz,tipc))<0) return(exit_status); } brkcnt = tipc; if(brkcnt>0) { if((exit_status = setup_and_init_input_brktable_constants(dz,brkcnt))<0) return(exit_status); } if((storage_cnt = tipc + ap->internal_param_cnt)>0) { if((exit_status = setup_parameter_storage_and_constants(storage_cnt,dz))<0) return(exit_status); if((exit_status = initialise_is_int_and_no_brk_constants(storage_cnt,dz))<0) return(exit_status); } if((exit_status = mark_parameter_types(dz,ap))<0) return(exit_status); // establish_infile_constants() replaced by dz->infilecnt = 1; //establish_bufptrs_and_extra_buffers(): if((exit_status = setup_internal_arrays_and_array_pointers(dz))<0) return(exit_status); return(FINISHED); } /********************** SETUP_PARAMETER_STORAGE_AND_CONSTANTS ********************/ /* RWD mallo changed to calloc; helps debug verison run as release! */ int setup_parameter_storage_and_constants(int storage_cnt,dataptr dz) { if((dz->param = (double *)calloc(storage_cnt, sizeof(double)))==NULL) { sprintf(errstr,"setup_parameter_storage_and_constants(): 1\n"); return(MEMORY_ERROR); } if((dz->iparam = (int *)calloc(storage_cnt, sizeof(int) ))==NULL) { sprintf(errstr,"setup_parameter_storage_and_constants(): 2\n"); return(MEMORY_ERROR); } if((dz->is_int = (char *)calloc(storage_cnt, sizeof(char)))==NULL) { sprintf(errstr,"setup_parameter_storage_and_constants(): 3\n"); return(MEMORY_ERROR); } if((dz->no_brk = (char *)calloc(storage_cnt, sizeof(char)))==NULL) { sprintf(errstr,"setup_parameter_storage_and_constants(): 5\n"); return(MEMORY_ERROR); } return(FINISHED); } /************** INITIALISE_IS_INT_AND_NO_BRK_CONSTANTS *****************/ int initialise_is_int_and_no_brk_constants(int storage_cnt,dataptr dz) { int n; for(n=0;nis_int[n] = (char)0; dz->no_brk[n] = (char)0; } return(FINISHED); } /***************************** MARK_PARAMETER_TYPES **************************/ int mark_parameter_types(dataptr dz,aplptr ap) { int n, m; /* PARAMS */ for(n=0;nmax_param_cnt;n++) { switch(ap->param_list[n]) { case('0'): break; /* dz->is_active[n] = 0 is default */ case('i'): dz->is_active[n] = (char)1; dz->is_int[n] = (char)1;dz->no_brk[n] = (char)1; break; case('I'): dz->is_active[n] = (char)1; dz->is_int[n] = (char)1; break; case('d'): dz->is_active[n] = (char)1; dz->no_brk[n] = (char)1; break; case('D'): dz->is_active[n] = (char)1; /* normal case: double val or brkpnt file */ break; default: sprintf(errstr,"Programming error: invalid parameter type in mark_parameter_types()\n"); return(PROGRAM_ERROR); } } /* OPTIONS */ for(n=0,m=ap->max_param_cnt;noption_cnt;n++,m++) { switch(ap->option_list[n]) { case('i'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break; case('I'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; break; case('d'): dz->is_active[m] = (char)1; dz->no_brk[m] = (char)1; break; case('D'): dz->is_active[m] = (char)1; /* normal case: double val or brkpnt file */ break; default: sprintf(errstr,"Programming error: invalid option type in mark_parameter_types()\n"); return(PROGRAM_ERROR); } } /* VARIANTS */ for(n=0,m=ap->max_param_cnt + ap->option_cnt;n < ap->variant_param_cnt; n++, m++) { switch(ap->variant_list[n]) { case('0'): break; case('i'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break; case('I'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; break; case('d'): dz->is_active[m] = (char)1; dz->no_brk[m] = (char)1; break; case('D'): dz->is_active[m] = (char)1; /* normal case: double val or brkpnt file */ break; default: sprintf(errstr,"Programming error: invalid variant type in mark_parameter_types()\n"); return(PROGRAM_ERROR); } } /* INTERNAL */ for(n=0, m=ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt; ninternal_param_cnt; n++,m++) { switch(ap->internal_param_list[n]) { case('0'): break; /* dummy variables: variables not used: but important for internal paream numbering!! */ case('i'): dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break; case('d'): dz->no_brk[m] = (char)1; break; default: sprintf(errstr,"Programming error: invalid internal param type in mark_parameter_types()\n"); return(PROGRAM_ERROR); } } return(FINISHED); } /************************ HANDLE_THE_OUTFILE *********************/ int handle_the_outfile(int *cmdlinecnt,char ***cmdline,dataptr dz) { int exit_status; char *filename = (*cmdline)[0]; if(filename[0]=='-' && filename[1]=='f') { dz->floatsam_output = 1; dz->true_outfile_stype = SAMP_FLOAT; filename+= 2; } if(!sloom) { if(file_has_invalid_startchar(filename) || value_is_numeric(filename)) { sprintf(errstr,"Outfile name %s has invalid start character(s) or looks too much like a number.\n",filename); return(DATA_ERROR); } } strcpy(dz->outfilename,filename); if((exit_status = create_sized_outfile(filename,dz))<0) return(exit_status); (*cmdline)++; (*cmdlinecnt)--; return(FINISHED); } /***************************** ESTABLISH_APPLICATION **************************/ int establish_application(dataptr dz) { aplptr ap; if((dz->application = (aplptr)malloc(sizeof (struct applic)))==NULL) { sprintf(errstr,"establish_application()\n"); return(MEMORY_ERROR); } ap = dz->application; memset((char *)ap,0,sizeof(struct applic)); return(FINISHED); } /************************* INITIALISE_VFLAGS *************************/ int initialise_vflags(dataptr dz) { int n; if((dz->vflag = (char *)malloc(dz->application->vflag_cnt * sizeof(char)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY: vflag store,\n"); return(MEMORY_ERROR); } for(n=0;napplication->vflag_cnt;n++) dz->vflag[n] = FALSE; return FINISHED; } /************************* SETUP_INPUT_PARAM_DEFAULTVALS *************************/ int setup_input_param_defaultval_stores(int tipc,aplptr ap) { int n; if((ap->default_val = (double *)malloc(tipc * sizeof(double)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY for application default values store\n"); return(MEMORY_ERROR); } for(n=0;ndefault_val[n] = 0.0; return(FINISHED); } /***************************** SETUP_AND_INIT_INPUT_PARAM_ACTIVITY **************************/ int setup_and_init_input_param_activity(dataptr dz,int tipc) { int n; if((dz->is_active = (char *)malloc((size_t)tipc))==NULL) { sprintf(errstr,"setup_and_init_input_param_activity()\n"); return(MEMORY_ERROR); } for(n=0;nis_active[n] = (char)0; return(FINISHED); } /************************* SETUP_RETIME_APPLICATION *******************/ int setup_retime_application(dataptr dz) { int exit_status; aplptr ap; if((exit_status = establish_application(dz))<0) // GLOBAL return(FAILED); ap = dz->application; // SEE parstruct FOR EXPLANATION of next 2 functions switch(dz->mode) { case(0): if((exit_status = set_param_data(ap,RETIME_DATA ,1,1,"d"))<0) return(FAILED); break; case(1): if((exit_status = set_param_data(ap,IDEAL_DATA ,3,3,"dDd"))<0) return(FAILED); break; case(2): if((exit_status = set_param_data(ap,0 ,4,4,"dddd"))<0) return(FAILED); break; case(3): if((exit_status = set_param_data(ap,0,3,3,"ddd"))<0) return(FAILED); break; case(4): if((exit_status = set_param_data(ap,0,2,2,"Dd"))<0) return(FAILED); break; case(5): if((exit_status = set_param_data(ap,RETEMPO_DATA,4,4,"dddd"))<0) return(FAILED); break; case(6): if((exit_status = set_param_data(ap,RETEMPO_DATA,3,3,"ddd"))<0) return(FAILED); break; case(7): if((exit_status = set_param_data(ap,0,5,5,"ddiid"))<0) return(FAILED); break; case(8): if((exit_status = set_param_data(ap,RETIME_MASK,1,1,"d"))<0) return(FAILED); break; case(9): if((exit_status = set_param_data(ap,0,2,2,"dd"))<0) return(FAILED); break; case(10): if((exit_status = set_param_data(ap,0,1,1,"d"))<0) return(FAILED); break; case(11): if((exit_status = set_param_data(ap,RETIME_FNAM,0,0,""))<0) return(FAILED); break; case(12): if((exit_status = set_param_data(ap,0,1,1,"d"))<0) return(FAILED); break; case(13): if((exit_status = set_param_data(ap,0,2,2,"dd"))<0) return(FAILED); break; } switch(dz->mode) { case(4): if((exit_status = set_vflgs(ap,"sea",3,"ddd","",0,0,""))<0) return(FAILED); break; case(9): if((exit_status = set_vflgs(ap,"mp",2,"id","",0,0,""))<0) return(FAILED); break; default: if((exit_status = set_vflgs(ap,"",0,"","",0,0,""))<0) return(FAILED); break; } // set_legal_infile_structure --> dz->has_otherfile = FALSE; // assign_process_logic --> switch(dz->mode) { case(8): case(9): dz->input_data_type = SNDFILES_ONLY; dz->process_type = EQUAL_SNDFILE; dz->outfiletype = SNDFILE_OUT; break; case(10): case(11): dz->input_data_type = SNDFILES_ONLY; dz->process_type = OTHER_PROCESS; dz->outfiletype = NO_OUTPUTFILE; break; default: dz->input_data_type = SNDFILES_ONLY; dz->process_type = UNEQUAL_SNDFILE; dz->outfiletype = SNDFILE_OUT; break; } return application_init(dz); //GLOBAL } /************************* PARSE_INFILE_AND_CHECK_TYPE *******************/ int parse_infile_and_check_type(char **cmdline,dataptr dz) { int exit_status; infileptr infile_info; if(!sloom) { if((infile_info = (infileptr)malloc(sizeof(struct filedata)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY for infile structure to test file data."); return(MEMORY_ERROR); } else if((exit_status = cdparse(cmdline[0],infile_info))<0) { sprintf(errstr,"Failed to parse input file %s\n",cmdline[0]); return(PROGRAM_ERROR); } else if(infile_info->filetype != SNDFILE) { sprintf(errstr,"File %s is not of correct type\n",cmdline[0]); return(DATA_ERROR); } else if((exit_status = copy_parse_info_to_main_structure(infile_info,dz))<0) { sprintf(errstr,"Failed to copy file parsing information\n"); return(PROGRAM_ERROR); } free(infile_info); } return(FINISHED); } /************************* SETUP_RETIME_PARAM_RANGES_AND_DEFAULTS *******************/ int setup_retime_param_ranges_and_defaults(dataptr dz) { int exit_status; double srate = (double)dz->infile->srate; int chans = dz->infile->channels; aplptr ap = dz->application; // set_param_ranges() ap->total_input_param_cnt = (char)(ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt); // NB total_input_param_cnt is > 0 !!! if((exit_status = setup_input_param_range_stores(ap->total_input_param_cnt,ap))<0) return(FAILED); // get_param_ranges() switch(dz->mode) { case(0): ap->lo[0] = 0.0; ap->hi[0] = 400.0; ap->default_val[0] = 60; break; case(1): ap->lo[0] = 0.0; ap->hi[0] = 400.0; ap->default_val[0] = 60; ap->lo[1] = 1.0; ap->hi[1] = 1000.0; ap->default_val[1] = 20; ap->lo[2] = 1.0; ap->hi[2] = 1000.0; ap->default_val[2] = 10; break; case(2): ap->lo[0] = (2.0/srate) * SECS_TO_MS; ap->hi[0] = 10000.0; ap->default_val[0] = (2.0/srate) * SECS_TO_MS; ap->lo[1] = 1.0; ap->hi[1] = 1000.0; ap->default_val[1] = 40; ap->lo[2] = 1.0; ap->hi[2] = 1000.0; ap->default_val[2] = 10; ap->lo[3] = 1.0; ap->hi[3] = 1000.0; ap->default_val[3] = 20; break; case(3): ap->lo[0] = 0.0; ap->hi[0] = 6000.0; ap->default_val[0] = 60; ap->lo[1] = (2.0/srate) * SECS_TO_MS; ap->hi[1] = 10000.0; ap->default_val[1] = 10; ap->lo[2] = 0.0; ap->hi[2] = 1.0; ap->default_val[2] = 1; break; case(4): ap->lo[0] = 0.01; ap->hi[0] = 100.0; ap->default_val[0] = 1.0; ap->lo[1] = (2.0/srate) * SECS_TO_MS; ap->hi[1] = 10000.0; ap->default_val[1] = 10; ap->lo[2] = 0.0; ap->hi[2] = (double)(dz->insams[0]/chans)/srate; ap->default_val[2] = 0.0; ap->lo[3] = 0.0; ap->hi[3] = (double)(dz->insams[0]/chans)/srate; ap->default_val[3] = (double)(dz->insams[0]/chans)/srate; ap->lo[4] = 0.0; ap->hi[4] = (double)(dz->insams[0]/chans)/srate; ap->default_val[4] = 0.0; break; case(5): ap->lo[0] = 0.01; // MM ap->hi[0] = 1000.0; ap->default_val[0] = 60.0; ap->lo[1] = 0.00; // Offset ap->hi[1] = 1000.0; ap->default_val[1] = 0.0; ap->lo[2] = (2.0/srate) * SECS_TO_MS; ap->hi[2] = 10000.0; // Minsil ap->default_val[2] = (2.0/srate) * SECS_TO_MS; ap->lo[3] = 0.0; ap->hi[3] = 1.0; // Pregain ap->default_val[3] = 1.0; break; case(6): ap->lo[0] = 0.00; // Offset ap->hi[0] = 1000.0; ap->default_val[0] = 0.0; ap->lo[1] = (2.0/srate) * SECS_TO_MS; ap->hi[1] = 10000.0; // Minsil ap->default_val[1] = (2.0/srate) * SECS_TO_MS; ap->lo[2] = 0.0; ap->hi[2] = 1.0; // Pregain ap->default_val[2] = 1.0; break; case(7): ap->lo[MM] = 0.01; ap->hi[MM] = 1000.0; ap->default_val[MM] = 60.0; ap->lo[BEAT_AT] = 0.0; ap->hi[BEAT_AT] = (double)(dz->insams[0]/chans)/srate; ap->default_val[BEAT_AT] = 0.0; ap->lo[BEAT_CNT] = 1.0; ap->hi[BEAT_CNT] = 24.0; ap->default_val[BEAT_CNT] = 1.0; ap->lo[BEAT_REPEATS] = 1.0; ap->hi[BEAT_REPEATS] = 1000.0; ap->default_val[BEAT_REPEATS] = 1.0; ap->lo[BEAT_SILMIN] = (2.0/srate) * SECS_TO_MS; ap->hi[BEAT_SILMIN] = 10000.0; ap->default_val[BEAT_SILMIN] = (2.0/srate) * SECS_TO_MS; break; case(8): ap->lo[0] = (2.0/srate) * SECS_TO_MS; ap->hi[0] = 10000.0; // Minsil ap->default_val[0] = (2.0/srate) * SECS_TO_MS; break; case(9): ap->lo[0] = (2.0/srate) * SECS_TO_MS; ap->hi[0] = 10000.0; ap->default_val[0] = (2.0/srate) * SECS_TO_MS; ap->lo[1] = 0.0; ap->hi[1] = 1.0; ap->default_val[1] = 0.5; ap->lo[2] = 0.0; ap->hi[2] = 32767.0; ap->default_val[2] = 0.0; ap->lo[3] = 0.0; ap->hi[3] = 1.0; ap->default_val[3] = 1.0; break; case(10): ap->lo[0] = (2.0/srate) * SECS_TO_MS; ap->hi[0] = 10000.0; ap->default_val[0] = (2.0/srate) * SECS_TO_MS; break; case(11): break; case(12): ap->lo[0] = 0.0; ap->hi[0] = 3600.0; ap->default_val[0] = 0.0; break; case(13): ap->lo[0] = 0.0; ap->hi[0] = 3600.0; ap->default_val[0] = 0.0; ap->lo[1] = 0.0; ap->hi[1] = 3600.0; ap->default_val[1] = 0.0; break; } if(!sloom) put_default_vals_in_all_params(dz); return(FINISHED); } /********************************* PARSE_SLOOM_DATA *********************************/ int parse_sloom_data(int argc,char *argv[],char ***cmdline,int *cmdlinecnt,dataptr dz) { int exit_status; int cnt = 1, infilecnt; int filesize, insams, inbrksize; double dummy; int true_cnt = 0; //aplptr ap; while(cnt<=PRE_CMDLINE_DATACNT) { if(cnt > argc) { sprintf(errstr,"Insufficient data sent from TK\n"); return(DATA_ERROR); } switch(cnt) { case(1): if(sscanf(argv[cnt],"%d",&dz->process)!=1) { sprintf(errstr,"Cannot read process no. sent from TK\n"); return(DATA_ERROR); } break; case(2): if(sscanf(argv[cnt],"%d",&dz->mode)!=1) { sprintf(errstr,"Cannot read mode no. sent from TK\n"); return(DATA_ERROR); } if(dz->mode > 0) dz->mode--; //setup_particular_application() = if((exit_status = setup_retime_application(dz))<0) return(exit_status); //ap = dz->application; break; case(3): if(sscanf(argv[cnt],"%d",&infilecnt)!=1) { sprintf(errstr,"Cannot read infilecnt sent from TK\n"); return(DATA_ERROR); } if(infilecnt < 1) { true_cnt = cnt + 1; cnt = PRE_CMDLINE_DATACNT; /* force exit from loop after assign_file_data_storage */ } if((exit_status = assign_file_data_storage(infilecnt,dz))<0) return(exit_status); break; case(INPUT_FILETYPE+4): if(sscanf(argv[cnt],"%d",&dz->infile->filetype)!=1) { sprintf(errstr,"Cannot read filetype sent from TK (%s)\n",argv[cnt]); return(DATA_ERROR); } break; case(INPUT_FILESIZE+4): if(sscanf(argv[cnt],"%d",&filesize)!=1) { sprintf(errstr,"Cannot read infilesize sent from TK\n"); return(DATA_ERROR); } dz->insams[0] = filesize; break; case(INPUT_INSAMS+4): if(sscanf(argv[cnt],"%d",&insams)!=1) { sprintf(errstr,"Cannot read insams sent from TK\n"); return(DATA_ERROR); } dz->insams[0] = insams; break; case(INPUT_SRATE+4): if(sscanf(argv[cnt],"%d",&dz->infile->srate)!=1) { sprintf(errstr,"Cannot read srate sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_CHANNELS+4): if(sscanf(argv[cnt],"%d",&dz->infile->channels)!=1) { sprintf(errstr,"Cannot read channels sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_STYPE+4): if(sscanf(argv[cnt],"%d",&dz->infile->stype)!=1) { sprintf(errstr,"Cannot read stype sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_ORIGSTYPE+4): if(sscanf(argv[cnt],"%d",&dz->infile->origstype)!=1) { sprintf(errstr,"Cannot read origstype sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_ORIGRATE+4): if(sscanf(argv[cnt],"%d",&dz->infile->origrate)!=1) { sprintf(errstr,"Cannot read origrate sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_MLEN+4): if(sscanf(argv[cnt],"%d",&dz->infile->Mlen)!=1) { sprintf(errstr,"Cannot read Mlen sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_DFAC+4): if(sscanf(argv[cnt],"%d",&dz->infile->Dfac)!=1) { sprintf(errstr,"Cannot read Dfac sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_ORIGCHANS+4): if(sscanf(argv[cnt],"%d",&dz->infile->origchans)!=1) { sprintf(errstr,"Cannot read origchans sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_SPECENVCNT+4): if(sscanf(argv[cnt],"%d",&dz->infile->specenvcnt)!=1) { sprintf(errstr,"Cannot read specenvcnt sent from TK\n"); return(DATA_ERROR); } dz->specenvcnt = dz->infile->specenvcnt; break; case(INPUT_WANTED+4): if(sscanf(argv[cnt],"%d",&dz->wanted)!=1) { sprintf(errstr,"Cannot read wanted sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_WLENGTH+4): if(sscanf(argv[cnt],"%d",&dz->wlength)!=1) { sprintf(errstr,"Cannot read wlength sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_OUT_CHANS+4): if(sscanf(argv[cnt],"%d",&dz->out_chans)!=1) { sprintf(errstr,"Cannot read out_chans sent from TK\n"); return(DATA_ERROR); } break; /* RWD these chanegs to samps - tk will have to deal with that! */ case(INPUT_DESCRIPTOR_BYTES+4): if(sscanf(argv[cnt],"%d",&dz->descriptor_samps)!=1) { sprintf(errstr,"Cannot read descriptor_samps sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_IS_TRANSPOS+4): if(sscanf(argv[cnt],"%d",&dz->is_transpos)!=1) { sprintf(errstr,"Cannot read is_transpos sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_COULD_BE_TRANSPOS+4): if(sscanf(argv[cnt],"%d",&dz->could_be_transpos)!=1) { sprintf(errstr,"Cannot read could_be_transpos sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_COULD_BE_PITCH+4): if(sscanf(argv[cnt],"%d",&dz->could_be_pitch)!=1) { sprintf(errstr,"Cannot read could_be_pitch sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_DIFFERENT_SRATES+4): if(sscanf(argv[cnt],"%d",&dz->different_srates)!=1) { sprintf(errstr,"Cannot read different_srates sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_DUPLICATE_SNDS+4): if(sscanf(argv[cnt],"%d",&dz->duplicate_snds)!=1) { sprintf(errstr,"Cannot read duplicate_snds sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_BRKSIZE+4): if(sscanf(argv[cnt],"%d",&inbrksize)!=1) { sprintf(errstr,"Cannot read brksize sent from TK\n"); return(DATA_ERROR); } if(inbrksize > 0) { switch(dz->input_data_type) { case(WORDLIST_ONLY): break; case(PITCH_AND_PITCH): case(PITCH_AND_TRANSPOS): case(TRANSPOS_AND_TRANSPOS): dz->tempsize = inbrksize; break; case(BRKFILES_ONLY): case(UNRANGED_BRKFILE_ONLY): case(DB_BRKFILES_ONLY): case(ALL_FILES): case(ANY_NUMBER_OF_ANY_FILES): if(dz->extrabrkno < 0) { sprintf(errstr,"Storage location number for brktable not established by CDP.\n"); return(DATA_ERROR); } if(dz->brksize == NULL) { sprintf(errstr,"CDP has not established storage space for input brktable.\n"); return(PROGRAM_ERROR); } dz->brksize[dz->extrabrkno] = inbrksize; break; default: sprintf(errstr,"TK sent brktablesize > 0 for input_data_type [%d] not using brktables.\n", dz->input_data_type); return(PROGRAM_ERROR); } break; } break; case(INPUT_NUMSIZE+4): if(sscanf(argv[cnt],"%d",&dz->numsize)!=1) { sprintf(errstr,"Cannot read numsize sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_LINECNT+4): if(sscanf(argv[cnt],"%d",&dz->linecnt)!=1) { sprintf(errstr,"Cannot read linecnt sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_ALL_WORDS+4): if(sscanf(argv[cnt],"%d",&dz->all_words)!=1) { sprintf(errstr,"Cannot read all_words sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_ARATE+4): if(sscanf(argv[cnt],"%f",&dz->infile->arate)!=1) { sprintf(errstr,"Cannot read arate sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_FRAMETIME+4): if(sscanf(argv[cnt],"%lf",&dummy)!=1) { sprintf(errstr,"Cannot read frametime sent from TK\n"); return(DATA_ERROR); } dz->frametime = (float)dummy; break; case(INPUT_WINDOW_SIZE+4): if(sscanf(argv[cnt],"%f",&dz->infile->window_size)!=1) { sprintf(errstr,"Cannot read window_size sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_NYQUIST+4): if(sscanf(argv[cnt],"%lf",&dz->nyquist)!=1) { sprintf(errstr,"Cannot read nyquist sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_DURATION+4): if(sscanf(argv[cnt],"%lf",&dz->duration)!=1) { sprintf(errstr,"Cannot read duration sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_MINBRK+4): if(sscanf(argv[cnt],"%lf",&dz->minbrk)!=1) { sprintf(errstr,"Cannot read minbrk sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_MAXBRK+4): if(sscanf(argv[cnt],"%lf",&dz->maxbrk)!=1) { sprintf(errstr,"Cannot read maxbrk sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_MINNUM+4): if(sscanf(argv[cnt],"%lf",&dz->minnum)!=1) { sprintf(errstr,"Cannot read minnum sent from TK\n"); return(DATA_ERROR); } break; case(INPUT_MAXNUM+4): if(sscanf(argv[cnt],"%lf",&dz->maxnum)!=1) { sprintf(errstr,"Cannot read maxnum sent from TK\n"); return(DATA_ERROR); } break; default: sprintf(errstr,"case switch item missing: parse_sloom_data()\n"); return(PROGRAM_ERROR); } cnt++; } if(cnt!=PRE_CMDLINE_DATACNT+1) { sprintf(errstr,"Insufficient pre-cmdline params sent from TK\n"); return(DATA_ERROR); } if(true_cnt) cnt = true_cnt; *cmdlinecnt = 0; while(cnt < argc) { if((exit_status = get_tk_cmdline_word(cmdlinecnt,cmdline,argv[cnt]))<0) return(exit_status); cnt++; } return(FINISHED); } /********************************* GET_TK_CMDLINE_WORD *********************************/ int get_tk_cmdline_word(int *cmdlinecnt,char ***cmdline,char *q) { if(*cmdlinecnt==0) { if((*cmdline = (char **)malloc(sizeof(char *)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline array.\n"); return(MEMORY_ERROR); } } else { if((*cmdline = (char **)realloc(*cmdline,((*cmdlinecnt)+1) * sizeof(char *)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline array.\n"); return(MEMORY_ERROR); } } if(((*cmdline)[*cmdlinecnt] = (char *)malloc((strlen(q) + 1) * sizeof(char)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline item %d.\n",(*cmdlinecnt)+1); return(MEMORY_ERROR); } strcpy((*cmdline)[*cmdlinecnt],q); (*cmdlinecnt)++; return(FINISHED); } /****************************** ASSIGN_FILE_DATA_STORAGE *********************************/ int assign_file_data_storage(int infilecnt,dataptr dz) { int exit_status; int no_sndfile_system_files = FALSE; dz->infilecnt = infilecnt; if((exit_status = allocate_filespace(dz))<0) return(exit_status); if(no_sndfile_system_files) dz->infilecnt = 0; return(FINISHED); } /************************* redundant functions: to ensure libs compile OK *******************/ int assign_process_logic(dataptr dz) { return(FINISHED); } void set_legal_infile_structure(dataptr dz) {} int set_legal_internalparam_structure(int process,int mode,aplptr ap) { return(FINISHED); } int establish_bufptrs_and_extra_buffers(dataptr dz) { return(FINISHED); } int inner_loop (int *peakscore,int *descnt,int *in_start_portion,int *least,int *pitchcnt,int windows_in_buf,dataptr dz) { return(FINISHED); } int get_process_no(char *prog_identifier_from_cmdline,dataptr dz) { return(FINISHED); } /******************************** USAGE1 ********************************/ int usage1(void) { usage2("retime"); return(USAGE_ONLY); } /********************************************************************************************/ int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz) { if(!strcmp(prog_identifier_from_cmdline,"retime")) dz->process = RETIME; else { sprintf(errstr,"Unknown program identification string '%s'\n",prog_identifier_from_cmdline); return(USAGE_ONLY); } return(FINISHED); } /****************************** GET_MODE *********************************/ int get_the_mode_from_cmdline(char *str,dataptr dz) { if(sscanf(str,"%d",&dz->mode)!=1) { sprintf(errstr,"Cannot read mode of program.\n"); return(USAGE_ONLY); } if(dz->mode <= 0 || dz->mode > dz->maxmode) { sprintf(errstr,"Program mode value [%d] is out of range [1 - %d].\n",dz->mode,dz->maxmode); return(USAGE_ONLY); } dz->mode--; /* CHANGE TO INTERNAL REPRESENTATION OF MODE NO */ return(FINISHED); } /******************************** SETUP_AND_INIT_INPUT_BRKTABLE_CONSTANTS ********************************/ int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt) { int n; if((dz->brk = (double **)malloc(brkcnt * sizeof(double *)))==NULL) { sprintf(errstr,"setup_and_init_input_brktable_constants(): 1\n"); return(MEMORY_ERROR); } if((dz->brkptr = (double **)malloc(brkcnt * sizeof(double *)))==NULL) { sprintf(errstr,"setup_and_init_input_brktable_constants(): 6\n"); return(MEMORY_ERROR); } if((dz->brksize = (int *)malloc(brkcnt * sizeof(int)))==NULL) { sprintf(errstr,"setup_and_init_input_brktable_constants(): 2\n"); return(MEMORY_ERROR); } if((dz->firstval = (double *)malloc(brkcnt * sizeof(double)))==NULL) { sprintf(errstr,"setup_and_init_input_brktable_constants(): 3\n"); return(MEMORY_ERROR); } if((dz->lastind = (double *)malloc(brkcnt * sizeof(double)))==NULL) { sprintf(errstr,"setup_and_init_input_brktable_constants(): 4\n"); return(MEMORY_ERROR); } if((dz->lastval = (double *)malloc(brkcnt * sizeof(double)))==NULL) { sprintf(errstr,"setup_and_init_input_brktable_constants(): 5\n"); return(MEMORY_ERROR); } if((dz->brkinit = (int *)malloc(brkcnt * sizeof(int)))==NULL) { sprintf(errstr,"setup_and_init_input_brktable_constants(): 7\n"); return(MEMORY_ERROR); } for(n=0;nbrk[n] = NULL; dz->brkptr[n] = NULL; dz->brkinit[n] = 0; dz->brksize[n] = 0; } return(FINISHED); } /******************************** USAGE2 ********************************/ int usage2(char *str) { if(!strcmp(str,"retime")) { fprintf(stderr, "USAGE:\n" "retime retime modenumber parameters.....\n" "\n" "MODE 1 Output user-specified peaks at regular pulse at given tempo.\n" "MODE 3 Shorten existing (silence-separated) events.\n" "MODE 4 Find existing (silence-separated) events and output at regular MM.\n" "MODE 5 Find existing (silence-separated) events and change speed by factor.\n" "MODE 6 Find existing (silence-separated) events: position at specified beats.\n" "MODE 7 Find existing (silence-separated) events: position at specified times.\n" "MODE 8 Mark (silence-separated) event within sound & repeat at specified tempo.\n" "MODE 9 Replace by silence (silence-separated) events in specified pattern.\n" "MODE 10 Adjusts levels (silence-separated) events, so more equal, or accented.\n" "MODE 11 Finds durations of shortest and longest (silence-separated) event.\n" "MODE 12 Find start of sound in file (1st non-zero sample).\n" "MODE 13 Find peak and move all data so peak goes to specified time.\n" "MODE 14 Mark peak, then move all data so peak goes to specified time.\n" "\n" "Retime works by editing existing files (removing sound or adding silence)\n" "and is best suited to making small changes to rhythmic placement.\n" "\n" "Type \"retime retime modenumber\" for more details\n"); } else fprintf(stdout,"Unknown option '%s'\n",str); return(USAGE_ONLY); } int usage3(char *str1,char *str2) { fprintf(stderr,"Insufficient parameters on command line.\n"); return(USAGE_ONLY); } /******************************** USAGE22 ********************************/ int usage22(char *str,char *str2) { if(strcmp(str,"retime")) { fprintf(stdout,"Unknown option '%s'\n",str); } else if(!strcmp(str2,"1")) { fprintf(stderr, "USAGE:\n" "retime retime 1 infile outfile refpoints tempo\n" "\n" "Output user-specified peaks at regular pulse at given tempo.\n" "\n" "Best applied to files with clear peaks.\n" "\n" "REFPOINTS times of peaks in the infile which will become on-the-beat events\n" " in the outfile.\n" "TEMPO Tempo of OUTFILE, as a MM (vals > 20 to 400)\n" " OR (for vals below 1.0) a beat duration in secs.\n"); } else if(!strcmp(str2,"2")) { fprintf(stderr,"Mode only accessible via Sound Loom Properties Files\n"); } else if(!strcmp(str2,"3")) { fprintf(stderr, "USAGE:\n" "retime retime 3 infile outfile minsil inevwidth outevwidth splicelen\n" "\n" "Shorten existing (silence-separated) events.\n" "\n" "MINSIL Dur (mS) of min silence between events (Range 2000/srate to 10000).\n" "INEVWIDTH (Min) width (in mS) of events in infile (Range 1 -1000)\n" "OUTEVWIDTH Width (in mS) of events in outfile (Range 1- 1000)\n" "SPLICELEN Dur of splices (mS) cutting events in outfile (Range 1- 1000).\n"); } else if(!strcmp(str2,"4")) { fprintf(stderr, "USAGE:\n" "retime retime 4 infile outfile tempo minsil pregain\n" "\n" "Find existing (silence-separated) events and output at regular MM.\n" "\n" "TEMPO Tempo of OUTFILE, as a MM (vals > 20 to 6000)\n" " OR (for vals below 1.0) a beat duration in secs.\n" "MINSIL Dur (mS) of min silence between events (Range 2000/srate to 10000).\n" "PREGAIN Gain of input signal (Range >0 to 1).\n"); } else if(!strcmp(str2,"5")) { fprintf(stderr, "USAGE:\n" "retime retime 5 infile outfile factor minsil [-sstart -eend -async]\n" "\n" "Find existing (silence-separated) events and change speed by factor.\n" "\n" "MINSIL Dur (mS) of min silence between events (Range 2000/srate to 10000).\n" "FACTOR Speed-change factor (can vary over time) (Range 0.01 - 100).\n" "START Time at which speed changing begins.\n" "END Time at which speed changing ends.\n" "SYNC Approx time of infile-event which syncs with its copy in output.\n" " (Time should be WITHIN the event. Zero implies sync at 1st event).\n"); } else if(!strcmp(str2,"6")) { fprintf(stderr, "USAGE:\n" "retime retime 6 infile outfile retempodata tempo offset minsil pregain\n" "\n" "Find existing (silence-separated) events: position at specified beats.\n" "\n" "RETEMPODATA File contains position of events in outfile, in BEATS,\n" " where events assumed to start at beat zero.\n" "TEMPO Tempo of OUTFILE, as a MM (vals > 20 to 1000)\n" " OR (for vals below 1.0) a beat duration in secs.\n" "OFFSET Time of first sounding event in output file (Range 0 -1000).\n" "MINSIL Dur (mS) of min silence between events (Range 2000/srate to 10000).\n" "PREGAIN Gain of input signal (Range >0 to 1).\n"); } else if(!strcmp(str2,"7")) { fprintf(stderr, "USAGE:\n" "retime retime 7 infile outfile retempodata offset minsil pregain\n" "\n" "Find existing (silence-separated) events: position at specified times.\n" "\n" "RETEMPODATA File contains position of events in outfile, in SECONDS,\n" " where events assumed to start at time zero.\n" "MINSIL Dur (mS) of min silence between events (Range 2000/srate to 10000).\n" "PREGAIN Gain of input signal (Range >0 to 1).\n" "OFFSET Time of first sounding event in output file (range 0 - 1000).\n"); } else if(!strcmp(str2,"8")) { fprintf(stderr, "USAGE:\n" "retime retime 8 infile outfile tempo eventtime cnt repeats minsil\n" "\n" "Mark one (silence-separated) event within a soundfile,\n" "OR the 1st event of \"cnt\" events (see below),\n" "and repeat it (or them) at a specified tempo WITHIN the original sound.\n" "\n" "TEMPO Tempo of OUTFILE, as a MM (vals > 20 to 1000)\n" " OR (for vals below 1.0) a beat duration in secs.\n" "EVENTTIME Time (roughly) of (1st) event to repeat (time must be INSIDE event).\n" "CNT Number of (silence-separated) events to capture (Range 1 to 24).\n" "REPEATS No. of times to repeat event(s): (NB: 2 repeats of A produces AAA).\n" " (Range 1 to 1000).\n" "MINSIL Dur (mS) of min silence between events (Range 2000/srate to 10000).\n"); } else if(!strcmp(str2,"9")) { fprintf(stderr, "USAGE:\n" "retime retime 9 infile outfile maskdata minsil\n" "\n" "Replace by silence (silence-separated) events in specified pattern.\n" "\n" "MASKDATA File with sequence of 0s and 1s: 0 masks event: 1 reveals event.\n" " 0s and 1s must be separated by space, or on different lines.\n" " Pattern of masking is repeated once its end is reached.\n" "MINSIL Dur (mS) of min silence between events (Range 2000/srate to 10000).\n"); } else if(!strcmp(str2,"10")) { fprintf(stderr, "USAGE:\n" "retime retime 10 infile outfile minsil evening [-mmeter] [-mpregain]\n" "\n" "Adjust levels (silence-separated) events, so more equal, or accented.\n" "\n" "MINSIL Dur (mS) of min silence between events (Range 2000/srate to 10000).\n" "PREGAIN Gain of input signal (Range >0 to 1).\n" "METER Pattern of accented beats.\n" " 0 : no events emphasized.\n" " 3 : every 3rd event accented.\n" "EVENING Range 0 - 1.\n" " With METER 0: the events are evened-out in level by \"EVENING\".\n" " 0 has no effect, while 1 tries to make event-levels equal.\n" " Intermediate values produce more or less evening-out of levels.\n" " With nonzero METER e.g. 3,\n" " unaccented beats take level relative specified in \"EVENING\".\n" " e.g. Evening = 0.3 sets unaccented beats to 1/3 level of accented.\n"); } else if(!strcmp(str2,"11")) { fprintf(stderr, "USAGE:\n" "retime retime 11 infile minsil\n" "\n" "MODE 11 Finds durations of shortest and longest (silence-separated) event.\n" "\n" "MINSIL Dur (mS) of min silence between events (Range 2000/srate to 10000).\n"); } else if(!strcmp(str2,"12")) { fprintf(stderr, "USAGE:\n" "retime retime 12 infile outfile.txt\n" "\n" "Find start of sound in file (1st non-zero sample).\n" "\n" "Outfile must have '.txt' extension.\n" "If file already exists, output is APPENDED to that file.\n"); } else if(!strcmp(str2,"13")) { fprintf(stderr, "USAGE:\n" "retime retime 13 infile outfile goalpeaktime\n" "\n" "Find sound peak and move all data so peak goes to specified time.\n" "\n" "GOALPEAKTIME Time to which file peak is moved (Range 0 - 3600)\n" "(must be greater than the original peaktime).\n"); } else if(!strcmp(str2,"14")) { fprintf(stderr, "USAGE:\n" "retime retime 14 infile outfile goalpeaktime peaktime\n" "\n" "Specify peak position, then move data so peak goes to specified time.\n" "\n" "GOALPEAKTIME Time to which file peak is moved (Range 0 - 3600).\n" " (must be greater than the original peaktime).\n" "PEAKTIME Time of existing peak in file.\n"); } else { fprintf(stdout,"Unknown mode '%s'\n",str); } return(USAGE_ONLY); } /******************************** CHECK_RETIME_PARAM_VALIDITY_AND_CONSISTENCY **********************************/ int check_retime_param_validity_and_consistency(dataptr dz) { int exit_status; double srate = (double)dz->infile->srate; int chans = dz->infile->channels; switch(dz->mode) { case(3): if(dz->param[2] == 0.0) { sprintf(errstr,"Pregain parameter of zero, will produce silent output.\n"); return(DATA_ERROR); } /* fall thro */ case(0): if(dz->param[MM] >= 20) dz->param[MM] = 60.0 / dz->param[MM]; else if(dz->param[MM] > 1.0 || dz->param[MM] < FLTERR) { sprintf(errstr,"Output tempo vals must be > 0 AND less than 1 (beat duration) OR >= 20 (MM)\n"); return(DATA_ERROR); } dz->iparam[MM] = (int)round(dz->param[MM] * srate) * chans; break; case(1): if(dz->param[MM] >= 20) dz->param[MM] = 60.0 / dz->param[MM]; else if(dz->param[MM] > 1.0 || dz->param[MM] < FLTERR) { sprintf(errstr,"Output tempo vals must be > 0 AND less than 1 (beat duration) OR >= 20 (MM)\n"); return(DATA_ERROR); } dz->iparam[MM] = (int)round(dz->param[MM] * srate) * chans; dz->iparam[RETIME_SPLICE] = (int)round(dz->param[RETIME_SPLICE] * MS_TO_SECS * srate) * chans; if(dz->brksize[RETIME_WIDTH] == 0) dz->iparam[RETIME_WIDTH] = (int)round(dz->param[RETIME_WIDTH] * MS_TO_SECS * srate) * chans; if((exit_status = establish_cuts_array(dz)) < 0) return(exit_status); break; case(2): dz->iparam[0] = (int)round(dz->param[0] * MS_TO_SECS * srate) * chans; dz->iparam[1] = (int)round(dz->param[1] * MS_TO_SECS * srate) * chans; dz->iparam[2] = (int)round(dz->param[2] * MS_TO_SECS * srate) * chans; //JUNE 2010 dz->iparam[3] = (int)round(dz->param[3] * MS_TO_SECS * srate) * chans; break; case(13): dz->iparam[1] = (int)round(dz->param[1] * srate) * chans; /* fall thro */ case(12): dz->iparam[0] = (int)round(dz->param[0] * srate) * chans; break; } switch(dz->mode) { case(4): if((!dz->brksize[0]) && (dz->param[0] == 1)) { sprintf(errstr,"No change in tempo.\n"); return(DATA_ERROR); } dz->iparam[2] = (int)round(dz->param[2] * srate) * chans; dz->iparam[3] = (int)round(dz->param[3] * srate) * chans; dz->iparam[4] = (int)round(dz->param[4] * srate) * chans; /* fall thro */ case(3): dz->iparam[1] = (int)round(dz->param[1] * MS_TO_SECS * srate) * chans; if((exit_status = locate_peaks(dz)) < 0) return(exit_status); break; case(5): dz->iparam[0] = (int)round((60.0/dz->param[0]) * srate); dz->iparam[1] = (int)round(dz->param[1] * srate) * chans; dz->iparam[2] = (int)round(dz->param[2] * MS_TO_SECS * srate) * chans; if(flteq(dz->param[3],0.0)) { sprintf(errstr,"Pregain is (effectively) zero: output will be silence.\n"); return(DATA_ERROR); } break; case(6): dz->iparam[0] = (int)round(dz->param[0] * srate) * chans; dz->iparam[1] = (int)round(dz->param[1] * MS_TO_SECS * srate) * chans; if(flteq(dz->param[2],0.0)) { sprintf(errstr,"Pregain is (effectively) zero: output will be silence.\n"); return(DATA_ERROR); } break; case(7): if(dz->param[MM] >= 20) dz->param[MM] = 60.0 / dz->param[MM]; else if(dz->param[MM] > 1.0 || dz->param[MM] < FLTERR) { sprintf(errstr,"Output tempo vals must be > 0 AND less than 1 (beat duration) OR >= 20 (MM)\n"); return(DATA_ERROR); } dz->iparam[MM] = (int)round(dz->param[MM] * srate) * chans; dz->iparam[BEAT_AT] = (int)round(dz->param[BEAT_AT] * srate) * chans; dz->iparam[BEAT_SILMIN] = (int)round(dz->param[BEAT_SILMIN] * MS_TO_SECS * srate) * chans; break; case(8): dz->iparam[0] = (int)round(dz->param[0] * MS_TO_SECS * srate) * chans; break; case(9): dz->iparam[0] = (int)round(dz->param[0] * MS_TO_SECS * srate) * chans; break; case(10): dz->iparam[0] = (int)round(dz->param[0] * MS_TO_SECS * srate) * chans; break; } return FINISHED; } /*************************************** READ_RETIME_DATA *********************************/ int read_retime_data(char *filename,dataptr dz) { double d, lasttime; int *p, arraysize = 0; char temp[200], *q; FILE *fp; if((fp = fopen(filename,"r"))==NULL) { sprintf(errstr,"Failed to open file %s for input.\n",filename); return(DATA_ERROR); } while(fgets(temp,200,fp)!=NULL) { q = temp; while(get_float_from_within_string(&q,&d)) { arraysize++; } } dz->itemcnt = arraysize; if((dz->lparray[0] = (int *) malloc(arraysize * sizeof(int)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to store retiming data.\n"); return(MEMORY_ERROR); } p = dz->lparray[0]; fseek(fp,0,0); lasttime = -1.0; while(fgets(temp,200,fp)!=NULL) { q = temp; while(get_float_from_within_string(&q,&d)) { if(d < 0.0 || d < lasttime) { sprintf(errstr,"TIME (%lf) OUT OF SEQUENCE OR INVALID, IN FILE %s.\n",d,filename); return(DATA_ERROR); } lasttime = d; *p = (int)(round(d * (double)dz->infile->srate) * dz->infile->channels); p++; } } return(FINISHED); } /*************************************** READ_RETEMPO_DATA *********************************/ int read_retempo_data(char *filename,dataptr dz) { double d, lastbeat, *p; int arraysize = 0, beatcnt; char temp[200], *q; FILE *fp; if((fp = fopen(filename,"r"))==NULL) { sprintf(errstr,"Failed to open file %s for input.\n",filename); return(DATA_ERROR); } while(fgets(temp,200,fp)!=NULL) { q = temp; while(get_float_from_within_string(&q,&d)) { arraysize++; } } dz->itemcnt = arraysize; if((dz->parray[0] = (double *) malloc(arraysize * sizeof(double)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to store retiming data.\n"); return(MEMORY_ERROR); } p = dz->parray[0]; fseek(fp,0,0); lastbeat = -1.0; beatcnt = 1; while(fgets(temp,200,fp)!=NULL) { q = temp; while(get_float_from_within_string(&q,&d)) { if(d < dz->application->min_special || d > dz->application->max_special) { sprintf(errstr,"BEAT (%lf) OUT OF RANGE (%lf to %lf), IN FILE %s.\n",d,dz->application->min_special,dz->application->max_special,filename); return(DATA_ERROR); } if(d <= lastbeat) { sprintf(errstr,"BEAT %d (= %lf) OUT OF SEQUENCE IN FILE %s.\n",beatcnt,d,filename); return(DATA_ERROR); } lastbeat = d; *p = d; p++; beatcnt++; } } return(FINISHED); } /*************************************** READ_RETIME_MASK *********************************/ int read_retime_mask(char *filename,dataptr dz) { double d; int arraysize = 0, *p; char temp[200], *q; FILE *fp; if((fp = fopen(filename,"r"))==NULL) { sprintf(errstr,"Failed to open file %s for input.\n",filename); return(DATA_ERROR); } while(fgets(temp,200,fp)!=NULL) { q = temp; while(get_float_from_within_string(&q,&d)) { arraysize++; } } dz->itemcnt = arraysize; if((dz->lparray[0] = (int *) malloc(arraysize * sizeof(int)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to store retiming data.\n"); return(MEMORY_ERROR); } p = dz->lparray[0]; fseek(fp,0,0); while(fgets(temp,200,fp)!=NULL) { q = temp; while(get_float_from_within_string(&q,&d)) { if(d < 0.0 || d > 1.0 || (d > 0.0 && d < 1.0)) { sprintf(errstr,"MASK VALUE (%lf) INVALID IN FILE %s.\n",d,filename); return(DATA_ERROR); } *p = (int)round(d); p++; } } return(FINISHED); } /*************************************** READ_IDEAL_DATA *********************************/ int read_ideal_data(char *filename,dataptr dz) { double d, lasttime0, lasttime1, *idealtimes, *realtimes; int finished; int *realtimesamps, arraysize = 0, cnt; char temp[200], *q; FILE *fp; if((fp = fopen(filename,"r"))==NULL) { sprintf(errstr,"Failed to open file %s for input.\n",filename); return(DATA_ERROR); } while(fgets(temp,200,fp)!=NULL) { q = temp; while(get_float_from_within_string(&q,&d)) { arraysize++; } } if(ODD(arraysize)) { sprintf(errstr,"Bad count of data in file %s.\n",filename); return(DATA_ERROR); } arraysize -= 2; if(arraysize <= 0) { sprintf(errstr,"Insufficient data in file %s.\n",filename); return(DATA_ERROR); } arraysize /= 2; dz->itemcnt = arraysize; if((dz->parray[0] = (double *) malloc(arraysize * sizeof(double)))==NULL) { // realtimes sprintf(errstr,"INSUFFICIENT MEMORY to store event data(1).\n"); return(MEMORY_ERROR); } if((dz->parray[1] = (double *) malloc(arraysize * sizeof(double)))==NULL) { // idealtimes sprintf(errstr,"INSUFFICIENT MEMORY to store event data(2).\n"); return(MEMORY_ERROR); } if((dz->lparray[0] = (int *) malloc(arraysize * sizeof(int)))==NULL) { // realtimes as samps sprintf(errstr,"INSUFFICIENT MEMORY to store event data(3).\n"); return(MEMORY_ERROR); } if((dz->lparray[1] = (int *) malloc(arraysize * sizeof(int)))==NULL) { // idealtimes as samps sprintf(errstr,"INSUFFICIENT MEMORY to store event data(4).\n"); return(MEMORY_ERROR); } if((dz->lparray[2] = (int *) malloc(arraysize * 4 * sizeof(int)))==NULL) { // realtime start & end of both splices, in samples sprintf(errstr,"INSUFFICIENT MEMORY to store event data(5).\n"); return(MEMORY_ERROR); } finished = 0; realtimesamps = dz->lparray[0]; realtimes = dz->parray[0]; idealtimes = dz->parray[1]; fseek(fp,0,0); lasttime0 = -1.0; lasttime1 = -1.0; cnt = 0; while(fgets(temp,200,fp)!=NULL) { q = temp; while(get_float_from_within_string(&q,&d)) { switch(cnt) { case(0): if(d <= 10 || d >= 600) { sprintf(errstr,"MM (%lf) INVALID, IN FILE %s.\n",d,filename); return(DATA_ERROR); } dz->MMin = d; break; case(1): if(d < 0) { sprintf(errstr,"OFFSET (%lf) INVALID, IN FILE %s.\n",d,filename); return(DATA_ERROR); } dz->offset = d; break; default: if(EVEN(cnt)) { if(d < 0.0 || d < lasttime0) { sprintf(errstr,"LHS TIME (%lf) OUT OF SEQUENCE OR INVALID, IN FILE %s.\n",d,filename); return(DATA_ERROR); } *realtimes = d; realtimes++; *realtimesamps = (int)(round(d * (double)dz->infile->srate) * dz->infile->channels); if(*realtimesamps >= dz->insams[0]) { dz->itemcnt = realtimesamps - dz->lparray[0]; finished = 1; } realtimesamps++; lasttime0 = d; } else { if(d < 0.0 || d < lasttime1) { sprintf(errstr,"RHS TIME (%lf) OUT OF SEQUENCE OR INVALID, IN FILE %s.\n",d,filename); return(DATA_ERROR); } *idealtimes = d; idealtimes++; if(finished) break; lasttime1 = d; } break; } cnt++; } } if(dz->itemcnt <= 0) { sprintf(errstr,"LHS TIMES IN FILE %s ARE ALL BEYOND END OF SOUNDFILE.\n",filename); return(DATA_ERROR); } return(FINISHED); } /************************ HANDLE_THE_SPECIAL_DATA *********************/ int handle_the_special_data(int *cmdlinecnt,char ***cmdline,dataptr dz) { int exit_status; aplptr ap = dz->application; if(ap->special_data) { if(!sloom) { if(*cmdlinecnt <= 0) { sprintf(errstr,"Insufficient parameters on command line.\n"); return(USAGE_ONLY); } } if((exit_status = setup_the_special_data_ranges (dz->mode,dz->infile->srate,dz->duration,dz->nyquist,dz->wlength,dz->infile->channels,ap))<0) return(exit_status); if((exit_status = read_special_data((*cmdline)[0],dz))<0) return(exit_status); (*cmdline)++; (*cmdlinecnt)--; } return(FINISHED); } /************************ SETUP_SPECIAL_DATA_RANGES *********************/ int setup_the_special_data_ranges(int mode,int srate,double duration,double nyquist,int wlength,int channels,aplptr ap) { switch(ap->special_data) { case(RETIME_DATA): case(IDEAL_DATA): case(RETEMPO_DATA): ap->min_special = 0; ap->max_special = 3600; // guestimate of highest poss user silence or max possible beat-cnt break; case(RETIME_FNAM): ap->special_range = FALSE; break; case(RETIME_MASK): ap->min_special = 0; ap->max_special = 1; break; default: sprintf(errstr,"Unknown special_data type: setup_the_special_data_ranges()\n"); return(PROGRAM_ERROR); } return(FINISHED); } /************************* READ_SPECIAL_DATA *******************/ int read_special_data(char *str,dataptr dz) { aplptr ap = dz->application; switch(ap->special_data) { case(RETIME_DATA): return read_retime_data(str,dz); case(IDEAL_DATA): return read_ideal_data(str,dz); case(RETEMPO_DATA): return read_retempo_data(str,dz); case(RETIME_FNAM): return read_retime_fnam(str,dz); case(RETIME_MASK): return read_retime_mask(str,dz); } return(FINISHED); } /*************************** CREATE_RETIME_SNDBUFS **************************/ int create_retime_sndbufs(dataptr dz) { size_t bigbufsize; int n, step, in, out, minsize = 0; size_t framesize = dz->infile->channels * F_SECSIZE; int *realcuts, *chunklen; switch(dz->mode) { case(0): for(n=2;n < dz->itemcnt;n++) { step = dz->lparray[0][n] - dz->lparray[0][n-1]; if(step > minsize) minsize = step * 4; } break; case(1): realcuts = dz->lparray[2]; minsize = 0; for(n=0,in=0,out=3;n < dz->itemcnt;n++,in+=4,out+=4) minsize = max(minsize,realcuts[out] - realcuts[in]); break; case(2): case(5): case(6): case(8): case(9): case(10): case(11): case(12): case(13): minsize = framesize; break; case(3): case(4): chunklen = dz->lparray[1]; minsize = 0; for(n=0;n < dz->itemcnt;n++) minsize = max(minsize,chunklen[n]); break; case(7): minsize = dz->iparam[MM] * (dz->iparam[BEAT_CNT] + 24); /* 24 is a safety margin, in case grabbable beat is longer than defined */ break; } if(dz->sbufptr == 0 || dz->sampbuf==0) { sprintf(errstr,"buffer pointers not allocated: create_retime_sndbufs()\n"); return(PROGRAM_ERROR); } bigbufsize = (size_t)Malloc(-1); dz->buflen = (int)(bigbufsize / sizeof(float)); dz->buflen = (dz->buflen / (framesize * dz->bufcnt)) * (framesize * dz->bufcnt); dz->buflen /= dz->bufcnt; while(dz->buflen < minsize) dz->buflen += framesize; if(dz->buflen <= 0) { sprintf(errstr,"BUFFERS TOO LARGE.\n"); return(PROGRAM_ERROR); } bigbufsize = dz->buflen * sizeof(float); if(bigbufsize * dz->bufcnt <= 0) { sprintf(errstr,"BUFFERS TOO LARGE.\n"); return(PROGRAM_ERROR); } if((dz->bigbuf = (float *)malloc(bigbufsize * dz->bufcnt)) == NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to create sound buffers.\n"); return(PROGRAM_ERROR); } for(n=0;nbufcnt;n++) dz->sbufptr[n] = dz->sampbuf[n] = dz->bigbuf + (dz->buflen * n); dz->sampbuf[n] = dz->bigbuf + (dz->buflen * n); memset((char *)dz->sampbuf[0],0,dz->buflen * dz->bufcnt * sizeof(float)); return(FINISHED); } /***************************** SETUP_INTERNAL_ARRAYS_AND_ARRAY_POINTERS **************************/ int setup_internal_arrays_and_array_pointers(dataptr dz) { int n; dz->ptr_cnt = -1; /* base constructor...process */ dz->array_cnt = -1; dz->iarray_cnt = -1; dz->larray_cnt = -1; switch(dz->mode) { case(0): dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 1; dz->ptr_cnt = 0; dz->fptr_cnt = 0; break; case(1): dz->array_cnt = 2; dz->iarray_cnt = 0; dz->larray_cnt = 3; dz->ptr_cnt = 0; dz->fptr_cnt = 0; break; case(2): dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 1; dz->ptr_cnt = 0; dz->fptr_cnt = 0; break; case(3): case(4): case(8): dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 2; dz->ptr_cnt = 0; dz->fptr_cnt = 0; break; case(5): case(6): dz->array_cnt = 1; dz->iarray_cnt = 0; dz->larray_cnt = 1; dz->ptr_cnt = 0; dz->fptr_cnt = 0; break; case(7): dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 1; dz->ptr_cnt = 0; dz->fptr_cnt = 0; break; case(9): dz->array_cnt = 1; dz->iarray_cnt = 0; dz->larray_cnt = 2; dz->ptr_cnt = 0; dz->fptr_cnt = 0; break; case(10): dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 1; dz->ptr_cnt = 0; dz->fptr_cnt = 0; break; case(11): case(12): case(13): dz->array_cnt = 0; dz->iarray_cnt = 0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0; break; } if(dz->array_cnt < 0 || dz->iarray_cnt < 0 || dz->larray_cnt < 0 || dz->ptr_cnt < 0 || dz->fptr_cnt < 0) { sprintf(errstr,"array_cnt not set in setup_internal_arrays_and_array_pointers()\n"); return(PROGRAM_ERROR); } if(dz->array_cnt) { if((dz->parray = (double **)malloc(dz->array_cnt * sizeof(double *)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY for internal double arrays.\n"); return(MEMORY_ERROR); } for(n=0;narray_cnt;n++) dz->parray[n] = NULL; } if(dz->larray_cnt) { if((dz->lparray = (int **)malloc(dz->larray_cnt * sizeof(int *)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY for internal long arrays.\n"); return(MEMORY_ERROR); } for(n=0;nlarray_cnt;n++) dz->lparray[n] = NULL; } return(FINISHED); } /************************* RETIME **********************************/ int retime(dataptr dz) { int exit_status, insig; int chans = dz->infile->channels; double srate = dz->infile->srate; int *intimes = dz->lparray[0]; int outstep = dz->iparam[MM]; float *ibuf = dz->sampbuf[0], *obuf = dz->sampbuf[2]; int obufpos = 0; int maxsil = 4; int splicelen = (int)round(15.0 * MS_TO_SECS * srate) * chans; int winsize = (int)round(RETIME_WINSIZE * MS_TO_SECS * srate) * chans; int *silat, *sillen, *pos; float *env; int abs_read_start, read_end_in_buf, last_time_in_inbuf, next_time_in_inbuf, samps_to_copy, timescnt, lasttime, timestep, timechange; int n, m, j, k, silcnt = 0, small_loc, large_loc, this_splicelen, splicestart, splicend, min_energy_point = 0; int smallest, largest; double spliceincr, spliceval; int silence_to_set, this_timechange; if ((silat = (int *)malloc((maxsil+1) * sizeof(int)))==NULL) { sprintf(errstr,"Insufficient memory to store silence locations between beats\n"); return(MEMORY_ERROR); } if ((sillen = (int *)malloc((maxsil+1) * sizeof(int)))==NULL) { sprintf(errstr,"Insufficient memory to store lengths of silences between beats\n"); return(MEMORY_ERROR); } if ((env = (float *)malloc(RETIME_ENVSIZE * sizeof(float)))==NULL) { sprintf(errstr,"Insufficient memory to store envelope data\n"); return(MEMORY_ERROR); } if ((pos = (int *)malloc(RETIME_ENVSIZE * sizeof(int)))==NULL) { sprintf(errstr,"Insufficient memory to store envelope positions\n"); return(MEMORY_ERROR); } memset((char *)dz->bigbuf,0,5 * dz->buflen * sizeof(float)); /* read sound into (double) inbuf */ if((exit_status = read_samps(dz->sampbuf[0],dz)) < 0) return(exit_status); abs_read_start = 0; read_end_in_buf = dz->ssampsread; if(dz->ssampsread == dz->buflen) { if((exit_status = read_samps(dz->sampbuf[1],dz)) < 0) { return(exit_status); } read_end_in_buf += dz->ssampsread; } last_time_in_inbuf = 0; for(n=0;nitemcnt;n++) { if(intimes[n] >= dz->insams[0]) { dz->itemcnt = n; break; } } if(dz->itemcnt == 0) { sprintf(errstr,"ALL ENTERED TIMES ARE TOO LATE FOR THIS SOUND.\n"); return(DATA_ERROR); } if(dz->itemcnt < 2) { sprintf(errstr,"TOO FEW ENTERED TIMES (MUST BE AT LEAST 2).\n"); return(DATA_ERROR); } if(intimes[0] > 0) { /* Deal with first time (copy initial block of sound) */ samps_to_copy = intimes[0]; while(samps_to_copy >= dz->buflen) { memcpy((char *)obuf,(char *)ibuf,dz->buflen * sizeof(float)); obufpos = dz->buflen; if((exit_status = advance_obuf(&obufpos,dz)) < 0) return(exit_status); if((exit_status = advance_ibuf(&abs_read_start,&read_end_in_buf,&last_time_in_inbuf,&next_time_in_inbuf,&min_energy_point,silcnt,silat,dz)) < 0) return(exit_status); samps_to_copy -= dz->buflen; } if(samps_to_copy) { memcpy((char *)obuf,(char *)ibuf,samps_to_copy * sizeof(float)); obufpos += samps_to_copy; if(obufpos >= dz->buflen * 2) { if((exit_status = advance_obuf(&obufpos,dz)) < 0) return(exit_status); } } last_time_in_inbuf = samps_to_copy; } timescnt = 1; lasttime = intimes[0]; next_time_in_inbuf = lasttime - abs_read_start; for(timescnt = 1;timescnt < dz->itemcnt;timescnt++) { last_time_in_inbuf = next_time_in_inbuf; while(last_time_in_inbuf >= dz->buflen) { /* advance in inbuf if ness */ if((exit_status = advance_ibuf(&abs_read_start,&read_end_in_buf,&last_time_in_inbuf,&next_time_in_inbuf,&min_energy_point,silcnt,silat,dz)) < 0) return(exit_status); } next_time_in_inbuf = intimes[timescnt] - abs_read_start; timestep = next_time_in_inbuf - last_time_in_inbuf; /* Find step between marked times */ timechange = outstep - timestep; /* Find difference bedtween marked times and required times */ /* IF SILENCE IS TO BE INSERTED */ if(timechange > chans) { /* LOOK FOR EXISTING SILENCES */ for(n=0;n= chans * 2) { /* if we've counted more than 'chan' zeros' in a previous silence */ silcnt++; /* this is a valid silence, keep it, and go to next */ if(silcnt > maxsil) { /* if we've used up the silence array */ smallest = (int)floor(MAXINT); small_loc = 0; for(n=0;n 0) { if(silcnt > 1) { largest = 0; large_loc = 0; for(n=0;n largest) { largest = sillen[n]; large_loc = n; } } for(m=0;m BIGGERSIL) { for(n = m+1;n m) large_loc--; silcnt--; m--; } } } } while(timechange/silcnt < chans) { /* if the individual silence-inserts are too small, ignore some silences */ smallest = (int)floor(MAXINT); small_loc = 0; for(n=0;n= dz->buflen) { memcpy((char *)(obuf+obufpos),(char *)(ibuf+last_time_in_inbuf),dz->buflen * sizeof(float)); obufpos += dz->buflen; if(obufpos >= dz->buflen * 2) { if((exit_status = advance_obuf(&obufpos,dz)) < 0) return(exit_status); } last_time_in_inbuf += dz->buflen; if(last_time_in_inbuf >= dz->buflen) { if((exit_status = advance_ibuf(&abs_read_start,&read_end_in_buf,&last_time_in_inbuf,&next_time_in_inbuf,&min_energy_point,silcnt,silat,dz)) < 0) return(exit_status); } samps_to_copy -= dz->buflen; } if(samps_to_copy) { memcpy((char *)(obuf+obufpos),(char *)(ibuf+last_time_in_inbuf),samps_to_copy * sizeof(float)); obufpos += samps_to_copy; if(obufpos >= dz->buflen * 2) { if((exit_status = advance_obuf(&obufpos,dz)) < 0) return(exit_status); } last_time_in_inbuf += samps_to_copy; if(last_time_in_inbuf >= dz->buflen) { if((exit_status = advance_ibuf(&abs_read_start,&read_end_in_buf,&last_time_in_inbuf,&next_time_in_inbuf,&min_energy_point,silcnt,silat,dz)) < 0) return(exit_status); } } silence_to_set = this_timechange; while(silence_to_set >= dz->buflen) { memset((char *)(obuf+obufpos),0,dz->buflen * sizeof(float)); obufpos += dz->buflen; if(obufpos >= dz->buflen * 2) { if((exit_status = advance_obuf(&obufpos,dz)) < 0) return(exit_status); } silence_to_set -= dz->buflen; } if(silence_to_set) { memset((char *)(obuf+obufpos),0,silence_to_set * sizeof(float)); obufpos += silence_to_set; if(obufpos >= dz->buflen * 2) { if((exit_status = advance_obuf(&obufpos,dz)) < 0) return(exit_status); } } last_time_in_inbuf = silat[n]; } /* copy any remaining insound before next time-marker */ samps_to_copy = next_time_in_inbuf - last_time_in_inbuf; while(samps_to_copy >= dz->buflen) { memcpy((char *)(obuf+obufpos),(char *)(ibuf+last_time_in_inbuf),dz->buflen * sizeof(float)); obufpos += dz->buflen; if(obufpos >= dz->buflen * 2) { if((exit_status = advance_obuf(&obufpos,dz)) < 0) return(exit_status); } last_time_in_inbuf += dz->buflen; if(last_time_in_inbuf >= dz->buflen) { if((exit_status = advance_ibuf(&abs_read_start,&read_end_in_buf,&last_time_in_inbuf,&next_time_in_inbuf,&min_energy_point,silcnt,silat,dz)) < 0) return(exit_status); } samps_to_copy -= dz->buflen; } if(samps_to_copy) { memcpy((char *)(obuf+obufpos),(char *)(ibuf+last_time_in_inbuf),samps_to_copy * sizeof(float)); obufpos += samps_to_copy; if(obufpos >= dz->buflen * 2) { if((exit_status = advance_obuf(&obufpos,dz)) < 0) return(exit_status); } last_time_in_inbuf += samps_to_copy; if(last_time_in_inbuf >= dz->buflen) { if((exit_status = advance_ibuf(&abs_read_start,&read_end_in_buf,&last_time_in_inbuf,&next_time_in_inbuf,&min_energy_point,silcnt,silat,dz)) < 0) return(exit_status); } } } else { /* ELSE, NO EXISTING SILENCES ... INSERTING SILENCE AT MIN ENERGY POINT */ if((exit_status = find_min_energy_point(&min_energy_point,last_time_in_inbuf,next_time_in_inbuf,winsize,ibuf,env,pos,dz)) < 0) return(exit_status); samps_to_copy = min_energy_point - last_time_in_inbuf; while(samps_to_copy >= dz->buflen) { memcpy((char *)(obuf+obufpos),(char *)(ibuf+last_time_in_inbuf),dz->buflen * sizeof(float)); obufpos += dz->buflen; if(obufpos >= dz->buflen * 2) { if((exit_status = advance_obuf(&obufpos,dz)) < 0) return(exit_status); } last_time_in_inbuf += dz->buflen; if(last_time_in_inbuf >= dz->buflen) { /* advance in inbuf if ness */ if((exit_status = advance_ibuf(&abs_read_start,&read_end_in_buf,&last_time_in_inbuf,&next_time_in_inbuf,&min_energy_point,silcnt,silat,dz)) < 0) return(exit_status); } samps_to_copy -= dz->buflen; } if(samps_to_copy) { memcpy((char *)(obuf+obufpos),(char *)(ibuf+last_time_in_inbuf),samps_to_copy * sizeof(float)); obufpos += samps_to_copy; /* copy to min energy pont */ if(obufpos >= dz->buflen * 2) { if((exit_status = advance_obuf(&obufpos,dz)) < 0) return(exit_status); } /* insert silence */ last_time_in_inbuf += samps_to_copy; if(last_time_in_inbuf >= dz->buflen) { /* advance in inbuf if ness */ if((exit_status = advance_ibuf(&abs_read_start,&read_end_in_buf,&last_time_in_inbuf,&next_time_in_inbuf,&min_energy_point,silcnt,silat,dz)) < 0) return(exit_status); } } while(timechange >= dz->buflen) { memset((char *)(obuf+obufpos),0,dz->buflen * sizeof(float)); obufpos += dz->buflen; if(obufpos >= dz->buflen * 2) { if((exit_status = advance_obuf(&obufpos,dz)) < 0) return(exit_status); } timechange -= dz->buflen; } if(timechange) { memset((char *)(obuf+obufpos),0,timechange * sizeof(float)); obufpos += timechange; if(obufpos >= dz->buflen * 2) { if((exit_status = advance_obuf(&obufpos,dz)) < 0) return(exit_status); } /* copy from min energy point to next-time */ } last_time_in_inbuf = min_energy_point; samps_to_copy = next_time_in_inbuf - min_energy_point; while(samps_to_copy >= dz->buflen) { memcpy((char *)(obuf+obufpos),(char *)(ibuf+last_time_in_inbuf),dz->buflen * sizeof(float)); obufpos += dz->buflen; if(obufpos >= dz->buflen * 2) { if((exit_status = advance_obuf(&obufpos,dz)) < 0) return(exit_status); } last_time_in_inbuf += dz->buflen; if(last_time_in_inbuf >= dz->buflen) { /* advance in inbuf if ness */ if((exit_status = advance_ibuf(&abs_read_start,&read_end_in_buf,&last_time_in_inbuf,&next_time_in_inbuf,&min_energy_point,silcnt,silat,dz)) < 0) return(exit_status); } samps_to_copy -= dz->buflen; } if(samps_to_copy) { memcpy((char *)(obuf+obufpos),(char *)(ibuf+last_time_in_inbuf),samps_to_copy * sizeof(float)); obufpos += samps_to_copy; if(obufpos >= dz->buflen * 2) { if((exit_status = advance_obuf(&obufpos,dz)) < 0) return(exit_status); } last_time_in_inbuf += samps_to_copy; if(last_time_in_inbuf >= dz->buflen) { /* advance in inbuf if ness */ if((exit_status = advance_ibuf(&abs_read_start,&read_end_in_buf,&last_time_in_inbuf,&next_time_in_inbuf,&min_energy_point,silcnt,silat,dz)) < 0) return(exit_status); } } } } else if(timechange < -chans) { /* Time must be removed, do overlap at min-level point */ if((exit_status = find_min_energy_point(&min_energy_point,last_time_in_inbuf,next_time_in_inbuf,winsize,ibuf,env,pos,dz)) < 0) return(exit_status); /* Copy samples up to min energy point */ samps_to_copy = min_energy_point - last_time_in_inbuf; this_splicelen = min(samps_to_copy,splicelen); splicestart = samps_to_copy - this_splicelen; spliceincr = 1.0 / this_splicelen; spliceval = 1.0; k = 0; while(samps_to_copy >= dz->buflen) { for(j=0;j < dz->buflen;j++) { if(k >= splicestart) spliceval -= spliceincr; obuf[obufpos] = (float) (obuf[obufpos] + (ibuf[last_time_in_inbuf] * spliceval)); last_time_in_inbuf++; if(last_time_in_inbuf >= dz->buflen) { /* advance in inbuf if ness */ if((exit_status = advance_ibuf(&abs_read_start,&read_end_in_buf,&last_time_in_inbuf,&next_time_in_inbuf,&min_energy_point,silcnt,silat,dz)) < 0) return(exit_status); } obufpos++; k++; } if(obufpos >= dz->buflen * 2) { if((exit_status = advance_obuf(&obufpos,dz)) < 0) return(exit_status); } samps_to_copy -= dz->buflen; } while(samps_to_copy > 0) { if(k >= splicestart) spliceval -= spliceincr; obuf[obufpos] = (float) (obuf[obufpos] + (ibuf[last_time_in_inbuf] * spliceval)); last_time_in_inbuf++; obufpos++; samps_to_copy--; k++; } obufpos += timechange; /* step back in obuf, (timechange is -ve) so samples overlap, shortening obuf file here */ if(obufpos < 0) { fprintf(stdout,"WARNING: Time modfification too extreme for buffers: Quitting before end of input sound.\n"); fflush(stdout); obufpos -= timechange; break; } if(obufpos >= dz->buflen * 2) { if((exit_status = advance_obuf(&obufpos,dz)) < 0) return(exit_status); } /* Copy samples from min energy point to next specified time */ samps_to_copy = next_time_in_inbuf - min_energy_point; this_splicelen = min(samps_to_copy,splicelen); splicend = this_splicelen; spliceincr = 1.0 / this_splicelen; spliceval = 0.0; k = 0; while(samps_to_copy >= dz->buflen) { for(j=0;j < dz->buflen;j++) { if(k < splicend) spliceval += spliceincr; obuf[obufpos] = (float) (obuf[obufpos] + (ibuf[last_time_in_inbuf] * spliceval)); last_time_in_inbuf++; if(last_time_in_inbuf >= dz->buflen) { /* advance in inbuf if ness */ if((exit_status = advance_ibuf(&abs_read_start,&read_end_in_buf,&last_time_in_inbuf,&next_time_in_inbuf,&min_energy_point,silcnt,silat,dz)) < 0) return(exit_status); } obufpos++; samps_to_copy--; k++; } if(obufpos >= dz->buflen * 2) { if((exit_status = advance_obuf(&obufpos,dz)) < 0) return(exit_status); } samps_to_copy -= dz->buflen; } while(samps_to_copy > 0) { if(k < splicend) spliceval += spliceincr; obuf[obufpos] = (float) (obuf[obufpos] + (ibuf[last_time_in_inbuf] * spliceval)); last_time_in_inbuf++; if(last_time_in_inbuf >= dz->buflen) { /* advance in inbuf if ness */ if((exit_status = advance_ibuf(&abs_read_start,&read_end_in_buf,&last_time_in_inbuf,&next_time_in_inbuf,&min_energy_point,silcnt,silat,dz)) < 0) return(exit_status); } obufpos++; samps_to_copy--; k++; } if(obufpos >= dz->buflen * 2) { if((exit_status = advance_obuf(&obufpos,dz)) < 0) return(exit_status); } } } if(obufpos > 0) { if((exit_status = write_samps(dz->sampbuf[2],obufpos,dz))<0) return(exit_status); } if(read_end_in_buf > last_time_in_inbuf) { if((exit_status = write_samps(dz->sampbuf[0] + last_time_in_inbuf,read_end_in_buf - last_time_in_inbuf,dz))<0) /* Write ALL samps remaining in inbuf */ return(exit_status); } while(dz->total_samps_read < dz->insams[0]) { /* Read and write any remaining samples in infile */ if((exit_status = read_samps(dz->sampbuf[0],dz)) < 0) return(exit_status); if((exit_status = write_samps(dz->sampbuf[0],dz->ssampsread,dz))<0) return(exit_status); } return FINISHED; } /******************************************* ADVANCE_OBUF *******************************************/ int advance_obuf(int *obufpos,dataptr dz) { int exit_status; if((exit_status = write_samps(dz->sampbuf[2],dz->buflen,dz))<0) return(exit_status); memcpy((char *)dz->sampbuf[2],(char *)dz->sampbuf[3],dz->buflen * sizeof(float)); memcpy((char *)dz->sampbuf[3],(char *)dz->sampbuf[4],dz->buflen * sizeof(float)); memset((char *)dz->sampbuf[4],0,dz->buflen * sizeof(float)); *obufpos -= dz->buflen; return FINISHED; } /******************************************* ADVANCE_IBUF *******************************************/ int advance_ibuf(int *abs_read_start,int *read_end_in_buf,int *last_time_in_inbuf,int *next_time_in_inbuf,int *min_energy_point,int silcnt,int *silat,dataptr dz) { int exit_status, n; memcpy((char *)dz->sampbuf[0],(char *)dz->sampbuf[1],dz->buflen * sizeof(float)); memset((char *)dz->sampbuf[1],0,dz->buflen * sizeof(float)); *read_end_in_buf -= dz->buflen; *last_time_in_inbuf -= dz->buflen; *next_time_in_inbuf -= dz->buflen; *min_energy_point -= dz->buflen; if(silcnt > 0) { for(n= 0;n < silcnt;n++) silat[n] -= dz->buflen; } if((exit_status = read_samps(dz->sampbuf[1],dz)) < 0) return(exit_status); if(dz->ssampsread > 0) { *abs_read_start += dz->buflen; *read_end_in_buf += dz->ssampsread; } return(FINISHED); } /******************************************* FIND_MIN_ENERGY_POINT *******************************************/ int find_min_energy_point(int *min_energy_point,int last_time_in_inbuf,int next_time_in_inbuf,int winsize,float *ibuf,float *env,int *pos,dataptr dz) { int envcnt = 0; int envarraycnt = 0; double maxsamp = 0.0, minsamp, max_local; int dist, k, minloc, startt, endd; int chans = dz->infile->channels, phase; float min_energy; int minpos; if((dist = next_time_in_inbuf - last_time_in_inbuf) >= winsize * 2) { /* FIND GROSS ENVELOPE USING 20mS WINDOWS */ for(k = last_time_in_inbuf;k < next_time_in_inbuf; k++,dist--) { if(envarraycnt >= RETIME_ENVSIZE) { sprintf(errstr,"Envelope overflow at gross envelope stage\n"); return(MEMORY_ERROR); } maxsamp = max(fabs(ibuf[k]),maxsamp); envcnt++; if((envcnt >= winsize) && (dist > winsize)) { env[envarraycnt++] = (float)maxsamp; envcnt = 0; } /* incorporate any final window < wsize in length, into final window */ } if(envcnt > 0) envarraycnt++; /* FIND MINIMUM IN GROSS ENVELOPE */ minsamp = HUGE; minloc = 0; for(k=0;k < envarraycnt;k++) { /* find minimum in envelope */ if(env[k] < minsamp) { minsamp = env[k]; minloc = k; } } /* FIND START AND END OF MINIMUM ENERGY WINDOW */ startt = last_time_in_inbuf + (minloc * winsize); if(k == envcnt - 1) endd = next_time_in_inbuf; else endd = last_time_in_inbuf + ((minloc+1) * winsize); } else { /* IF TIMESTEP TOO SHORT FOR 20mS WINDOWING, USE WHOLE LENGTH OF TIMESTEP INSTEAD */ startt = last_time_in_inbuf; endd = next_time_in_inbuf; } /* FIND MINIMUM ENERGY POINT */ k = startt; while(ibuf[k] == 0.0) { k++; if(k == endd) { /* if entire window is zero, put min-energy point in middle of it */ *min_energy_point = (((startt + endd)/2)/chans) * chans; return(FINISHED); } } max_local = 0.0; envcnt = 0; if(ibuf[k] > 0.0) phase = 1; else phase = -1; while(k < endd) { if(envcnt >= RETIME_ENVSIZE) { sprintf(errstr,"Envelope overflow at min-energy stage\n"); return(MEMORY_ERROR); } switch(phase) { case(1): if(ibuf[k] < 0.0) { /* If phase has changed */ env[envcnt++] = (float)max_local; /* store local energy peak, and go to next envelope-store location */ max_local = 0.0; phase = -1; } else { if(ibuf[k] > max_local) { /* get local energy peak, and its location */ pos[envcnt] = k; max_local = ibuf[k]; } k++; } break; case(-1): if(ibuf[k] > 0.0) { env[envcnt] = (float)max_local; pos[envcnt++] = k; max_local = 0.0; phase = 1; } else { if(fabs(ibuf[k]) > max_local) { pos[envcnt] = k; max_local = fabs(ibuf[k]); } k++; } break; } } env[envcnt++] = (float)max_local; /* FIND MINIMUM LOCAL ENERGY-PEAK */ min_energy = env[0]; minpos = pos[0]; for(k = 1;k 0.0) { while(ibuf[k] > 0.0) { k++; if(k == endd) { k = minpos; while(ibuf[k] > 0.0) { k--; if(k == startt) { *min_energy_point = k; fprintf(stdout,"WARNING: Failed to find zero-crossing: try filtering out lowest frqs\n"); fflush(stdout); return(FINISHED); } } } } } else if(ibuf[k] < 0.0) { while(ibuf[k] < 0.0) { k++; if(k == endd) { k = minpos; while(ibuf[k] < 0.0) { k--; if(k == startt) { *min_energy_point = k; fprintf(stdout,"WARNING: Failed to find zero-crossing: try filtering out lowest frqs\n"); fflush(stdout); return(FINISHED); } } } } } *min_energy_point = k; return(FINISHED); } /******************************************* IDEAL_RETIME *******************************************/ int ideal_retime(dataptr dz) { int exit_status; int chans = dz->infile->channels, k, thisevent; int *cuts = dz->lparray[2], in, on, off, out; // in = start of upsplice, on = start of full-level chunk, off = end of full-level chunk, out = end of downsplice int *idealsamps = dz->lparray[1]; float *ibuf = dz->sampbuf[0], *obuf = dz->sampbuf[1], *ovflowbuf = dz->sampbuf[2], *splbuf = dz->sampbuf[3]; int obufpos, lastwrite, ibufstart, obufstart, overflow, chunklen, upsplen, dnsplen, upsplicecnt, dnsplicecnt, n, m; double upincr, dnincr, splval; memset((char *)obuf,0,2 * dz->buflen * sizeof(float)); memset((char *)splbuf,0,dz->buflen * sizeof(float)); ibufstart = 0; obufstart = 0; lastwrite = 0; /* FOR EVERY OUTCHUNK and INCHUNK */ for(thisevent=0,in=0,on=1,off=2,out=3;thiseventitemcnt;thisevent++,in+=4,on+=4,off+=4,out+=4) { obufpos = idealsamps[thisevent] - obufstart; while(obufpos >= dz->buflen) { // WHERE NESS, WRITE COMPLETED BUFFERS OR SILENT BUFS (e.g. at start) if((exit_status = write_samps(obuf,dz->buflen,dz)) < 0) return exit_status; memset((char *)obuf,0,dz->buflen * sizeof(float)); if((overflow = lastwrite - dz->buflen) > 0) { // IF LAST WRITE SPILLED OVER INTO OVERFLOW BUFFER, COPY OVERFLOW INTO MAIN OBUF memcpy((char *)obuf,(char*)ovflowbuf,overflow * sizeof(float)); memset((char *)ovflowbuf,0,dz->buflen * sizeof(float)); } lastwrite = 0; obufpos -= dz->buflen; obufstart += dz->buflen; // INCREMENTING THE SAMPLCNT OF obufstart } chunklen = cuts[out] - cuts[in]; // GET DATA FOR THIS CHUNK upsplen = cuts[on] - cuts[in]; dnsplen = cuts[out] - cuts[off]; m = cuts[in] - ibufstart; // COPY CHUNK FROM INBUF TO SPLICE BUF for(n = 0;n < chunklen;n++) { while(m >= dz->ssampsread) { // WHERE NECESSARY, SKIP TO NEXT INBUF m -= dz->ssampsread; ibufstart += dz->ssampsread; // INCREMENTING THE SAMPLCNT OF ibufstart if((exit_status = read_samps(ibuf,dz)) < 0) return exit_status; if(dz->ssampsread == 0) { // IF END OF FILE REACHED BEFORE END OF CHUNK chunklen = n; // SHORTEN CHUNK dnsplen = 0; // REMOVE DOWNSPLICE AT END dz->itemcnt = thisevent; // FORCE INNER LOOP EXIT break; } } if(dz->ssampsread == 0) // AND FORCE OUTER LOOP EXIT break; splbuf[n] = ibuf[m]; m++; } // DO SPLICES IN SPLICE BUF upsplicecnt = upsplen/chans; upincr = 1.0 /(double)upsplicecnt; splval = 0.0; m = 0; for(n=0;n 0) { if((exit_status = write_samps(obuf,lastwrite,dz)) < 0) return exit_status; } return FINISHED; } /*************************** SHAVE ****************************/ int shave(dataptr dz) { int exit_status, chans = dz->infile->channels, warned; float *ibuf = dz->sampbuf[0]; int *events; int ibufpos = 0, buf_start, n, m, j, total_shrunk_dur, evlen, data_end; int eventsegscnt, orig_eventsegscnt, cnt; double splic, splicincr; int event_start, orig_event_end, new_event_end, new_event_splice_end; splicincr = 1.0/(double)(dz->iparam[2]/chans); if((exit_status = count_events(0,0,&eventsegscnt,dz))<0) { return(exit_status); } events = dz->lparray[0]; /* ELIMININATE ALL EVENTS WHICH CANNOT BE SHORTENED * new * retained end * _________________________splice * | \ : old * | orig event \ : end * | - - - - - - - - - - - -\- -: splice * | / \ :\ * | / \ : \ * |/ --- found dur of old event-\-----\ * : * Limit * : */ warned = 0; orig_eventsegscnt = eventsegscnt; // JUNE 2010 total_shrunk_dur = dz->iparam[1] + dz->iparam[3]; for(n=0;niparam[3]; if(evlen <= 0) { if(!warned) { fprintf(stdout,"WARNING: Some events are shorter than the 'splice length' specified.\n"); fflush(stdout); warned = 1; } } if(evlen <= total_shrunk_dur) { for(m = n+2; m < eventsegscnt; m++) events[m-2] = events[m]; eventsegscnt -= 2; n -= 2; } } if(eventsegscnt <= 0) { sprintf(errstr,"No Events Will Be Shortened, With These Parameter Settings.\n"); return(DATA_ERROR); } else { fprintf(stdout,"INFO: %d of %d events will be shortened\n",eventsegscnt/2,orig_eventsegscnt/2); fflush(stdout); } if((sndseekEx(dz->ifd[0],0,0)<0)){ sprintf(errstr,"sndseek() failed\n"); return SYSTEM_ERROR; } reset_filedata_counters(dz); buf_start = 0; dz->ssampsread = 0; cnt = 0; event_start = events[cnt++]; orig_event_end = events[cnt++]; //JUNE 2010 new_event_end = event_start + dz->iparam[2]; //JUNE 2010 new_event_splice_end = new_event_end + dz->iparam[3]; if((exit_status = read_samps(ibuf,dz))<0) { sprintf(errstr,"Failed to read data from sndfile.\n"); return(DATA_ERROR); } while(dz->ssampsread) { while(event_start >= dz->buflen) { if((exit_status = write_samps(ibuf,dz->buflen,dz))<0) { sprintf(errstr,"Failed to write data to sndfile.\n"); return(DATA_ERROR); } buf_start += dz->buflen; event_start -= dz->buflen; new_event_end -= dz->buflen; new_event_splice_end -= dz->buflen; orig_event_end -= dz->buflen; if((exit_status = read_samps(ibuf,dz))<0) { sprintf(errstr,"Failed to read data from sndfile.\n"); return(DATA_ERROR); } } ibufpos = event_start; while(ibufpos < new_event_end) { if(ibufpos >= dz->buflen) { if((exit_status = write_samps(ibuf,dz->buflen,dz))<0) { sprintf(errstr,"Failed to write data to sndfile.\n"); return(DATA_ERROR); } buf_start += dz->buflen; new_event_end -= dz->buflen; new_event_splice_end -= dz->buflen; orig_event_end -= dz->buflen; if((exit_status = read_samps(ibuf,dz))<0) { sprintf(errstr,"Failed to read data from sndfile.\n"); return(DATA_ERROR); } ibufpos = 0; } ibufpos++; } splic = 1.0 - splicincr; while(ibufpos < new_event_splice_end) { if(ibufpos >= dz->buflen) { if((exit_status = write_samps(ibuf,dz->buflen,dz))<0) { sprintf(errstr,"Failed to write data to sndfile.\n"); return(DATA_ERROR); } buf_start += dz->buflen; new_event_splice_end -= dz->buflen; orig_event_end -= dz->buflen; if((exit_status = read_samps(ibuf,dz))<0) { sprintf(errstr,"Failed to read data from sndfile.\n"); return(DATA_ERROR); } ibufpos = 0; } for(j=0;j= eventsegscnt) break; while(ibufpos < orig_event_end) { if(ibufpos >= dz->buflen) { if((exit_status = write_samps(ibuf,dz->buflen,dz))<0) { sprintf(errstr,"Failed to write data to sndfile.\n"); return(DATA_ERROR); } buf_start += dz->buflen; orig_event_end -= dz->buflen; if((exit_status = read_samps(ibuf,dz))<0) { sprintf(errstr,"Failed to read data from sndfile.\n"); return(DATA_ERROR); } ibufpos = 0; } ibuf[ibufpos++] = 0.0f; } if(cnt >= eventsegscnt) // SAFETY, in case of accounting error break; event_start = events[cnt++] - buf_start; orig_event_end = events[cnt++] - buf_start; //JUNE 2010 new_event_end = event_start + dz->iparam[2]; //JUNE 2010 new_event_splice_end = new_event_end + dz->iparam[3]; data_end = dz->insams[0] - buf_start; if(new_event_splice_end >= data_end) { new_event_end = data_end; new_event_splice_end = data_end; } } if(ibufpos > 0) { if((exit_status = write_samps(ibuf,ibufpos,dz))<0) { sprintf(errstr,"Failed to write data to sndfile.\n"); return(DATA_ERROR); } } return FINISHED; } /******************************************* LOCATE-PEAKS *******************************************/ #define MAX_CHUNKS (4000) int locate_peaks(dataptr dz) { int exit_status; double srate = (double)dz->infile->srate; int chans = dz->infile->channels; float *tempibuf; int inchunk = 0; int silcnt = 0; int thischunklen = 0, thischunkcounter = 0, chunkcnt = 0, n, bufstart; int *chunkat, *chunklen; int minsil = (int)round((dz->param[1] * MS_TO_SECS) * srate) * chans; dz->buflen = F_SECSIZE * chans; if((tempibuf = (float *)malloc(dz->buflen * sizeof(float)))==NULL) { sprintf(errstr,"Insufficient memory create temp inbuf to read chunklens.\n"); return(MEMORY_ERROR); } if((dz->lparray[0] = (int *)malloc(MAX_CHUNKS * sizeof(int)))==NULL) { sprintf(errstr,"Insufficient memory to store peak positions\n"); return(MEMORY_ERROR); } if((dz->lparray[1] = (int *)malloc(MAX_CHUNKS * sizeof(int)))==NULL) { sprintf(errstr,"Insufficient memory to store peak widths\n"); return(MEMORY_ERROR); } chunkat = dz->lparray[0]; chunklen = dz->lparray[1]; if((exit_status = read_samps(tempibuf,dz)) < 0) return exit_status; bufstart = 0; while (dz->ssampsread > 0) { for(n=0;nssampsread;n++) { if(tempibuf[n] > 0 || tempibuf[n] < 0) { if(silcnt && (thischunkcounter > 0)) // If we've been in silence, and still counting chunk thischunklen = thischunkcounter; // Reset chunklen to chunkcounter silcnt = 0; if(inchunk) { // If in a chunk, keep counting until encountering silence thischunklen++; thischunkcounter++; } else { chunkat[chunkcnt] = bufstart + n; // If just found chunk start, set up a new chunk and start counting it inchunk = 1; thischunklen = 1; thischunkcounter = 1; } } else { if(inchunk) { // If (was) in a chunk, but come into silence thischunkcounter++; // chunklen stops counting (assuming chunk has ended) BUT // thischunkcounter continues to count in case this is a silence WITHIN an event if(silcnt >= minsil) { // Once we're sure we have minimum silence gap chunklen[chunkcnt] = thischunklen; // Then save the chunk inchunk = 0; thischunklen = 0; thischunkcounter = 0; // Set chunkcounter back to zero chunkcnt++; if(chunkcnt >= MAX_CHUNKS) { sprintf(errstr,"More than %d chunks : Cannot proceed\n",MAX_CHUNKS); return(DATA_ERROR); } } } silcnt++; // Count silence } } bufstart += dz->ssampsread; if((exit_status = read_samps(tempibuf,dz)) < 0) return exit_status; } if(inchunk) { chunklen[chunkcnt] = thischunklen; chunkcnt++; } dz->itemcnt = chunkcnt; switch(dz->itemcnt) { case(0): sprintf(errstr,"No peaks found in soundfile.\n"); return(MEMORY_ERROR); case(1): fprintf(stdout,"WARNING: WARNING: only 1 event found: Change inter-event silence ??\n"); fflush(stdout); break; default: fprintf(stdout,"INFO: %d events found\n",dz->itemcnt); fflush(stdout); break; } free(tempibuf); if((sndseekEx(dz->ifd[0],0,0)<0)){ sprintf(errstr,"sndseek() failed\n"); return SYSTEM_ERROR; } reset_filedata_counters(dz); return FINISHED; } /******************************************* RETIME_FOUND_PEAKS *******************************************/ int retime_found_peaks(dataptr dz) { int exit_status, done = 0, chans = dz->infile->channels; double srate = (double)dz->infile->srate, time, timefact = 1.0; float *ibuf = dz->sampbuf[0], *obuf = dz->sampbuf[1], *ovflwbuf = dz->sampbuf[2]; int *chunkat = dz->lparray[0], *chunklen = dz->lparray[1]; int ibufstart = 0; // position in infile of start of current input buffer int obufstart = 0; // position in outfile of start of current output buffer int osamppos = 0; // position in outfile int obufpos = 0; // position within current buffer int lastwrite = 0; // position in current outbuf (or its overflow) of the furthest write int n, m, k, chunkstart, chunkend, step, overflow; int chanoffset; // in multichan case, ensures output chunk positioned at same channel as input chunk int initial_silence = 0;// length of leading silence before 1st event in output int pregain = 0; if((dz->mode == 3) && dz->param[2] < 1.0) pregain = 1; memset((char *)obuf,0,dz->buflen * sizeof(float)); memset((char *)ovflwbuf,0,dz->buflen * sizeof(float)); if(dz->brksize[0] == 0) timefact = 1.0/dz->param[0]; if((exit_status = get_initial_silence(&initial_silence,dz)) < 0) return(exit_status); osamppos += initial_silence; for(n=0;nitemcnt;n++) { chanoffset = (chunkat[n]/chans) * chans; // Find any channel chanoffset of the in-chunk */ chanoffset = chunkat[n] - chanoffset; while(dz->total_samps_read < chunkat[n]) { // If next chunk to read is beyond current input buffer ibufstart += dz->ssampsread; // Get another buffer of data if((exit_status = read_samps(ibuf,dz)) < 0) return exit_status; if(pregain) { for(m=0;mssampsread;m++) ibuf[m] = (float)(ibuf[m] * dz->param[2]); } if(dz->ssampsread == 0) { fprintf(stdout,"WARNING: Ran out of samples in input (1)\n"); fflush(stdout); done = 1; break; } } if(done) break; chunkstart = chunkat[n] - ibufstart; // get address of chunkstart within this buffer chunkend = chunkstart + chunklen[n]; // and relative address of chunk end if(n > 0) { // After first inchunk, calculate position of next outchunk switch(dz->mode) { case(3): osamppos += dz->iparam[MM]; // Advance by beat-len step break; case(4): if(chunkat[n-1] < dz->iparam[2] || chunkat[n-1] >= dz->iparam[3]) timefact = 1.0; // If previous chunk lies outside limits, don't time-shrink else { if(dz->brksize[0]) { // Advance by distance between beats * speed-change factor time = (chunkat[n]/chans)/srate; read_value_from_brktable(time,0,dz); } timefact = 1.0/dz->param[0]; } step = (int)round((double)(chunkat[n] - chunkat[n-1]) * timefact); step = (step/chans) * chans; osamppos += step; break; } } osamppos += chanoffset; while((obufpos = osamppos - obufstart) >= dz->buflen) { // If next write is beyond buffer end if((exit_status = write_samps(obuf,dz->buflen,dz))<0) // Write buffer(s) return(exit_status); memset((char *)obuf,0,dz->buflen * sizeof(float)); // And set to zero (as buffer is ADDED into) if((overflow = lastwrite - dz->buflen) > 0) { // If there wasc anhy buffer overflow memcpy((char *)obuf,(char *)ovflwbuf,overflow * sizeof(float)); // Bakcopy it into buffer memset((char *)ovflwbuf,0,dz->buflen * sizeof(float)); // and zero overflow buffer } lastwrite -= dz->buflen; obufstart += dz->buflen; // Advance buffer-start count in output samples } k = chunkstart; while(k < chunkend) { obuf[obufpos] = (float)(obuf[obufpos] + ibuf[k]); // Add chunk into outbuf obufpos++; if(++k >= dz->ssampsread) { // If at input buffer end ibufstart += dz->ssampsread; // Update address of buffer start k -= dz->ssampsread; // decrease both counter, and counter-end marker, by length of last buf chunkend -= dz->ssampsread; if((exit_status = read_samps(ibuf,dz)) < 0) // Read more insamps return exit_status; if(dz->ssampsread == 0) { if(k != chunkend) { fprintf(stdout,"WARNING: Ran out of samples in input (2)\n"); fflush(stdout); } done = 1; break; } if(pregain) { for(m=0;mssampsread;m++) ibuf[m] = (float)(ibuf[m] * dz->param[2]); } } lastwrite = max(lastwrite,obufpos); // Note address of MAXIMUM write, withib obuf (or its overflow) } if(done) break; } if(lastwrite > 0) { if((exit_status = write_samps(obuf,lastwrite,dz))<0) // Write last buffer return(exit_status); } if(dz->total_samps_written <= 0) { sprintf(errstr,"No output samples written\n"); return(PROGRAM_ERROR); } return FINISHED; } /******************************************* ESTABLISH_CUTS_ARRAY *******************************************/ int establish_cuts_array(dataptr dz) { int chans = dz->infile->channels; double srate = (double)dz->infile->srate; int twosplices, n, in, on, off, out, lastin = 0, laston = 0, lastoff = 0, lastout = 0, gap; int eliminated = 0; double *realtimes = dz->parray[0]; double *idealtimes = dz->parray[1]; int *realsamps = dz->lparray[0]; int *idealsamps = dz->lparray[1]; int *realcuts = dz->lparray[2]; double mm_in, timescaling; int *lost,lostcnt; if((lost = (int *)malloc(dz->itemcnt * sizeof(int)))==NULL) { sprintf(errstr,"Insufficient memory to lost array\n"); return(MEMORY_ERROR); } twosplices = dz->iparam[RETIME_SPLICE] * 2; mm_in = 60.0 / dz->MMin; if (!flteq(mm_in,dz->param[MM])) { // if output tempo != input tempo timescaling = dz->param[MM]/mm_in; // Convert to output tempo for(n=0;nitemcnt;n++) { // Retaining 1st accent at same time idealtimes[n] -= dz->offset; idealtimes[n] *= timescaling; idealtimes[n] += dz->offset; } } for(n=0;nitemcnt;n++) // Convert to samples idealsamps[n] = (int)(round(idealtimes[n] * srate) * chans); /* FROM THE EVENT TIMING INFO, GENERATE splicestart (in) peakstart (on) peakend (off) and spliceend (out) info */ /* adjusting splice lengths or event lengths (or eliminating events) where events are TOO close. */ /* Idea is to avoid output event overlaps which would create echos in the output */ lostcnt = 0; for(n=0,in=0,on=1,off=2,out=3;nitemcnt;n++,in+=4,on+=4,off+=4,out+=4) { // Get positions of starts and ends of insplice and outsplice for each event realcuts[in] = realsamps[n] - dz->iparam[RETIME_SPLICE]; // in,on,off,out in that order... if(realcuts[in] < 0) realcuts[in] = 0; // First splicestart may be too near file start realcuts[on] = realsamps[n]; if(n >= 1) { gap = realcuts[on] - realcuts[lastoff]; // Distance between start of event-proper and last event-proper (ignoring splices) if(gap < twosplices) { // If 2 events are too close (less than 2 splices) gap = realcuts[on] - (realcuts[laston] + twosplices); // gap between start of previous event + 2 splices (dn-up and current event) if(gap >= 0) { realcuts[lastout] = realcuts[in]; realcuts[lastoff] = realcuts[lastout] - dz->iparam[RETIME_SPLICE]; } else { //Eliminate last event realcuts[lastin] = realcuts[in]; realcuts[laston] = realcuts[on]; eliminated++; in -= 4; on -= 4; off -= 4; out -= 4; lost[lostcnt++] = n; } } } if(dz->brksize[RETIME_WIDTH]) { // Read brkvals relative to time in INFILE read_value_from_brktable(realtimes[n],RETIME_WIDTH,dz); dz->iparam[RETIME_WIDTH] = (int)round(dz->param[RETIME_WIDTH] * MS_TO_SECS * srate) * chans; } realcuts[off] = realsamps[n] + dz->iparam[RETIME_WIDTH]; realcuts[out] = realcuts[off] + dz->iparam[RETIME_SPLICE]; lastin = in; laston = on; lastoff = off; lastout = out; } if(eliminated) { fprintf(stdout,"INFO: With this splicelength, %d events have been eliminated\n", eliminated); fflush(stdout); dz->itemcnt = eliminate_lost_ideal_and_real_events(lost,lostcnt,dz); } return FINISHED; } /*************************** ELIMINATE_LOST_IDEAL_AND_REAL_EVENTS ****************************/ int eliminate_lost_ideal_and_real_events(int *lost,int lostcnt,dataptr dz) { double *realtimes = dz->parray[0]; double *idealtimes = dz->parray[1]; int *realsamps = dz->lparray[0]; int *idealsamps = dz->lparray[1]; int outcnt = dz->itemcnt, n, k, j; for(n = 0;n < lostcnt;n++) { k = lost[n]; if(k+1 < outcnt) { for(j = k+1; j < outcnt; j++) { realtimes[j-1] = realtimes[j]; idealtimes[j-1] = idealtimes[j]; realsamps[j-1] = realsamps[j]; idealsamps[j-1] = idealsamps[j]; } } outcnt--; } return outcnt; } /*************************** REPOSITION_PEAK ****************************/ int reposition_peak(dataptr dz) { int exit_status; float *ibuf = dz->sampbuf[0], *obuf = dz->sampbuf[1]; double srate =(double)dz->infile->srate; int chans = dz->infile->channels, gotstartsig = 0; double maxsamp = 0.0, thissamp; int startsig = 0, newstartsig; int maxpos = 0, n, obufpos, bufstart = 0, shift = 0; switch(dz->mode) { case(12): while(dz->samps_left > 0) { if((exit_status = read_samps(ibuf,dz))<0) return(exit_status); for(n=0;nssampsread;n++) { if(!gotstartsig) { if(ibuf[n] != 0.0) { startsig = n + bufstart; gotstartsig = 1; } } thissamp = fabs(ibuf[n]); if(thissamp > maxsamp) { maxsamp = thissamp; maxpos = bufstart + n; } } bufstart += dz->ssampsread; } if((maxpos = (maxpos/chans) * chans) == 0) { sprintf(errstr,"No Peak found in file.\n"); return(DATA_ERROR); } shift = dz->iparam[0] - maxpos; break; case(13): while(dz->samps_left > 0) { if((exit_status = read_samps(ibuf,dz))<0) return(exit_status); for(n=0;nssampsread;n++) { if(!gotstartsig) { if(ibuf[n] != 0.0) { startsig = n + bufstart; gotstartsig = 1; break; } } } if(gotstartsig) break; bufstart += dz->ssampsread; } maxpos = (dz->iparam[1]/chans) * chans; shift = dz->iparam[0] - maxpos; break; } if(!gotstartsig) { sprintf(errstr,"No signal found in soundfile.\n"); return(DATA_ERROR); } if((newstartsig = startsig + shift) < 0) { sprintf(errstr,"Peak at %lf secs: snd starts at %lf: Cannot move peak to %lf secs\n", (double)(maxpos/chans)/srate,(double)(startsig/chans)/srate,dz->param[0]); return(DATA_ERROR); } else if(shift == 0) { sprintf(errstr,"Peak is already at %lf\n",dz->param[0]); return(DATA_ERROR); } if((sndseekEx(dz->ifd[0],0,0)<0)){ sprintf(errstr,"sndseek() failed\n"); return SYSTEM_ERROR; } reset_filedata_counters(dz); memset((char *)obuf,0,dz->buflen * sizeof(float)); memset((char *)ibuf,0,dz->buflen * sizeof(float)); if(shift > 0) { while(shift > dz->buflen) { if((exit_status = write_samps(obuf,dz->buflen,dz))<0) return(exit_status); shift -= dz->buflen; } obufpos = shift; } else { while(newstartsig >= dz->buflen) { if((exit_status = write_samps(obuf,dz->buflen,dz))<0) return(exit_status); newstartsig -= dz->buflen; } obufpos = newstartsig; if((sndseekEx(dz->ifd[0],startsig,0)<0)){ sprintf(errstr,"sndseek() failed\n"); return SYSTEM_ERROR; } dz->samps_left = dz->insams[0] - startsig; } while(dz->samps_left > 0) { if((exit_status = read_samps(ibuf,dz))<0) return(exit_status); for(n=0;nssampsread;n++) { obuf[obufpos++] = ibuf[n]; if(obufpos >= dz->buflen) { if((exit_status = write_samps(obuf,dz->buflen,dz))<0) return(exit_status); obufpos = 0; } } } if(obufpos > 0) { if((exit_status = write_samps(obuf,obufpos,dz))<0) return(exit_status); } return(FINISHED); } /*************************** REPEAT_BEATS ****************************/ int repeat_beats(dataptr dz) { int exit_status; float *ibuf = dz->sampbuf[0], *obuf = dz->sampbuf[1], *overflw = dz->sampbuf[2], *beatsbuf = dz->sampbuf[3]; int *events; int ibufpos = 0, obufpos, bbufpos, k, j; int eventsegscnt; int beats_start, beats_end, beats_len, beats_step, skip, beatsloc, input_end; memset((char *)obuf,0,dz->buflen * 2 * sizeof(float)); /* COUNT (VALID-LENGTH) SILENCES IN DATA */ if((exit_status = count_events(BEAT_SILMIN,0,&eventsegscnt,dz))<0) { return(exit_status); } events = dz->lparray[0]; fprintf(stdout,"INFO: Found %d events: Locating and cutting event to repeat.\n",eventsegscnt/2); fflush(stdout); /* LOCATE AND MEASURE THE EVENTS TO BE REPEATED */ beats_start = -1; for(k = 0;k < eventsegscnt; k += 2) { /* TEST */ fprintf(stderr,"dz->iparam[BEAT_AT] = %d events[k] = %d events[k+1] = %d\n",dz->iparam[BEAT_AT],events[k],events[k+1]); /* TEST */ if(dz->iparam[BEAT_AT] >= events[k] && dz->iparam[BEAT_AT] <= events[k+1]) { beats_start = events[k]; break; } } if(beats_start < 0) { sprintf(errstr,"Time indicating event position does not lie within a sounding event.\n"); return(DATA_ERROR); } beats_step = dz->iparam[MM] * dz->iparam[BEAT_CNT]; beats_end = beats_start + beats_step; while(k < eventsegscnt) { /* beats_end must be after beats_start so we can resume search at k */ if(beats_end < events[k]) break; k++; } if(ODD(k)) { /* beatend lies within a new event */ j = k - 2; if((j < 0) || (events[j] <= beats_start)) /* if cannot splice at end of previous event - splice at end of this event, making event longer */ beats_end = events[k]; else /* else splice at end of previous event, making event shorter */ beats_end = events[j]; } /* ELSE beatend lies within silence, before a new event, OK to splice there */ if((beats_len = beats_end - beats_start) > dz->buflen) { sprintf(errstr,"Buffers too small to store beats-to-copy. Probably too many events not separated by silence.\n"); /* Should be impossible !! */ return(DATA_ERROR); } if((skip = beats_step - beats_len) < 0) { /* if events have longer duration than step between them, must step back in obuf when writing output */ fprintf(stdout,"WARNING: Repeated events will OVERLAP each other.\n"); fflush(stdout); } /* COPY EVENTS TO REPEAT, TO A BUFFER */ beatsloc = (beats_start/dz->buflen) * dz->buflen; if((sndseekEx(dz->ifd[0],beatsloc,0)<0)){ sprintf(errstr,"sndseek() failed\n"); return SYSTEM_ERROR; } ibufpos = beats_start - beatsloc; if((exit_status = read_samps(ibuf,dz))<0) { sprintf(errstr,"Failed to read data from sndfile.\n"); return(DATA_ERROR); } bbufpos = 0; while(bbufpos < beats_len) { beatsbuf[bbufpos] = ibuf[ibufpos++]; if(ibufpos >= dz->buflen) { if((exit_status = read_samps(ibuf,dz))<0) { sprintf(errstr,"Failed to read data from sndfile.\n"); return(DATA_ERROR); } if(dz->ssampsread == 0) { sprintf(errstr,"Ran off end of file before beats could be cut.\n"); return(DATA_ERROR); } ibufpos = 0; } bbufpos++; } fprintf(stdout,"INFO: Repeating Events.\n"); fflush(stdout); /* COPY START OF ORIG EVENT, BEFORE REPETS START */ if((sndseekEx(dz->ifd[0],0,0)<0)){ sprintf(errstr,"sndseek() failed\n"); return SYSTEM_ERROR; } reset_filedata_counters(dz); dz->ssampsread = 0; //buf_start = 0; input_end = dz->insams[0]; if((exit_status = read_samps(ibuf,dz))<0) { sprintf(errstr,"Failed to read data from sndfile.\n"); return(DATA_ERROR); } while(beats_start >= dz->ssampsread) { if((exit_status = write_samps(ibuf,dz->ssampsread,dz))<0) return(exit_status); beats_start -= dz->ssampsread; beats_end -= dz->ssampsread; input_end -= dz->ssampsread; if((exit_status = read_samps(ibuf,dz))<0) { sprintf(errstr,"Failed to read data from sndfile.\n"); return(DATA_ERROR); } } if(beats_start > 0) memcpy((char *)obuf,(char *)ibuf,beats_start * sizeof(float)); obufpos = beats_start; /* COPY THE REPEATED EVENTS */ for(k = 0;k < dz->iparam[BEAT_REPEATS]; k++) { for(bbufpos = 0;bbufpos < beats_len; bbufpos++) { obuf[obufpos] = (float)(obuf[obufpos] + beatsbuf[bbufpos]); if(++obufpos >= dz->buflen * 2) { if((exit_status = write_samps(obuf,dz->buflen,dz))<0) return(exit_status); memcpy((char *)obuf,(char *)overflw,dz->buflen * sizeof(float)); memset((char *)overflw,0,dz->buflen * sizeof(float)); obufpos -= dz->buflen; } } obufpos += skip; if(obufpos < 0) { sprintf(errstr,"Overlap of events failed in output buffers.\n"); return(DATA_ERROR); } else if(obufpos >= dz->buflen * 2) { while (obufpos >= dz->buflen * 2) { if((exit_status = write_samps(obuf,dz->buflen,dz))<0) return(exit_status); memcpy((char *)obuf,(char *)overflw,dz->buflen * sizeof(float)); memset((char *)overflw,0,dz->buflen * sizeof(float)); obufpos -= dz->buflen; } } } /* COPY REMAINDER OF ORIGINAL EVENT */ ibufpos = beats_start; k = ibufpos; while(k < input_end) { if(ibufpos >= dz->ssampsread) { if((exit_status = read_samps(ibuf,dz))<0) { sprintf(errstr,"Failed to read data from sndfile.\n"); return(DATA_ERROR); } if(dz->ssampsread == 0) { fprintf(stdout,"WARNING: Reached end of infile too soon.\n"); fflush(stdout); break; } ibufpos = 0; } obuf[obufpos] = (float)(obuf[obufpos] + ibuf[ibufpos]); if(++obufpos >= dz->buflen * 2) { if((exit_status = write_samps(obuf,dz->buflen,dz))<0) return(exit_status); memcpy((char *)obuf,(char *)overflw,dz->buflen * sizeof(float)); memset((char *)overflw,0,dz->buflen * sizeof(float)); obufpos -= dz->buflen; } ibufpos++; k++; } if(obufpos > 0) { if((exit_status = write_samps(obuf,obufpos,dz))<0) return(exit_status); } return(FINISHED); } /*************************** GET_INITIAL_SILENCE ****************************/ int get_initial_silence(int *initial_silence,dataptr dz) { int *chunkat = dz->lparray[0], *chunklen = dz->lparray[1]; int step, bakstep = INT_MAX, n, syncchunk, synctime, new_synctime, outlen = 0, silence_change; int chans = dz->infile->channels; double timefact = 1.0, time, srate = (double)dz->infile->srate; if(dz->iparam[RETIME_SYNCAT] == 0) { /* If syncpoint for file is specified as start of file, return */ *initial_silence = chunkat[0]; return (FINISHED); } /* FIND WHICH CHUNK IS NEAREST TO SPECIFIED SYNCTIME */ for(n=0;nitemcnt;n++) { if(chunkat[n] > dz->iparam[RETIME_SYNCAT]) { /* If we're at chunk after synctime */ step = chunkat[n] - dz->iparam[RETIME_SYNCAT]; /* which chunk is nearer to synctime? this chunkstart */ if(n > 0) /* OR (the end of) the previous chunk, if there is one */ bakstep = dz->iparam[RETIME_SYNCAT] - (chunkat[n-1] + chunklen[n-1]); if(bakstep < step) n--; break; } } /* if no chuck has been found AFTER synctime, n gets to dz->itemcnt */ if(n == dz->itemcnt) /* But in this case, last chunk is sync-chunk */ n--; /* so mark last chunk as sync-chunk */ syncchunk = n; if(syncchunk == 0) { /* If sync is at first event ... */ *initial_silence = chunkat[0]; /* initial silence-offset of events does not change */ return(FINISHED); } synctime = chunkat[syncchunk]; /* the original synctime is start of event closest to synctime */ new_synctime = synctime; /* Prevents error-warnings : new_synctime is always set below */ for(n=0;nitemcnt;n++) { if(n==0) outlen = (chunkat[0]/chans) * chans; else { if(chunkat[n-1] < dz->iparam[2] || chunkat[n-1] >= dz->iparam[3]) timefact = 1.0; // If previous chunk lies outside limits, don't time-shrink else { if(dz->brksize[0]) { // Advance by distance between beats * speed-change factor time = (chunkat[n]/chans)/srate; read_value_from_brktable(time,0,dz); } timefact = 1.0/dz->param[0]; } step = (int)round((double)(chunkat[n] - chunkat[n-1]) * timefact); step = (step/chans) * chans; outlen += step; // Position in output advances by the timechanged step if(n == syncchunk) { // If it's the syncchunk that we've just repositioned new_synctime = outlen; // It's new start-time is the new syncing time break; } } } silence_change = synctime - new_synctime; *initial_silence = chunkat[0] + silence_change; if(*initial_silence < 0) { fprintf(stdout,"WARNING: Cannot synchronise accent in output with that in input: syncing at event start.\n"); fflush(stdout); *initial_silence = chunkat[0]; } return(FINISHED); } /*************************** FIND_SOUND_START ****************************/ int find_sound_start(dataptr dz) { int exit_status, gotit = 0; float *ibuf = dz->sampbuf[0]; int n = 0, start_buf = 0; double srate = (double)dz->infile->srate, time; dz->ssampsread = 0; while(dz->samps_left > 0) { start_buf += dz->ssampsread; if((exit_status = read_samps(ibuf,dz)) < 0) return(exit_status); for(n=0;nssampsread;n++) { if(ibuf[n] != 0.0) { gotit = 1; break; } } if(gotit) break; } time = (double)(n + start_buf)/srate; fprintf(dz->fp,"%lf\t%s\n",time,infilename); return FINISHED; } /*************************** READ_RETIME_FNAM ****************************/ int read_retime_fnam(char *filename,dataptr dz) { char nufilename[1000]; char *p = strrchr(filename, '.'); strcpy(nufilename,filename); if(p == NULL) strcat(nufilename,".txt"); else { p++; if(_stricmp(p,"txt")) { sprintf(errstr,"Output textfile (%s) must have a '.txt' extension, or none.\n",filename); return(DATA_ERROR); } } if((dz->fp = fopen(nufilename,"a"))==NULL) { /* permits bulk-processing of files to same outfile */ sprintf(errstr,"Cannot open output file %s\n",nufilename); return(USER_ERROR); } dz->process_type = TO_TEXTFILE; dz->outfiletype = TEXTFILE_OUT; return(FINISHED); } /*************************** FIND_SHORTEST_EVENT ****************************/ int find_shortest_event(dataptr dz) { int exit_status, inchans = dz->infile->channels; int n = 0, evlen, evlenshortest, evlenlongest, eventsegscnt, *events; double srate = (double)dz->infile->srate, longest, shortest; if((exit_status = count_events(0,0,&eventsegscnt,dz))<0) { return(exit_status); } evlenshortest = dz->insams[0] + 1; evlenlongest = -1; events = dz->lparray[0]; for(n=0;nsampbuf[0]; int *silences, *events; int ibufpos = 0, silstart = 0, silend, buf_start, k; int insil = 0, event_at_end = 1; int silsegscnt = 0; fprintf(stdout,"INFO: Counting silences between events.\n"); fflush(stdout); while(dz->samps_left > 0) { if((exit_status = read_samps(ibuf,dz))<0) { sprintf(errstr,"Failed to read data from sndfile.\n"); return(DATA_ERROR); } for(ibufpos=0;ibufposssampsread;ibufpos++) { if(ibuf[ibufpos] == 0.0) insil++; else { if(insil) { if(insil >= dz->iparam[paramno]) { silsegscnt++; } } insil = 0; } } } if(insil) silsegscnt++; if(silsegscnt == 0) { sprintf(errstr,"NO SILENCE-GAPS FOUND IN FILE.\n"); return(DATA_ERROR); } silsegscnt++; /* in case less silences than sounds */ if((sndseekEx(dz->ifd[0],0,0)<0)){ sprintf(errstr,"sndseek() failed\n"); return SYSTEM_ERROR; } reset_filedata_counters(dz); buf_start = 0; /* STORE LOCATION OF STARTS AND ENDS OF SILENCE BLOCKS */ if((dz->lparray[arrayno] = (int *)malloc((silsegscnt * 2) * sizeof(int)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY TO STORE SILENCE LOCATIONS.\n"); return(MEMORY_ERROR); } silsegscnt = 0; insil = 0; silences = dz->lparray[arrayno]; fprintf(stdout,"INFO: Marking silence-separated Events.\n"); fflush(stdout); while(dz->samps_left > 0) { if((exit_status = read_samps(ibuf,dz))<0) { sprintf(errstr,"Failed to read data from sndfile.\n"); return(DATA_ERROR); } for(ibufpos=0;ibufposssampsread;ibufpos++) { if(ibuf[ibufpos] == 0.0) { if(insil == 0) silstart = buf_start + ibufpos; insil++; } else { if(insil) { if(insil >= dz->iparam[paramno]) { silend = buf_start + ibufpos; silences[silsegscnt++] = silstart; silences[silsegscnt++] = silend; } } insil = 0; } } buf_start += dz->ssampsread; } if(insil) { /* if silence at end */ silend = dz->insams[0]; silences[silsegscnt++] = silstart; silences[silsegscnt++] = silend; event_at_end = 0; } events = dz->lparray[arrayno]; /* we write over the original data store */ if(silences[0] == 0) { /* If first silence is at time zero */ for(k=1;kinsams[0]; /* so add the end of file as end of final event, and silsegcnt stays same. --X--X-- thro XX-XX- to XX-XX-XX */ else /* otherwise final silent end, does NOT start a new event, so delete last entry */ silsegscnt -= 2; /* --X--X-- thro XX-XX- to XX-XX: subtract a start-end pair from count */ } else { /* first event at time zero */ for(k=silsegscnt;k>0;k--) /* map gaps between silences forwards into (=) events (eventually using extra address space assigned at end) */ events[k] = silences[k-1]; events[0] = 0; /* Add start of file as start of firsst event. --X--X-- to XX-XX-XX- */ if(event_at_end) { /* if last silence does not end at file end, it starts a final event */ events[silsegscnt+1] = dz->insams[0]; /* so add the end of file as end of final event */ silsegscnt += 2; /* --X--X-- thro XX-XX-XX- to XX-XX-XX-XX add a start-end pair to count */ } else { /* last silence is at end of file, and does not start an event .... --X--X-- thro XX-XX-XX- to XX-XX-XX silsegscnt stays as is, last entry forgotten */ } } *eventsegscnt = silsegscnt; return FINISHED; } /*************************** EQUALISE_EVENT_LEVELS ****************************/ int equalise_event_levels(dataptr dz) { int exit_status, warned = 0, done = 0, accents = dz->iparam[2]; float *ibuf = dz->sampbuf[0]; int *events; int n; int eventsegscnt, abs_samp_cnt, cnt, envcnt, actual_envcnt; double *env, maxval, boostrange, maxboost, boost, equaliser = dz->param[1], pregain = dz->param[3]; int event_start, event_end, bufpos; if((exit_status = count_events(0,0,&eventsegscnt,dz))<0) { return(exit_status); } if((envcnt = eventsegscnt/2) * 2 != eventsegscnt) envcnt++; events = dz->lparray[0]; if((dz->parray[0] = (double *)malloc(envcnt * sizeof(double))) == NULL) { sprintf(errstr,"INSUFFICIENT MEMORY establishing envelope storage.\n"); return(MEMORY_ERROR); } env = dz->parray[0]; if((sndseekEx(dz->ifd[0],0,0)<0)){ sprintf(errstr,"sndseek() failed\n"); return SYSTEM_ERROR; } reset_filedata_counters(dz); dz->ssampsread = 0; cnt = 0; actual_envcnt = 0; abs_samp_cnt = 0; bufpos = 0; event_start = events[cnt++]; event_end = events[cnt++]; if((exit_status = read_samps(ibuf,dz))<0) { sprintf(errstr,"Failed to read data from sndfile.\n"); return(DATA_ERROR); } fprintf(stdout,"INFO: Extracting events envelope\n"); fflush(stdout); while(abs_samp_cnt < dz->insams[0]) { while(abs_samp_cnt < event_start) { if(bufpos >= dz->ssampsread) { if((exit_status = read_samps(ibuf,dz))<0) { sprintf(errstr,"Failed to read data from sndfile.\n"); return(DATA_ERROR); } bufpos = 0; if(dz->ssampsread == 0) { done = 1; break; } } abs_samp_cnt++; bufpos++; } if(done) break; maxval = 0.0; while(abs_samp_cnt < event_end) { if(bufpos >= dz->ssampsread) { if((exit_status = read_samps(ibuf,dz))<0) { sprintf(errstr,"Failed to read data from sndfile.\n"); return(DATA_ERROR); } bufpos = 0; if(dz->ssampsread == 0) { done = 1; break; } } if(fabs(ibuf[bufpos]) > maxval) maxval = fabs(ibuf[bufpos]); abs_samp_cnt++; bufpos++; } if(actual_envcnt >= envcnt) { sprintf(errstr,"Bug : Error in envelope accounting (1)\n"); return(PROGRAM_ERROR); } env[actual_envcnt++] = maxval; if(done || (cnt >= eventsegscnt)) break; event_start = events[cnt++]; event_end = events[cnt++]; } if(envcnt != actual_envcnt) { fprintf(stdout,"WARNING: Error in envelope accounting (2)\n"); fflush(stdout); } maxval = 0; for(n=0;nifd[0],0,0)<0)){ sprintf(errstr,"sndseek() failed\n"); return SYSTEM_ERROR; } reset_filedata_counters(dz); dz->ssampsread = 0; if((exit_status = read_samps(ibuf,dz))<0) { sprintf(errstr,"Failed to read data from sndfile.\n"); return(DATA_ERROR); } cnt = 0; n = 0; abs_samp_cnt = 0; bufpos = 0; event_start = events[cnt++]; event_end = events[cnt++]; fprintf(stdout,"INFO: Adjusting events loudness\n"); fflush(stdout); while(abs_samp_cnt < dz->insams[0]) { while(abs_samp_cnt < event_start) { if(bufpos >= dz->ssampsread) { if((exit_status = write_samps(ibuf,dz->ssampsread,dz))<0) { sprintf(errstr,"Failed to write data to sndfile.\n"); return(DATA_ERROR); } if((exit_status = read_samps(ibuf,dz))<0) { sprintf(errstr,"Failed to read data from sndfile.\n"); return(DATA_ERROR); } bufpos = 0; if(dz->ssampsread == 0) { done = 1; break; } } abs_samp_cnt++; bufpos++; } if(done) break; while(abs_samp_cnt < event_end) { if(n > envcnt) { n--; if(!warned) { fprintf(stdout,"WARNING: Error in envelope accounting (3)\n"); fflush(stdout); warned = 1; } } if(bufpos >= dz->ssampsread) { if((exit_status = write_samps(ibuf,dz->ssampsread,dz))<0) { sprintf(errstr,"Failed to write data to sndfile.\n"); return(DATA_ERROR); } if((exit_status = read_samps(ibuf,dz))<0) { sprintf(errstr,"Failed to read data from sndfile.\n"); return(DATA_ERROR); } bufpos = 0; if(dz->ssampsread == 0) { done = 1; break; } } ibuf[bufpos] = (float)(ibuf[bufpos] * env[n]); abs_samp_cnt++; bufpos++; } if(done) break; n++; if(cnt >= eventsegscnt) { event_start = abs_samp_cnt; event_end = dz->insams[0]; } else { event_start = events[cnt++]; event_end = events[cnt++]; } } if(bufpos > 0) { if((exit_status = write_samps(ibuf,bufpos,dz))<0) { sprintf(errstr,"Failed to write data to sndfile.\n"); return(DATA_ERROR); } } return FINISHED; } /******************************************* RETEMPO_EVENTS *******************************************/ int retempo_events(dataptr dz) { int exit_status, done = 0, chans = dz->infile->channels; float *ibuf = dz->sampbuf[0], *obuf = dz->sampbuf[1], *ovflwbuf = dz->sampbuf[2]; int *chunkat; double srate = (double)dz->infile->srate; double *beat = dz->parray[0]; int ibufstart = 0; // position in infile of start of current input buffer int obufstart = 0; // position in outfile of start of current output buffer int osamppos = 0; // position in outfile int obufpos = 0; // position within current output buffer int lastwrite = 0; // position in current outbuf (or its overflow) of the furthest write int n, m, k, b, chunkstart, chunkend, overflow; int chanoffset; // in multichan case, ensures output chunk positioned at same channel as input chunk int thisbeat = 0; // Current beat position in outfile, in samples int tempo=0, startoffset = 0; double pregain = 0.0; int eventsegscnt = 0; switch(dz->mode) { case(5): tempo = dz->iparam[0]; startoffset = dz->iparam[1]; pregain = dz->param[3]; if((exit_status = count_events(2,0,&eventsegscnt,dz))<0) return(exit_status); break; case(6): startoffset = dz->iparam[0]; pregain = dz->param[2]; if((exit_status = count_events(1,0,&eventsegscnt,dz))<0) return(exit_status); break; } chunkat = dz->lparray[0]; if((sndseekEx(dz->ifd[0],0,0)<0)){ sprintf(errstr,"sndseek() failed\n"); return SYSTEM_ERROR; } reset_filedata_counters(dz); dz->ssampsread = 0; if(dz->itemcnt * 2 < eventsegscnt) { sprintf(errstr,"Found %d events, but only %d out-event-beat-placements specified.\n",eventsegscnt/2,dz->itemcnt); return(DATA_ERROR); } else if(dz->itemcnt * 2 > eventsegscnt) { fprintf(stdout,"WARNING: Found %d events : %d out-event-beat-placements specified.\n",eventsegscnt/2,dz->itemcnt); fflush(stdout); } memset((char *)obuf,0,dz->buflen * sizeof(float)); memset((char *)ovflwbuf,0,dz->buflen * sizeof(float)); for(n=0, b= 0;ntotal_samps_read < chunkat[n]) { // If next chunk to read is beyond current input buffer ibufstart += dz->ssampsread; // Get another buffer of data if((exit_status = read_samps(ibuf,dz)) < 0) return exit_status; for(m=0;mssampsread;m++) ibuf[m] = (float)(ibuf[m] * pregain); if(dz->ssampsread == 0) { fprintf(stdout,"WARNING: Ran out of samples in input (1)\n"); fflush(stdout); done = 1; break; } } if(done) break; chunkstart = chunkat[n] - ibufstart; // get address of chunkstart within this buffer chunkend = chunkat[n+1] - ibufstart; // and relative address of chunk end switch(dz->mode) { case(5): thisbeat = (int)round(beat[b] * (double)tempo) * chans; break; case(6): thisbeat = (int)round(beat[b] * srate) * chans; break; } osamppos = startoffset + thisbeat; osamppos += chanoffset; obufpos = osamppos - obufstart; if(obufpos < 0) { sprintf(errstr,"Events too long (relative to silence) to achieve this tempo change.\n"); return(DATA_ERROR); } while(obufpos >= dz->buflen) { // If next write is beyond buffer end if((exit_status = write_samps(obuf,dz->buflen,dz))<0) // Write buffer(s) return(exit_status); memset((char *)obuf,0,dz->buflen * sizeof(float)); // And set to zero (as buffer is ADDED into) if((overflow = lastwrite - dz->buflen) > 0) { // If there was any buffer overflow memcpy((char *)obuf,(char *)ovflwbuf,overflow * sizeof(float)); // Bakcopy it into buffer memset((char *)ovflwbuf,0,dz->buflen * sizeof(float)); // and zero overflow buffer } lastwrite -= dz->buflen; obufstart += dz->buflen; // Advance buffer-start count in output samples obufpos -= dz->buflen; } k = chunkstart; while(k < chunkend) { if(k >= dz->ssampsread) { // If at input buffer end ibufstart += dz->ssampsread; // Update address of buffer start k -= dz->ssampsread; // decrease both counter, and counter-end marker, by length of last buf chunkend -= dz->ssampsread; if((exit_status = read_samps(ibuf,dz)) < 0) // Read more insamps return exit_status; if(dz->ssampsread == 0) { if(k != chunkend) { fprintf(stdout,"WARNING: Ran out of samples in input (2)\n"); fflush(stdout); } done = 1; break; } for(m=0;mssampsread;m++) ibuf[m] = (float)(ibuf[m] * pregain); } if(obufpos >= dz->buflen) { // If next write is beyond output buffer end if((exit_status = write_samps(obuf,dz->buflen,dz))<0) // Write buffer(s) return(exit_status); memset((char *)obuf,0,dz->buflen * sizeof(float)); // And set to zero (as buffer is ADDED into) if((overflow = lastwrite - dz->buflen) > 0) { // If there was any buffer overflow memcpy((char *)obuf,(char *)ovflwbuf,overflow * sizeof(float)); // Bakcopy it into buffer memset((char *)ovflwbuf,0,dz->buflen * sizeof(float)); // and zero overflow buffer } lastwrite -= dz->buflen; obufstart += dz->buflen; // Advance buffer-start count in output samples obufpos = 0; } obuf[obufpos] = (float)(obuf[obufpos] + ibuf[k]); // Add chunk into outbuf obufpos++; k++; lastwrite = max(lastwrite,obufpos); // Note address of MAXIMUM write, withib obuf (or its overflow) } if(done) break; } if(lastwrite > 0) { if((exit_status = write_samps(obuf,lastwrite,dz))<0) // Write last buffer return(exit_status); } if(dz->total_samps_written <= 0) { sprintf(errstr,"No output samples written\n"); return(PROGRAM_ERROR); } return FINISHED; } /******************************************* MASK_EVENTS *******************************************/ int mask_events(dataptr dz) { int exit_status, done = 0, chans = dz->infile->channels; float *buf = dz->sampbuf[0]; int *chunkat, *mask = dz->lparray[0]; int ibufstart = 0; // position in infile of start of current input buffer int n, m, k, chunkstart, chunkend; int chanoffset; // in multichan case, ensures output chunk positioned at same channel as input chunk int eventsegscnt = 0; if((exit_status = count_events(0,1,&eventsegscnt,dz))<0) return(exit_status); chunkat = dz->lparray[1]; if((sndseekEx(dz->ifd[0],0,0)<0)){ sprintf(errstr,"sndseek() failed\n"); return SYSTEM_ERROR; } reset_filedata_counters(dz); if((exit_status = read_samps(buf,dz)) < 0) return exit_status; m = 0; for(n=0;ntotal_samps_read < chunkat[n]) { // If next chunk to read is beyond current input buffer ibufstart += dz->ssampsread; // Write cuurent buffer if((exit_status = write_samps(buf,dz->ssampsread,dz)) < 0) return exit_status; if((exit_status = read_samps(buf,dz)) < 0) // Get another buffer of data return exit_status; if(dz->ssampsread == 0) { fprintf(stdout,"WARNING: Ran out of samples in input (1)\n"); fflush(stdout); done = 1; break; } } if(done) break; chunkstart = chunkat[n] - ibufstart; // get address of chunkstart within this buffer chunkend = chunkat[n+1] - ibufstart; // and relative address of chunk end k = chunkstart; while(k < chunkend) { if(k >= dz->ssampsread) { // If at input buffer end ibufstart += dz->ssampsread; // Update address of buffer start k -= dz->ssampsread; // decrease both counter, and counter-end marker, by length of last buf chunkend -= dz->ssampsread; // Write data if((exit_status = write_samps(buf,dz->ssampsread,dz)) < 0) return exit_status; if((exit_status = read_samps(buf,dz)) < 0) // Read more insamps return exit_status; if(dz->ssampsread == 0) { if(k != chunkend) { fprintf(stdout,"WARNING: Ran out of samples in input (2)\n"); fflush(stdout); } done = 1; break; } } if(mask[m] == 0) // Zero event, where masked buf[k] = 0.0f; k++; } if(done) break; if(++m >= dz->itemcnt) // Loop around mask m = 0; } while(dz->ssampsread > 0) { // Copy end of file if((exit_status = write_samps(buf,dz->ssampsread,dz)) < 0) return exit_status; if((exit_status = read_samps(buf,dz)) < 0) return exit_status; } return FINISHED; }