/* * 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 static int rwd_accumulate(int index,float *flbufptr, float *windowbuf); static int do_fold(int vc,double lofrq_limit,double hifrq_limit,dataptr dz); static int fold_in(int vc,double thisfrq,dataptr dz); static int do_stable_peaks_filter(int *peakscore,int *descnt,double lofrq_limit,double hifrq_limit,dataptr dz); static int extract_formant_peaks(int *pkcnt_here,double lofrq_limit,double hifrq_limit,int *least,dataptr dz); static int establish_bottom_and_top_of_filter_bands(int pkcnt_here,dataptr dz); static int do_focu_filter(float *thisbuf,dataptr dz); static int design_filter(int *peakscore,int *descnt,dataptr dz); static int increment_pointer_in_output_buffer(dataptr dz); static int insert_new_peak_in_peaklist(int position_in_formant,int *least,dataptr dz); static int sort_focu_peaks_by_frq(int pkcnt_here,dataptr dz); static int write_last_focu_buffers(dataptr dz); static int read_first_buffer(int *windows_in_buf,dataptr dz); static int sfwind(int *windows_in_buf,int *wndws_read_pre_thisbuf,dataptr dz); static int get_buffer_containing_frzpos(int frztime,int *frzpos,int *windows_in_buf, int *wndws_read_pre_thisbuf,dataptr dz); static int get_freeze_template(dataptr dz); static int get_startwindow_position(int *startwpos,int this_segtime,int *wndws_read_pre_thisbuf, int *windows_in_buf,int buffer_saved,dataptr dz); static int freeze_data(dataptr dz); static int save_buffer(dataptr dz); static int sfrewind(int *windows_in_buf,int window_sought,int *wndws_read_pre_thisbuf,dataptr dz); static int restore_buffer(dataptr dz); static int do_specstep(int wc,dataptr dz); /* NEW CODE */ static int read_buffer(int *windows_in_buf,dataptr dz); /* NEW CODE */ /********************************** SPECACCU **********************************/ int specaccu(dataptr dz) { int exit_status; int vc, cc; if(dz->param[ACCU_GLIS] > 0.0) { if(dz->param[ACCU_DECAY] < 1.0) { for(cc = 0, vc = 0; cc < dz->clength; cc++, vc += 2) { dz->windowbuf[0][AMPP] = (float)(dz->windowbuf[0][AMPP] * dz->param[ACCU_DINDEX]); dz->windowbuf[0][FREQ] = (float)(dz->windowbuf[0][FREQ] * dz->param[ACCU_GINDEX]); if((exit_status = rwd_accumulate(vc,dz->flbufptr[0],dz->windowbuf[0]))<0) return(exit_status); } } else { for(cc = 0, vc = 0; cc < dz->clength; cc++, vc += 2) { dz->windowbuf[0][FREQ] = (float)(dz->windowbuf[0][FREQ] * dz->param[ACCU_GINDEX]); if((exit_status = rwd_accumulate(vc,dz->flbufptr[0],dz->windowbuf[0]))<0) return(exit_status); } } } else if(dz->param[ACCU_DECAY] < 1.0) { for(cc = 0, vc = 0; cc < dz->clength; cc++, vc += 2) { dz->windowbuf[0][AMPP] = (float)(dz->windowbuf[0][AMPP] * dz->param[ACCU_DINDEX]); if((exit_status = rwd_accumulate(vc,dz->flbufptr[0],dz->windowbuf[0]))<0) return(exit_status); } } else { for(cc = 0, vc = 0; cc < dz->clength; cc++, vc += 2) { if((exit_status = rwd_accumulate(vc,dz->flbufptr[0],dz->windowbuf[0]))<0) return(exit_status); } } return(FINISHED); } /********************************** RWD_ACCUMULATE **********************************/ int rwd_accumulate(int index,float *flbufptr, float *windowbuf) { int frq = index+1; if(flbufptr[index] > windowbuf[index]) { /* if current amp > amp in accumulator */ windowbuf[index] = flbufptr[index]; windowbuf[frq] = flbufptr[frq]; /* replace amp in accumulator with current amp */ } else { flbufptr[index] = windowbuf[index]; /* else replace current amp with amp in accumulator */ flbufptr[frq] = windowbuf[frq]; } return(FINISHED); } /**************************** SPECEXAG ****************************/ int specexag(int *zero_set,dataptr dz) { int cc, vc; double post_totalamp = 0.0, pre_totalamp = 0.0; double maxamp = 0.0, normaliser; for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2) { pre_totalamp += dz->flbufptr[0][vc]; if(dz->flbufptr[0][vc] > maxamp) maxamp = dz->flbufptr[0][vc]; } if(maxamp<=0.0) { *zero_set = TRUE; return(FINISHED); } normaliser = 1.0/maxamp; for(cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2) { dz->flbufptr[0][vc] = (float)(dz->flbufptr[0][vc] * normaliser); dz->flbufptr[0][vc] = (float)(pow(dz->flbufptr[0][vc],dz->param[EXAG_EXAG])); post_totalamp += dz->flbufptr[0][vc]; } return normalise(pre_totalamp,post_totalamp,dz); } /**************************** SPECFOLD ***************************/ int specfold(dataptr dz) { int exit_status; int vc; double hifrq_limit = dz->param[FOLD_HIFRQ]; double lofrq_limit = dz->param[FOLD_LOFRQ]; if(hifrq_limit < lofrq_limit) swap(&lofrq_limit,&hifrq_limit); if(dz->brksize[FOLD_HIFRQ]) { dz->iparam[FOLD_HICHAN] = (int)((hifrq_limit + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */ dz->param[FOLD_HICHANTOP] = ((double)dz->iparam[FOLD_HICHAN] * dz->chwidth) + dz->halfchwidth; if(dz->iparam[FOLD_HICHAN] != 0) dz->iparam[FOLD_HICHAN] <<= 1; } if(dz->brksize[FOLD_LOFRQ]) { dz->iparam[FOLD_LOCHAN] = (int)((lofrq_limit + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */ if(dz->iparam[FOLD_LOCHAN] > 0) dz->param[FOLD_LOCHANBOT] = ((double)(dz->iparam[FOLD_LOCHAN]-1) * dz->chwidth) + dz->halfchwidth; else dz->param[FOLD_LOCHANBOT] = 0.0; if(dz->iparam[FOLD_LOCHAN] != 0) dz->iparam[FOLD_LOCHAN]<<= 1; } for(vc = 0; vc < dz->wanted; vc += 2) { if((exit_status = do_fold(vc,lofrq_limit,hifrq_limit,dz))<0) return(exit_status); } return(FINISHED); } /******************************* DO_FOLD **************************/ int do_fold(int vc,double lofrq_limit,double hifrq_limit,dataptr dz) { int exit_status; double thisfrq = fabs((double)dz->flbufptr[0][FREQ]); if(thisfrq < 1.0) { dz->flbufptr[0][AMPP] = 0.0f; return(FINISHED); } if(thisfrq < lofrq_limit) { while(thisfrq < lofrq_limit) thisfrq *= 2.0; if(thisfrq < hifrq_limit) { if((exit_status = fold_in(vc,thisfrq,dz))<0) return(exit_status); } dz->flbufptr[0][AMPP] = 0.0f; } else { if(thisfrq > hifrq_limit) { while(thisfrq > hifrq_limit) thisfrq /= 2.0; if(thisfrq > lofrq_limit) { if((exit_status = fold_in(vc,thisfrq,dz))<0) return(exit_status); } dz->flbufptr[0][AMPP] = 0.0f; } } return(FINISHED); } /******************************** FOLD_IN ************************/ int fold_in(int vc,double thisfrq,dataptr dz) { #define THISCHANSCAN (4) int truecc, truevc; int minscan, maxscan, n; truecc = (int)((thisfrq + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */ truevc = truecc * 2; switch(dz->vflag[FOLD_WITH_BODY]) { case(FALSE): if(dz->flbufptr[0][AMPP] > dz->flbufptr[0][truevc]) { dz->flbufptr[0][truevc++] = dz->flbufptr[0][AMPP]; dz->flbufptr[0][truevc] = dz->flbufptr[0][FREQ]; } break; case(TRUE): if(dz->flbufptr[0][AMPP] > dz->flbufptr[0][truevc]) { dz->flbufptr[0][truevc++] = dz->flbufptr[0][AMPP]; dz->flbufptr[0][truevc] = dz->flbufptr[0][FREQ]; return(FINISHED); } minscan = max(dz->iparam[FOLD_LOCHAN]-2,truevc - (THISCHANSCAN * 2)); maxscan = min(dz->iparam[FOLD_HICHAN]+2,truevc + (THISCHANSCAN * 2)); for(n=truevc-2;n>minscan;n-=2) { if(dz->flbufptr[0][AMPP] > dz->flbufptr[0][n]) { dz->flbufptr[0][n++] = dz->flbufptr[0][AMPP]; dz->flbufptr[0][n] = dz->flbufptr[0][FREQ]; return(FINISHED); } } for(n=truevc+2;nflbufptr[0][AMPP] > dz->flbufptr[0][n]) { dz->flbufptr[0][n++] = dz->flbufptr[0][AMPP]; dz->flbufptr[0][n] = dz->flbufptr[0][FREQ]; return(FINISHED); } } break; default: sprintf(errstr,"Unknown case in fold_in()\n"); return(PROGRAM_ERROR); } return(FINISHED); } /**************************** OUTER_FOCU_LOOP ****************************/ int outer_focu_loop(dataptr dz) { int exit_status; int samps_read, got, windows_in_buf; int peakscore = 0, pitchcnt = 0; int in_start_portion = TRUE, least = 0, descnt = 0; if(dz->vflag[FOCUS_STABLE]) dz->flbufptr[1] = dz->flbufptr[2]; while((samps_read = fgetfbufEx(dz->bigfbuf, dz->buflen,dz->ifd[0],0)) > 0) { got = samps_read; dz->flbufptr[0] = dz->bigfbuf; windows_in_buf = got/dz->wanted; if((exit_status = inner_loop(&peakscore,&descnt,&in_start_portion,&least,&pitchcnt,windows_in_buf,dz))<0) return(exit_status); if(!dz->vflag[FOCUS_STABLE] && (samps_read > 0)) { if((exit_status = write_exact_samps(dz->bigfbuf,samps_read,dz))<0) return(exit_status); } } if(samps_read < 0) { sprintf(errstr,"Sound read error.\n"); return(SYSTEM_ERROR); } if(dz->vflag[FOCUS_STABLE]) return write_last_focu_buffers(dz); return(FINISHED); } /**************************** SPECFOCUS ***************************/ int specfocus(int *peakscore,int *descnt,int *least,dataptr dz) { int exit_status; double lofrq_limit, hifrq_limit, d; int pkcnt_here; lofrq_limit = dz->param[FOCU_LOFRQ]; hifrq_limit = dz->param[FOCU_HIFRQ]; if(dz->brksize[FOCU_LOFRQ] || dz->brksize[FOCU_HIFRQ]) { if(flteq(lofrq_limit,hifrq_limit)) { sprintf(errstr,"Frequency limits define a zero-width band at time %lf.\n",dz->time); return(USER_ERROR); } if(lofrq_limit > hifrq_limit) swap(&lofrq_limit,&hifrq_limit); } if(dz->brksize[FOCU_BW]) { d = dz->param[FOCU_BW]/2.0; /* d is halfbandwidth. */ dz->scalefact = PI/d; /* Convert an 8va offset from filter centre-frq */ /* to a fraction of the bandwidth * PI */ dz->param[FOCU_BRATIO_UP] = pow(2.0,d); /* upward transp ratio to top of filtband */ dz->param[FOCU_BRATIO_DN] = 1.0/dz->param[FOCU_BRATIO_UP]; } /* Downward transp ratio to bot of fband */ rectify_window(dz->flbufptr[0],dz); if((exit_status = extract_specenv(0,0,dz))<0) return(exit_status); if(dz->vflag[FOCUS_STABLE]) return do_stable_peaks_filter(peakscore,descnt,lofrq_limit,hifrq_limit,dz); if((exit_status = extract_formant_peaks(&pkcnt_here,lofrq_limit,hifrq_limit,least,dz))<0) return(exit_status); if((exit_status = establish_bottom_and_top_of_filter_bands(pkcnt_here,dz))<0) return(exit_status); if((exit_status = construct_filter_envelope(pkcnt_here,dz->flbufptr[0],dz))<0) return(exit_status); return do_focu_filter(dz->flbufptr[0],dz); } /****************************** DO_STABLE_PEAKS_FILTER ***************************/ int do_stable_peaks_filter(int *peakscore,int *descnt,double lofrq_limit,double hifrq_limit,dataptr dz) { int exit_status, thispkcnt; // int *fppk = dz->stable->fpk[dz->iparam[FOCU_SL1]], n; int n; /* shufl bak stord specenvs: */ /* put latest specenvarray here */ memmove((char *)dz->stable->spec[0], //TW CODE ERROR // (char *)dz->stable->spec[1],dz->iparam[FOCU_SL1] * dz->infile->specenvcnt * sizeof(int)); (char *)dz->stable->spec[1],dz->iparam[FOCU_SL1] * dz->infile->specenvcnt * sizeof(float)); memmove((char *)dz->stable->spec[dz->iparam[FOCU_SL1]], //TW CODE ERROR // (char *)dz->specenvamp,dz->infile->specenvcnt * sizeof(int)); (char *)dz->specenvamp,dz->infile->specenvcnt * sizeof(float)); memmove((char *)dz->stable->fpk[0], (char *)dz->stable->fpk[1], dz->iparam[FOCU_SL1] * dz->infile->specenvcnt * sizeof(int)); memmove((char *)dz->stable->total_pkcnt,(char *)(dz->stable->total_pkcnt+1),dz->iparam[FOCU_SL1] * sizeof(int)); /* shufl bak stord fpks & shufl bak stored fpk_totals */ if((exit_status = extract_formant_peaks2(FOCU_SL1,&thispkcnt,lofrq_limit,hifrq_limit,dz))<0) return(exit_status); /* put into into last fpk[z] store */ dz->stable->total_pkcnt[dz->iparam[FOCU_SL1]] = thispkcnt; /* put into into last fpk[z] store */ if(dz->total_windows >= dz->iparam[FOCU_SL1]) { /* before this we can't design a filter */ if((exit_status = design_filter(peakscore,descnt,dz))<0) return(exit_status); if(dz->total_windows==dz->iparam[FOCU_SL1]) { /* If 1st time to do filtering */ memmove((char *)(dz->flbufptr[1]),(char *)dz->stable->sbuf[0],(size_t)dz->wanted * sizeof(float)); /* copy zero-amp-1st-buff */ if((exit_status = increment_pointer_in_output_buffer(dz))<0) return(exit_status); for(n = 1; n <= dz->stable->offset; n++) { /* filter all windows <= offset, using 1st filter */ if((exit_status = do_focu_filter(dz->stable->sbuf[n],dz))<0) return(exit_status); /* and output them */ memmove((char *)(dz->flbufptr[1]),(char *)dz->stable->sbuf[n],(size_t)dz->wanted * sizeof(float)); if((exit_status = increment_pointer_in_output_buffer(dz))<0) return(exit_status); } } else { /* all later times to do filtering */ /* filter buffer at offset and output it */ if((exit_status = do_focu_filter(dz->stable->sbuf[dz->stable->offset],dz))<0) return(exit_status); memmove((char *)dz->flbufptr[1],(char *)dz->stable->sbuf[dz->stable->offset],(size_t)dz->wanted * sizeof(float)); if((exit_status = increment_pointer_in_output_buffer(dz))<0) return(exit_status); } } memmove((char *)dz->stable->sbuf[0],(char *)dz->stable->sbuf[1], (size_t)(dz->wanted * sizeof(float) * dz->iparam[FOCU_SL1])); /* shuffle back stored bufs */ memmove((char *)dz->stable->sbuf[dz->iparam[FOCU_SL1]],(char *)dz->flbufptr[0],(size_t)dz->wanted * sizeof(float)); return(FINISHED); /* copy new buf to store */ } /****************************** EXTRACT_FORMANT_PEAKS ***************************/ int extract_formant_peaks(int *pkcnt_here,double lofrq_limit,double hifrq_limit,int *least,dataptr dz) { int exit_status; int n = 0; int falling = 0, last_channel_was_in_range = 1; *pkcnt_here = 0; for(n=0;nitemcnt;n++) dz->filtpeak[n] = 0.0; n = 1; while(ninfile->specenvcnt) { if(dz->specenvfrq[n] < lofrq_limit) { last_channel_was_in_range = 0; n++; continue; } if(dz->specenvamp[n] > dz->specenvamp[n-1]) falling = 0; else { if(!falling) { if(last_channel_was_in_range) { if((exit_status = insert_new_peak_in_peaklist(n-1,least,dz))<0) return(exit_status); } (*pkcnt_here)++; falling = 1; } } last_channel_was_in_range = 1; if(dz->specenvfrq[n] > hifrq_limit) break; n++; } *pkcnt_here = min(*pkcnt_here,dz->itemcnt); return sort_focu_peaks_by_frq(*pkcnt_here,dz); } /******************************** ESTABLISH_BOTTOM_AND_TOP_OF_FILTER_BANDS ************************/ int establish_bottom_and_top_of_filter_bands(int pkcnt_here,dataptr dz) { int n; for(n=0;nfbandbot[n] = dz->specenvfrq[dz->peakno[n]] * dz->param[FOCU_BRATIO_DN]; dz->fbandtop[n] = min(dz->specenvfrq[dz->peakno[n]] * dz->param[FOCU_BRATIO_UP],dz->nyquist); } return(FINISHED); } /****************************** DO_FOCU_FILTER ***************************/ int do_focu_filter(float *thisbuf,dataptr dz) { int cc, vc; for(cc=0, vc=0; cc < dz->clength; cc++, vc += 2) thisbuf[AMPP] = (float)(thisbuf[AMPP] * dz->fsampbuf[cc]); return(FINISHED); } /****************************** DESIGN_FILTER ******************************/ int design_filter(int *peakscore,int *descnt,dataptr dz) { int exit_status; int this_pkcnt; int n = 0; int pkcnt_here; if(dz->total_windows<=dz->iparam[FOCU_SL1]) memset((char *)dz->stable->design_score,0,dz->infile->specenvcnt * sizeof(int)); if((exit_status = score_peaks(peakscore,FOCU_SL1,FOCU_STABL,dz))<0) return(exit_status); if(*peakscore==0) { memset(dz->fsampbuf,0,(size_t)dz->wanted * sizeof(float)); /* zero filter */ return(FINISHED); } if((exit_status = collect_scores(&this_pkcnt,descnt,dz))<0) return(exit_status); /* Find how many times each peak occurs across the stabilise buffers */ if((exit_status = sort_design(this_pkcnt,dz))<0) /* Sort these on the basis of the most commonly occuring */ return(exit_status); if(this_pkcnt<=dz->itemcnt || (dz->stable->des[dz->itemcnt-1]->score > dz->stable->des[dz->itemcnt]->score)) { pkcnt_here = min(this_pkcnt,dz->itemcnt); for(n=0;npeakno[n] = dz->stable->des[n]->chan;/* these are the peaks to keep */ } else { /* Else choose amongst equivalent peaks, in terms of amplitude */ if((exit_status = sort_equivalent_scores(this_pkcnt,dz))<0) return(exit_status); pkcnt_here = dz->itemcnt; } if((exit_status = sort_focu_peaks_by_frq(pkcnt_here,dz))<0) return(exit_status); if((exit_status = establish_bottom_and_top_of_filter_bands(pkcnt_here,dz))<0) return(exit_status); if((exit_status = construct_filter_envelope(pkcnt_here,dz->stable->sbuf[dz->stable->offset],dz))<0) return(exit_status); if(dz->total_windows>dz->iparam[FOCU_SL1]) { /* Logically this should be '>=dz->iparam[FOCU_SL1]' : but */ if((exit_status = unscore_peaks(peakscore,dz))<0) return(exit_status); /* don't have to subtract window 0, as there are NO PEAKS there */ } return(FINISHED); } /****************************** INCREMENT_POINTER_IN_OUTPUT_BUFFER ***************************/ int increment_pointer_in_output_buffer(dataptr dz) { int exit_status; if((dz->flbufptr[1] += dz->wanted) >= dz->flbufptr[3]) { if((exit_status = write_exact_samps(dz->flbufptr[2],dz->buflen,dz))<0) return(exit_status); dz->flbufptr[1] = dz->flbufptr[2]; } return(FINISHED); } /****************************** INSERT_NEW_PEAK_IN_PEAKLIST ***************************/ int insert_new_peak_in_peaklist(int position_in_formant,int *least,dataptr dz) { int n; double smallest = DBL_MAX; if(dz->specenvamp[position_in_formant] > dz->filtpeak[*least]) { dz->filtpeak[*least] = dz->specenvamp[position_in_formant]; dz->peakno[*least] = position_in_formant; } for(n=0;nitemcnt;n++) { if(dz->filtpeak[n] < smallest) { *least = n; smallest = dz->filtpeak[n]; } } return(FINISHED); } /****************************** SORT_FOCU_PEAKS_BY_FRQ ***************************/ int sort_focu_peaks_by_frq(int pkcnt_here,dataptr dz) { int n, m, k; for(n=0;nspecenvfrq[dz->peakno[n]] > dz->specenvfrq[dz->peakno[m]]) { k = dz->peakno[m]; dz->peakno[m] = dz->peakno[n]; dz->peakno[n] = k; } } } return(FINISHED); } /****************************** WRITE_LAST_FOCU_BUFFERS ******************************/ int write_last_focu_buffers(dataptr dz) { int exit_status; int n; for(n = dz->stable->offset+1; n < dz->iparam[FOCU_STABL]; n++) { if((exit_status = do_focu_filter(dz->stable->sbuf[n],dz))<0) return(exit_status); memmove((char *)dz->flbufptr[1],(char *)dz->stable->sbuf[n],(size_t)dz->wanted * sizeof(float)); if((exit_status = increment_pointer_in_output_buffer(dz))<0) return(exit_status); } if(dz->flbufptr[1]!=dz->flbufptr[2]) { if((exit_status = write_exact_samps(dz->flbufptr[2],(dz->flbufptr[1] - dz->flbufptr[2]),dz))<0) return(exit_status); } return(FINISHED); } /****************** SPECFREEZE ******************** * * (1) if no freezing needed. * (2) write any complete buffers before next timepoint. * (3) advance to buffer containing freeze-window if ness. * (4) advance within current buffer, to freeze-window. * (5) get number of windows to process. * (6) set endwindow relative to current buffer. * (7) advance within current buffer, to start-window. * (8) process windows from here to end-window. * (9) if current buffer overrun: proceed to next buffer. * (10) readjust window counters to be relative to nextbuffer start. * (11) write data and go to next buffer. * (12) flush buffer. */ int specfreeze(dataptr dz) { int exit_status; int n = 0, buffer_saved; int wc, wndws_read_pre_thisbuf = 0, frzpos; int startwpos = 0, endwpos = 0, windiff; int windows_in_buf; if((exit_status = read_first_buffer(&windows_in_buf,dz))<0) return(exit_status); while(nitemcnt-1) { if(dz->lparray[FRZ_FRZTIME][n] < 0L) { /* 1 */ while(dz->lparray[FRZ_SEGTIME][n+1] > wndws_read_pre_thisbuf + windows_in_buf) { if((exit_status = sfwind(&windows_in_buf,&wndws_read_pre_thisbuf,dz))<0) return(exit_status); /* 2 */ if(exit_status == FINISHED) { sprintf(errstr,"Window search miscalculation 1, specfreeze()\n"); return(PROGRAM_ERROR); } } endwpos = dz->lparray[FRZ_SEGTIME][n+1] - wndws_read_pre_thisbuf; } else { buffer_saved = 0; frzpos = dz->lparray[FRZ_FRZTIME][n] - wndws_read_pre_thisbuf; if(frzpos > windows_in_buf) { /* 3 */ if((exit_status = get_buffer_containing_frzpos (dz->lparray[FRZ_FRZTIME][n],&frzpos,&windows_in_buf,&wndws_read_pre_thisbuf,dz))<0) return(exit_status); buffer_saved = 1; } dz->flbufptr[0] = dz->bigfbuf + (frzpos * dz->wanted); /* 4 */ if((exit_status = get_freeze_template(dz))<0) return(exit_status); windiff = dz->lparray[FRZ_SEGTIME][n+1] - dz->lparray[FRZ_SEGTIME][n];/* 5 */ if((exit_status = get_startwindow_position (&startwpos,dz->lparray[FRZ_SEGTIME][n],&wndws_read_pre_thisbuf,&windows_in_buf,buffer_saved,dz))<0) return(exit_status); endwpos = startwpos + windiff; /* 6 */ wc = startwpos; /* 7 */ dz->flbufptr[0] = dz->bigfbuf + (startwpos * dz->wanted); /* 8 */ exit_status = CONTINUE; while(wcflbufptr[0] += dz->wanted; if(++wc >= windows_in_buf) { /* 9 */ wc = 0; /* 10 */ endwpos -= windows_in_buf; /* 11 */ if((exit_status = sfwind(&windows_in_buf,&wndws_read_pre_thisbuf,dz))<0) return(exit_status); } } } n++; } if((endwpos > 0) && (windows_in_buf > 0)) { /* 12 */ if((exit_status = write_exact_samps(dz->bigfbuf,windows_in_buf * dz->wanted,dz))<0) return(exit_status); } return(FINISHED); } /*************************** READ_FIRST_BUFFER ******************************/ int read_first_buffer(int *windows_in_buf,dataptr dz) { int samps_read, got; if((samps_read = fgetfbufEx(dz->bigfbuf, dz->buflen,dz->ifd[0],0)) < 0) { sprintf(errstr,"Cannot read data from input file: read_first_buffer()\n"); return(SYSTEM_ERROR); } got = samps_read; *windows_in_buf = got/dz->wanted; return(FINISHED); } /*************************** SFWIND *******************************/ int sfwind(int *windows_in_buf,int *wndws_read_pre_thisbuf,dataptr dz) { int exit_status; int got, samps_read; *wndws_read_pre_thisbuf += *windows_in_buf; if(*windows_in_buf > 0) { if((exit_status = write_exact_samps(dz->bigfbuf,*windows_in_buf * dz->wanted,dz))<0) return(exit_status); } if((samps_read = fgetfbufEx(dz->bigfbuf, dz->buflen,dz->ifd[0],0)) < 0) { sprintf(errstr,"Failed to read sound data: sfwind()\n"); return(SYSTEM_ERROR); } got = samps_read; *windows_in_buf = got/dz->wanted; dz->flbufptr[0] = dz->bigfbuf; if(samps_read==0) return(FINISHED); return(CONTINUE); } /*************************** GET_BUFFER_CONTAINING_FRZPOS *******************************/ int get_buffer_containing_frzpos(int frztime,int *frzpos,int *windows_in_buf,int *wndws_read_pre_thisbuf,dataptr dz) { int exit_status; int samps_read, got; int buffer_saved = 0; while(*frzpos > *windows_in_buf) { if(!buffer_saved) { if((exit_status = save_buffer(dz))<0) return(exit_status); } buffer_saved = 1; *wndws_read_pre_thisbuf += *windows_in_buf; if((samps_read = fgetfbufEx(dz->bigfbuf, dz->buflen,dz->ifd[0],0)) <= 0) { if(samps_read<0) { sprintf(errstr,"Sound read error.\n"); return(SYSTEM_ERROR); } else { sprintf(errstr,"Buffer accnting probl: Can't read input data: get_buffer_containing_frzpos()\n"); return(PROGRAM_ERROR); } } got = samps_read; *windows_in_buf = got/dz->wanted; *frzpos = frztime - *wndws_read_pre_thisbuf; } return(FINISHED); } /*************************** GET_FREEZE_TEMPLATE *******************************/ int get_freeze_template(dataptr dz) { int cc, vc; switch(dz->mode) { case(FRZ_AMP): for(cc = 0, vc = 0; cc < dz->clength; cc++, vc += 2) dz->windowbuf[0][AMPP] = dz->flbufptr[0][AMPP]; break; case(FRZ_FRQ): for(cc = 0, vc = 0; cc < dz->clength; cc++, vc += 2) dz->windowbuf[0][FREQ] = dz->flbufptr[0][FREQ]; break; case(FRZ_AMP_AND_FRQ): for(vc = 0; vc < dz->wanted; vc++) dz->windowbuf[0][vc] = dz->flbufptr[0][vc]; break; default: sprintf(errstr,"unknown mode in get_freeze_template()\n"); return(PROGRAM_ERROR); } return(FINISHED); } /*************************** GET_STARTWINDOW_POSITION ****************************** * * If startwindow is not in this buffer: rewind. */ int get_startwindow_position (int *startwpos,int this_segtime,int *wndws_read_pre_thisbuf,int *windows_in_buf,int buffer_saved,dataptr dz) { int exit_status; if((*startwpos = this_segtime - *wndws_read_pre_thisbuf)<0) { if((exit_status = sfrewind(windows_in_buf,this_segtime,wndws_read_pre_thisbuf,dz))<0) return(exit_status); if(buffer_saved) { if((exit_status = restore_buffer(dz))<0) return(exit_status); } *startwpos = this_segtime - *wndws_read_pre_thisbuf; } return(FINISHED); } /*************************** FREEZE_DATA ******************************/ int freeze_data(dataptr dz) { int cc, vc; switch(dz->mode) { case(FRZ_AMP): for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2) dz->flbufptr[0][AMPP] = dz->windowbuf[0][AMPP]; break; case(FRZ_FRQ): for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2) dz->flbufptr[0][FREQ] = dz->windowbuf[0][FREQ]; break; case(FRZ_AMP_AND_FRQ): for(vc = 0; vc < dz->wanted; vc++) dz->flbufptr[0][vc] = dz->windowbuf[0][vc]; break; default: sprintf(errstr,"unknown mode in freeze_data()\n"); return(PROGRAM_ERROR); } return(CONTINUE); } /*************************** SAVE_BUFFER *******************************/ int save_buffer(dataptr dz) { memmove((char *)(dz->flbufptr[2]),(char *)dz->bigfbuf,(size_t)dz->buflen * sizeof(float)); return(FINISHED); } /***************************** SFREWIND ********************************/ int sfrewind(int *windows_in_buf,int window_sought,int *wndws_read_pre_thisbuf,dataptr dz) { int samps_read, got; int big_wsize = dz->buflen/dz->wanted; int zzz = (window_sought/big_wsize) * big_wsize; /* TRUNCATE to a multiple of bigbufsize (in windows) */ if((sndseekEx(dz->ifd[0],zzz * dz->wanted, 0))<0) { sprintf(errstr,"Window seek failed. sfrewind()\n"); return(SYSTEM_ERROR); } *wndws_read_pre_thisbuf = zzz; if((samps_read = fgetfbufEx(dz->bigfbuf, dz->buflen,dz->ifd[0],0)) <= 0) { if(samps_read<0) { sprintf(errstr,"Sound read error.\n"); return(SYSTEM_ERROR); } else { sprintf(errstr,"Window reverse search miscalculation.sfrewind()\n"); return(PROGRAM_ERROR); } } got = samps_read; *windows_in_buf = got/dz->wanted; return(FINISHED); } /*************************** RESTORE_BUFFER *******************************/ int restore_buffer(dataptr dz) { memmove((char *)dz->bigfbuf,(char *)(dz->flbufptr[2]),(size_t)dz->buflen * sizeof(float)); return(FINISHED); } /**************************** SPECSTEP ****************************/ int specstep(dataptr dz) { int exit_status; int samps_read, got, windows_in_buf, wc; while((samps_read = fgetfbufEx(dz->bigfbuf, dz->buflen,dz->ifd[0],0)) > 0) { got = samps_read; dz->flbufptr[0] = dz->bigfbuf; windows_in_buf = got/dz->wanted; for(wc=0; wctotal_windows++; dz->flbufptr[0] += dz->wanted; } if(dz->total_windows % dz->iparam[STEP_STEP]!=0) /* at bigbufend, if not at start of step */ memmove((char *)(dz->windowbuf[0]),(char *)(dz->flbufptr[1]),(size_t)dz->wanted * sizeof(float)); /* copy the unchanging window into saving buffer */ if((exit_status = write_exact_samps(dz->bigfbuf,samps_read,dz))<0) return(exit_status); } return(FINISHED); } /**************************** DO_SPECSTEP ***************************/ int do_specstep(int wc,dataptr dz) { if(wc==0) { /* if at start of a bigfbuf */ if(dz->total_windows % dz->iparam[STEP_STEP]!=0) /* and not at start of a step */ memmove((char *)(dz->flbufptr[0]),(char *)(dz->windowbuf[0]),(size_t)dz->wanted * sizeof(float)); /* get the saved unchanging window into 1st buf of bigfbuf */ dz->flbufptr[1] = dz->flbufptr[0];/* point to this window, as unchanging window */ } else if(dz->total_windows % dz->iparam[STEP_STEP]==0) /* if at start of a step */ dz->flbufptr[1] = dz->flbufptr[0];/* point to this window, as unchanging window */ else /* if not at start of a step */ memmove((char *)(dz->flbufptr[0]),(char *)(dz->flbufptr[1]),(size_t)dz->wanted * sizeof(float)); /* copy the unchanging window into current window */ return(FINISHED); } /* NEW CODE */ /****************** SPECFREEZE2 ******************** * * (1) if no freezing needed. * (2) write any complete buffers before next timepoint. * (3) advance to buffer containing freeze-window if ness. * (4) advance within current buffer, to freeze-window. * (5) get number of windows to process. * (6) set endwindow relative to current buffer. * (7) advance within current buffer, to start-window. * (8) process windows from here to end-window. * (9) if current buffer overrun: proceed to next buffer. * (10) readjust window counters to be relative to nextbuffer start. * (11) write data and go to next buffer. * (12) flush buffer. */ int specfreeze2(dataptr dz) { int exit_status; int n = 0, m; int windows_in_buf, inwindowcnt = 0, outbufwincnt = 0, inbufwincnt = 0; int bufwinlen = dz->buflen/dz->wanted; if((exit_status = read_first_buffer(&windows_in_buf,dz))<0) return(exit_status); dz->flbufptr[0] = dz->bigfbuf; dz->flbufptr[1] = dz->flbufptr[2]; while(nitemcnt) { while(inwindowcnt < dz->lparray[FRZ_FRZTIME][n]) { /* 1 */ memcpy((char *)dz->flbufptr[1],(char *)dz->flbufptr[0],dz->wanted * sizeof(float)); if(++inwindowcnt >= dz->wlength) { dz->finished = TRUE; break; } else if(++inbufwincnt >= windows_in_buf) { if((exit_status = read_buffer(&windows_in_buf,dz))<0) return(exit_status); dz->flbufptr[0] = dz->bigfbuf; inbufwincnt = 0; } else dz->flbufptr[0] += dz->wanted; if(++outbufwincnt >= bufwinlen) { if((exit_status = write_samps(dz->flbufptr[2],dz->buflen,dz))<0) return(exit_status); dz->flbufptr[1] = dz->flbufptr[2]; outbufwincnt = 0; } else dz->flbufptr[1] += dz->wanted; } if(dz->finished) break; for(m=0;mlparray[FRZ_SEGTIME][n];m++) { memcpy((char *)dz->flbufptr[1],(char *)dz->flbufptr[0],dz->wanted * sizeof(float)); if(++outbufwincnt >= bufwinlen) { if((exit_status = write_samps(dz->flbufptr[2],dz->buflen,dz))<0) return(exit_status); dz->flbufptr[1] = dz->flbufptr[2]; outbufwincnt = 0; } else dz->flbufptr[1] += dz->wanted; } n++; } while(inwindowcnt < dz->wlength) { memcpy((char *)dz->flbufptr[1],(char *)dz->flbufptr[0],dz->wanted * sizeof(float)); if(++outbufwincnt >= bufwinlen) { if((exit_status = write_samps(dz->flbufptr[2],dz->buflen,dz))<0) return(exit_status); dz->flbufptr[1] = dz->flbufptr[2]; outbufwincnt = 0; } else dz->flbufptr[1] += dz->wanted; inwindowcnt++; if(++inbufwincnt >= windows_in_buf) { if((exit_status = read_buffer(&windows_in_buf,dz))<0) return(exit_status); dz->flbufptr[0] = dz->bigfbuf; inbufwincnt = 0; } else dz->flbufptr[0] += dz->wanted; } if(dz->flbufptr[1] != dz->flbufptr[2]) { if((exit_status = write_samps(dz->flbufptr[2],(dz->flbufptr[1] - dz->flbufptr[2]),dz))<0) return(exit_status); } return(FINISHED); } /*************************** READ_BUFFER ******************************/ int read_buffer(int *windows_in_buf,dataptr dz) { int samps_read, got; if((samps_read = fgetfbufEx(dz->bigfbuf, dz->buflen,dz->ifd[0],0)) < 0) { sprintf(errstr,"Can't read samples from input soundfile.\n"); return(SYSTEM_ERROR); } got = samps_read; *windows_in_buf = got/dz->wanted; return(FINISHED); } /* END OF NEW CODE */