/* * Copyright (c) 1983-2023 Trevor Wishart and Composers Desktop Project Ltd * http://www.trevorwishart.co.uk * http://www.composersdesktop.com * This file is part of the CDP System. The CDP System is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The CDP System is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the CDP System; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int inner_level_loop(int windows_in_buf,dataptr dz); static int do_speclevel(dataptr dz); static int normalise_as_transfering_to_sndbuf_and_write_to_file(dataptr dz); static int read_another_buffer(int *totalwindows_in_buf,dataptr dz); static int zero_energy_bands(dataptr dz); static int print_energy_bands(dataptr dz); static int inner_textout_only_loop(int *peakscore,int *descnt,int windows_in_buf,dataptr dz); static int output_peak_data(dataptr dz); static int specpeak(dataptr dz); static int specprint(dataptr dz); static int specreport(int *peakscore,int *descnt,dataptr dz); static int find_maximum(int *maxloc,dataptr dz); static int print_window(int windowcnt,dataptr dz); static int report_stable_peaks(int *peakscore,int *descnt,dataptr dz); static int sort_peaks(int *peakscore,int *descnt,dataptr dz) ; static int sort_report_peaks_by_amplitude(int pkcnt_here,dataptr dz); static int sort_report_peaks_by_frq(int pkcnt_here,dataptr dz); static int show_new_peaks(int pkcnt_here,dataptr dz); static int print_peaks(int pkcnt_here,dataptr dz); /****************************** SPECWCNT ***************************/ int specwcnt(dataptr dz) { sprintf(errstr,"File contains %d windows\n",dz->wlength); return(FINISHED); } /************************* SPECCHAN ***************************/ int specchan(dataptr dz) { int thischan = (int)((dz->param[CHAN_FRQ]+(dz->halfchwidth))/dz->chwidth); /* TRUNCATE */ sprintf(errstr,"%.2lf Hz is in channel %d\n",dz->param[CHAN_FRQ],thischan); return(FINISHED); } /************************* SPECFRQ ***************************/ int specfrq(dataptr dz) { double frq = (double)dz->iparam[FRQ_CHAN] * dz->chwidth; sprintf(errstr,"%.2lf Hz is centre frq of channel %d\n",frq,dz->iparam[FRQ_CHAN]); return(FINISHED); } /**************************** SPECLEVEL ****************************/ int speclevel(dataptr dz) { int exit_status; int samps_read, windows_in_buf; if(sloom) dz->total_samps_read = 0L; while((samps_read = fgetfbufEx(dz->bigfbuf,dz->big_fsize,dz->ifd[0],0)) > 0) { if(sloom) dz->total_samps_read += samps_read; dz->flbufptr[0] = dz->bigfbuf; windows_in_buf = samps_read/dz->wanted; if((exit_status = inner_level_loop(windows_in_buf,dz))<0) return(exit_status); if(dz->finished) break; } if(samps_read<0) { sprintf(errstr,"Sound read error.\n"); return(SYSTEM_ERROR); } if((exit_status = normalise_as_transfering_to_sndbuf_and_write_to_file(dz))<0) return(exit_status); return(FINISHED); } /**************************** INNER_LEVEL_LOOP ****************************/ int inner_level_loop(int windows_in_buf,dataptr dz) { int exit_status; int wc; for(wc=0; wcflbufptr[0] += dz->wanted; dz->total_windows++; } return(FINISHED); } /**************************** DO_SPECLEVEL ****************************/ int do_speclevel(dataptr dz) { #define VERY_BIG (10000000.0) int vc; dz->parray[0][dz->itemcnt] = 0.0; for(vc = 0; vc < dz->wanted; vc += 2) dz->parray[0][dz->itemcnt] += dz->flbufptr[0][vc]; if(dz->parray[0][dz->itemcnt] > VERY_BIG) { sprintf(errstr,"Apparent(?) huge signal level in analysis window %d. do_speclevel()\n",dz->itemcnt + 1); return(PROGRAM_ERROR); } if(++dz->itemcnt > dz->wlength) { sprintf(errstr,"Storage arithmetic problem in do_speclevel().\n"); return(PROGRAM_ERROR); } return(FINISHED); } /********** NORMALISE_AS_TRANSFERING_TO_SNDBUF_AND_WRITE_TO_FILE *********/ int normalise_as_transfering_to_sndbuf_and_write_to_file(dataptr dz) { double maxwindow = 0.0, normaliser; int n; for(n=0;nwlength;n++) { if(dz->parray[0][n] > maxwindow) maxwindow = dz->parray[0][n]; } if(flteq(maxwindow,0.0)) { sprintf(errstr,"No signal level in analysis file.\n"); return(DATA_ERROR); } normaliser = F_MAXSAMP/maxwindow; for(n=0;nwlength;n++) dz->sndbuf[n] = (float)(dz->parray[0][n] * normaliser); return write_samps(dz->sndbuf,dz->wlength,dz); } /**************************** SPECOCTVU ****************************/ int specoctvu(dataptr dz) { int exit_status; int totalwindows_in_buf, windownumber_in_buf; int x, q, n; double topfrq; if((exit_status = read_another_buffer(&totalwindows_in_buf,dz))!=CONTINUE) { if(exit_status==FINISHED) fprintf(stdout,"WARNING: No data in input file.\n"); return(exit_status); } windownumber_in_buf = 0; while(dz->total_windows < dz->wlength && totalwindows_in_buf > 0) { if((exit_status = zero_energy_bands(dz))<0) return(exit_status); for(x = 0; xiparam[OCTVU_TBLOK];x++) { if(windownumber_in_buf >= totalwindows_in_buf) { if((exit_status = read_another_buffer(&totalwindows_in_buf,dz))!=CONTINUE) break; windownumber_in_buf = 0; } q = n = 0; topfrq = dz->param[OCTVU_BBBTOP]; for(q=0;qitemcnt;q++) { for(n = dz->iparray[OCTVU_CHBBOT][q]; n < dz->iparray[OCTVU_CHBTOP][q]; n += 2) { if(fabs(dz->flbufptr[0][n+1]) < topfrq) dz->parray[OCTVU_ENERGY][q] += dz->flbufptr[0][n]; } topfrq *= 2.0; } dz->flbufptr[0] += dz->wanted; windownumber_in_buf++; if(++dz->total_windows >= dz->wlength) { break; } } if(exit_status<0) return(exit_status); if(x>0 && (exit_status = print_energy_bands(dz))<0) return(exit_status); } return(FINISHED); } /**************************** READ_ANOTHER_BUFFER ****************************/ int read_another_buffer(int *totalwindows_in_buf,dataptr dz) { int samps_read; if((samps_read = fgetfbufEx(dz->bigfbuf, dz->big_fsize,dz->ifd[0],0)) <= 0) { if(samps_read<0) { sprintf(errstr,"Sound read error.\n"); return(SYSTEM_ERROR); } return(FINISHED); } dz->flbufptr[0] = dz->bigfbuf; *totalwindows_in_buf = samps_read/dz->wanted; return(CONTINUE); } /**************************** ZERO_ENERGY_BANDS ****************************/ int zero_energy_bands(dataptr dz) { int n; for(n=0;nitemcnt;n++) dz->parray[OCTVU_ENERGY][n] = 0.0; return(FINISHED); } /******************** PRINT_ENERGY_BANDS ***********************/ int print_energy_bands(dataptr dz) { #define SCALEFACT (5000.0) int n; char temp[64]; double output; errstr[0] = ENDOFSTR; for(n=0;nitemcnt;n++) { output = SCALEFACT * dz->parray[OCTVU_ENERGY][n]; if(output>0) { output = log(output); if(sloom) { sprintf(temp,"%.3lf",output); strcat(errstr,temp); } fprintf(dz->fp,"%.3lf",output); } else { if(sloom) { sprintf(temp,"-----"/*,output*/); strcat(errstr,temp); } fprintf(dz->fp,"-----"); } if(n < dz->itemcnt-1) { if(sloom) strcat(errstr,"\t"); fprintf(dz->fp,"\t"); } else { if(sloom) { fprintf(stdout,"INFO: %s\n",errstr); fflush(stdout); errstr[0] = ENDOFSTR; } fprintf(dz->fp,"\n"); } } return(FINISHED); } /**************************** OUTER_TEXTOUT_ONLY_LOOP ****************************/ int outer_textout_only_loop(dataptr dz) { int exit_status; int samps_read, windows_in_buf; int peakscore = 0; int descnt = 0; dz->time = 0.0f; while((samps_read = fgetfbufEx(dz->bigfbuf, dz->big_fsize,dz->ifd[0],0)) > 0) { dz->flbufptr[0] = dz->bigfbuf; windows_in_buf = samps_read/dz->wanted; if((exit_status = inner_textout_only_loop(&peakscore,&descnt,windows_in_buf,dz))<0) return(exit_status); if(dz->finished) break; } if(samps_read<0) { sprintf(errstr,"Sound read error.\n"); return(SYSTEM_ERROR); } if(dz->process == PEAK && dz->itemcnt) { if((exit_status = output_peak_data(dz))<0) return(exit_status); } return(FINISHED); } /**************************** INNER_TEXTOUT_ONLY_LOOP ****************************/ int inner_textout_only_loop(int *peakscore,int *descnt,int windows_in_buf,dataptr dz) { int exit_status; int wc; for(wc=0; wctotal_windows==0) { if((exit_status = skip_or_special_operation_on_window_zero(dz))<0) return(exit_status); if(exit_status==TRUE) { dz->flbufptr[0] += dz->wanted; dz->total_windows++; continue; } } if((exit_status = read_values_from_all_existing_brktables((double)dz->time,dz))<0) return(exit_status); switch(dz->process) { case(PEAK): exit_status = specpeak(dz); break; case(PRINT): exit_status = specprint(dz); break; case(REPORT): exit_status = specreport(peakscore,descnt,dz); break; default: sprintf(errstr,"unknown process in inner_textout_only_loop()\n"); return(PROGRAM_ERROR); } if(exit_status<0) return(exit_status); dz->flbufptr[0] += dz->wanted; dz->total_windows++; dz->time = (float)(dz->time + dz->frametime); } return(FINISHED); } /******************************** OUTPUT_PEAK_DATA *************************/ int output_peak_data(dataptr dz) { int exit_status; int here; int k; double frqtop, frqbot, starttime; starttime = dz->param[PEAK_ENDTIME]; dz->param[PEAK_ENDTIME] += (dz->iparam[PEAK_TGROUP] * dz->frametime); if((exit_status = find_maximum(&here,dz))<0) return(exit_status); if(here==0) frqbot = dz->param[PEAK_CUTOFF]; else frqbot = dz->parray[PEAK_BAND][here-1]; frqtop = dz->parray[PEAK_BAND][here]; if(sloom) { fprintf(stdout,"INFO: WINDOW\t%.4lf\t%.4lf\t:PEB \t%.4lf\tTO\t%.4lf\n",starttime, dz->param[PEAK_ENDTIME], frqbot, frqtop); fflush(stdout); } fprintf(dz->fp,"WINDOW\t%.4lf\t%.4lf\t:PEB \t%.4lf\tTO\t%.4lf\n",starttime, dz->param[PEAK_ENDTIME], frqbot, frqtop); for(k=0;kiparam[PEAK_BANDCNT];k++) dz->parray[PEAK_MAXI][k] = 0.0; return(FINISHED); } /****************************** SPECPEAK ****************************/ int specpeak(dataptr dz) { int exit_status; double thisamp, sensitivity_of_ear; int cc, vc, n; for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2) { if(dz->flbufptr[0][FREQ]param[PEAK_CUTOFF] || dz->flbufptr[0][FREQ]>dz->nyquist) continue; n = 0; while(dz->flbufptr[0][FREQ] > dz->parray[PEAK_BAND][n]) n++; thisamp = dz->flbufptr[0][AMPP]; if(dz->vflag[PEAK_HEAR]) { if((exit_status = getspecenvamp(&sensitivity_of_ear,dz->flbufptr[0][FREQ],0,dz))<0) return(exit_status); thisamp *= sensitivity_of_ear; } dz->parray[PEAK_MAXI][n] += thisamp; } if(++dz->itemcnt >= dz->iparam[PEAK_TGROUP]) { if((exit_status = output_peak_data(dz))<0) return(exit_status); dz->itemcnt = 0; } return(FINISHED); } /****************************** SPECPRINT ****************************/ int specprint(dataptr dz) { int exit_status; if(dz->total_windows >= dz->iparam[PRNT_ENDW]) { dz->finished = 1; return(FINISHED); } if(dz->total_windows >= dz->iparam[PRNT_STARTW]) { if((exit_status = print_window(dz->total_windows,dz))<0) return(exit_status); } return(FINISHED); } /**************************** SPECREPORT ***************************/ int specreport(int *peakscore,int *descnt,dataptr dz) { int exit_status; double lofrq, hifrq; lofrq = dz->param[REPORT_LOFRQ]; hifrq = dz->param[REPORT_HIFRQ]; if(dz->brksize[REPORT_LOFRQ] || dz->brksize[REPORT_HIFRQ]) { if(flteq(lofrq,hifrq)) { sprintf(errstr,"Frequency limits define a zero-width band at time %.2lf.\n",dz->time); return(USER_ERROR); } if(lofrq > hifrq) swap(&lofrq,&hifrq); } rectify_window(dz->flbufptr[0],dz); if((exit_status = extract_specenv(0,0,dz))<0) return(exit_status); if((exit_status = report_stable_peaks(peakscore,descnt,dz))<0) return(exit_status); return(FINISHED); } /**************************** FIND_MAXIMUM **************************/ int find_maximum(int *maxloc,dataptr dz) { double thismax = -1.0; int k; *maxloc = -1; for(k=0;kiparam[PEAK_BANDCNT];k++) { if(dz->parray[PEAK_MAXI][k] > thismax) { thismax = dz->parray[PEAK_MAXI][k]; *maxloc = k; } } /* what if maxloc is NOT SET */ if(*maxloc < 0) { sprintf(errstr,"Failed to find any peak in data\n"); return(GOAL_FAILED); } return(FINISHED); } /******************************** PRINT_WINDOW *************************/ int print_window(int windowcnt,dataptr dz) { int cc, vc; fprintf(dz->fp,"************* WINDOW %d *****************\n",windowcnt); for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2) { fprintf(dz->fp,"amp[%d] = %.12f\t",cc,dz->flbufptr[0][AMPP]); if(dz->flbufptr[0][FREQ] < .01f) fprintf(dz->fp,"frq[%d] = %lf\n",cc,dz->flbufptr[0][FREQ]); else fprintf(dz->fp,"frq[%d] = %.2lf\n",cc,dz->flbufptr[0][FREQ]); } return(FINISHED); } /****************************** REPORT_STABLE_PEAKS ***************************/ int report_stable_peaks(int *peakscore,int *descnt,dataptr dz) { int exit_status; int thispkcnt; /* shuffle back stored specenvs */ memmove((char *)dz->stable->spec[0], (char *)dz->stable->spec[1],dz->iparam[REPORT_SL1] * (dz->infile->specenvcnt * sizeof(int))); /* put latest specenv array here */ memmove((char *)dz->stable->spec[dz->iparam[REPORT_SL1]], (char *)dz->specenvamp,(dz->infile->specenvcnt * sizeof(int))); /* shuffle back stored fpks */ memmove((char *)dz->stable->fpk[0], (char *)dz->stable->fpk[1],dz->iparam[REPORT_SL1] * (dz->infile->specenvcnt * sizeof(int))); /* shuffle back stored fpk_totals */ memmove((char *)dz->stable->total_pkcnt, (char *)(dz->stable->total_pkcnt+1),dz->iparam[REPORT_SL1] * sizeof(int)); /* put into last fpk[z] store */ if((exit_status = extract_formant_peaks2(REPORT_SL1,&thispkcnt,dz->param[REPORT_LOFRQ],dz->param[REPORT_HIFRQ],dz))<0) return(exit_status); dz->stable->total_pkcnt[dz->iparam[REPORT_SL1]] = thispkcnt; if(dz->total_windows >= dz->iparam[REPORT_SL1]) { if((exit_status = sort_peaks(peakscore,descnt,dz))<0) return(exit_status); } return(FINISHED); } /****************************** SORT_PEAKS ****************6**************/ int sort_peaks(int *peakscore,int *descnt,dataptr dz) { int exit_status; int this_pkcnt; int n = 0, pkcnt_here; if(dz->total_windows<=dz->iparam[REPORT_SL1]) memset((char *)dz->stable->design_score,0,dz->infile->specenvcnt * sizeof(int)); if((exit_status = score_peaks(peakscore,REPORT_SL1,REPORT_STABL,dz))<0) return(exit_status); if(*peakscore==0) return(FINISHED); /* Find how many times each peak occurs across the stabilise buffers */ if((exit_status = collect_scores(&this_pkcnt,descnt,dz))<0) return(exit_status); /* Sort these on the basis of the most commonly occuring */ if((exit_status = sort_design(this_pkcnt,dz))<0) 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; } switch(dz->mode) { case(AMP_ORDERED_TIMED): case(AMP_ORDERED_UNTIMED): if((exit_status = sort_report_peaks_by_amplitude(pkcnt_here,dz))<0) return(exit_status); break; case(FRQ_ORDERED_TIMED): case(FRQ_ORDERED_UNTIMED): if((exit_status = sort_report_peaks_by_frq(pkcnt_here,dz))<0) return(exit_status); break; default: sprintf(errstr,"unknown case in sort_peaks()\n"); return(PROGRAM_ERROR); } if((exit_status = show_new_peaks(pkcnt_here,dz))<0) return(exit_status); if(dz->total_windows>dz->iparam[REPORT_SL1]) { /* Logically this should be '>=sl1' : but */ if((exit_status = unscore_peaks(peakscore,dz))<0) /* don't have to subtract window 0, as NO PEAKS there */ return(exit_status); } return(FINISHED); } /****************************** SORT_REPORT_PEAKS_BY_AMPLITUDE ******************************/ int sort_report_peaks_by_amplitude(int pkcnt_here,dataptr dz) { int n, m, thischan; double thisamp; for(n=0;nstable->des[n]->amp = 0.0; /* and store in des-array assocd with channel */ thischan = dz->stable->des[n]->chan; for(m=0;miparam[REPORT_STABL];m++) /* sum amplitudes in that chan across all specenv buffers */ dz->stable->des[n]->amp += dz->stable->spec[m][thischan]; /* and store in des-array assocd with channel */ } for(n=1;nstable->des[n]->amp; m = n-1; while(m >= 0 && dz->stable->des[m]->amp > thisamp) { dz->stable->des[m+1]->amp = dz->stable->des[m]->amp; dz->stable->des[m+1]->chan = dz->stable->des[m]->chan; m--; } dz->stable->des[m+1]->amp = dz->stable->des[n]->amp; dz->stable->des[m+1]->chan = dz->stable->des[n]->chan; } return(FINISHED); } /****************************** SORT_REPORT_PEAKS_BY_FRQ ***************************/ int sort_report_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); } /****************************** SHOW_NEW_PEAKS ***************************/ int show_new_peaks(int pkcnt_here,dataptr dz) { int exit_status; int n, m, newpeak = 0; /*RWD added init */ if(pkcnt_here!=dz->iparam[REPORT_LAST_PKCNT_HERE]) { if((exit_status = print_peaks(pkcnt_here,dz))<0) return(exit_status); } else { for(n=0;niparam[REPORT_LAST_PKCNT_HERE];m++) { if(dz->peakno[n] == dz->lastpeakno[m]) { newpeak = 0; break; } } if(newpeak) break; } if(newpeak) { if((exit_status = print_peaks(pkcnt_here,dz))<0) return(exit_status); } } dz->iparam[REPORT_LAST_PKCNT_HERE] = pkcnt_here; for(n = 0;n < pkcnt_here; n++) dz->lastpeakno[n] = dz->peakno[n]; return(FINISHED); } /****************************** PRINT_PEAKS ***************************/ int print_peaks(int pkcnt_here,dataptr dz) { int n; char temp[200]; switch(dz->mode) { case(FRQ_ORDERED_TIMED): case(AMP_ORDERED_TIMED): if(sloom) sprintf(errstr,"%.3lf secs : ",dz->time - (dz->stable->offset * dz->frametime)); fprintf(dz->fp,"%.3lf secs : ",dz->time - (dz->stable->offset * dz->frametime)); case(FRQ_ORDERED_UNTIMED): case(AMP_ORDERED_UNTIMED): for(n=0;nspecenvfrq[dz->peakno[n]]); strcat(errstr,temp); } fprintf(dz->fp,"\t%.2f",dz->specenvfrq[dz->peakno[n]]); if(n && n%8==0) { if(sloom) { fprintf(stdout,"INFO: %s\n",errstr); fflush(stdout); sprintf(errstr,"\t\t"); } fprintf(dz->fp,"\n\t\t"); } } break; default: sprintf(errstr,"Unknown case in print_peaks()\n"); return(PROGRAM_ERROR); } if(sloom) { fprintf(stdout,"INFO: %s\n",errstr); fflush(stdout); } fprintf(dz->fp,"\n"); return(FINISHED); }