| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506 |
- /*
- * Copyright (c) 1983-2020 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
- *
- */
- /*floatsm version */
- #include <stdio.h>
- #include <stdlib.h>
- #include <structures.h>
- #include <tkglobals.h>
- #include <globcon.h>
- #include <processno.h>
- #include <modeno.h>
- #include <logic.h>
- #include <arrays.h>
- #include <grain.h>
- #include <cdpmain.h>
- #include <sfsys.h>
- //#ifdef unix
- #define round(x) lround((x))
- //#endif
- static int grains(int *ibufposition,int bufno,int *crosbuf,int *inithole,int *grainstart,int * is_first_grain,
- int *gapcnt,int *holecnt,int *obufpos,int *graincnt,int chans,int *grainadjusted,
- double samptotime,double **env,double **envstep,double *envel_val,int winsize,dataptr dz);
- static int read_gate(int abs_ipos,int chans,dataptr dz);
- static double get_grainstart_time
- (int ibufpos,int grainstart,int abs_ipos,int crosbuf,double samptotime,dataptr dz);
- static int adjust_gate(double *gate,double *ngate,int abs_ipos,int winsize,
- double **env,double **envstep,double *envel_val,dataptr dz);
- static void swap_infile_and_otherfile(dataptr dz);
- static int count_grains_for_assess(int *graincnt,dataptr dz);
- /**************************** PROCESS_GRAINS *****************************/
- int process_grains(dataptr dz)
- {
- int exit_status;
- int ibufpos = 0, obufpos = 0, graincnt = 0, gapcnt = 0, holecnt = 0, grainadjusted = 0;
- int bufno = 0, crosbuf = 0, inithole = TRUE;
- int is_first_grain = TRUE;
- int chans = dz->infile->channels;
- double samptotime = 1.0/(double)(dz->infile->srate * chans);
- int grainstart = 0, winsize = dz->iparam[GR_WSIZE_SAMPS];
- double *env = dz->parray[GR_ENVEL];
- double *envstep = dz->parray[GR_ENVSTEP];
- double envel_val;
- int grain_get_flag = 1;
- int real_process = 0;
- int firstpass = 1;
- display_virtual_time(0,dz);
- while(grain_get_flag == 1) {
- if(firstpass) {
- if((dz->process == GRAIN_GET) || (dz->process == GRAIN_ALIGN)) {
- real_process = dz->process;
- dz->process = GRAIN_COUNT;
- fprintf(stdout,"INFO: Counting the grains.\n");
- fflush(stdout);
- } else {
- grain_get_flag = 0;
- }
- } else {
- if(graincnt == 0) {
- sprintf(errstr,"ERROR: No grains were found.\n");
- return(GOAL_FAILED);
- }
- fprintf(stdout,"INFO: Getting the grains.\n");
- fflush(stdout);
- if(sndseekEx(dz->ifd[0],0,0)<0) {
- sprintf(errstr,"Failed to seek to start of file.");
- return(SYSTEM_ERROR);
- }
- dz->total_samps_read = 0;
- dz->samps_left = dz->insams[0];
- display_virtual_time(0,dz);
- dz->process = real_process;
- env = dz->parray[GR_ENVEL];
- envstep = dz->parray[GR_ENVSTEP];
- ibufpos = 0;
- obufpos = 0;
- gapcnt = 0;
- holecnt = 0;
- bufno = 0;
- crosbuf = 0;
- grainadjusted = 0;
- inithole = TRUE;
- is_first_grain = TRUE;
- grain_get_flag = 0;
- if(sndseekEx(dz->ifd[0],0,0)<0) {
- sprintf(errstr,"ERROR: seek failed.\n");
- return(SYSTEM_ERROR);
- }
- }
- while(dz->samps_left > 0) {
- if((exit_status = read_samps(dz->sampbuf[bufno],dz))<0)
- return(exit_status);
- if((exit_status = grains(&ibufpos,bufno,&crosbuf,&inithole,&grainstart,&is_first_grain,
- &gapcnt,&holecnt,&obufpos,&graincnt,chans,&grainadjusted,samptotime,&env,&envstep,&envel_val,winsize,dz))<0)
- return(exit_status);
- if(exit_status!=CONTINUE)
- break;
- bufno = !bufno;
- }
- //TW REVISED
- if((exit_status = deal_with_last_grains(ibufpos,bufno,&graincnt,grainstart,
- &grainadjusted, &obufpos,crosbuf,chans,samptotime,&is_first_grain,dz))<0)
- return(exit_status);
- if(dz->outfiletype==SNDFILE_OUT && dz->process != GRAIN_ALIGN && obufpos!=0
- && (exit_status = write_samps(dz->sampbuf[2],obufpos ,dz))<0)
- return(exit_status);
- if(grainadjusted>0) {
- fprintf(stdout,"WARNING: %d output grains too small: size adjusted\n",grainadjusted);
- fflush(stdout);
- }
- firstpass = 0;
- }
-
- return(FINISHED);
- }
- /**************************** GRAINS *****************************/
- int grains(int *ibufposition,int bufno,int *crosbuf,int *inithole,int *grainstart,int *is_first_grain,
- int *gapcnt,int *holecnt,int *obufpos,int *graincnt,int chans,int *grainadjusted,
- double samptotime,double **env,double **envstep,double *envel_val,int winsize,dataptr dz)
- {
- int exit_status;
- register int ibufpos, abs_ipos;
- int in_grain, m;
- double gate, ngate;
- double thistime;
- float *obuf = dz->sampbuf[2];
- float *b = dz->sampbuf[bufno];
- int has_snd_output = FALSE;
- int samps_read_before_thisbuf = dz->total_samps_read - dz->ssampsread;
- if(dz->outfiletype==SNDFILE_OUT && dz->process != GRAIN_ALIGN)
- has_snd_output = TRUE;
- for(ibufpos = 0,abs_ipos = samps_read_before_thisbuf; ibufpos < dz->ssampsread; ibufpos+=chans,abs_ipos+=chans) {
- if(dz->ptr[GR_GATEVALS]!=NULL && (exit_status = read_gate(abs_ipos,chans,dz))<0)
- return(exit_status);
- gate = dz->param[GR_GATE] * F_MAXSAMP;
- ngate = dz->param[GR_NGATE] * F_MAXSAMP;
- if(dz->iparam[GR_WSIZE_SAMPS] > 0) { /* envelope tracking */
- if((exit_status = adjust_gate(&gate,&ngate,abs_ipos,winsize,env,envstep,envel_val,dz))<0)
- return(exit_status);
- }
- in_grain = FALSE;
- for(m=0;m<chans;m++) {
- if(b[ibufpos+m]>gate || b[ibufpos+m]<ngate)
- in_grain = TRUE;
- }
- if(in_grain) {
- if(*inithole) {
- *grainstart = ibufpos;
- *inithole = 0;
- }
- if(*holecnt) {
- if(*holecnt >= dz->iparam[GR_MINHOLE]) {
- thistime = get_grainstart_time(ibufpos,*grainstart,abs_ipos,*crosbuf,samptotime,dz);
- if((exit_status = read_values_from_all_existing_brktables(thistime,dz))<0)
- return(exit_status);
- if((exit_status = do_the_grain(ibufpos,graincnt,bufno,*gapcnt,obufpos,*grainstart,
- *crosbuf,chans,grainadjusted,samptotime,is_first_grain,dz))<0)
- return(exit_status);
- if(exit_status!=CONTINUE) {
- *ibufposition = ibufpos;
- return(FINISHED); /* grsync ran out of sync-times */
- }
- *grainstart = ibufpos;
- *gapcnt = 0;
- *crosbuf = 0;
- }
- }
- *holecnt = 0;
- } else {
- if(*inithole) {
- if(has_snd_output) {
- for(m=0;m<chans;m++)
- obuf[(*obufpos)++] = b[ibufpos+m];
- if(*obufpos >= dz->buflen) {
- if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
- return(exit_status);
- *obufpos = 0;
- }
- }
- continue;
- }
- *holecnt += chans;
- }
- *gapcnt += chans;
- }
- *ibufposition = ibufpos;
- if(*crosbuf==TRUE) { /* If crosbuf STILL set */
- if(dz->ssampsread == dz->buflen) { /* Reached end of buffer while doing crosbuf grain */
- if(dz->process == GRAIN_COUNT && dz->itemcnt == GRAIN_ASSESS) {
- if(dz->vflag[0] == 0) {
- fprintf(stdout,"WARNING: Encountered grain too large for buffer: counting grains so far\n");
- dz->vflag[0] = 1;
- }
- } else
- fprintf(stdout,"WARNING: Encountered grain too large for buffer: writing file so far\n");
- fflush(stdout);
- }
- return(FINISHED); /* Else reached end of file while doing crosbuf grain */
- }
- if(dz->samps_left) /* UNLESS we've reached end of src */
- *crosbuf = TRUE; /* mark crossing into next buffer */
- return(CONTINUE);
- }
- /************************** COPYGRAIN ******************************/
- int copygrain(int start,int end,int bufno,int *obufposition,dataptr dz)
- {
- int exit_status;
- float *b = dz->sampbuf[bufno];
- float *obuf = dz->sampbuf[2];
- register int n, obufpos = *obufposition;
- for(n=start;n<end;n++) {
- obuf[obufpos++] = b[n];
- if(obufpos >= dz->buflen) {
- if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
- return(exit_status);
- obufpos = 0;
- }
- }
- *obufposition = obufpos;
- return(FINISHED);
- }
- /************************ CROSBUF_GRAIN_TYPE3 **********************/
- int crosbuf_grain_type3(int grainstart,int grainend,int bufno,int *obufpos,dataptr dz)
- {
- int exit_status;
- if((exit_status = copygrain(grainstart,dz->buflen,!bufno,obufpos,dz))<0)
- return(exit_status);
- return copygrain(0L,grainend,bufno,obufpos,dz);
- }
- /***************************** CHECK_GRAIN_CONSISTENCY ******************************/
- int check_grain_consistency(dataptr dz)
- {
- int exit_status;
- int maxval;
- double dmaxval;
- switch(dz->process) {
- case(GRAIN_OMIT): /* Check grains-to-KEEP vals against OUT-OF */
- if(dz->brksize[GR_KEEP]) {
- if((exit_status = get_maxvalue_in_brktable(&dmaxval,GR_KEEP,dz))<0)
- return(exit_status);
- maxval = round(dmaxval);
- } else
- maxval = dz->iparam[GR_KEEP];
- if(maxval > dz->iparam[GR_OUT_OF]) {
- sprintf(errstr,"A value of %d grains-to-keep out of each %d is impossible.\n",maxval,(int)dz->iparam[GR_OUT_OF]);
- return(DATA_ERROR);
- }
- break;
- default:
- sprintf(errstr,"Unknown case in check_grain_consistency()\n");
- return(PROGRAM_ERROR);
- }
- return(FINISHED);
- }
- /***************************** READ_GATE ******************************/
- int read_gate(int abs_ipos,int chans,dataptr dz)
- {
- double sampstep;
- if(abs_ipos >= dz->iparam[GR_NEXTBRKSAMP]) {
- dz->iparam[GR_THISBRKSAMP] = dz->iparam[GR_NEXTBRKSAMP];
- dz->param[GR_GATE] = dz->param[GR_NEXTGATE];
- dz->param[GR_NGATE] = -(dz->param[GR_GATE]);
- dz->iparam[GR_NEXTBRKSAMP] = round(*(dz->ptr[GR_GATEVALS]++));
- dz->param[GR_NEXTGATE] = *(dz->ptr[GR_GATEVALS]++);
- if((dz->iparam[GR_TESTLIM] = dz->iparam[GR_NEXTBRKSAMP] - (GR_INTERPLIMIT * chans)) < dz->iparam[GR_THISBRKSAMP])
- dz->iparam[GR_TESTLIM] = dz->iparam[GR_NEXTBRKSAMP];
- sampstep = (double)((dz->iparam[GR_NEXTBRKSAMP] - dz->iparam[GR_THISBRKSAMP])/chans);
- dz->param[GR_GATESTEP] = (double)(dz->param[GR_NEXTGATE] - dz->param[GR_GATE])/sampstep;
- if(dz->param[GR_GATESTEP]>0.0)
- dz->iparam[GR_UP] = TRUE;
- else
- dz->iparam[GR_UP] = FALSE;
- } else {
- dz->param[GR_GATE] += dz->param[GR_GATESTEP];
- if(abs_ipos > dz->iparam[GR_TESTLIM]) { /* allowing for arithmetic rounding */
- if(dz->iparam[GR_UP]==TRUE) {
- if(dz->param[GR_GATE] > dz->param[GR_NEXTGATE])
- dz->param[GR_GATE] = dz->param[GR_NEXTGATE];
- } else {
- if(dz->param[GR_GATE] < dz->param[GR_NEXTGATE])
- dz->param[GR_GATE] = dz->param[GR_NEXTGATE];
- }
- }
- dz->param[GR_NGATE] = -(dz->param[GR_GATE]);
- }
- return(FINISHED);
- }
- /**************************** GET_GRAINSTART_TIME ***************************/
- double get_grainstart_time(int ibufpos,int grainstart,int abs_ipos,int crosbuf,double samptotime,dataptr dz)
- {
- double thistime;
- int abs_grainstart;
- int grainlen = ibufpos - grainstart;
- if(crosbuf)
- grainlen += dz->buflen;
- abs_grainstart = abs_ipos - grainlen;
- thistime = (double)abs_grainstart * samptotime;
- return thistime;
- }
- /******************* SWAP_TO_OTHERFILE_AND_READJUST_COUNTERS *******************/
- int swap_to_otherfile_and_readjust_counters(dataptr dz)
- {
- swap_infile_and_otherfile(dz); /* Now process 2nd file AS IF it were infile. */
- dz->infile->channels = dz->otherfile->channels;
- dz->infile->srate = dz->otherfile->srate;
- dz->infile->stype = dz->otherfile->stype;
- reset_filedata_counters(dz); /* initalise all counters before starting 2nd processing */
- if(dz->iparam[GR_WSIZE_SAMPS] > 0) { /* Free envelope storage arrays */
- free(dz->parray[GR_ENVEL]);
- free(dz->parray[GR_ENVSTEP]);
- }
- return(FINISHED);
- }
- /***************************** SWAP_INFILE_AND_OTHERFILE **************************
- *
- * SWAPPING (rather than simply replacing ifd0 by ifd1) ensures that both files
- * are closed properly in finish().
- */
- void swap_infile_and_otherfile(dataptr dz)
- {
- int fd;
- int filesize;
- int insamples;
- fd = dz->ifd[0];
- dz->ifd[0] = dz->ifd[1];
- dz->ifd[1] = fd;
- filesize = dz->insams[0];
- dz->insams[0] = dz->insams[1];
- dz->insams[1] = filesize;
- insamples = dz->insams[0];
- dz->insams[0] = dz->insams[1];
- dz->insams[1] = insamples;
- }
- /**************************** ADJUST_GATE ***************************/
- int adjust_gate(double *gate,double *ngate,int abs_ipos,int winsize,
- double **env,double **envstep,double *envel_val,dataptr dz)
- {
- int cnt;
- if(abs_ipos==0)
- *envel_val = **env;
- else if((cnt = abs_ipos%winsize)==0) {
- (*env)++;
- (*envstep)++;
- if(*env >= dz->ptr[GR_ENVEND] || *envstep >= dz->ptr[GR_ESTEPEND]) {
- sprintf(errstr,"Envelope array overflow: adjust_gate()\n");
- return(PROGRAM_ERROR);
- }
- *envel_val = **env;
- } else
- *envel_val += **envstep;
- *gate *= *envel_val;
- *ngate = -(*gate);
- return(FINISHED);
- }
- /*************************** ASSESS_GRAINS **************************/
- int assess_grains(dataptr dz)
- {
- int exit_status;
- int lastgraincnt = 0, graincnt = 0;
- int firsttime = 1;
- double step = 0.1;
- double bestgate;
- double hi_error = 1.0 -FLTERR;
- dz->process = GRAIN_COUNT;
- dz->itemcnt = GRAIN_ASSESS; /*n temporary storage */
- dz->param[GR_GATE] = GR_GATE_DEFAULT;
- dz->param[GR_NGATE] = -(dz->param[GR_GATE]);
- bestgate = dz->param[GR_GATE];
- fprintf(stdout,"INFO: Scanning file\n");
- fflush(stdout);
- step = 0.1;
- firsttime = 1;
- if((exit_status = count_grains_for_assess(&graincnt,dz)) < 0) {
- dz->process = GRAIN_ASSESS;
- return(exit_status);
- }
- dz->param[GR_GATE] += step;
- dz->param[GR_NGATE] = -(dz->param[GR_GATE]);
- while(fabs(step) > .00002) {
- lastgraincnt = graincnt;
- graincnt = 0;
- if((exit_status = count_grains_for_assess(&graincnt,dz)) < 0) {
- dz->process = GRAIN_ASSESS;
- return(exit_status);
- }
- if(graincnt >= lastgraincnt) {
- firsttime = 0;
- bestgate = dz->param[GR_GATE];
- dz->param[GR_GATE] += step;
- if(dz->param[GR_GATE] >= hi_error || dz->param[GR_GATE] < 0.0) {
- dz->param[GR_GATE] -= step;
- step *= 0.1;
- dz->param[GR_GATE] += step;
- firsttime = 1;
- }
- } else if(firsttime) {
- graincnt = lastgraincnt;
- step = -step;
- if((dz->param[GR_GATE] += (step * 2.0)) < 0.0) {
- break;
- }
- firsttime = 0;
- } else {
- dz->param[GR_GATE] -= step;
- bestgate = dz->param[GR_GATE];
- graincnt = lastgraincnt;
- step *= 0.1;
- dz->param[GR_GATE] += step;
- firsttime = 1;
- }
- dz->param[GR_NGATE] = -dz->param[GR_GATE];
- }
- if(lastgraincnt == 0)
- sprintf(errstr,"Unable to find any grains in this sound.\n");
- else
- sprintf(errstr,"Maximum grains found = %d at gate value %lf and windowlen 50ms\n",lastgraincnt,bestgate);
- fflush(stdout);
- dz->process = GRAIN_ASSESS;
- return(FINISHED);
- }
- /*************************** COUNT_GRAINS_FOR_ASSESS **************************/
- int count_grains_for_assess(int *graincnt,dataptr dz)
- {
- int exit_status;
- int ibufpos = 0, obufpos = 0, gapcnt = 0, holecnt = 0, grainadjusted = 0;
- int bufno = 0, crosbuf = 0, inithole = TRUE;
- int is_first_grain = TRUE;
- int chans = dz->infile->channels;
- double samptotime = 1.0/(double)(dz->infile->srate * chans);
- int grainstart=0, winsize = dz->iparam[GR_WSIZE_SAMPS];
- double *env = dz->parray[GR_ENVEL];
- double *envstep = dz->parray[GR_ENVSTEP];
- double envel_val;
- sndseekEx(dz->ifd[0],0,0);
- reset_filedata_counters(dz);
- display_virtual_time(0,dz);
- while(dz->samps_left > 0) {
- if((exit_status = read_samps(dz->sampbuf[bufno],dz)<0))
- return(exit_status);
- if((exit_status = grains(&ibufpos,bufno,&crosbuf,&inithole,&grainstart,&is_first_grain,
- &gapcnt,&holecnt,&obufpos,graincnt,chans,&grainadjusted,samptotime,&env,&envstep,&envel_val,winsize,dz))<0)
- return(exit_status);
- if(exit_status!=CONTINUE)
- break;
- bufno = !bufno;
- }
- if((exit_status = deal_with_last_grains(ibufpos,bufno,graincnt,grainstart,
- &grainadjusted, &obufpos,crosbuf,chans,samptotime,&is_first_grain,dz))<0)
- return(exit_status);
- return(FINISHED);
- }
|