/* * 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 #define round(x) lround((x)) #define SPACECNT (32) static int try_header(int chans,double inverse_sr,dataptr dz); static void make_time_display(char temp[],char timestr[],double secs); static int get_and_set_float_maxmina(float *flbuf,dataptr dz); static int get_and_set_float_maxmin(float *buf,int chans, double inverse_sr,dataptr dz); static int compare_sndfile_properties(char temp[],dataptr dz); static int compare_analfile_properties(dataptr dz); static int read_both_the_files(int samesize,dataptr dz); static int read_samps_for_cdiff(dataptr dz); static void compare_samps(char temp[],int *badmatch,int *limitcnt,double threshold,dataptr dz); static void anal_file_time(char temp[],int n,dataptr dz); static void snd_file_time(char temp[],int n,dataptr dz); static int sfdiff_process(char temp[],int samesize,dataptr dz); static int compare_infile_sizes(int *same_size,dataptr dz); static int do_sfdiff(char temp[],dataptr dz); static int prntprops(SFPROPS *prop, dataptr dz); static int get_float_maxmin(float *buf,int chans, double inverse_sr,dataptr dz); /*RWD 6:2001 */ static int getpeakdata(int ifd, float *peakval,SFPROPS *props); static int do_zcross_ratio(dataptr dz); /****************************** DO_SNDINFO ******************************/ int do_sndinfo(dataptr dz) { int exit_status; float *flbuf; float *buf; double sr = (double)dz->infile->srate; int chans = dz->infile->channels, maxpos; double other_sr = (double)dz->otherfile->srate; int other_chans = dz->otherfile->channels; double inverse_sr = 1.0, secs; int thisspace, m; float *chanmax; int ftype = dz->infile->filetype; int is_a_text_file = FALSE; int n, k, j; fileptr fptr = dz->infile; char timestr[64]; char temp[200]; int holesize = 0, holesamp = 0; int maxholesize = 0; int maxholesamp = 0; double maxholelen, maxholetime; double threshold, level = 0.0; int orig_ifd0; SFPROPS props = {0}; infileptr ifp; double maxamp, maxloc; int maxrep; int getmax = 0, getmaxinfo = 0; if(sr > 0.0) inverse_sr = 1.0/sr; switch(dz->process) { case(INFO_TIMESUM): secs = 0.0; for(n=0;ninfilecnt;n++) { secs += (double)(dz->insams[n]/chans) * inverse_sr; secs -= dz->param[TIMESUM_SPLEN] * MS_TO_SECS; } sprintf(errstr,"TOTAL TIME "); make_time_display(temp,timestr,secs); strcat(errstr,timestr); strcat(errstr,"\n"); print_outmessage(errstr); break; case(INFO_TIMELIST): if((ifp = (infileptr)malloc(sizeof(struct filedata)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to store data on file.\n"); return(MEMORY_ERROR); } secs = (double)(dz->insams[0]/chans) * inverse_sr; sprintf(errstr,"%s",dz->wordstor[0]); thisspace = SPACECNT - strlen(dz->wordstor[0]); thisspace = max(thisspace,2); for(m=0;mfp)<0) { sprintf(errstr,"Cannot output data to file\n"); return(SYSTEM_ERROR); } } for(n=1;ninfilecnt;n++) { if((exit_status = readhead(ifp,dz->ifd[n],dz->wordstor[n],&maxamp,&maxloc,&maxrep,getmax,getmaxinfo))<0) { sprintf(errstr,"Cannot re-read file %d header.\n",n+1); return(PROGRAM_ERROR); } copy_to_fileptr(ifp,dz->infile); secs = (double)(dz->insams[n]/dz->infile->channels)/(double)dz->infile->srate; sprintf(errstr,"%s",dz->wordstor[n]); thisspace = SPACECNT - strlen(dz->wordstor[n]); thisspace = max(thisspace,2); for(m=0;mfp)<0) { sprintf(errstr,"Cannot output data to file\n"); return(SYSTEM_ERROR); } } } break; case(INFO_LOUDLIST): orig_ifd0 = dz->ifd[0]; for(m=0;minfilecnt;m++) { float fmaxamp = 0.0f; /*RWD 6:2001 */ int gotpeak = 0; /*RWD 6:2001 try to read PEAK chunk too! */ if(getpeakdata(dz->ifd[m],&fmaxamp,&props)){ level = fmaxamp; gotpeak = 1; } else { /* RWD impossible to report int values without lot of hoohaa */ /* just look as if its floatsam file, for now */ if(sndgetprop(dz->ifd[m],"fmaxamp",(char *)&fmaxamp,sizeof(float)) < 0 ) { dz->samps_left = dz->insams[m]; dz->ifd[0] = dz->ifd[m]; while(dz->samps_left) { if((exit_status = read_samps(dz->bigbuf,dz))<0) return(exit_status); for(n=0;nssampsread;n++) fmaxamp = (float)max(fmaxamp,fabs(dz->bigbuf[n])); } } } if(!gotpeak) /*RWD 6:2001 */ level = (double)fmaxamp/F_MAXSAMP; sprintf(errstr,"%s\t",dz->wordstor[m]); sprintf(timestr,"%lf\n",level); strcat(errstr,timestr); print_outmessage(errstr); if(fputs(timestr,dz->fp)<0) { sprintf(errstr,"Cannot output data to file\n"); return(SYSTEM_ERROR); } dz->ifd[0] = orig_ifd0; } break; case(INFO_TIMEDIFF): sprintf(errstr,"DIFFERENCE IS "); secs = (dz->insams[0]/chans) * inverse_sr; secs -= (dz->insams[1]/other_chans)/other_sr; secs = fabs(secs); make_time_display(temp,timestr,secs); strcat(errstr,timestr); strcat(errstr,"\n"); print_outmessage(errstr); break; case(INFO_SFLEN): switch(dz->infile->filetype) { case(SNDFILE): print_outmessage("A soundfile\n"); sprintf(errstr,"DURATION: "); secs = (double)(dz->insams[0]/dz->infile->channels) * inverse_sr; make_time_display(temp,timestr,secs); strcat(errstr,timestr); sprintf(temp,"samples %d\n",dz->insams[0]); strcat(errstr,temp); break; case(ANALFILE): print_outmessage("An analysis data file\n"); sprintf(errstr,"DURATION: "); secs = (double)dz->wlength * dz->frametime; make_time_display(temp,timestr,secs); strcat(errstr,timestr); sprintf(temp,"windows %d : floats %d\n",dz->wlength,dz->insams[0]); strcat(errstr,temp); break; case(PITCHFILE): print_outmessage("A binary pitch data file\n"); sprintf(errstr,"DURATION: "); secs = (double)dz->insams[0] * dz->frametime; make_time_display(temp,timestr,secs); strcat(errstr,timestr); sprintf(temp,"windows %d : floats %d\n",dz->insams[0],dz->insams[0]); strcat(errstr,temp); break; case(TRANSPOSFILE): print_outmessage("A binary transposition data file\n"); sprintf(errstr,"DURATION: "); secs = (double)dz->insams[0] * dz->frametime; make_time_display(temp,timestr,secs); strcat(errstr,timestr); sprintf(temp,"windows %d : floats %d\n",dz->insams[0],dz->insams[0]); strcat(errstr,temp); break; case(ENVFILE): print_outmessage("A binary envelope file\n"); sprintf(errstr,"DURATION: "); secs = (double)dz->insams[0] * dz->infile->window_size * MS_TO_SECS; make_time_display(temp,timestr,secs); strcat(errstr,timestr); sprintf(temp,"windows %d : floats %d\n",dz->wlength,dz->insams[0]); strcat(errstr,temp); break; case(FORMANTFILE): print_outmessage("A formant data file\n"); sprintf(errstr,"DURATION: "); dz->wlength = (dz->insams[0]/dz->specenvcnt) - DESCRIPTOR_DATA_BLOKS; secs = (double)dz->wlength * dz->frametime; make_time_display(temp,timestr,secs); strcat(errstr,timestr); n = dz->insams[0] - (dz->specenvcnt * DESCRIPTOR_DATA_BLOKS); sprintf(temp,"windows %d : floats %d\n",dz->wlength,n); strcat(errstr,temp); break; default: sprintf(errstr,"This process only works with soundfiling-system files.\n"); return(DATA_ERROR); } print_outmessage(errstr); break; case(INFO_LOUDCHAN): if(dz->infile->channels==MONO) { sprintf(errstr,"This program does not works with MONO files.\n"); return(GOAL_FAILED); } if((chanmax = (float *)malloc(chans *sizeof(float)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to store channel maximi.\n"); return(MEMORY_ERROR); } for(m=0;msamps_left) { if((exit_status = read_samps(dz->bigbuf,dz))<0) return(exit_status); for(n=0;nssampsread;n+=chans) { for(m=0;mbigbuf[n+m])); } } maxpos = 0; for(m=1;m chanmax[maxpos]) maxpos = m; } sprintf(errstr,"LOUDEST CHANNEL is %d\n",maxpos+1); print_outmessage(errstr); free(chanmax); break; case(INFO_SAMPTOTIME): if(!dz->vflag[CHAN_GROUPED]) dz->iparam[INFO_SAMPS] /= chans; secs = dz->iparam[INFO_SAMPS] * inverse_sr; make_time_display(temp,timestr,secs); sprintf(errstr,"TIME %s",timestr); strcat(errstr,"\n"); print_outmessage(errstr); break; case(INFO_TIMETOSAMP): n = round(dz->param[INFO_TIME] * sr); if(!dz->vflag[CHAN_GROUPED]) n *= chans; sprintf(errstr,"SAMPLE %d\n",n); print_outmessage(errstr); break; case(INFO_PROPS): errstr[0] = ENDOFSTR; switch(ftype) { case(SNDFILE): sprintf(errstr,"A SOUND file.\n"); break; case(ANALFILE): sprintf(errstr,"An ANALYSIS file.\n"); break; case(PITCHFILE): sprintf(errstr,"A binary PITCH file.\n"); break; case(TRANSPOSFILE): sprintf(errstr,"A binary TRANSPOSITION file.\n"); break; case(FORMANTFILE): sprintf(errstr,"A FORMANT data file.\n"); break; case(ENVFILE): sprintf(errstr,"A binary ENVELOPE file.\n"); break; default: if(is_a_textfile_type(ftype)) { sprintf(errstr,"A TEXT data file.\n"); is_a_text_file = TRUE; } else { print_outmessage("UNKNOWN input file type.\n"); return(FINISHED); } break; } print_outmessage(errstr); if(is_a_text_file) { sprintf(errstr,"Contains %d LINES\n",dz->linecnt); print_outmessage(errstr); sprintf(errstr,"Contains %d WORDS\n",dz->all_words); print_outmessage(errstr); if(ftype==MIXFILE) { sprintf(errstr,"Could be a MIXFILE with output channel cnt %d\n",dz->out_chans); print_outmessage(errstr); } else if(ftype==SYNCLIST) { sprintf(errstr,"Could be a LIST OF SOUNDFILES TO SYNCHRONISE.\n"); print_outmessage(errstr); } else if(ftype==SNDLIST) { sprintf(errstr,"Could be a LIST OF SOUNDFILES.\n"); print_outmessage(errstr); } if(dz->tempsize >0 || (dz->extrabrkno >= 0 && dz->brksize[dz->extrabrkno] > 0)) { sprintf(errstr,"Could be a BREAKPOINT FILE:\n"); print_outmessage(errstr); sprintf(errstr,"length %d minval %lf maxval %lf duration %lf\n", dz->numsize/2,dz->minbrk,dz->maxbrk,dz->duration); print_outmessage(errstr); } if(dz->numsize > 0) { sprintf(errstr,"Could be a NUMBER LIST:\n"); print_outmessage(errstr); sprintf(errstr,"length %d minval %lf maxval %lf\n",dz->numsize,dz->minnum,dz->maxnum); print_outmessage(errstr); } } else { sprintf(errstr,"samples: ............ %d\n",dz->insams[0]); print_outmessage(errstr); if(ftype!=SNDFILE) { switch(ftype) { case(ANALFILE): sprintf(errstr,"file type: .......... ANALYSIS DATA\n"); break; case(PITCHFILE): sprintf(errstr,"file type: .......... PITCH DATA (binary)\n"); break; case(TRANSPOSFILE): sprintf(errstr,"file type: .......... TRANSPOSITION DATA (binary)\n"); break; case(FORMANTFILE): sprintf(errstr,"file type: .......... FORMANT DATA (binary)\n"); break; case(ENVFILE): sprintf(errstr,"file type: .......... ENVELOPE DATA (binary)\n"); break; } print_outmessage(errstr); //TW UPDATE: moved srate & chans, as ENVFILES have srate and channels sprintf(errstr,"sample rate: ........ %d\n",fptr->srate); print_outmessage(errstr); sprintf(errstr,"channels: ........... %d\n",fptr->channels); print_outmessage(errstr); if(fptr->filetype==ENVFILE) { sprintf(errstr,"window size: ........ %f ms\n",fptr->window_size); print_outmessage(errstr); return(FINISHED); } if(fptr->filetype==FORMANTFILE) { sprintf(errstr,"formant envelope cnt: %d\n",fptr->specenvcnt); print_outmessage(errstr); } /*RWD*/ //TW NOW REDUNDANT: flagging changed // if(fptr->filetype!=SNDFILE){ sprintf(errstr,"original sampsize: .. %d\n",fptr->origstype); print_outmessage(errstr); sprintf(errstr,"original sample rate: %d\n",fptr->origrate); print_outmessage(errstr); sprintf(errstr,"analysis rate: ...... %f\n",fptr->arate); print_outmessage(errstr); sprintf(errstr,"analysis window len: %d\n",fptr->Mlen); print_outmessage(errstr); sprintf(errstr,"decimation factor: .. %d\n",fptr->Dfac); print_outmessage(errstr); // } if(fptr->filetype==PITCHFILE || fptr->filetype==TRANSPOSFILE) { sprintf(errstr,"original channels: .. %d\n",fptr->origchans); print_outmessage(errstr); } } else { sprintf(errstr,"file type: ........... SOUND\n"); print_outmessage(errstr); sprintf(errstr,"sample rate: ........ %d\n",fptr->srate); print_outmessage(errstr); sprintf(errstr,"channels: ........... %d\n",fptr->channels); print_outmessage(errstr); } if((exit_status = prntprops(&props,dz))<0) return(exit_status); } break; case(INFO_MAXSAMP): if(is_a_text_input_filetype(dz->infile->filetype)) { sprintf(errstr,"This is a text file.\n"); return(GOAL_FAILED); } /* RWD 2022 this hangs if user supplies anal file */ /* now fixed by TW 2022 (tlkib3.c) */ //if(dz->infile->filetype == ANALFILE){ // sprintf(errstr,"This is an anlysis file.\n"); // return(GOAL_FAILED); //} flbuf = (float *)dz->bigbuf; buf = dz->bigbuf; if(!dz->vflag[FORCE_SCAN] && try_header(chans,inverse_sr,dz)==FINISHED) break; else { if(dz->infile->filetype != SNDFILE) { if((exit_status = get_and_set_float_maxmina(flbuf,dz))<0) return(exit_status); } else { if((exit_status = get_and_set_float_maxmin(buf,chans,inverse_sr,dz))<0) return(exit_status); } } break; case(INFO_MAXSAMP2): buf = dz->bigbuf; if((exit_status = get_float_maxmin(buf,chans,inverse_sr,dz))<0) return(exit_status); break; case(INFO_PRNTSND): dz->ssampsread = 0; dz->iparam[PRNT_START] = round(dz->param[PRNT_START] * sr) * chans; dz->iparam[PRNT_END] = round(dz->param[PRNT_END] * sr) * chans; if(dz->iparam[PRNT_START] >= dz->iparam[PRNT_END]) { sprintf(errstr,"Incompatible start and end times.\n"); return(DATA_ERROR); } if(dz->iparam[PRNT_START] >= dz->insams[0]) { sprintf(errstr,"Start time is at end of file: can't proceed.\n"); return(DATA_ERROR); } dz->total_samps_read = 0; for(;;) { if((exit_status = read_samps(dz->bigbuf,dz))<0) return(exit_status); if(dz->iparam[PRNT_START] > dz->ssampsread) { dz->iparam[PRNT_START] -= dz->ssampsread; dz->iparam[PRNT_END] -= dz->ssampsread; } else break; } k = 0; j = (dz->total_samps_read - dz->ssampsread + dz->iparam[PRNT_START])/chans; display_virtual_time(0L,dz); for(n=dz->iparam[PRNT_START];niparam[PRNT_END];n+=chans,k+=chans,j++) { fprintf(dz->fp,"[%d]\t",j); for(m=0;mfp,"%.6f\t",(float) dz->bigbuf[n+m]); /*RWD 12:2003 was %d */ fprintf(dz->fp,"\n"); if(n >= dz->ssampsread) { if((exit_status = read_samps(dz->bigbuf,dz))<0) return(exit_status); //TW CHANGED to samps display_virtual_time(k,dz); dz->iparam[PRNT_END] -= dz->ssampsread; n = 0; } } //TW CHANGED to samps display_virtual_time(k,dz); break; case(INFO_FINDHOLE): threshold = dz->param[HOLE_THRESH] * (double)F_MAXSAMP; while(dz->samps_left) { if((exit_status = read_samps(dz->bigbuf,dz))<0) return(exit_status); for(n = 0; n < dz->ssampsread; n++) { if(holesize==0) { if(fabs(dz->bigbuf[n])total_samps_read - dz->ssampsread + n; } } else { if(fabs(dz->bigbuf[n]) maxholesize) { maxholesize = holesize; maxholesamp = holesamp; } holesize = 0; } } } } maxholelen = (double)(maxholesize/chans) * inverse_sr; maxholetime = (double)(maxholesamp/chans) * inverse_sr; sprintf(errstr,"Maximum holesize is %.6lf at time %.6lf\n",maxholelen,maxholetime); print_outmessage(errstr); break; case(INFO_CDIFF): case(INFO_DIFF): if((exit_status = do_sfdiff(temp,dz))<0) return(exit_status); break; case(ZCROSS_RATIO): if((exit_status = do_zcross_ratio(dz))<0) return(exit_status); break; default: sprintf(errstr,"Unknown process in do_sndinfo()\n"); return(PROGRAM_ERROR); } fflush(stdout); return(FINISHED); } /************************** TRY_HEADER ************************/ int try_header(int chans,double inverse_sr,dataptr dz) { int pos_repeats, neg_repeats, repeats, maxloc, maxamp = -1; float maxpfamp, maxnfamp; double gain, dbgain; float newmaxamp = 0.0f; if(dz->infile->filetype != SNDFILE) { //TW SUBSTITUTED SNDgetprop if( sndgetprop(dz->ifd[0],"maxpfamp",(char *)&maxpfamp,sizeof(float)) < 0 ) return(CONTINUE); if( sndgetprop(dz->ifd[0],"maxnfamp",(char *)&maxnfamp,sizeof(float)) < 0 ) return(CONTINUE); if(sndgetprop(dz->ifd[0],"maxprep",(char *)&pos_repeats,sizeof(float)) < 0 ) return(CONTINUE); if(sndgetprop(dz->ifd[0],"maxnrep",(char *)&neg_repeats,sizeof(int)) < 0 ) return(CONTINUE); sprintf(errstr,"maximum float value: %f\n",maxpfamp); print_outmessage(errstr); sprintf(errstr,"occurs: ............ %d times\n",pos_repeats); print_outmessage(errstr); sprintf(errstr,"minimum float value: %f\n",maxnfamp); print_outmessage(errstr); sprintf(errstr,"occurs: ............ %d times\n",neg_repeats); print_outmessage(errstr); } else { if( sndgetprop(dz->ifd[0],"maxamp",(char *)&maxamp,sizeof(int)) < 0 /* old files */ && sndgetprop(dz->ifd[0],"maxpfamp",(char *)&newmaxamp,sizeof(float)) < 0) /* new files */ return(CONTINUE); if( sndgetprop(dz->ifd[0],"maxloc",(char *)&maxloc,sizeof(int)) < 0 ) return(CONTINUE); if( sndgetprop(dz->ifd[0],"maxrep",(char *)&repeats,sizeof(int)) < 0 ) return(CONTINUE); if(maxamp>=0) newmaxamp = (float)(maxamp/(double)MAXSAMP); sprintf(errstr,"maximum abs value:.. %f\n",newmaxamp); print_outmessage(errstr); sprintf(errstr,"at: ................ %d samples\n",maxloc); print_outmessage(errstr); sprintf(errstr,"time: .............. %.4lf secs\n",(double)(maxloc/chans) *inverse_sr); print_outmessage(errstr); sprintf(errstr,"repeated: .......... %d times\n",repeats); print_outmessage(errstr); if(newmaxamp>=0.0) { gain = 1.0/(double)maxamp; dbgain = log10(gain) * 20.0; sprintf(errstr,"max possible gain:.. %.4lf\n",gain); print_outmessage(errstr); sprintf(errstr,"max dB gain:........ %.4lf\n",dbgain); print_outmessage(errstr); } } return(FINISHED); } /************************** MAKE_TIME_DISPLAY ************************/ void make_time_display(char temp[],char timestr[],double secs) { int mins = 0, hrs = 0; if(secs > 60.0) { mins = round(floor(secs/60.0)); secs -= (double)(mins * 60); } if(mins > 60) { hrs = round(floor((double)mins/60.0)); mins -= hrs * 60; } timestr[0] = ENDOFSTR; if(hrs) { sprintf(temp,"%d hrs ",hrs); strcat(timestr,temp); } if(mins) { sprintf(temp,"%d mins ",mins); strcat(timestr,temp); } sprintf(temp,"%.6lf secs ",secs); strcat(timestr,temp); } /************************** GET_AND_SET_FLOAT_MAXMIN ************************/ /* RWD assumes analysis ?*/ int get_and_set_float_maxmina(float *flbuf,dataptr dz) { int exit_status; double maxpdamp = DBL_MIN; double maxndamp = DBL_MAX; float maxpfamp, maxnfamp; int maxprep = 1, maxnrep = 1; int n; dz->samps_left = dz->insams[0]; if(sndseekEx(dz->ifd[0],0,0)<0) { sprintf(errstr,"sndseek() failed. get_and_set_float_maxmin()\n"); return(SYSTEM_ERROR); } while(dz->samps_left > 0) { if((exit_status = read_samps(flbuf,dz))<0) return(exit_status); for(n=0;nssampsread;n++) { if(flbuf[n] < maxpdamp) /* IF < max, ignore */ ; else if(flbuf[n] > maxpdamp) { maxpdamp = flbuf[n]; /* IF > max, reset max and count */ maxprep = 1; } else /* else must be EQUAL to max; incr counter */ maxprep++; if(flbuf[n] > maxndamp) ; else if(flbuf[n] < maxndamp) { maxndamp = flbuf[n]; maxnrep = 1; } else maxnrep++; } } maxpfamp = (float)maxpdamp; maxnfamp = (float)maxndamp; //TW cannot reset header of a read-in file // if( sndputprop(dz->ifd[0],"maxpfamp",(char *)&maxpfamp,sizeof(float)) < 0 ) // fprintf(stdout,"WARNING: Cannot write maximum float value to header\n"); // if(sndputprop(dz->ifd[0],"maxprep",(char *)&maxprep,sizeof(long)) < 0 ) // fprintf(stdout,"WARNING: Cannot write maxfloat repeats-count to header\n"); // if( sndputprop(dz->ifd[0],"maxnfamp",(char *)&maxnfamp,sizeof(float)) < 0 ) // fprintf(stdout,"WARNING: Cannot write mimimum float value to header\n"); // if(sndputprop(dz->ifd[0],"maxnrep",(char *)&maxnrep,sizeof(long)) < 0 ) // fprintf(stdout,"WARNING: Cannot write minfloat repeats-count to header\n"); sprintf(errstr,"maximum float value: %f\n",maxpfamp); print_outmessage(errstr); sprintf(errstr,"occurs: ........... %d times\n",maxprep); print_outmessage(errstr); sprintf(errstr,"minimum float value: %f\n",maxnfamp); print_outmessage(errstr); sprintf(errstr,"occurs: ........... %d times\n",maxnrep); print_outmessage(errstr); return(FINISHED); } /************************** GET_AND_SET_SHORT_MAXMIN ************************/ int get_and_set_float_maxmin(float *buf,int chans, double inverse_sr,dataptr dz) { int exit_status; /*int maxamp = MINSAMP, mag;*/ float maxamp = F_MINSAMP, mag; int maxloc = 0; int maxrep = 1; int n; double gain = 0.0, dbgain = 0.0; while(dz->samps_left) { if((exit_status = read_samps(buf,dz))<0) return(exit_status); for(n=0;nssampsread;n++) { mag = (float) fabs(buf[n]); if(mag > maxamp) { maxloc = dz->total_samps_read - dz->ssampsread + n; maxamp = mag; maxrep = 1; } else if(mag==maxamp) maxrep++; } } //TW Cannot alter heqader of an input file // if(sndputprop(dz->ifd[0],"maxamp",(char *)&maxamp,sizeof(float)) < 0 ) // if(sndputprop(dz->ifd[0],"maxpfamp",(char *)&maxamp,sizeof(float)) < 0 ) // fprintf(stdout,"WARNING: Cannot write maximum value to header.\n"); // if(sndputprop(dz->ifd[0],"maxloc",(char *)&maxloc,sizeof(long)) < 0 ) // fprintf(stdout,"WARNING: Cannot write location of maximum value to header.\n"); // if(sndputprop(dz->ifd[0],"maxrep",(char *)&maxrep,sizeof(long)) < 0 ) // fprintf(stdout,"WARNING: Cannot write maximum repeats to header.\n"); if(maxamp>0.0f) { gain = F_MAXSAMP/(double)maxamp; dbgain = log10(gain) * 20.0; } sprintf(errstr,"maximum abs value:.. %f\n",maxamp); print_outmessage(errstr); sprintf(errstr,"at: ................ %d samples\n",maxloc); print_outmessage(errstr); sprintf(errstr,"time: .............. %.4lf secs\n",(double)(maxloc/chans) *inverse_sr); print_outmessage(errstr); sprintf(errstr,"repeated: .......... %d times\n",maxrep); print_outmessage(errstr); if(maxamp>0.0f) { sprintf(errstr,"max possible gain:.. %.4lf\n",gain); print_outmessage(errstr); sprintf(errstr,"max dB gain:........ %.4lf\n",dbgain); print_outmessage(errstr); } return(FINISHED); } /************************ COMPARE_INFILE_SIZES ***********************/ int compare_infile_sizes(int *samesize,dataptr dz) { if(dz->insams[0] != dz->insams[1]) { print_outmessage_flush("Files are not same size.\n"); if(!dz->vflag[IGNORE_LENDIFF]) return(FINISHED); else { dz->insams[0] = min(dz->insams[0],dz->insams[1]); *samesize = FALSE; } } dz->samps_left = dz->insams[0]; return(CONTINUE); } /************************** COMPARE_SNDFILE_PROPERTIES *********************/ int compare_sndfile_properties(char temp[],dataptr dz) { errstr[0] = ENDOFSTR; if(dz->infile->srate != dz->otherfile->srate) { sprintf(errstr,"Files don't have same sample rate.\n"); return(FINISHED); } if(dz->infile->channels != dz->otherfile->channels) { sprintf(errstr,"Files don't have same number of channels. "); if(dz->vflag[IGNORE_CHANDIFF]) { sprintf(temp,"1st has %d : 2nd has %d\n",dz->infile->channels,dz->otherfile->channels); strcat(errstr,temp); } else { strcat(errstr,"\n"); return(FINISHED); } print_outmessage(errstr); } return(CONTINUE); } /*************************** SFDIFF_PROCESS **************************/ int sfdiff_process(char temp[],int samesize,dataptr dz) { int exit_status; int limitcnt = 0, badmatch = 0; double threshold = dz->param[SFDIFF_THRESH] /* * (double)MAXSAMP*/; display_virtual_time(0L,dz); if(sndseekEx(dz->ifd[0],0,0)<0) { sprintf(errstr,"sndseekEx() problem in sfdiff_process()\n"); return(SYSTEM_ERROR); } if(dz->process==INFO_DIFF && sndseekEx(dz->ifd[1],0,0)<0) { sprintf(errstr,"sndseekEx() problem 2 in sfdiff_process()\n"); return(SYSTEM_ERROR); } while(dz->samps_left > 0) { if(dz->process==INFO_CDIFF) { if((exit_status = read_samps_for_cdiff(dz))<0) return(exit_status); } else { if((exit_status = read_both_the_files(samesize,dz))<0) return(exit_status); } compare_samps(temp,&badmatch,&limitcnt,threshold,dz); display_virtual_time(dz->total_samps_read,dz); fflush(stdout); } if(limitcnt == 0) { if(dz->process==INFO_CDIFF) sprintf(errstr,"Channels are IDENTICAL"); else { if(samesize) sprintf(errstr,"Files are IDENTICAL"); else sprintf(errstr,"Files are otherwise IDENTICAL"); } if(dz->process==INFO_CDIFF) { if(dz->param[SFDIFF_THRESH] > 0) { sprintf(temp," to within %lf\n",dz->param[SFDIFF_THRESH]); strcat(errstr,temp); }else strcat(errstr,"\n"); } else { switch(dz->infile->filetype) { case(SNDFILE): if(dz->param[SFDIFF_THRESH] > 0) { sprintf(temp," to within %lf\n",dz->param[SFDIFF_THRESH]); strcat(errstr,temp); } else strcat(errstr,"\n"); break; default: if(dz->param[SFDIFF_THRESH] > 0.0) { sprintf(temp," to within %lf\n",dz->param[SFDIFF_THRESH]); strcat(errstr,temp); } else strcat(errstr,"\n"); break; } } } else if(badmatch) { if(limitcnt < dz->iparam[SFDIFF_CNT]) strcat(errstr," : as far as end of file.\n"); else strcat(errstr," : comparison stopped here.\n"); } return(FINISHED); } /************************ READ_BOTH_THE_FILES *******************************/ int read_both_the_files(int samesize,dataptr dz) { int samps_read2; if((dz->ssampsread = fgetfbufEx(dz->sampbuf[0], /*dz->bigbufsize*/dz->buflen,dz->ifd[0],0)) < 0) { sprintf(errstr, "Can't read samps from 1st soundfile\n"); return(SYSTEM_ERROR); } if((samps_read2 = fgetfbufEx(dz->sampbuf[1], dz->buflen,dz->ifd[1],0)) < 0) { sprintf(errstr, "Can't read samps from 2nd soundfile\n"); return(SYSTEM_ERROR); } if((dz->ssampsread != samps_read2)) { if(samesize) { sprintf(errstr, "Anomaly in soundfile read.\n"); return(PROGRAM_ERROR); } else dz->ssampsread = min(dz->ssampsread,samps_read2); } dz->total_samps_read += dz->ssampsread; dz->samps_left -= dz->ssampsread; return(FINISHED); } /************************ READ_SAMPS_FOR_CDIFF *******************************/ int read_samps_for_cdiff(dataptr dz) { int n, m; if((dz->ssampsread = fgetfbufEx(dz->sampbuf[2], dz->buflen * 2,dz->ifd[0],0)) < 0) { sprintf(errstr, "Can't read samples from soundfile\n"); return(SYSTEM_ERROR); } for(n=0,m=0;mssampsread;n++,m+=2) { dz->sampbuf[0][n] = dz->sampbuf[2][m]; dz->sampbuf[1][n] = dz->sampbuf[2][m+1]; } dz->total_samps_read += dz->ssampsread; dz->samps_left -= dz->ssampsread; return(FINISHED); } /**************************** COMPARE_SAMPS ***************************/ void compare_samps(char temp[],int *badmatch,int *limitcnt,double threshold,dataptr dz) { int n; int sampsread = dz->ssampsread; switch(dz->infile->filetype) { case(SNDFILE): if(dz->process==INFO_CDIFF) sampsread /= STEREO; for(n=0;nsampbuf[0][n]-dz->sampbuf[1][n]) > threshold) { if(*badmatch==0) { sprintf(errstr,"Badmatch from "); snd_file_time(temp,n,dz); *badmatch = 1; if(++(*limitcnt) >= dz->iparam[SFDIFF_CNT]) { dz->samps_left = 0; /* force calling loop to end */ return; } } } else { if(*badmatch) { strcat(errstr," as far as "); snd_file_time(temp,n,dz); strcat(errstr,"\n"); print_outmessage(errstr); *badmatch = 0; } } } break; case(ANALFILE): dz->ssampsread = sampsread; for(n=0;nssampsread;n+=2) { if(fabs(dz->flbufptr[0][n]-dz->flbufptr[1][n]) > threshold) { if(*badmatch==0) { sprintf(errstr,"Bad frq match from "); anal_file_time(temp,n,dz); *badmatch = 1; if(++(*limitcnt) >= dz->iparam[SFDIFF_CNT]) { dz->samps_left = 0; return; } } } else { if(*badmatch) { strcat(errstr," as far as "); anal_file_time(temp,n,dz); strcat(errstr,"\n"); print_outmessage(errstr); *badmatch = 0; } } } if(*badmatch) { strcat(errstr," as far as "); anal_file_time(temp,n,dz); strcat(errstr,"\n"); print_outmessage(errstr); *badmatch = 0; } for(n=1;nssampsread;n+=2) { if(fabs(dz->flbufptr[0][n]-dz->flbufptr[1][n]) > threshold) { if(*badmatch==0) { sprintf(errstr,"Bad amp match from "); anal_file_time(temp,n,dz); *badmatch = 1; if(++(*limitcnt) >= dz->iparam[SFDIFF_CNT]) { dz->samps_left = 0; return; } } } else { if(*badmatch) { strcat(errstr," as far as "); anal_file_time(temp,n,dz); strcat(errstr,"\n"); print_outmessage(errstr); *badmatch = 0; } } } if(*badmatch) { strcat(errstr," to buffer end "); anal_file_time(temp,n,dz); strcat(errstr,"\n"); print_outmessage(errstr); *badmatch = 0; } break; default: /* float files */ dz->ssampsread = sampsread; for(n=0;nssampsread;n++) { if(fabs(dz->flbufptr[0][n]-dz->flbufptr[1][n]) > threshold) { if(*badmatch==0) { sprintf(errstr,"Badmatch from "); anal_file_time(temp,n,dz); *badmatch = 1; if(++(*limitcnt) >= dz->iparam[SFDIFF_CNT]) { dz->samps_left = 0; return; } } } else { if(*badmatch) { strcat(errstr," as far as "); anal_file_time(temp,n,dz); strcat(errstr,"\n"); print_outmessage(errstr); *badmatch = 0; } } } break; } } /***************************** ANAL_FILE_TIME *************************/ void anal_file_time(char temp[],int n,dataptr dz) { int this_channel; double this_time; int wanted; int this_sample = (dz->total_samps_read - dz->ssampsread) + n; int this_window; switch(dz->infile->filetype) { case(ANALFILE): wanted = dz->infile->Mlen + 2; this_window = this_sample/wanted; /* TRUNCATE */ this_sample = this_sample%wanted; /* sample count from window base */ this_channel = this_sample/2; this_time = (double)this_window/(double)dz->infile->arate; sprintf(temp," channel %d: window %d: time %.4lf ",this_channel,this_window,this_time); break; case(PITCHFILE): case(TRANSPOSFILE): this_window = this_sample; this_time = (double)this_window/(double)dz->infile->arate; sprintf(temp," window %d: time %.4lf ",this_window,this_time); break; case(ENVFILE): this_window = this_sample; this_time = (double)this_window * dz->infile->window_size * MS_TO_SECS; sprintf(temp," window %d: time %.4lf ",this_window,this_time); break; case(FORMANTFILE): this_sample -= dz->specenvcnt * DESCRIPTOR_DATA_BLOKS; this_window = this_sample/dz->specenvcnt; /* TRUNCATE */ this_channel = this_sample%dz->specenvcnt; this_time = (double)this_window/(double)dz->infile->arate; sprintf(temp," channel %d: window %d: time %.4lf ",this_channel,this_window,this_time); break; } strcat(errstr,temp); } /**************************** SND_FILE_TIME ***************************/ void snd_file_time(char temp [],int n,dataptr dz) { int this_sample; double this_time, sr = (double)dz->infile->srate; if(dz->process==INFO_CDIFF) { this_sample = ((dz->total_samps_read - dz->ssampsread)/STEREO) + n; this_time = (double)this_sample/sr; } else { this_sample = (dz->total_samps_read - dz->ssampsread) + n; this_time = (double)this_sample/(sr * (double)dz->infile->channels); } sprintf(temp,"sample %d: time %.4lf ",this_sample,this_time); strcat(errstr,temp); } /**************************** COMPARE_ANALFILE_PROPERTIES ***************************/ int compare_analfile_properties(dataptr dz) { errstr[0] = ENDOFSTR; switch(dz->infile->filetype) { case(ENVFILE): if(dz->infile->window_size != dz->otherfile->window_size) { sprintf(errstr,"Files do not have same WINDOW_SIZE.\n"); return(FINISHED); } break; case(FORMANTFILE): if(dz->infile->specenvcnt != dz->otherfile->specenvcnt) { sprintf(errstr,"Files do not have same FORMANT WINDOW CNT.\n"); return(FINISHED); } break; case(PITCHFILE): case(TRANSPOSFILE): if(dz->infile->origchans != dz->otherfile->origchans) { sprintf(errstr,"Files do not have same ORIGINAL NO. OF CHANNELS.\n"); return(FINISHED); } break; } if(dz->infile->stype != dz->otherfile->stype) { sprintf(errstr,"Files do not have same SAMPLE TYPE.\n"); return(FINISHED); } if(dz->infile->srate != dz->otherfile->srate) { sprintf(errstr,"Files do not have same SAMPLING RATE.\n"); return(FINISHED); } if(dz->infile->channels != dz->otherfile->channels) { sprintf(errstr,"Files do not have same NO. OF CHANNELS.\n"); return(FINISHED); } if(dz->infile->filetype!=ENVFILE) { if(dz->infile->origstype != dz->otherfile->origstype) { sprintf(errstr,"Files do not have same ORIGINAL SAMPLE TYPE.\n"); return(FINISHED); } if(dz->infile->origrate != dz->otherfile->origrate) { sprintf(errstr,"Files do not have same ORIGINAL SAMPLING RATE.\n"); return(FINISHED); } if(dz->infile->arate != dz->otherfile->arate) { sprintf(errstr,"Files do not have same ANALYSIS RATE.\n"); return(FINISHED); } if(dz->infile->Mlen != dz->otherfile->Mlen) { sprintf(errstr,"Files do not have same ANALYSIS WINDOW LENGTH.\n"); return(FINISHED); } if(dz->infile->Dfac != dz->otherfile->Dfac) { sprintf(errstr,"Files do not have same DECIMATION FACTOR.\n"); return(FINISHED); } } return(CONTINUE); } /********************************* DO_SFDIFF ***********************************/ int do_sfdiff(char temp[],dataptr dz) { int exit_status; int samesize = TRUE; switch(dz->process) { case(INFO_CDIFF): if(dz->infile->channels!=2) { sprintf(errstr,"Process only works with STEREO files.\n"); return(DATA_ERROR); } break; default: if(is_a_text_input_filetype(dz->infile->filetype) || is_a_text_input_filetype(dz->otherfile->filetype)) { sprintf(errstr,"Program only works with soundfiling system files.\n"); return(DATA_ERROR); } if(dz->infile->filetype != dz->otherfile->filetype) { print_outmessage_flush("Files are not of the same type.\n"); return(FINISHED); } if(compare_infile_sizes(&samesize,dz)!=CONTINUE) return(FINISHED); switch(dz->infile->filetype) { case(SNDFILE): if(compare_sndfile_properties(temp,dz)!=CONTINUE) { print_outmessage_flush(errstr); return(FINISHED); } break; default: if(compare_analfile_properties(dz)!=CONTINUE) { print_outmessage_flush(errstr); return(FINISHED); } dz->flbufptr[0] = dz->sampbuf[0]; dz->flbufptr[1] = dz->sampbuf[1]; break; } break; } if((exit_status = sfdiff_process(temp,samesize,dz))<0) return(exit_status); print_outmessage_flush(errstr); return(FINISHED); } /********************************* PRNTPROPS ***********************************/ /* RWD much adapted to report PEAK data if available */ int prntprops(SFPROPS *props,dataptr dz) { char *prop; time_t thistime; char *p; CHPEAK peaks[2000]; int chans, peaktime; if((prop = (char *)malloc(max(sizeof(unsigned int),sizeof(double))))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to get properties.\n"); return(MEMORY_ERROR); } /*RWD find PEAK chunk as priority */ if(snd_headread(dz->ifd[0],props)){ if((*props).type == wt_wave) { switch(props->samptype){ /*RWD Nov 2003 show sample type now we have so many possibilities! */ case(SHORT16): sprintf(errstr,"sample type: 16bit\n"); break; case(FLOAT32): sprintf(errstr,"sample type: 32bit floats\n"); break; case(INT2424): sprintf(errstr,"sample type: 24bit packed\n"); break; case(SHORT8): sprintf(errstr,"sample type: 8bit\n"); break; case(INT2432): sprintf(errstr,"sample type: 24bit in 32bit frames\n"); break; case(INT_32): sprintf(errstr,"sample type: 32bit integer\n"); break; default: sprintf(errstr,"sample type unknown (custom format)\n"); break; } print_outmessage(errstr); chans = (*props).chans; if(sndreadpeaks(dz->ifd[0],chans,peaks,&peaktime)>0){ int i; thistime = (time_t) peaktime; sprintf(errstr,"PEAK data at: %s\n",ctime(&thistime)); print_outmessage(errstr); for(i=0;i < chans;i++){ sprintf(errstr,"CH %d:\tamp = %.4f (%.2f dB)\tFrame %u\n", i+1,peaks[i].value,20 * log10(peaks[i].value),peaks[i].position); print_outmessage(errstr); } } else { sprintf(errstr,"No PEAK chunk in this file"); print_outmessage(errstr); } } } if(sndgetprop(dz->ifd[0], "date", prop, sizeof(unsigned int))>=0 || sndgetprop(dz->ifd[0], "DATE", prop, sizeof(unsigned int))>=0) { thistime = (time_t) *(int*)prop; p = ctime(&thistime); sprintf(errstr,"Date: %s\n",p); print_outmessage(errstr); } fflush(stdout); return(FINISHED); } /************************** GET_SHORT_MAXMIN ************************/ int get_float_maxmin(float *buf,int chans, double inverse_sr,dataptr dz) { int exit_status; /*int maxamp = MINSAMP;*/ float maxamp = F_MINSAMP,mag; int maxloc = 0; int maxrep = 1; int n; double gain = 0.0, dbgain = 0.0; double convertor = (double)(chans * dz->infile->srate); int startsamp = round(dz->param[MAX_STIME] * convertor); int endsamp = round(dz->param[MAX_ETIME] * convertor); int last_total_samps_read; int startsrch, endsrch; dz->total_samps_read = 0; /* REDUNDANT ? */ while(dz->samps_left) { last_total_samps_read = dz->total_samps_read; if((exit_status = read_samps(buf,dz))<0) return(exit_status); if(dz->total_samps_read <= startsamp) continue; else startsrch = max(0,startsamp - last_total_samps_read); if(dz->total_samps_read > endsamp) { if((endsrch = endsamp - last_total_samps_read) < 0) break; } else endsrch = dz->ssampsread; for(n=startsrch;n maxamp) { maxloc = last_total_samps_read + n; maxamp = mag; maxrep = 1; } else if(mag==maxamp) maxrep++; } } if(maxamp>0.0f) { gain = (double)F_MAXSAMP/(double)maxamp; dbgain = log10(gain) * 20.0; } sprintf(errstr,"maximum abs value:.. %f\n",maxamp); print_outmessage(errstr); sprintf(errstr,"at: ................ %d samples\n",maxloc); print_outmessage(errstr); sprintf(errstr,"time: .............. %.4lf secs\n",(double)(maxloc/chans) *inverse_sr); print_outmessage(errstr); sprintf(errstr,"repeated: .......... %d times\n",maxrep); print_outmessage(errstr); if(maxamp>0.0f) { sprintf(errstr,"max possible gain:.. %.4lf\n",gain); print_outmessage(errstr); sprintf(errstr,"max dB gain:........ %.4lf\n",dbgain); print_outmessage(errstr); } return(FINISHED); } /*RWD 6:2001 read PEAK chunk */ int getpeakdata(int ifd, float *peakval,SFPROPS *props) { CHPEAK peaks[16]; int chans, peaktime; float maxamp = 0.0f; if(snd_headread(ifd,props)){ chans = (*props).chans; if(sndreadpeaks(ifd,chans,peaks,&peaktime)){ int i; for(i=0;i < chans;i++) maxamp = max(maxamp,peaks[i].value); *peakval = maxamp; return 1; } } /* sf_headread error; but can't do much about it */ return 0; } /************************** DO_ZCROSS_RATIO ************************/ int do_zcross_ratio(dataptr dz) { int exit_status; int chans = dz->infile->channels, *phase, k, m; int n, *cnt, cntsum = 0, zc0, zc1, lastzc0, lastzc1, bufstart, bufend, bufskip, skipsamps, totsams, total_samps_processed; double zc_ratio; float *buf = dz->sampbuf[0]; double srate = dz->infile->srate; if((cnt = (int *)malloc(chans * sizeof(int)))==NULL) { sprintf(errstr,"NO MEMORY TO STORE ZERO-CROSSING COUNTERS.\n"); return(MEMORY_ERROR); } if((phase = (int *)malloc(chans * sizeof(int)))==NULL) { sprintf(errstr,"NO MEMORY TO STORE PHASE MARKERS.\n"); return(MEMORY_ERROR); } dz->iparam[ZC_START] = (int)round(dz->param[ZC_START] * srate) * chans; bufend = (int)round(dz->param[ZC_END] * srate) * chans; totsams = bufend - dz->iparam[ZC_START]; dz->tempsize = totsams; bufstart = dz->iparam[ZC_START] % dz->buflen; if((bufskip = dz->iparam[ZC_START] / dz->buflen) > 0) { skipsamps = bufskip * dz->buflen; sndseekEx(dz->ifd[0],skipsamps,0); bufend -= skipsamps; } if((exit_status = read_samps(buf,dz)) < 0) return(exit_status); if(dz->ssampsread < chans * 2) { sprintf(errstr,"INSUFFICIENT DATA TO COUNT ZERO-CROSSINGS.\n"); return(DATA_ERROR); } total_samps_processed = 0; for(m=0,n = bufstart;m 0) phase[m] = 1; else if(buf[n] < 0) phase[m] = -1; else phase[m] = 0; cnt[m] = 0; } k = bufstart + chans; while(bufend > dz->buflen) { for(n = k; n < dz->ssampsread;n+=chans) { for(m=0;m 0) phase[m] = 1; else if(buf[n+m] < 0) phase[m] = -1; break; case(1): if(buf[n+m] < 0) { cnt[m]++; phase[m] = -1; } break; case(-1): if(buf[n+m] > 0) { cnt[m]++; phase[m] = 1; } break; } } } total_samps_processed += (dz->ssampsread - k); display_virtual_time(total_samps_processed,dz); if((exit_status = read_samps(buf,dz)) < 0) return(exit_status); bufend -= dz->buflen; k = 0; } if(bufend > 0) { for(n = k; n < bufend;n+=chans) { for(m=0;m 0) phase[m] = 1; else if(buf[n+m] < 0) phase[m] = -1; break; case(1): if(buf[n+m] < 0) { cnt[m]++; phase[m] = -1; } break; case(-1): if(buf[n+m] > 0) { cnt[m]++; phase[m] = 1; } break; } } } total_samps_processed += (bufend - k); display_virtual_time(total_samps_processed,dz); } for(m=0;m 0 && zc1 >= 64); zc0 = lastzc0; zc1 = lastzc1; while(EVEN(zc0)) { zc0 /= 2; zc1 /= 2; } fprintf(stdout,"INFO: Proportion of zero-crossings = %lf or approx %d:%d\n",zc_ratio,zc0,zc1); fflush(stdout); return FINISHED; }