/* * 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 * */ // (2) Do need an entry in standalone .... #include #include #include #include #include #include #include char errstr[2400]; static int local_print_messages_and_close_sndfiles(int exit_status,int is_launched,int ofd,int *ifd,int infilecnt); static int local_read_samps(float *bbuf,int wanted,int *total_samps_read, int *ssampsread,int n,int *ifd, int totalsize); static int reset_file_to_start_and_pointers_to_after_descriptor_blocks (int *ifd,int *windows_in_buf,int n,int wanted,int specenvcnt,float *bigfbuf,float **flbufptr, int *total_samps_read,int totalsize); static int check_the_formant_data(int *windows_in_buf,float *specenvpch,float *specenvtop,float *bigfbuf,float **flbufptr,char **argv, infileptr ifp,int specenvcnt,int wanted,int *total_samps_read,int totalsize,int n,int *ifd); static int initialise_the_formant_data(int *windows_in_buf,float *specenvpch,float *specenvtop,float *bigfbuf,float **flbufptr, infileptr ifp,int specenvcnt,int wanted,int *total_samps_read,int totalsize,int n,int *ifd); static void display_sloom_time(int samps_sent,int totalsize); static int local_readhead(infileptr inputfile,int ifd,char *filename,int getmax,int needmaxinfo); static void local_splice_multiline_string(char *str,char *prefix); static int flteq(double f1,double f2); static int formant_headwrite(int ofd,infileptr ifp); #define FAILED (-1) #define SUCCEEDED (0) #define PBAR_LENGTH (256) #define CONTINUE (1) #define FINISHED (0) #define GOAL_FAILED (-1) /* program succeeds, but users goal not achieved: e.g. find pitch */ #define USER_ERROR (-2) /* program fails because wrong data, no data etc given by user */ #define DATA_ERROR (-3) /* Data is unsuitable, incorrect or missing */ #define MEMORY_ERROR (-4) /* program fails because ran out of, or mismanaged, memory */ #define SYSTEM_ERROR (-5) /* failure to write to or truncate outfile: usually means H/D is full */ #define PROGRAM_ERROR (-6) /* program fails because the programming is naff */ #define USAGE_ONLY (-7) /* program interrogated for usage_message only */ #define TK_USAGE (-8) /* program interrogated by TK for usage_message only */ #define BAD_INFILECNT (-9) /* Bad infilecnt sent from TK at program testing stage */ #ifndef FALSE #define FALSE (0) #endif #ifndef TRUE #define TRUE (1) #endif #define DESCRIPTOR_DATA_BLOKS (2) #define ENDOFSTR ('\0') #define FLTERR (0.000002) /**************************************** MAIN *********************************************/ // cmdline formav formfil1 formfil2 [formfil3 ....] outformfil dur int main(int argc,char *argv[]) { int exit_status, n, m, k, infilecnt; int is_launched = FALSE; int *ifd = NULL, ofd = -1; int specenvcnt; int wanted, windows_in_buf,outfltcnt,outwindowcnt; infileptr ifp,ifp2; float *bigfbuf, *bigbufend, *flbufptr, *oflbufptr, *specenvpch, *specenvtop; int total_windows = 0, ssampsread, min_inwindowsize, totalsize, size, total_samps_read; double dur; if(sflinit("cdp")){ sfperror("cdp: initialisation\n"); return(FAILED); } if(argc < 5) { fprintf(stdout,"ERROR: Insufficient arguments on commandline.\n"); fflush(stdout); return(FAILED); } if(sscanf(argv[argc-1],"%lf",&dur)!=1) { fprintf(stdout,"ERROR: Cannot read output duration from command line.\n"); fflush(stdout); return(FAILED); } if (dur < 0.2) { fprintf(stdout,"ERROR: Output duration (%lf) too short (min 0.2 secs).\n",dur); fflush(stdout); return(FAILED); } if((ifp = (infileptr)malloc(sizeof(struct filedata)))==NULL) { fprintf(stdout,"ERROR: INSUFFICIENT MEMORY to store data on infiles (1)\n"); fflush(stdout); return(FAILED); } if((ifp2 = (infileptr)malloc(sizeof(struct filedata)))==NULL) { fprintf(stdout,"ERROR: INSUFFICIENT MEMORY to store data on infiles (2)\n"); fflush(stdout); return(FAILED); } if((ifd = (int *)malloc((argc-3) * sizeof(int))) == NULL) { fprintf(stdout,"ERROR: Insufficient memory.\n"); fflush(stdout); return(FAILED); } for(n=1;nfiletype != FORMANTFILE) { sprintf(errstr,"First input file is not a formant file.\n"); exit_status = DATA_ERROR; local_print_messages_and_close_sndfiles(exit_status,is_launched,ofd,ifd,infilecnt); return(FAILED); } ifp2->filetype = ifp->filetype; ifp2->srate = ifp->srate; ifp2->stype = ifp->stype; ifp2->origstype = ifp->origstype; ifp2->origrate = ifp->origrate; ifp2->channels = ifp->channels; ifp2->origchans = ifp->origchans; ifp2->specenvcnt = ifp->specenvcnt; ifp2->Mlen = ifp->Mlen; ifp2->Dfac = ifp->Dfac; ifp2->arate = ifp->arate; ifp2->descriptor_samps = ifp->descriptor_samps; } else { if(ifp2->filetype != ifp->filetype || ifp2->srate != ifp->srate || ifp2->stype != ifp->stype || ifp2->origstype != ifp->origstype || ifp2->origrate != ifp->origrate || ifp2->channels != ifp->channels || ifp2->origchans != ifp->origchans || ifp2->specenvcnt != ifp->specenvcnt || ifp2->Mlen != ifp->Mlen || ifp2->Dfac != ifp->Dfac || ifp2->arate != ifp->arate || ifp2->descriptor_samps != ifp->descriptor_samps) { sprintf(errstr,"Input files have incompatible properties.\n"); exit_status = DATA_ERROR; local_print_messages_and_close_sndfiles(exit_status,is_launched,ofd,ifd,infilecnt); return(FAILED); } } } wanted = ifp->specenvcnt * 8; specenvcnt = ifp->specenvcnt; min_inwindowsize = 10000000; totalsize = 0; for(n=0;nframetime) * specenvcnt) + 2; if((ofd = sndcreat_formatted(argv[argc-1],outfltcnt,SAMP_FLOAT, ifp->channels,ifp->srate,CDP_CREATE_NORMAL)) < 0) { sprintf(errstr,"Cannot open output file %s\n", argv[argc-1]); exit_status = SYSTEM_ERROR; local_print_messages_and_close_sndfiles(exit_status,is_launched,ofd,ifd,infilecnt); return(FAILED); } outwindowcnt = (outfltcnt/specenvcnt) - 2; is_launched = 1; if((specenvpch = (float *)malloc(specenvcnt * sizeof(float))) == NULL) { sprintf(errstr,"Insufficient memory to store formant descriptor data 1.\n"); exit_status = MEMORY_ERROR; local_print_messages_and_close_sndfiles(exit_status,is_launched,ofd,ifd,infilecnt); return(FAILED); } if((specenvtop = (float *)malloc(specenvcnt * sizeof(float))) == NULL) { sprintf(errstr,"Insufficient memory to store formant descriptor data 2.\n"); exit_status = MEMORY_ERROR; local_print_messages_and_close_sndfiles(exit_status,is_launched,ofd,ifd,infilecnt); return(FAILED); } if((oflbufptr = (float *)malloc(specenvcnt * sizeof(float))) == NULL) { sprintf(errstr,"Insufficient memory to store output formant data.\n"); exit_status = MEMORY_ERROR; local_print_messages_and_close_sndfiles(exit_status,is_launched,ofd,ifd,infilecnt); return(FAILED); } memset((char *)oflbufptr,0,specenvcnt * sizeof(float)); if((bigfbuf = (float *)malloc(wanted * sizeof(float))) == NULL) { sprintf(errstr,"Insufficient memory to store input formant data.\n"); exit_status = MEMORY_ERROR; local_print_messages_and_close_sndfiles(exit_status,is_launched,ofd,ifd,infilecnt); return(FAILED); } bigbufend = bigfbuf + wanted; memset((char *)bigfbuf,0,wanted * sizeof(float)); total_samps_read = 0; for(n=0;ndescriptor_samps/DESCRIPTOR_DATA_BLOKS; if((exit_status = local_read_samps(bigfbuf,wanted,total_samps_read,&ssampsread,n,ifd,totalsize)) < 0) return(exit_status); if(ssampsread < ifp->descriptor_samps) { sprintf(errstr,"No significant data in formantfile.\n"); return(DATA_ERROR); } *flbufptr = bigfbuf; memcpy((char *)specenvpch,(char *)(*flbufptr),(size_t)(fsamps_to_read * sizeof(float))); *flbufptr += specenvcnt; memcpy((char *)specenvtop,(char *)(*flbufptr),(size_t)(fsamps_to_read * sizeof(float))); *flbufptr = bigfbuf + (DESCRIPTOR_DATA_BLOKS * specenvcnt); *windows_in_buf = ssampsread/specenvcnt; if((*windows_in_buf -= DESCRIPTOR_DATA_BLOKS) <= 0) { sprintf(errstr,"Buffers too SMALL for formant data.\n"); return(PROGRAM_ERROR); } return reset_file_to_start_and_pointers_to_after_descriptor_blocks (ifd,windows_in_buf,n,wanted,specenvcnt,bigfbuf,flbufptr,total_samps_read,totalsize); } /***************************** CHECK_THE_FORMANT_DATA *************************/ int check_the_formant_data(int *windows_in_buf,float *specenvpch,float *specenvtop,float *bigfbuf,float **flbufptr,char **argv, infileptr ifp,int specenvcnt,int wanted,int *total_samps_read,int totalsize,int n,int *ifd) { int exit_status, k; int ssampsread; int fsamps_to_read = ifp->descriptor_samps/DESCRIPTOR_DATA_BLOKS; if((exit_status = local_read_samps(bigfbuf,wanted,total_samps_read,&ssampsread,n,ifd,totalsize)) < 0) return(exit_status); if(ssampsread < ifp->descriptor_samps) { sprintf(errstr,"No significant data in formantfile.\n"); return(DATA_ERROR); } *flbufptr = bigfbuf; for(k=0;k= 0 && (exit_status!=FINISHED || !is_launched) && sndunlink(ofd) < 0) fprintf(stdout, "ERROR: Can't set output soundfile for deletion.\n"); // if((ofd >= 0) && dz->needpeaks){ // if(sndputpeaks(dz->ofd,dz->outchans,dz->outpeaks)) { // fprintf(stdout,"WARNING: failed to write PEAK data\n"); // fflush(stdout); // } // } if(ofd >= 0 && sndcloseEx(ofd) < 0) { fprintf(stdout, "WARNING: Can't close output sf-soundfile : %s\n",sferrstr()); fflush(stdout); } if(ifd != NULL && infilecnt >= 0) { for(n=0;n= 0 && sndcloseEx(ifd[n]) < 0) fprintf(stdout, "WARNING: Can't close input sf-soundfile %d.\n",n+1); } } sffinish(); fprintf(stdout,"END:"); fflush(stdout); if(exit_status != FINISHED) { return(FAILED); } return(SUCCEEDED); } int local_readhead(infileptr inputfile,int ifd,char *filename,int getmax,int needmaxinfo) { SFPROPS props = {0}; int isenv = 0; int os; if(!snd_headread(ifd,&props)) { fprintf(stdout,"INFO: Failure to read properties, in %s\n",filename); fflush(stdout); return(DATA_ERROR); } inputfile->srate = props.srate; inputfile->channels = props.chans; switch(props.samptype) { case(SHORT16): inputfile->stype = SAMP_SHORT; break; case(FLOAT32): inputfile->stype = SAMP_FLOAT; break; case(SHORT8): inputfile->stype = SAMP_BYTE; break; default: /* remaining symbols have same int value */ break; } //TW TEMPORARY SUBSTITUTION inputfile->filetype = SNDFILE; if(sndgetprop(ifd,"is an envelope",(char *) &isenv,sizeof(int)) >= 0) inputfile->filetype = ENVFILE; else if(sndgetprop(ifd,"is a formant file",(char *) &isenv,sizeof(int)) >= 0) inputfile->filetype = FORMANTFILE; else if(sndgetprop(ifd,"is a pitch file",(char *) &isenv,sizeof(int)) >= 0) inputfile->filetype = PITCHFILE; else if(sndgetprop(ifd,"is a transpos file",(char *) &isenv,sizeof(int)) >= 0) inputfile->filetype = TRANSPOSFILE; else if(sndgetprop(ifd,"original sampsize",(char *) &os,sizeof(int)) > 0) inputfile->filetype = ANALFILE; inputfile->specenvcnt = props.specenvcnt; if(inputfile->channels != 1) { sprintf(errstr,"Channel count not equal to 1 in %s: readhead()\n" "Implies failure to write correct header in another program.\n", filename); return(PROGRAM_ERROR); } if(sndgetprop(ifd,"orig channels",(char *)&(inputfile->origchans),sizeof(int)) < 0) { fprintf(stdout,"Cannot read original channels count: %s\n",filename); fflush(stdout); return(DATA_ERROR); } if(sndgetprop(ifd,"original sampsize",(char *)&(inputfile->origstype),sizeof(int)) < 0) { fprintf(stdout,"Cannot read original sample type: %s\n",filename); fflush(stdout); return(DATA_ERROR); } if(sndgetprop(ifd,"original sample rate",(char *)&(inputfile->origrate),sizeof(int)) < 0) { fprintf(stdout,"Cannot read original sample rate: %s\n",filename); fflush(stdout); return(DATA_ERROR); } if(sndgetprop(ifd,"arate",(char *)&(inputfile->arate),sizeof(float)) < 0) { fprintf(stdout,"Cannot read analysis rate: %s\n",filename); fflush(stdout); return(DATA_ERROR); } if(sndgetprop(ifd,"analwinlen",(char *)&(inputfile->Mlen),sizeof(int)) < 0) { fprintf(stdout,"Cannot read analysis window length: %s\n",filename); fflush(stdout); return(DATA_ERROR); } if(sndgetprop(ifd,"decfactor",(char *)&(inputfile->Dfac),sizeof(int)) < 0) { fprintf(stdout,"Cannot read original decimation factor: %s\n",filename); fflush(stdout); return(DATA_ERROR); } return(FINISHED); } /****************************** LOCAL_SPLICE_MULTILINE_STRING ******************************/ void local_splice_multiline_string(char *str,char *prefix) { char *p, *q, c; p = str; q = str; while(*q != ENDOFSTR) { while(*p != '\n' && *p != ENDOFSTR) p++; c = *p; *p = ENDOFSTR; fprintf(stdout,"%s %s\n",prefix,q); *p = c; if(*p == '\n') p++; while(*p == '\n') { fprintf(stdout,"%s \n",prefix); p++; } q = p; p++; } } /**************************** FLTEQ *******************************/ int flteq(double f1,double f2) { double upperbnd, lowerbnd; upperbnd = f2 + FLTERR; lowerbnd = f2 - FLTERR; if((f1>upperbnd) || (f1specenvcnt), sizeof(int)) < 0){ sprintf(errstr,"Failure to write specenvcnt: headwrite()\n"); return(PROGRAM_ERROR); } if(sndputprop(ofd,"orig channels", (char *)&(ifp->origchans), sizeof(int)) < 0){ sprintf(errstr,"Failure to write original channel data: headwrite()\n"); return(PROGRAM_ERROR); } if(sndputprop(ofd,"original sampsize", (char *)&(ifp->origstype), sizeof(int)) < 0){ sprintf(errstr,"Failure to write original sample size. headwrite()\n"); return(PROGRAM_ERROR); } if(sndputprop(ofd,"original sample rate", (char *)&(ifp->origrate), sizeof(int)) < 0){ sprintf(errstr,"Failure to write original sample rate. headwrite()\n"); return(PROGRAM_ERROR); } if(sndputprop(ofd,"arate",(char *)&(ifp->arate),sizeof(float)) < 0){ sprintf(errstr,"Failed to write analysis sample rate. headwrite()\n"); return(PROGRAM_ERROR); } if(sndputprop(ofd,"analwinlen",(char *)&(ifp->Mlen),sizeof(int)) < 0){ sprintf(errstr,"Failure to write analysis window length. headwrite()\n"); return(PROGRAM_ERROR); } if(sndputprop(ofd,"decfactor",(char *)&(ifp->Dfac),sizeof(int)) < 0){ sprintf(errstr,"Failure to write decimation factor. headwrite()\n"); return(PROGRAM_ERROR); } if(sndputprop(ofd,"is a formant file", (char *)&property_marker, sizeof(int)) < 0){ sprintf(errstr,"Failure to write formant property: headwrite()\n"); return(PROGRAM_ERROR); } return(FINISHED); }