/* * Copyright (c) 1983-2013 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 #include #include #include #include #include #include #ifdef unix #define round(x) lround((x)) #else #define round(x) cdp_round((x)) #endif static int do_extra_files(dataptr dz); static void strip_ext(char *temp) ; static int assign_wavetype(dataptr dz); extern char *get_other_filename_x(char *filename,char c); void dz2props(dataptr dz, SFPROPS* props); /*RWD we only do this for SNDFILEs, not analfiles etc */ void dz2props(dataptr dz, SFPROPS* props) { if(dz->outfiletype == SNDFILE_OUT){ switch(dz->true_outfile_stype){ case SAMP_SHORT: props->samptype = SHORT16; break; case SAMP_FLOAT: props->samptype = FLOAT32; break; case SAMP_BYTE: props->samptype = SHORT8; break; case SAMP_LONG: props->samptype = INT_32; break; case SAMP_2424: props->samptype = INT2424; break; case SAMP_2432: props->samptype = INT2432; break; case SAMP_2024: props->samptype = INT2024; break; default: props->samptype = INT_MASKED; break; } props->srate = dz->outfile->srate; props->chans = dz->outchans; //or outfile->channels? props->type = wt_wave; props->format = WAVE_EX; props->chformat = MC_STD; } } /************************ SETUP_PARAM_RANGES_AND_DEFAULTS *********************/ int setup_param_ranges_and_defaults(dataptr dz) { int exit_status; aplptr ap = dz->application; if(ap->total_input_param_cnt>0) { if((exit_status = set_param_ranges(dz->process,dz->mode,dz->nyquist,dz->frametime,dz->infile->arate, dz->infile->srate,dz->wlength,dz->insams[0],dz->infile->channels,dz->wanted, dz->infile->filetype,dz->linecnt,dz->duration,ap))<0) return(exit_status); if((exit_status = INITIALISE_DEFAULT_VALUES(dz->process,dz->mode,dz->infile->channels, dz->nyquist,dz->frametime,dz->insams[0],dz->infile->srate,dz->wanted, dz->linecnt,dz->duration,ap->default_val,dz->infile->filetype,ap))<0) return(exit_status); if(!sloom) put_default_vals_in_all_params(dz); else if(dz->process == BRASSAGE || dz->process == SAUSAGE) put_default_vals_in_all_params(dz); } return(FINISHED); } /************************ HANDLE_FORMANTS *********************/ int handle_formants(int *cmdlinecnt,char ***cmdline,dataptr dz) { int exit_status; aplptr ap = dz->application; if(ap->formant_flag) { if(!sloom) { if(*cmdlinecnt <= 0) { sprintf(errstr,"Insufficient parameters on command line\n"); return(USAGE_ONLY); } } if((exit_status = read_formantband_data_and_setup_formants(cmdline,cmdlinecnt,dz))<0) return(exit_status); } return(FINISHED); } /************************ HANDLE_FORMANT_QUIKSEARCH *********************/ int handle_formant_quiksearch(int *cmdlinecnt,char ***cmdline,dataptr dz) { int exit_status; aplptr ap = dz->application; if(ap->formant_qksrch) { if((exit_status = read_formant_qksrch_flag(cmdline,cmdlinecnt,dz))<0) return(exit_status); } return(FINISHED); } /************************ HANDLE_SPECIAL_DATA *********************/ int handle_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_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); } /************************ READ_FORMANT_QKSRCH_FLAG *********************/ int read_formant_qksrch_flag(char ***cmdline,int *cmdlinecnt,dataptr dz) { if(!sloom) { if(*cmdlinecnt <= 0) return(FINISHED); if(!strcmp((*cmdline)[0],"-i")) { dz->deal_with_chan_data = IGNORE_ACTUAL_CHAN_FRQS; (*cmdline)++; (*cmdlinecnt)--; } } else { ((*cmdline)[0])++; /* Skip numericval marker */ switch((*cmdline)[0][0]) { case('0'): break; /* default value remains set */ case('1'): dz->deal_with_chan_data = IGNORE_ACTUAL_CHAN_FRQS; break; default: sprintf(errstr,"Unknown data at formant_quicksearch position in data sent from TK\n"); return(DATA_ERROR); } (*cmdline)++; (*cmdlinecnt)--; } return(FINISHED); } /************************ HOUSEKEEP_FILES *********************/ int do_housekeep_files(char *filename,dataptr dz) { int exit_status; if(dz->process==HOUSE_BUNDLE) { if(dz->wordstor!=NULL) free_wordstors(dz); dz->all_words = 0; if((exit_status = store_filename(filename,dz))<0) return(exit_status); } if(!sloom) { /* cmdline uses infilename as default outname */ if((exit_status = setup_file_outname_where_ness(filename,dz))<0) return(exit_status); } if(dz->process==HOUSE_COPY) { if(dz->mode!=COPYSF) { if(dz->infile->filetype!=SNDFILE) { sprintf(errstr,"This process only works with soundfiles.\n"); return(DATA_ERROR); } return(FINISHED); } switch(dz->infile->filetype) { case(WORDLIST): dz->process_type = TO_TEXTFILE; dz->outfiletype = TEXTFILE_OUT; break; case(SNDFILE): dz->process_type = EQUAL_SNDFILE; dz->outfiletype = SNDFILE_OUT; break; case(ANALFILE): dz->process_type = EQUAL_ANALFILE; dz->outfiletype = ANALFILE_OUT; break; case(PITCHFILE): dz->process_type = PITCH_TO_PITCH; dz->outfiletype = PITCH_OUT; break; case(TRANSPOSFILE): dz->process_type = PITCH_TO_PITCH; dz->outfiletype=PITCH_OUT; dz->is_transpos=TRUE; break; case(FORMANTFILE): dz->process_type = EQUAL_FORMANTS; dz->outfiletype = FORMANTS_OUT; break; case(ENVFILE): dz->process_type = EQUAL_ENVFILE; dz->outfiletype = ENVFILE_OUT; break; default: sprintf(errstr,"Impossible infile type: assign_copy_constants()\n"); return(PROGRAM_ERROR); } } return(FINISHED); } /************************* CHECK_REPITCH_TYPE **********************/ int check_repitch_type(dataptr dz) { if(dz->infile->filetype==PITCHFILE && dz->mode==TTT) { sprintf(errstr,"Cannot do a tranpos/transpos operation on a pitchfile\n"); return(DATA_ERROR); } else if(dz->infile->filetype==TRANSPOSFILE) { if(dz->mode==PPT) { sprintf(errstr,"Can't do a pitch/pitch operation on a transposition file.\n"); return(DATA_ERROR); } else if(dz->mode==PTP) { sprintf(errstr,"Can't do a pitch/transpos starting with a transposition file.\n"); return(DATA_ERROR); } } return(FINISHED); } /****************************** EXCEPTIONAL_REPITCH_VALIDITY_CHECK *********************************/ int exceptional_repitch_validity_check(int *is_valid,dataptr dz) { switch(dz->mode) { case(PPT): case(PTP): if(dz->could_be_pitch==FALSE) *is_valid = FALSE; /*RWD was == both times */ break; case(TTT): if(dz->could_be_transpos==FALSE) *is_valid = FALSE; break; default: sprintf(errstr,"Unknown case in exceptional_repitch_validity_check()\n"); return(PROGRAM_ERROR); } return(FINISHED); } /****************************** SETUP_BRKTABLESIZES *********************************/ int setup_brktablesizes(infileptr infile_info,dataptr dz) { if(could_be_transpos_and_or_pitch_infiletype(dz->infile->filetype)) { if(dz->input_data_type==BRKFILES_ONLY || dz->input_data_type==ALL_FILES || dz->input_data_type==DB_BRKFILES_ONLY || dz->input_data_type==UNRANGED_BRKFILE_ONLY) { /* is NOT pitch or transpos data */ if(dz->extrabrkno < 0 || dz->brk==NULL) { sprintf(errstr,"Attempt to use brksize before allocated:1: setup_brktablesizes()\n"); return(PROGRAM_ERROR); } dz->brksize[dz->extrabrkno] = infile_info->brksize; } else /* must be a pitch or transpos process */ dz->tempsize = infile_info->brksize; } else if(is_brkfile_infiletype(dz->infile->filetype)) { if(dz->extrabrkno < 0 || dz->brk==NULL) { sprintf(errstr,"Attempt to use brksize before allocated:2: setup_brktablesizes()\n"); return(PROGRAM_ERROR); } dz->brksize[dz->extrabrkno] = infile_info->brksize; } return(FINISHED); } /****************************** STORE_FILENAME *********************************/ int store_filename(char *filename,dataptr dz) { if(dz->wordstor != NULL) { sprintf(errstr,"Cannot store filename: wordstor already allocated.\n"); return(PROGRAM_ERROR); } if((dz->wordstor = (char **)malloc(sizeof(char *)))==NULL) { sprintf(errstr,"Cannot store filename.\n"); return(MEMORY_ERROR); } if((dz->wordstor[0] = (char *)malloc((strlen(filename)+1) * sizeof(char)))==NULL) { sprintf(errstr,"Cannot store filename.\n"); return(MEMORY_ERROR); } if(strcpy(dz->wordstor[0],filename)!= dz->wordstor[0]) { sprintf(errstr,"Failed to copy filename to store.\n"); return(PROGRAM_ERROR); } dz->all_words++; return(FINISHED); } /****************************** STORE_FURTHER_FILENAME *********************************/ int store_further_filename(int n,char *filename,dataptr dz) { if(dz->wordstor == NULL) { if((dz->wordstor = (char **)malloc((n+1) *sizeof(char *)))==NULL) { sprintf(errstr,"Cannot store further filename.\n"); return(MEMORY_ERROR); } } else { if((dz->wordstor = (char **)realloc((dz->wordstor),(n+1) *sizeof(char *)))==NULL) { sprintf(errstr,"Cannot store further filename.\n"); return(MEMORY_ERROR); } } if((dz->wordstor[n] = (char *)malloc((strlen(filename)+1) * sizeof(char)))==NULL) { sprintf(errstr,"Cannot store further filename.\n"); return(MEMORY_ERROR); } if(strcpy(dz->wordstor[n],filename)!=dz->wordstor[n]) { sprintf(errstr,"Failed to copy filename to store.\n"); return(PROGRAM_ERROR); } dz->all_words++; return(FINISHED); } /************************ COUNT_AND_ALLOCATE_FOR_INFILES *********************/ int count_and_allocate_for_infiles(int argc,char *argv[],dataptr dz) { int exit_status; switch(dz->input_data_type) { case(NO_FILE_AT_ALL): /* processes actually do NOT USE the input file */ dz->infilecnt = 0; break; case(SNDFILES_ONLY): case(ANALFILE_ONLY): case(MIXFILES_ONLY): case(SNDLIST_ONLY): case(WORDLIST_ONLY): case(ENVFILES_ONLY): case(BRKFILES_ONLY): case(DB_BRKFILES_ONLY): case(FORMANTFILE_ONLY): case(PITCHFILE_ONLY): case(PITCH_OR_TRANSPOS): case(SND_OR_MIXLIST_ONLY): case(SND_SYNC_OR_MIXLIST_ONLY): case(UNRANGED_BRKFILE_ONLY): dz->infilecnt = 1; break; case(ALL_FILES): /* i.e. processes accept and use any type of file */ switch(dz->process) { case(HOUSE_BUNDLE): if((exit_status = count_bundle_files(argc,argv,dz))<0) return(exit_status); break; case(INFO_DIFF): dz->infilecnt = 2; break; default: dz->infilecnt = 1; break; } break; case(TWO_SNDFILES): case(SNDFILE_AND_ENVFILE): case(SNDFILE_AND_BRKFILE): case(SNDFILE_AND_DB_BRKFILE): case(TWO_ANALFILES): case(ANAL_AND_FORMANTS): case(PITCH_AND_FORMANTS): case(PITCH_AND_PITCH): case(PITCH_AND_TRANSPOS): case(TRANSPOS_AND_TRANSPOS): case(ANAL_WITH_PITCHDATA): case(ANAL_WITH_TRANSPOS): case(SNDFILE_AND_UNRANGED_BRKFILE): dz->infilecnt = 2; break; case(THREE_ANALFILES): //TW NEW case(PFE): dz->infilecnt = 3; break; case(ONE_OR_MANY_SNDFILES): //TW NEW case(ONE_OR_MORE_SNDSYS): if((exit_status = count_infiles(argc,argv,dz))<0) return(exit_status); break; case(MANY_SNDFILES): case(MANY_ANALFILES): case(ANY_NUMBER_OF_ANY_FILES): if((exit_status = count_infiles(argc,argv,dz))<0) return(exit_status); if(dz->infilecnt < 2) { sprintf(errstr,"Insufficient input files for this process\n"); return(USAGE_ONLY); } break; default: sprintf(errstr,"Unknown input_data_type: count_and_allocate_for_infiles()\n"); return(PROGRAM_ERROR); } return allocate_filespace(dz); } /************************ COUNT_INFILES *********************/ int count_infiles(int argc,char *argv[],dataptr dz) { int files_to_skip = 1, diff; int other_unflagged_items; //TW NEW CODE OK if(dz->outfiletype != NO_OUTPUTFILE) files_to_skip++; argc -= files_to_skip; argv += files_to_skip; if(argc<0) { sprintf(errstr,"Insufficient cmdline parameters.\n"); return(USAGE_ONLY); } other_unflagged_items = 0; while(argc > 0) { /* count all unflagged items after outfile */ if(*(argv[0])!='-' || !isalpha(argv[0][1])) other_unflagged_items++; /* options, variants, formants, and formant_qiksrch are flagged */ argc--; argv++; } if(dz->application->special_data) /* subtract any special data item : not flagged */ other_unflagged_items--; if((diff = other_unflagged_items - dz->application->param_cnt)<0) { sprintf(errstr,"Insufficient cmdline parameters.\n"); return(USAGE_ONLY); } dz->infilecnt = diff + 1; /* i.e. plus first infile */ return(FINISHED); } /************************ COUNT_BUNDLE_FILES *********************/ int count_bundle_files(int argc,char *argv[],dataptr dz) { /*int files_to_skip = 1;*/ int orig_argc = argc; if(argc<1) { sprintf(errstr,"Insufficient cmdline parameters.\n"); return(USAGE_ONLY); } while(argc > 0) { if(*(argv[0])=='-') { sprintf(errstr,"Invalid flag or parameter on cmdline.\n"); return(DATA_ERROR); } argc--; argv++; } dz->infilecnt = orig_argc - 1; /* i.e. minus outfile */ return(FINISHED); } /******************************* PUT_DEFAULT_VALS_IN_ALL_PARAMS **************************/ void put_default_vals_in_all_params(dataptr dz) { aplptr ap = dz->application; int n; for(n=0;ntotal_input_param_cnt;n++) { dz->param[n] = ap->default_val[n]; if(dz->is_int[n]) dz->iparam[n] = round(dz->param[n]); } } /************************ MAKE_INITIAL_CMDLINE_CHECK *********************/ int make_initial_cmdline_check(int *argc,char **argv[]) { int exit_status; if(*argc<4) { /* INITIAL CHECK OF CMDLINE OR PRE-CMDLINE DATA */ /*RWD May 2005*/ fprintf(stdout,"CDP Release 7.1 2016\n"); if((exit_status = usage(*argc,*argv))<0) return(exit_status); } (*argv)++; (*argc)--; return(FINISHED); } /************************ TEST_APPLICATION_VALIDITY *********************/ int test_application_validity(infileptr infile_info,int process,int *valid,dataptr dz) { int exit_status; int is_valid = valid_application(process,valid); if((dz->process==REPITCH || process==REPITCHB) && is_a_text_input_filetype(infile_info->filetype) && is_valid) { if((exit_status = exceptional_repitch_validity_check(&is_valid,dz))<0) return(exit_status); } if(!is_valid) { /* GUI: invalid applics WON'T BE DISPLAYED on menus */ sprintf(errstr,"Application doesn't work with this type of infile.\n"); return(USAGE_ONLY); /* validity can be checked from dz->valid bitflags */ } return(FINISHED); } /************************ PARSE_INFILE_AND_HONE_TYPE *********************/ int parse_infile_and_hone_type(char *filename,int *valid,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 TK data."); return(MEMORY_ERROR); } if((exit_status = cdparse(filename,infile_info))<0) return(exit_status); if((exit_status = establish_application_validities(infile_info->filetype,infile_info->channels,valid))<0) return(exit_status); if((exit_status = test_application_validity(infile_info,dz->process,valid,dz))<0) return(exit_status); if((exit_status = copy_parse_info_to_main_structure(infile_info,dz))<0) return(exit_status); free(infile_info); } /* KNOWING POSSIBLE TYPE OF INFILE, AND TYPE NEEDED BY PROCESS, HONE TYPE */ if(is_a_text_input_filetype(dz->infile->filetype)) { if((exit_status = redefine_textfile_types(dz))<0) return(exit_status); } switch(dz->process) { case(HOUSE_COPY): case(HOUSE_CHANS): case(HOUSE_EXTRACT): case(HOUSE_SPEC): case(HOUSE_BUNDLE): case(HOUSE_SORT): case(HOUSE_DISK): case(HOUSE_GATE): if((exit_status = do_housekeep_files(filename,dz))<0) return(exit_status); break; case(INFO_TIMELIST): case(MIXDUMMY): case(INFO_LOUDLIST): case(MIX_ON_GRID): case(MIX_AT_STEP): case(TOPNTAIL_CLICKS): case(MAKE_VFILT): dz->all_words = 0; if((exit_status = store_filename(filename,dz))<0) return(exit_status); break; case(MOD_LOUDNESS): if(dz->mode==LOUDNESS_LOUDEST || dz->mode==LOUDNESS_EQUALISE) { dz->all_words = 0; if((exit_status = store_filename(filename,dz))<0) return(exit_status); } break; case(RANDCUTS): case(RANDCHUNKS): if(!sloom) { dz->all_words = 0; if((exit_status = store_filename(filename,dz))<0) return(exit_status); } break; case(REPITCH): case(REPITCHB): if(!is_a_text_input_filetype(dz->infile->filetype)) { if((exit_status = check_repitch_type(dz))<0) return(exit_status); } break; } if(anal_infiles) { if((exit_status = set_chunklens_and_establish_windowbufs(dz))<0) return(exit_status); } return(FINISHED); } /************************* SET_CHUNKLENS_AND_ESTABLISH_WINDOWBUFS **********************/ int set_chunklens_and_establish_windowbufs(dataptr dz) { int exit_status; int n; switch(dz->infile->filetype) { case(ANALFILE): dz->clength = dz->wanted / 2; dz->chwidth = dz->nyquist/(double)(dz->clength-1); dz->halfchwidth = dz->chwidth/2.0; if((exit_status = float_array(&dz->amp,dz->clength))<0) return(exit_status); if((exit_status = float_array(&dz->freq,dz->clength))<0) return(exit_status); break; case(PITCHFILE): case(TRANSPOSFILE): dz->wanted = dz->infile->origchans; dz->clength = dz->infile->origchans / 2; dz->chwidth = dz->nyquist/(double)(dz->clength-1); dz->halfchwidth = dz->chwidth/2.0; if((exit_status = float_array(&dz->amp,dz->clength))<0) return(exit_status); if((exit_status = float_array(&dz->freq,dz->clength))<0) return(exit_status); break; case(FORMANTFILE): dz->wanted = dz->infile->specenvcnt; break; } for(n=0;nextra_bufcnt;n++) { if((exit_status = float_array(&(dz->windowbuf[n]),dz->wanted))<0) return(exit_status); } return(FINISHED); } /******************************** SETUP_FILE_OUTNAME_WHERE_NESS ************************ * * CMDLINE uses infilename as basis of outfilename(s) * TK uses the default outfilename instead */ int setup_file_outname_where_ness(char *filename,dataptr dz) { int exit_status; switch(dz->process) { case(RANDCUTS): case(RANDCHUNKS): case(HOUSE_CHANS): case(EDIT_CUTMANY): case(MANY_ZCUTS): case(SYLLABS): case(SHUDDER): case(JOIN_SEQ): case(JOIN_SEQDYN): case(SYNTH_WAVE): case(SYNTH_NOISE): case(SYNTH_SIL): case(CLICK): case(ENV_CREATE): case(ENV_EXTRACT): case(MULTI_SYN): case(FORMANTS): case(FMNTSEE): case(P_SEE): case(P_HEAR): case(PVOC_ANAL): case(PVOC_SYNTH): case(P_SYNTH): case(P_VOWELS): case(ANALENV): case(LEVEL): case(ENVSYN): dz->all_words = 0; if((exit_status = store_filename(filename,dz))<0) return(exit_status); break; case(RRRR_EXTEND): if(dz->mode == 2) { dz->all_words = 0; if((exit_status = store_filename(filename,dz))<0) return(exit_status); } break; case(HOUSE_COPY): if(dz->mode == DUPL) { dz->all_words = 0; if((exit_status = store_filename(filename,dz))<0) return(exit_status); } break; case(HOUSE_EXTRACT): if(dz->mode==HOUSE_CUTGATE) { dz->all_words = 0; if((exit_status = store_filename(filename,dz))<0) return(exit_status); } break; case(HOUSE_SORT): if((exit_status = store_further_filename(dz->all_words,filename,dz))<0) return(exit_status); break; case(HF_PERM1): case(HF_PERM2): if(dz->mode == HFP_SNDSOUT) { dz->all_words = 0; if((exit_status = store_filename(filename,dz))<0) return(exit_status); } break; case(SYNTH_SPEC): case(TWIXT): case(HOUSE_GATE): case(TIME_GRID): case(FORMSEE): case(MAKE): dz->all_words = 0; if((exit_status = store_filename(filename,dz))<0) return(exit_status); break; case(MAKE_VFILT): if((exit_status = store_further_filename(dz->all_words,filename,dz))<0) return(exit_status); break; case(MOD_LOUDNESS): if(dz->mode==LOUDNESS_LOUDEST || dz->mode==LOUDNESS_EQUALISE) { if((exit_status = store_further_filename(dz->all_words,filename,dz))<0) return(exit_status); } break; case(MOD_RADICAL): //TW Store outputfile name, for use with tempfile mechanism to avoic sndseek problems if(dz->mode==MOD_LOBIT || dz->mode==MOD_LOBIT2) { dz->all_words = 0; if((exit_status = store_filename(filename,dz))<0) return(exit_status); } break; case(BRASSAGE): case(SAUSAGE): //TW Store outputfile name, for use with tempfile mechanism to avoic sndseek problems dz->all_words = 0; if((exit_status = store_filename(filename,dz))<0) return(exit_status); break; } return(FINISHED); } /****************************** SET_SPECIAL_PROCESS_SIZES *********************************/ int set_special_process_sizes(dataptr dz) { int maxsize, minsize; int n; switch(dz->process) { case(SUM): /* progs where outsize is maximum of insizes */ case(MAX): maxsize = dz->insams[0]; for(n=0;ninfilecnt;n++) maxsize = max(dz->insams[n],maxsize); dz->wlength = maxsize/dz->wanted; break; case(CROSS): /* progs where outsize is minimum of insizes */ case(MEAN): case(VOCODE): case(LEAF): minsize = dz->insams[0]; for(n=1;ninfilecnt;n++) minsize = min(dz->insams[n],minsize); dz->wlength = minsize/dz->wanted; break; } return(FINISHED); } /************************ COPY_PARSE_INFO_TO_MAIN_STRUCTURE *********************/ int copy_parse_info_to_main_structure(infileptr infile_info,dataptr dz) { if(dz->infilecnt < 1 || dz->insams==NULL) { sprintf(errstr,"Attempt to use file arrays before allocated: copy_parse_info_to_main_structure()\n"); return(PROGRAM_ERROR); } dz->infile->filetype = infile_info->filetype; /*dz->infilesize[0] = infile_info->infilesize;*/ dz->insams[0] = infile_info->insams; dz->infile->srate = infile_info->srate; dz->infile->channels = infile_info->channels; dz->infile->stype = infile_info->stype; dz->infile->origstype = infile_info->origstype; dz->infile->origrate = infile_info->origrate; dz->infile->Mlen = infile_info->Mlen; dz->infile->Dfac = infile_info->Dfac; dz->infile->origchans = infile_info->origchans; dz->infile->specenvcnt = infile_info->specenvcnt; dz->specenvcnt = infile_info->specenvcnt; dz->wanted = infile_info->wanted; dz->wlength = infile_info->wlength; dz->out_chans = infile_info->out_chans; dz->descriptor_samps = infile_info->descriptor_samps; /*RWD ???? */ dz->is_transpos = infile_info->is_transpos; dz->could_be_transpos = infile_info->could_be_transpos; dz->could_be_pitch = infile_info->could_be_pitch; dz->different_srates = infile_info->different_srates; dz->duplicate_snds = infile_info->duplicate_snds; dz->numsize = infile_info->numsize; dz->linecnt = infile_info->linecnt; dz->all_words = infile_info->all_words; dz->infile->arate = infile_info->arate; dz->frametime = infile_info->frametime; dz->infile->window_size = infile_info->window_size; dz->nyquist = infile_info->nyquist; dz->duration = infile_info->duration; dz->minbrk = infile_info->minbrk; dz->maxbrk = infile_info->maxbrk; dz->minnum = infile_info->minnum; dz->maxnum = infile_info->maxnum; if(dz->process==MIXDUMMY || dz->process==HOUSE_BUNDLE || dz->process==HOUSE_SORT || dz->process==MIX_ON_GRID || dz->process==ADDTOMIX || dz->process==MIX_AT_STEP || dz->process==BATCH_EXPAND || dz->process==MIX_MODEL) return FINISHED; return setup_brktablesizes(infile_info,dz); } /************************ ALLOCATE_FILESPACE *********************/ int allocate_filespace(dataptr dz) { int n; int zerofiles = 0; /* BELOW CHANGED FROM < 0: JAN 2000 */ if(dz->infilecnt <= 0) { zerofiles = 1; dz->infilecnt = 1; /* always want to allocate pointers */ } /* if((dz->infilesize = (int *)malloc(dz->infilecnt * sizeof(int)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY for infilesize array.\n"); return(MEMORY_ERROR); } */ if((dz->insams = (int *)malloc(dz->infilecnt * sizeof(int)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY for infile-sampsize array.\n"); return(MEMORY_ERROR); } if((dz->ifd = (int *)malloc(dz->infilecnt * sizeof(int)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY for infile poniters array.\n"); return(MEMORY_ERROR); } for(n=0;ninfilecnt;n++) { dz->ifd[n] = -1; dz->insams[n] = 0L; /*dz->infilesize[n] = 0L;*/ } if(zerofiles) dz->infilecnt = 0; return(FINISHED); } /************************ HANDLE_EXTRA_INFILES *********************/ int handle_extra_infiles(char ***cmdline,int *cmdlinecnt,dataptr dz) { /* OPEN ANY FURTHER INFILES, CHECK COMPATIBILITY, STORE DATA AND INFO */ int exit_status; int n, k = 0; char *filename; if(dz->process == ADDTOMIX || dz->process == BATCH_EXPAND || dz->process == MIX_MODEL) k = dz->all_words - 1; if(dz->infilecnt > 1) { for(n=1;ninfilecnt;n++) { filename = (*cmdline)[0]; switch(dz->process) { case(ADDTOMIX): case(BATCH_EXPAND): case(MIX_MODEL): if((exit_status = store_further_filename(n+k,filename,dz))<0) return(exit_status); if((exit_status = handle_other_infile(n,filename,dz))<0) return(exit_status); break; case(MIX_ON_GRID): case(MIX_AT_STEP): if((exit_status = store_further_filename(n,filename,dz))<0) return(exit_status); break; case(HOUSE_BUNDLE): case(MIXDUMMY): if((exit_status = store_further_filename(n,filename,dz))<0) return(exit_status); break; case(INFO_TIMELIST): case(INFO_LOUDLIST): if((exit_status = store_further_filename(n,filename,dz))<0) return(exit_status); if((exit_status = handle_other_infile(n,filename,dz))<0) return(exit_status); break; case(MOD_LOUDNESS): if(dz->mode==LOUDNESS_LOUDEST || dz->mode==LOUDNESS_EQUALISE) { if((exit_status = store_further_filename(n,filename,dz))<0) return(exit_status); } if((exit_status = handle_other_infile(n,filename,dz))<0) return(exit_status); break; default: if((exit_status = handle_other_infile(n,filename,dz))<0) return(exit_status); break; } (*cmdline)++; (*cmdlinecnt)--; } if((exit_status = set_special_process_sizes(dz))<0) return(exit_status); } if(dz->process == BATCH_EXPAND || dz->process == MIX_MODEL) dz->itemcnt = dz->infilecnt - 1; return(FINISHED); } /************************ HANDLE_OUTFILE *********************/ /* RWD I have a theory: this could be split into two functions where indicated: * handle_outfile_name() * and handle_outfile() * and then handle_outfile() can be relocated at the end of param_preprocess(), * wher it belongs; and all these tests can be eliminated! */ /************************ HANDLE_OUTFILE *********************/ int handle_outfile(int *cmdlinecnt,char ***cmdline,int is_launched,dataptr dz) { int exit_status; char *filename = NULL; char *filename2; int n; int look_for_float_flag = 0; if(dz->outfiletype==NO_OUTPUTFILE) { /* Look at all those "NO_OUTPUTFILE" processes which actually give a sound output (!!! it's a int story!) */ /* Some of these processes have NO output file name in the cmdline situation but DO have an outfilename in SLOOM */ /* as all SLOOM processes have an outfilename */ if(sloom) { if (dz->process == RANDCUTS || dz->process == RANDCHUNKS || dz->process == HOUSE_CHANS || (dz->process == HOUSE_EXTRACT && dz->mode == HOUSE_CUTGATE)) { look_for_float_flag = 1; } } /* Some of these processes DO have an output file name in the cmdline situation (and, as always, in SLOOM) */ if (dz->process == MIXINBETWEEN || dz->process == CYCINBETWEEN || dz->process == SYNTH_SPEC || dz->process == HOUSE_GATE || (dz->process == HF_PERM1 && dz->mode == HFP_SNDSOUT) || (dz->process == HF_PERM2 && dz->mode == HFP_SNDSOUT)) { look_for_float_flag = 1; } } else if(dz->outfiletype == SNDFILE_OUT) { /* Look at all processes with a SOUNDFILE output: all such processes have an output file name in the cmdline */ look_for_float_flag = 1; } if(look_for_float_flag) { /* For all these cases, check if the output file is flagged as float, and strip any flag */ if(!sloom && (*cmdlinecnt<=0)) { sprintf(errstr,"Insufficient cmdline parameters.\n"); return(USAGE_ONLY); } filename = (*cmdline)[0]; if(filename[0]=='-' && filename[1]=='f') { dz->floatsam_output = 1; dz->true_outfile_stype = SAMP_FLOAT; filename+= 2; } } if(dz->outfiletype==NO_OUTPUTFILE) { /* These processes generate an output which is NOT a soundfile, and hence have an output file name on the cmd line */ if(dz->process == MAKE_VFILT || (dz->process == MOD_PITCH && (dz->mode == MOD_TRANSPOS_INFO || dz->mode == MOD_TRANSPOS_SEMIT_INFO))) { if(!sloom && (*cmdlinecnt<=0)) { sprintf(errstr,"Insufficient cmdline parameters.\n"); return(USAGE_ONLY); } filename = (*cmdline)[0]; if(filename[0]=='-' && filename[1]=='f') { sprintf(errstr,"-f flag used incorrectly on command line (output is not a sound file).\n"); return(USAGE_ONLY); } } } if (!sloom) { if(dz->process == MAKE) { if((filename = (*cmdline)[0]) == NULL) { return(USAGE_ONLY); } } if(dz->process == MAKE || dz->process == FORMSEE) { if((exit_status = setup_file_outname_where_ness(filename,dz))<0) { print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(exit_status); } } if (dz->process == MAKE) { if((filename = get_other_filename_x(filename,'1')) == NULL) { sprintf(errstr,"Insufficient memory to store modified outfilename.\n"); return MEMORY_ERROR; } } } /* in all these cases we wish to remember the name of the output filename from the cmdline */ if(dz->process == ANALENV || dz->process == BRASSAGE || dz->process == CLICK || dz->process == EDIT_CUTMANY || dz->process == MANY_ZCUTS || dz->process == ENV_CREATE || dz->process == ENV_EXTRACT || dz->process == FMNTSEE || dz->process == FORMANTS || ((dz->process == FORMSEE) && sloom) || dz->process == HF_PERM1 || dz->process == HF_PERM2 || dz->process == JOIN_SEQ || dz->process == JOIN_SEQDYN || dz->process == LEVEL || ((dz->process == MAKE) && sloom) || dz->process == P_HEAR || dz->process == P_SEE || dz->process == P_SYNTH || dz->process == P_VOWELS || dz->process == PVOC_ANAL || dz->process == PVOC_SYNTH || dz->process == SAUSAGE || dz->process == SHUDDER || dz->process == SYLLABS || dz->process == SYNTH_NOISE || dz->process == SYNTH_WAVE || dz->process == MULTI_SYN || dz->process == SYNTH_SIL || dz->process == TIME_GRID || dz->process == TWIXT || dz->process == ENVSYN || (dz->process == RRRR_EXTEND && dz->mode == 2) || (dz->process == MOD_RADICAL && (dz->mode == MOD_LOBIT || dz->mode == MOD_LOBIT2))) { /* all processes with a SOUNDFILE output have already been checked, so any outfiles found here must be NON soundfiles */ if(filename == NULL) { if(!sloom && (*cmdlinecnt<=0)) { sprintf(errstr,"Insufficient cmdline parameters.\n"); return(USAGE_ONLY); } filename = (*cmdline)[0]; if(filename[0]=='-' && filename[1]=='f') { sprintf(errstr,"-f flag used incorrectly on command line (output is not a sound file).\n"); return(USAGE_ONLY); } } if((exit_status = setup_file_outname_where_ness(filename,dz))<0) { print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(exit_status); } } if (!sloom) { if (dz->process==SHUDDER || dz->process == BRASSAGE || dz->process == SAUSAGE || dz->process == FORMSEE) { if((filename = get_other_filename_x(filename,'1')) == NULL) { sprintf(errstr,"Insufficient memory to store modified outfilename.\n"); return MEMORY_ERROR; } if((n = sndopenEx(dz->wordstor[0],0,CDP_OPEN_RDONLY)) >= 0) { sprintf(errstr,"Output file %s already exists",dz->wordstor[0]); if(sndcloseEx(n) < 0) strcat(errstr,": Cannot close the file."); strcat(errstr,"\n"); return(GOAL_FAILED); } } } if(sloom) { /* ALL sound loom processes have an output filename: so get it, if not already found */ if(filename == NULL) filename = (*cmdline)[0]; /* These cases, on the soundloom , have ANALFILE & PITCHFILE output, and need to save or use outfilename as basis for additional outfile names */ if(dz->process==PITCH || dz->process==TRACK) { dz->all_words = 0; if((exit_status = store_filename(filename,dz))<0) return(exit_status); if((exit_status = do_extra_files(dz)) != FINISHED) return(exit_status); } if(dz->process==HOUSE_COPY && dz->mode == DUPL) { if((exit_status = setup_file_outname_where_ness(filename,dz))<0) { print_messages_and_close_sndfiles(exit_status,is_launched,dz); return(exit_status); } } } if(dz->outfiletype==NO_OUTPUTFILE) { /* in these cases also, we wish to remember the name of the output file name on the cmdline. */ /* In non-soundloom case, some programs use the input filename to generate the outfilename, */ /* whereas Sound Loom ALWAYS has an outfilename which can be used. */ if(sloom) { if(dz->process == MIXINBETWEEN || dz->process == CYCINBETWEEN) { if((exit_status = read_new_filename(filename,dz))<0) return(exit_status); /* read outfile as if it were special data */ } else if(dz->process != HF_PERM1 && dz->process != HF_PERM2) { if((exit_status = setup_file_outname_where_ness(filename,dz))<0) return(exit_status); } } else { if(dz->process == MIXINBETWEEN || dz->process == CYCINBETWEEN) { if(file_has_invalid_startchar(filename)) { sprintf(errstr,"Filename %s has invalid start character(s)\n",filename); return(DATA_ERROR); } if((exit_status = read_new_filename(filename,dz))<0) return(exit_status); /* read outfile as if it were special data */ } if(dz->process == SYNTH_SPEC || dz->process == MAKE_VFILT) { if(file_has_invalid_startchar(filename)) { sprintf(errstr,"Filename %s has invalid start character(s)\n",filename); return(DATA_ERROR); } if((exit_status = setup_file_outname_where_ness(filename,dz))<0) return(exit_status); } } } else { /* all other processes have an outputfile but not a sound outputfile (these were checked previously) */ /* so, if a filename does not yet exist, get it from the cmdline */ /* (all sloom outfilenames have already been read) */ if(filename == NULL) { if(*cmdlinecnt<=0) { sprintf(errstr,"Insufficient cmdline parameters.\n"); return(USAGE_ONLY); } filename = (*cmdline)[0]; if(filename[0]=='-' && filename[1]=='f') { sprintf(errstr,"-f flag used incorrectly on command line (output is not a sound file).\n"); return(USAGE_ONLY); } 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); } } } //TW mechanics to setup sloom (and cmdline) compatible temp file: + normal usage SHUDDER if(sloom) { if (dz->process==SHUDDER || dz->process == BRASSAGE || dz->process == SAUSAGE || dz->process == FORMSEE || dz->process == MAKE) get_other_filename(filename,'1'); } // DEC 2009 FIX // if(dz->process==HOUSE_BUNDLE || dz->process==INFO_DIFF /* || (sloom && dz->process==PITCH) */ if(dz->process==HOUSE_BUNDLE || dz->process==HOUSE_DUMP || (dz->process == MOD_LOUDNESS && dz->mode == LOUDNESS_EQUALISE)) { if((exit_status = store_further_filename(dz->all_words,filename,dz))<0) return(exit_status); } if(!sloom) { if(dz->process == EDIT_CUTMANY || dz->process == SYLLABS || dz->process == MANY_ZCUTS) { n = strlen(filename); if ((filename2 = (char *)malloc(n+2))==NULL) { sprintf(errstr,"Insufficient memory to store output filename.\n"); return(MEMORY_ERROR); } strcpy(filename2,filename); insert_new_number_at_filename_end(filename2,1,0); filename = filename2; } } /* EXCEPT IN THOSE CASES WHERE outfile creation has to be delayed, create the outfile NOW */ if(!( dz->process == SYNTH_WAVE || (!sloom && dz->process == HOUSE_COPY && dz->mode == DUPL) || dz->process == MULTI_SYN || dz->process == SYNTH_NOISE || dz->process == SYNTH_SPEC || dz->process == SYNTH_SIL || dz->process == HOUSE_SPEC || dz->process == HOUSE_CHANS || dz->process == MIXINTERL || (dz->process >= SIMPLE_TEX && dz->process <= TMOTIFSIN) || (dz->process == MOD_SPACE && dz->mode == MOD_PAN) || (dz->process == MOD_REVECHO && dz->mode == MOD_STADIUM) || (dz->process == BRASSAGE && dz->mode == GRS_REVERB) || (dz->process == BRASSAGE && dz->mode == GRS_BRASSAGE) || (dz->process == BRASSAGE && dz->mode == GRS_FULL_MONTY) || dz->process == SAUSAGE || (dz->process == MIXMAX && dz->mode == MIX_LEVEL_ONLY) || dz->process == AUTOMIX || dz->process == MIX || dz->process == MIXTWO || dz->process == ENV_EXTRACT || dz->process == ENV_CREATE || dz->process == ENV_BRKTOENV || dz->process == ENV_DBBRKTOENV || dz->process == FORMANTS || dz->process == FMNTSEE || dz->process == FORMSEE || dz->process == P_SEE || dz->process == P_HEAR || dz->process == PVOC_ANAL || dz->process == PVOC_SYNTH || dz->process == P_SYNTH || dz->process == P_VOWELS || dz->process == ANALENV || dz->process == LEVEL || (dz->process == HF_PERM1 && (dz->mode == HFP_SNDOUT || dz->mode == HFP_SNDSOUT)) || (dz->process == HF_PERM2 && (dz->mode == HFP_SNDOUT || dz->mode == HFP_SNDSOUT)) || dz->process == DEL_PERM || dz->process == P_GEN || dz->process == CLICK || dz->process == MIXINBETWEEN || dz->process == CYCINBETWEEN || dz->process == SCALED_PAN || (dz->process == HOUSE_EXTRACT && dz->mode == HOUSE_CUTGATE) || dz->process == HOUSE_GATE || dz->process == HOUSE_SORT //NEW DEC 2010 || dz->process == TIME_GRID /* and those cases where there really is no outfile */ || (( dz->process == ENV_WARPING || dz->process == ENV_REPLOTTING || dz->process == ENV_RESHAPING) && dz->mode == ENV_PEAKCNT) || (dz->process == MOD_LOUDNESS && dz->mode == LOUDNESS_LOUDEST) || (dz->process == MOD_PITCH && (dz->mode == MOD_TRANSPOS_SEMIT_INFO || dz->mode == MOD_TRANSPOS_INFO)) || (dz->process == TSTRETCH && dz->mode == TSTR_LENGTH) || dz->process == GRAIN_ASSESS || dz->process == GRAIN_COUNT || dz->process == DISTORT_CYCLECNT || dz->process == FIND_PANPOS || dz->process == INFO_PROPS || dz->process == INFO_SFLEN || (dz->process == INFO_TIMELIST && !sloom) || dz->process == INFO_TIMESUM || dz->process == INFO_TIMEDIFF || dz->process == INFO_SAMPTOTIME || dz->process == INFO_TIMETOSAMP || dz->process == INFO_MAXSAMP || dz->process == INFO_MAXSAMP2 || dz->process == INFO_LOUDCHAN || dz->process == INFO_FINDHOLE || dz->process == INFO_DIFF || dz->process == INFO_CDIFF || dz->process == INFO_MUSUNITS || dz->process == WINDOWCNT || dz->process == CHANNEL || dz->process == FREQUENCY || dz->process == P_INFO || dz->process == P_ZEROS || dz->process == ZCROSS_RATIO || dz->process == MAKE_VFILT || dz->process == RANDCHUNKS || dz->process == RANDCUTS || dz->process == ENVSYN )) { if((exit_status = create_sized_outfile(filename,dz))<0) return(exit_status); } /* if an outfile name has been read, copy it to dz->outfilename and advance along the cmdline */ if(filename != NULL) { /*RWD.7.98 - mainly for SYNTH */ //TW also for MIX programs ETC so may as well do it universally strcpy(dz->outfilename,filename); (*cmdline)++; (*cmdlinecnt)--; } return(FINISHED); } /****************************** PRINT_MESSAGES_AND_CLOSE_SNDFILES ******************************/ int print_messages_and_close_sndfiles(int exit_status,int is_launched,dataptr dz) { int n; /* OUTPUT ERROR MESSAGES */ switch(exit_status) { case(FINISHED): break; case(PROGRAM_ERROR): fprintf(stdout,"ERROR: INTERNAL ERROR: (Bug?)\n"); splice_multiline_string(errstr,"ERROR:"); break; case(SYSTEM_ERROR): fprintf(stdout,"ERROR: SYSTEM ERROR\n"); splice_multiline_string(errstr,"ERROR:"); break; case(MEMORY_ERROR): fprintf(stdout,"ERROR: MEMORY ERROR\n"); splice_multiline_string(errstr,"ERROR:"); break; case(USER_ERROR): if(sloom) { fprintf(stdout,"ERROR: DATA OR RANGE ERROR\n"); splice_multiline_string(errstr,"ERROR:"); } else { fprintf(stdout,"ERROR: INCORRECT USE\n"); splice_multiline_string(errstr,"ERROR:"); } break; case(DATA_ERROR): fprintf(stdout,"ERROR: INVALID DATA\n"); splice_multiline_string(errstr,"ERROR:"); break; case(GOAL_FAILED): fprintf(stdout,"ERROR: CANNOT ACHIEVE TASK:\n"); splice_multiline_string(errstr,"ERROR:"); break; case(USAGE_ONLY): if(sloom) { fprintf(stdout,"ERROR: PROGRAM ERROR: usage messages should not be called.\n"); fflush(stdout); } else fprintf(stdout,"%s",errstr); break; case(TK_USAGE): if(!sloom) fprintf(stdout,"ERROR: PROGRAM ERROR: TK usage messages should not be called.\n"); else exit_status = FINISHED; break; default: fprintf(stdout,"ERROR: INTERNAL ERROR: (Bug?)\n"); fprintf(stdout,"ERROR: Unknown case in print_messages_and_close_sndfiles)\n"); exit_status = PROGRAM_ERROR; break; } if(dz != NULL) { /* CLOSE (& DELETE) SNDFILES */ if(dz->ofd >= 0 && (exit_status!=FINISHED || !is_launched) && sndunlink(dz->ofd) < 0) fprintf(stdout, "ERROR: Can't set output soundfile for deletion.\n"); if((dz->ofd >= 0) && dz->needpeaks){ if(sndputpeaks(dz->ofd,dz->outchans,dz->outpeaks)) { fprintf(stdout,"WARNING: failed to write PEAK data\n"); fflush(stdout); } } // if(dz->ofd >= 0 && sndcloseEx(dz->ofd) < 0) { // fprintf(stdout, "WARNING: Can't close output sf-soundfile : %s\n",sferrstr()); // fflush(stdout); // } if(dz->ofd >= 0) { if(sndcloseEx(dz->ofd) < 0) { fprintf(stdout, "WARNING: Can't close output sf-soundfile : %s\n",sferrstr()); fflush(stdout); } } if(dz->other_file >= 0 && exit_status!=FINISHED && sndunlink(dz->other_file) < 0) { fprintf(stdout, "ERROR: Can't set secondary soundfile for deletion.\n"); fflush(stdout); } if((dz->other_file >= 0) && dz->needotherpeaks){ if(sndputpeaks(dz->other_file,dz->otheroutchans,dz->otherpeaks)) { fprintf(stdout,"WARNING: failed to write PEAK data\n"); fflush(stdout); } } if(dz->other_file >= 0 && sndcloseEx(dz->other_file) < 0) fprintf(stdout, "WARNING: Can't close secondary soundfile.\n"); if(dz->ifd != NULL && dz->infilecnt >= 0) { for(n=0;ninfilecnt;n++) { /* ALL OTHER CASES */ if(dz->ifd[n] >= 0 && sndcloseEx(dz->ifd[n]) < 0) fprintf(stdout, "WARNING: Can't close input sf-soundfile %d.\n",n+1); } } } // sffinish(); if(sloom) fprintf(stdout,"END:"); else #ifdef unix fprintf(stdout,"\n\n"); #else fprintf(stdout,"\n"); #endif fflush(stdout); if(exit_status != FINISHED) { return(FAILED); } return(SUCCEEDED); } /****************************** DO_EXTRA_FILES *********************************/ int do_extra_files(dataptr dz) { char temp[200]; int endword = dz->all_words - 1; strcpy(temp,dz->wordstor[endword]); //TW REVISION Dec 2002 // p = temp + strlen(temp) - 1; // sprintf(p,"1"); insert_new_number_at_filename_end(temp,1,1); switch(dz->mode) { case(PICH_TO_BIN): //TW CORRECTED Dec 2002 if((dz->other_file = sndcreat_formatted(temp,dz->insams[0]/dz->wanted,SAMP_FLOAT, 1,dz->infile->srate,CDP_CREATE_NORMAL)) < 0) { sprintf(errstr,"Cannot open output pitch file %s\n",temp); return(DATA_ERROR); } break; case(PICH_TO_BRK): strip_ext(temp); if((dz->fp = fopen(temp,"w"))==NULL) { sprintf(errstr,"Cannot open file %s for output.\n",temp); return(DATA_ERROR); } break; default: sprintf(errstr,"Unknown mode.\n"); return(DATA_ERROR); } return(FINISHED); } /******************************* CREATE_SIZED_OUTFILE **************************/ int create_sized_outfile(char *filename,dataptr dz) { int maxsize, minsize; int exit_status, n, orig_chans = 1; int stype = SAMP_FLOAT; switch(dz->process) { case(PVOC_ANAL): dz->true_outfile_stype = stype; dz->outfilesize = -1; break; case(PVOC_SYNTH): case(PVOC_EXTRACT): if(dz->floatsam_output != 1) stype = dz->outfile->stype; //NOV 2005: proposed RWD fix, changes above line to PVOC // stype = dz->outfile->stype; dz->true_outfile_stype = stype; dz->outfilesize = -1; break; case(SYNTH_SPEC): dz->outfilesize = -1; break; default: switch(dz->process_type) { case(EQUAL_SNDFILE): /*RWD May 2005 */ #ifdef NOTDEF if(dz->floatsam_output != 1) stype = SAMP_SHORT; else stype = dz->infile->stype; dz->true_outfile_stype = stype; #else if(dz->infile->stype < 0) /* if no infile, default to shorts */ dz->infile->stype = SAMP_SHORT; if(dz->floatsam_output != 1) stype = dz->infile->stype; /* keep infile stype for outfile */ else stype = SAMP_FLOAT; /* or force floats */ dz->true_outfile_stype = stype; #endif dz->outfilesize = dz->insams[0]; /* RWD watch this... */ break; case(EQUAL_ENVFILE): case(EQUAL_ANALFILE): case(PITCH_TO_PITCH): stype = dz->infile->stype; dz->true_outfile_stype = stype; dz->outfilesize = dz->insams[0]; /* RWD watch this... */ break; case(CREATE_ENVFILE): dz->infile->channels = 1; /* fallthro */ case(EXTRACT_ENVFILE): case(UNEQUAL_ENVFILE): case(BIG_ANALFILE): case(PITCH_TO_BIGPITCH): dz->true_outfile_stype = stype; dz->outfilesize = -1; break; case(ANAL_TO_FORMANTS): case(EQUAL_FORMANTS): dz->true_outfile_stype = stype; /* DO FORMANT FILES HAVE TO HAVE ONE CHANNEL ????? YES */ dz->outfilesize = -1; // COMMENT dz->infile->channels (MUST BE/IS) set to correct outval, then reset, external to this call break; case(PITCH_TO_ANAL): dz->true_outfile_stype = stype; dz->outfilesize = -1; // This reset of infile->channels is for the benefit of MAKE & MAKE2: reset is below orig_chans = dz->infile->channels; dz->infile->channels = dz->infile->origchans; break; case(UNEQUAL_SNDFILE): /*RWD May 2005 this code back to front! */ #ifdef NOTDEF if(dz->floatsam_output!=1) stype = SAMP_SHORT; else stype = dz->infile->stype; dz->true_outfile_stype = stype; dz->outfilesize = -1; #else if(dz->infile->stype < 0) /* if no infile, default to shorts */ dz->infile->stype = SAMP_SHORT; if(dz->floatsam_output!=1) stype = dz->infile->stype; /* outfile has infile sample type */ else stype = SAMP_FLOAT; dz->true_outfile_stype = stype; /* or floats if asked for */ dz->outfilesize = -1; #endif break; case(PSEUDOSNDFILE): dz->true_outfile_stype = SAMP_SHORT; dz->outfilesize = -1; // COMMENT dz->infile->channels (MUST BE/IS) set to correct outval, then reset, external to this call break; case(MAX_ANALFILE): maxsize = dz->insams[0]; for(n=1;ninfilecnt;n++) maxsize = max(maxsize,dz->insams[n]); dz->outfilesize = maxsize; break; case(MIN_ANALFILE): minsize = dz->insams[0]; for(n=1;ninfilecnt;n++) minsize = min(minsize,dz->insams[n]); dz->outfilesize = minsize; break; case(PITCH_TO_PSEUDOSND): dz->outfilesize = dz->wlength; /* RWD watch this... */ // COMMENT dz->infile->channels (MUST BE/IS) set to correct outval, then reset, external to this call break; case(TO_TEXTFILE): if(file_has_reserved_extension(filename)) { sprintf(errstr,"Cannot open a textfile (%s) with a reserved extension.\n",filename); return(USER_ERROR); } if((dz->fp = fopen(filename,"w"))==NULL) { sprintf(errstr,"Cannot open output file %s\n",filename); return(USER_ERROR); } return FINISHED; default: sprintf(errstr,"Invalid process_type %d: create_sized_outfile()\n",dz->process_type); return(PROGRAM_ERROR); } break; } /* RWD April 2005 write WAVE_EX if possible! */ /*TODO: read channel format from input, somewhere into dz*/ if(dz->outfiletype== SNDFILE_OUT && (dz->infile->channels > 2 || stype > SAMP_FLOAT)){ SFPROPS props, inprops; dz2props(dz,&props); props.chans = dz->infile->channels; props.srate = dz->infile->srate; if(dz->ifd && dz->ifd[0] >=0) { if(snd_headread(dz->ifd[0], &inprops)) /* snd_getchanformat not working ...*/ props.chformat = inprops.chformat; } #ifdef _DEBUG printf("DEBUG: writing WAVE_EX outfile\n"); #endif dz->ofd = sndcreat_ex(filename,dz->outfilesize,&props,SFILE_CDP,CDP_CREATE_NORMAL); if(dz->ofd < 0){ sprintf(errstr,"Cannot open output file %s\n", filename); return(DATA_ERROR); } } else{ if((dz->ofd = sndcreat_formatted(filename,dz->outfilesize,stype, dz->infile->channels,dz->infile->srate,CDP_CREATE_NORMAL)) < 0) { sprintf(errstr,"Cannot open output file %s\n", filename); return(DATA_ERROR); } } dz->outchans = dz->infile->channels; if((exit_status = establish_peak_status(dz))<0) return(exit_status); switch(dz->process_type) { case(PITCH_TO_ANAL): /* RESET, See above */ dz->infile->channels = orig_chans; break; } switch(dz->process) { case(PVOC_ANAL): case(PVOC_SYNTH): case(PVOC_EXTRACT): dz->outfilesize = sndsizeEx(dz->ofd); dz->total_samps_written = 0; break; default: switch(dz->process_type) { case(UNEQUAL_SNDFILE): case(UNEQUAL_ENVFILE): case(CREATE_ENVFILE): case(EXTRACT_ENVFILE): case(BIG_ANALFILE): case(ANAL_TO_FORMANTS): case(PITCH_TO_ANAL): case(PITCH_TO_BIGPITCH): case(PSEUDOSNDFILE): case(PITCH_TO_PSEUDOSND): // TW THIS doesn't achieve anythuing, I think. dz->outfilesize = sndsizeEx(dz->ofd); break; } break; } if(dz->process_type != TO_TEXTFILE) { if((exit_status = assign_wavetype(dz)) < 0) return exit_status; } return(FINISHED); } /* RWD.7.98 sfsys98 version, for SYNTH */ //TW REDUNDANT ?? //int create_sized_outfile_formatted(const char *filename,int srate,int channels, int stype,dataptr dz) //{ // if((dz->ofd = sndcreat_formatted(filename,-1,stype, // channels,srate,CDP_CREATE_NORMAL)) < 0) { // sprintf(errstr,"Cannot open output file %s: %s\n", filename,rsferrstr); // return SYSTEM_ERROR; // } // //RWD.10.98 // dz->true_outfile_stype = stype; // dz->total_samps_written = 0L; // return FINISHED; //} //TW CREATE TEMPFILE NAME (for bad sndseek cases: and other spcial cases) void get_other_filename(char *filename,char c) { char *p, *end; p = filename + strlen(filename); end = p; while(p > filename) { p--; if(*p == '.') break; /* return start of final name extension */ else if(*p == '/' || *p == '\\') { p = end; /* directory path component found before finding filename extension */ break; /* go to end of name */ } } if(p == filename) p = end; /* no finalname extension found, go to end of name */ p--; /* insert '1' at name end */ *p = c; return; } void insert_new_number_at_filename_end(char *filename,int num,int overwrite_last_char) /* FUNCTIONS ASSUMES ENOUGH SPACE IS ALLOCATED !! */ { char *p; char ext[64]; p = filename + strlen(filename) - 1; while(p > filename) { if(*p == '/' || *p == '\\' || *p == ':') { p = filename; break; } if(*p == '.') { strcpy(ext,p); if(overwrite_last_char) p--; sprintf(p,"%d",num); strcat(filename,ext); return; } p--; } if(p == filename) { p += strlen(filename); if(overwrite_last_char) p--; sprintf(p,"%d",num); } } void insert_new_chars_at_filename_end(char *filename,char *str) /* FUNCTIONS ASSUMES ENOUGH SPACE IS ALLOCATED !! */ { char *p; char ext[64]; p = filename + strlen(filename) - 1; while(p > filename) { if(*p == '/' || *p == '\\' || *p == ':') { p = filename; break; } if(*p == '.') { strcpy(ext,p); *p = ENDOFSTR; strcat(filename,str); strcat(filename,ext); return; } p--; } if(p == filename) strcat(filename,str); } void replace_filename_extension(char *filename,char *ext) /* FUNCTIONS ASSUMES ENOUGH SPACE IS ALLOCATED !! */ { char *p; p = filename + strlen(filename) - 1; while(p > filename) { if(*p == '/' || *p == '\\' || *p == ':') { p = filename; break; } if(*p == '.') { *p = ENDOFSTR; strcat(filename,ext); return; } p--; } if(p == filename) strcat(filename,ext); } void delete_filename_lastchar(char *filename) { char *p, *q = filename + strlen(filename); p = q - 1; while(p > filename) { if(*p == '/' || *p == '\\' || *p == ':') { p = filename; break; } if(*p == '.') { while(p <= q) { *(p - 1) = *p; p++; } return; } p--; } if(p == filename) { p = q - 1; *p = ENDOFSTR; } } int reset_peak_finder(dataptr dz) { int j; if(dz->needpeaks && (dz->ofd >= 0)){ if(sndputpeaks(dz->ofd,dz->outchans,dz->outpeaks)) { fprintf(stdout,"WARNING: failed to write PEAK data\n"); fflush(stdout); } } if(dz->outpeaks==NULL) { dz->outpeaks = (CHPEAK *) malloc(sizeof(CHPEAK) * dz->outchans); if(dz->outpeaks==NULL) return MEMORY_ERROR; dz->outpeakpos = (unsigned int *) malloc(sizeof(unsigned int) * dz->outchans); if(dz->outpeakpos==NULL) return MEMORY_ERROR; } //JAN 2007 moved for(j = 0;joutchans;j++) dz->outpeakpos[j] = 0; for(j = 0;joutchans;j++) { dz->outpeaks[j].value = 0.0; dz->outpeaks[j].position = 0; } dz->needpeaks = 1; return FINISHED; } int establish_peak_status(dataptr dz) { int i; if(dz->outpeaks!=NULL) return FINISHED; if(dz->process < FOOT_OF_GROUCHO_PROCESSES) { switch(dz->process) { //sound or pseudosnd output case(FMNTSEE): case(FORMSEE): case(PVOC_SYNTH): case(LEVEL): case(P_SEE): // 2010 case(MTON): case(FLUTTER): case(SETHARES): case(MCHSHRED): case(MCHZIG): case(MCHSTEREO): break; default: //spectral output dz->needpeaks = 0; return FINISHED; } } //spectral output switch(dz->process) { case(P_SYNTH): case(P_INSERT): case(P_PTOSIL): case(P_NTOSIL): case(P_SINSERT): case(P_GEN): case(P_INTERP): case(MAKE2): case(ANALENV): case(FREEZE2): case(PVOC_ANAL): case(MAKE): case(ENVSYN): // 2010 case(ANALJOIN): case(ONEFORM_GET): case(ONEFORM_PUT): case(ONEFORM_COMBINE): case(SPEC_REMOVE): case(SPECROSS): case(SPECLEAN): case(SPECTRACT): case(BRKTOPI): case(SPECSLICE): case(TUNEVARY): /* RWD Nov 21, may need to add other progs here... */ /* RWD 2023 here we go...*/ case(SPECANAL): case(FRACSPEC): case(FTURANAL): case(SPECRAND): case(SPECSQZ): case(SPECMORPH): case(SPECULATE): case(SPECTUNE): case(SPECFOLD): case(CALTRAIN): dz->needpeaks = 0; return FINISHED; //processes which generate text data. // 2010 switch(dz->process) { case(PTOBRK): case(RMRESP): case(MULTIMIX): dz->needpeaks = 0; return FINISHED; } //processes which write to intermediate temporary files: needpeaks set to 1 later. case(SYNTH_SPEC): case(MIXTWO): case(SHUDDER): dz->needpeaks = 0; return FINISHED; //processes which are normalised via an intermediate temporary files: needpeaks set to 1 later. case(MOD_RADICAL): if(dz->mode == MOD_LOBIT || dz->mode == MOD_LOBIT2) { dz->needpeaks = 0; return FINISHED; } break; //processes with several outputs, where peak is reset to zero before each file is written-to case(HOUSE_GATE): case(TIME_GRID): dz->needpeaks = 0; return FINISHED; case(TWIXT): if(dz->mode == TRUE_EDIT) { dz->needpeaks = 0; return FINISHED; } break; //processes needing no maxsamp data case(HOUSE_DUMP): dz->needpeaks = 0; return FINISHED; } dz->needpeaks = 1; dz->outpeaks = (CHPEAK *) malloc(sizeof(CHPEAK) * dz->outchans); if(dz->outpeaks==NULL) return MEMORY_ERROR; dz->outpeakpos = (unsigned int *) malloc(sizeof(unsigned int) * dz->outchans); if(dz->outpeakpos==NULL) return MEMORY_ERROR; for(i=0;i < dz->outchans;i++){ dz->outpeaks[i].value = 0.0f; dz->outpeaks[i].position = 0; dz->outpeakpos[i] = 0; } return FINISHED; } void strip_ext(char *temp) { char *p = temp + strlen(temp) - 1; while(p > temp) { if(*p == '.') { *p = ENDOFSTR; return; } p--; } } int assign_wavetype(dataptr dz) { //wavetype wtype; int isenv = 1; int dummy = 1; switch(dz->process) { case(PVOC_ANAL): //wtype = wt_analysis; break; case(PVOC_SYNTH): case(PVOC_EXTRACT): case(SYNTH_SPEC): //wtype = wt_wave; break; case(REPITCH): //if(dz->mode == PTP) // wtype = wt_transposition; //else // wtype = wt_pitch; break; default: switch(dz->process_type) { case(EQUAL_SNDFILE): case(UNEQUAL_SNDFILE): case(PSEUDOSNDFILE): case(PITCH_TO_PSEUDOSND): // wtype = wt_wave; break; case(EQUAL_ENVFILE): case(CREATE_ENVFILE): case(EXTRACT_ENVFILE): case(UNEQUAL_ENVFILE): if(sndputprop(dz->ofd,"is an envelope",(char *) &isenv,sizeof(int)) < 0){ sprintf(errstr,"Failure to write envelope property. assign_wavetype()\n"); return(PROGRAM_ERROR); } // wtype = wt_binenv; break; case(EQUAL_ANALFILE): case(BIG_ANALFILE): case(MAX_ANALFILE): case(MIN_ANALFILE): case(PITCH_TO_ANAL): // wtype = wt_analysis; break; case(PITCH_TO_PITCH): case(PITCH_TO_BIGPITCH): if((dz->process == REPITCH && dz->mode != PTP) || dz->is_transpos) { if(sndputprop(dz->ofd,"is a transpos file", (char *)&dummy, sizeof(int)) < 0) { sprintf(errstr,"Failure to write transposition property. assign_wavetype()\n"); return(PROGRAM_ERROR); } // wtype = wt_transposition; } else if((dz->process == P_APPROX || dz->process == P_INVERT || dz->process == P_QUANTISE || dz->process == P_RANDOMISE || dz->process == P_SMOOTH || dz->process == P_VIBRATO) && (dz->mode == 1)) { if(sndputprop(dz->ofd,"is a transpos file", (char *)&dummy, sizeof(int)) < 0) { sprintf(errstr,"Failure to write transposition property. assign_wavetype()\n"); return(PROGRAM_ERROR); } } else if((dz->process == P_EXAG) && (dz->mode == 1 || dz->mode == 3 || dz->mode == 5)) { if(sndputprop(dz->ofd,"is a transpos file", (char *)&dummy, sizeof(int)) < 0) { sprintf(errstr,"Failure to write transposition property. assign_wavetype()\n"); return(PROGRAM_ERROR); } } else { if(sndputprop(dz->ofd,"is a pitch file", (char *)&dummy, sizeof(int)) < 0) { sprintf(errstr,"Failure to write pitch property. assign_wavetype()\n"); return(PROGRAM_ERROR); } // wtype = wt_pitch; } break; case(ANAL_TO_FORMANTS): case(EQUAL_FORMANTS): if(sndputprop(dz->ofd,"is a formant file", (char *)&dummy, sizeof(int)) < 0) { sprintf(errstr,"Failure to write formant property. assign_wavetype(): %s\n",sferrstr()); return(PROGRAM_ERROR); } // wtype = wt_formant; break; default: sprintf(errstr,"Unknown process_type while assigning output wavetype.\n"); return PROGRAM_ERROR; } } // if(sndputprop(dz->ofd,"type",(char *)&wtype,sizeof(wavetype)) < 0){ // sprintf(errstr,"Failure to write wavetype factor. assign_wavetype()\n"); // return(PROGRAM_ERROR); // } return FINISHED; } //TW MODIFY INPUT OUTFILENAME, to deal with intermediate temp files, in comdline case. //char *get_other_filename_x(char *filename,char c) //{ // char *p, *nufilename; // int len = strlen(filename); // char temp[] = "_cdptemp"; // len += 9; // if(((char *)nufilename = (char *)malloc(len)) == NULL) // return NULL; // strcpy(nufilename,filename); // strcat(nufilename,temp); // p = nufilename + len; // *p = ENDOFSTR; // p--; // *p = c; // return nufilename; //} char *get_other_filename_x(char *filename,char c) { char *p, *nufilename, ext[24]; int len = strlen(filename); char temp[] = "_cdptemp"; len += 12; if((nufilename = (char *)malloc(len)) == NULL) return NULL; strcpy(nufilename,filename); ext[0] = c; ext[1] = ENDOFSTR; p = nufilename; while(*p != ENDOFSTR) { if(*p == '.') { strcat(ext,p); *p = ENDOFSTR; break; } p++; } strcat(nufilename,temp); strcat(nufilename,ext); return nufilename; } // FEB 2010 TW void insert_separator_on_sndfile_name(char *filename,int cnt) /* FUNCTIONS ASSUMES ENOUGH SPACE IS ALLOCATED !! */ { int n; char ext[8]; char *p = filename, *z = filename; // z will be place to insert separator p += strlen(filename); p -= 4; // p set to start of any 4char extension [p]..a1 OR a1[p].wav OR a1.[p]aiff OR [p]aaa1 OR aaa[p]aaa1 OR aaaaaa1[p].wav OR aaaaaa1.[p]aiff // if p <= start of name ... // insert separator at end [p]..a1 --> a1_ if(p > filename) { // if p is at start of 4 letter extension ... // insert separator at [p] a1[p].wav --> a1_.wav aaaaaa1[p].wav --> aaaaaa1_.wav if(!strcmp(p,".wav") || !strcmp(p,".aif")) { strcpy(ext,p); z = p; } else { p--;// p set to start of any 5char extension aa[p]aaaa1 OR aaaaaa1[p].aiff // if p less than start of name ... // insert separator at end [p]..aaa1 --> aaa1_ if(p > filename) { // if p is at start of 5 letter extension ... // insert separator at [p] a1[p].aiff --> a1_.aiff aaaaaa1[p].aiff --> aaaaaa1_.aiff if(!strcmp(p,".aiff")) { strcpy(ext,p); z = p; // else, no extension match // insert separator at end of name aa[p]aaaa1 --> aaaaaa1_ } } } } if(z == filename) { for(n=0;n