/* * 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 #define VERYBIG (10000.0) #define SRCFILE (0) #define NOISEFILE (1) #define COMPAREFILE (2) static int copy_cut_samps(int startwindow,int *endwindow,int windows_per_buf,int endchunksize,dataptr dz); static int outer_clean_loop(int whichfile,int no_of_marked_channels,dataptr dz); static int adjust_noise_level(dataptr dz); static int setup_cleaning_filter(dataptr dz); static int reorganise_marks(int *no_of_marked_channels,dataptr dz); static int read_noise_data(int windows_in_buffer,dataptr dz); static int read_comparison_data(int windows_in_buffer,dataptr dz); static int do_cleaning(int windows_in_buffer,int no_of_marked_channels,dataptr dz); static int skip_skipwindows(int *wc,int windows_in_buffer,dataptr dz); static int generate_magnified_outfile(dataptr dz); static int read_cut_samps(dataptr dz); /*********************** SPECGAIN ***************************/ int specgain(dataptr dz) { int vc; for( vc = 0; vc < dz->wanted; vc += 2) dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[GAIN_GAIN]); return(FINISHED); } /*********************** SPECLIMIT ***************************/ int speclimit(dataptr dz) { int vc; for( vc = 0; vc < dz->wanted; vc += 2) { if(dz->flbufptr[0][AMPP] < dz->param[LIMIT_THRESH]) dz->flbufptr[0][AMPP] = 0.0f; } return(FINISHED); } /**************************** SPECCLEAN ***************************/ int specclean(dataptr dz) { int exit_status; int no_of_marked_channels = 0; if((exit_status = outer_clean_loop(NOISEFILE,no_of_marked_channels,dz))<0) return(exit_status); if((exit_status = adjust_noise_level(dz))<0) return(exit_status); switch(dz->mode) { case(FILTERING): if((exit_status = setup_cleaning_filter(dz))<0) return(exit_status); break; case(COMPARING): if((exit_status = outer_clean_loop(COMPAREFILE,no_of_marked_channels,dz))<0) return(exit_status); if((exit_status = reorganise_marks(&no_of_marked_channels,dz))<0) return(exit_status); break; } return outer_clean_loop(SRCFILE,no_of_marked_channels,dz); } /**************************** OUTER_CLEAN_LOOP ****************************/ int outer_clean_loop(int whichfile,int no_of_marked_channels,dataptr dz) { int exit_status; int samps_read, windows_in_buffer; while((samps_read = fgetfbufEx(dz->bigfbuf, dz->big_fsize,dz->ifd[whichfile],0)) > 0) { dz->flbufptr[0] = dz->bigfbuf; windows_in_buffer = samps_read/dz->wanted; switch(whichfile) { case(NOISEFILE): if((exit_status = read_noise_data(windows_in_buffer,dz))<0) return(exit_status); break; case(COMPAREFILE): if((exit_status = read_comparison_data(windows_in_buffer,dz))<0) return(exit_status); break; case(SRCFILE): if((exit_status = do_cleaning(windows_in_buffer,no_of_marked_channels,dz))<0) return(exit_status); break; default: sprintf(errstr,"Unknown option in outer_clean_loop()\n"); return(PROGRAM_ERROR); } if(whichfile==SRCFILE && (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(whichfile!=SRCFILE) dz->time = 0.0f; return(FINISHED); } /************************ ADJUST_NOISE_LEVEL **********************/ int adjust_noise_level(dataptr dz) { int cc; for( cc = 0; cc < dz->clength; cc++) dz->amp[cc] = (float)(dz->amp[cc] * dz->param[CL_GAIN]); return(FINISHED); } /************************* SETUP_CLEANING_FILTER ***************************/ int setup_cleaning_filter(dataptr dz) { int cc, vc; double chtop = dz->chwidth/2.0; if(chtop < dz->param[CL_FRQ]) dz->amp[0] = 0.0f; for( cc = 1, vc = 2; cc < dz->clength; cc++, vc +=2) { chtop += dz->chwidth; if(chtop < dz->param[CL_FRQ]) dz->amp[cc] = 0.0f; } return(FINISHED); } /************************ REORGANISE_MARKS ********************** * * Instead of keeping 1024 marks, keep the locations of all SET marks!! * Convert locations fron channel no (cc) to buffer location (vc) */ int reorganise_marks(int *no_of_marked_channels,dataptr dz) { int n; *no_of_marked_channels = 0; for(n=0;n < dz->clength;n++) { if(dz->iparray[CL_MARK][n]) { dz->iparray[CL_MARK][*no_of_marked_channels] = n; (*no_of_marked_channels)++; } } if(*no_of_marked_channels==0) { sprintf(errstr,"Comparison file is already clean, relative to noisefile.\n"); return(GOAL_FAILED); } for(n=0;n < *no_of_marked_channels; n++) /* change marks from cc to vc */ dz->iparray[CL_MARK][n] *= 2; return(FINISHED); } /************************* READ_NOISE_DATA ***************************/ int read_noise_data(int windows_in_buffer,dataptr dz) { int wc; int cc, vc; for(wc=0; wcclength; cc++, vc += 2) { if(dz->flbufptr[0][AMPP] > dz->amp[cc]) dz->amp[cc] = dz->flbufptr[0][AMPP]; } dz->flbufptr[0] += dz->wanted; } return(FINISHED); } /************************* READ_COMPARISON_DATA ***************************/ int read_comparison_data(int windows_in_buffer,dataptr dz) { int wc; int cc, vc; for(wc=0; wcclength; cc++, vc += 2) { if(dz->flbufptr[0][AMPP] > dz->amp[cc]) dz->iparray[CL_MARK][cc] = 0; } dz->flbufptr[0] += dz->wanted; } return(FINISHED); } /************************* DO_CLEANING ***************************/ int do_cleaning(int windows_in_buffer,int no_of_marked_channels,dataptr dz) { int exit_status; int wc = 0; int n, cc, vc; switch(dz->mode) { case(COMPARING): for(wc=0; wcflbufptr[0][dz->iparray[CL_MARK][n]] = 0.0F; dz->flbufptr[0] += dz->wanted; } break; case(FROMTIME): case(ANYWHERE): wc = 0; if(!dz->finished) { if((exit_status = skip_skipwindows(&wc,windows_in_buffer,dz))<0) return(exit_status); if(exit_status==FINISHED) break; } /* fall thro */ case(FILTERING): for(; wcclength; cc++, vc += 2) { if(dz->flbufptr[0][AMPP] < dz->amp[cc]) { dz->flbufptr[0][AMPP] = 0.0F; if(dz->mode==FROMTIME) dz->amp[cc] = (float)VERYBIG; } } dz->flbufptr[0] += dz->wanted; } break; default: sprintf(errstr,"unknown case in do_cleaning()\n"); return(PROGRAM_ERROR); } return(FINISHED); } /************************ SKIP_SKIPWINDOWS **********************/ int skip_skipwindows(int *wc,int windows_in_buffer,dataptr dz) { int step; if((step = dz->iparam[CL_SKIPW] - dz->total_windows) >= windows_in_buffer) { dz->total_windows += windows_in_buffer; dz->time += dz->frametime * windows_in_buffer; return(FINISHED); } else { dz->total_windows += step; *wc = step; dz->time += dz->frametime * step; dz->flbufptr[0] += step * dz->wanted; dz->finished = TRUE; } return(CONTINUE); } /************************* SPECCUT ***************************/ int speccut(dataptr dz) { int exit_status; int samps_remain, bufs_to_skip, endchunksize; int startwindow = (int)(dz->param[CUT_STIME]/dz->frametime); int endwindow = (int)(dz->param[CUT_ETIME]/dz->frametime); int windows_per_buf = dz->big_fsize/dz->wanted; int w_to_skip = 0; endwindow = min(endwindow,dz->wlength); if((bufs_to_skip = startwindow/windows_per_buf) > 0) { /* TRUNCATE */ w_to_skip = bufs_to_skip * windows_per_buf; if((sndseekEx(dz->ifd[0],w_to_skip * dz->wanted,0))<0) { sprintf(errstr,"Window seek failed: speccut().\n"); return(SYSTEM_ERROR); } } startwindow -= w_to_skip; endwindow -= w_to_skip; if((exit_status = read_cut_samps(dz))<0) return(exit_status); dz->flbufptr[0] = dz->bigfbuf + (startwindow * dz->wanted); endchunksize = windows_per_buf - startwindow; dz->flbufptr[1] = dz->flbufptr[2]; if(endwindow > 0) { do { if((exit_status = copy_cut_samps(startwindow,&endwindow,windows_per_buf,endchunksize,dz))<0) return(exit_status); } while(exit_status==CONTINUE); } if((samps_remain = dz->flbufptr[1] - dz->flbufptr[2]) > 0) { if((exit_status = write_samps(dz->flbufptr[2],samps_remain,dz))<0) return(exit_status); } return(FINISHED); } /************************* COPY_CUT_SAMPS ***************************/ int copy_cut_samps(int startwindow,int *endwindow,int windows_per_buf,int endchunksize,dataptr dz) { int exit_status; if(*endwindow >= windows_per_buf) { memmove((char *)dz->flbufptr[1],(char *)dz->flbufptr[0],(size_t)(endchunksize * dz->wanted * sizeof(float))); dz->flbufptr[1] += endchunksize * dz->wanted; dz->flbufptr[0] = dz->bigfbuf; if((exit_status = read_cut_samps(dz))<0) return(exit_status); *endwindow -= windows_per_buf; } else { memmove((char *)dz->flbufptr[1],(char *)dz->flbufptr[0],(size_t)((*endwindow - startwindow) * dz->wanted * sizeof(float))); dz->flbufptr[1] += (*endwindow - startwindow) * dz->wanted; return(FINISHED); } if(*endwindow >= startwindow) { if(startwindow > 0) memmove((char *)dz->flbufptr[1],(char *)dz->flbufptr[0],(size_t)(startwindow * dz->wanted * sizeof(float))); if((exit_status = write_exact_samps(dz->flbufptr[2],dz->big_fsize,dz))<0) return(exit_status); dz->flbufptr[1] = dz->flbufptr[2]; dz->flbufptr[0] += startwindow * dz->wanted; } else { memmove((char *)dz->flbufptr[1],(char *)dz->flbufptr[0],(size_t)(*endwindow * dz->wanted * sizeof(float))); dz->flbufptr[1] += *endwindow * dz->wanted; return(FINISHED); } return(CONTINUE); } /****************************** SPECGRAB_OR_MAGNIFY ***************************/ int specgrab_or_magnify(int frztime_paramno,dataptr dz) { int exit_status; int frzwindow, bufs_to_seek, samps_read; int big_wsize = dz->big_fsize/dz->wanted; frzwindow = (int)(dz->param[frztime_paramno]/dz->frametime); /* truncate */ frzwindow = min(frzwindow,dz->wlength-1); /* if time > filelen, get last window */ bufs_to_seek = (frzwindow * dz->wanted)/dz->big_fsize; /* truncate */ if(sndseekEx(dz->ifd[0],bufs_to_seek * dz->big_fsize,0)<0) { sprintf(errstr,"seek failed in specgrab_or_magnify().\n"); return(SYSTEM_ERROR); } if((samps_read = fgetfbufEx(dz->bigfbuf,dz->big_fsize,dz->ifd[0],0)) < dz->wanted) { if(samps_read<0) { sprintf(errstr,"Sound read error.\n"); return(SYSTEM_ERROR); } else { sprintf(errstr,"Problem reading infile data in specgrab_or_magnify().\n"); return(PROGRAM_ERROR); } } frzwindow -= bufs_to_seek * big_wsize; dz->flbufptr[0] = dz->bigfbuf + (frzwindow * dz->wanted); switch(dz->process) { case(GRAB): if((exit_status = write_samps(dz->flbufptr[0],dz->wanted,dz))<0) return(exit_status); break; case(MAGNIFY): dz->total_windows = round(dz->param[MAG_DUR]/dz->frametime); return generate_magnified_outfile(dz); break; default: sprintf(errstr,"unknown application in specgrab_or_magnify()\n"); return(PROGRAM_ERROR); } return(FINISHED); } /******************************** GENERATE_MAGNIFIED_OUTFILE **********************************/ int generate_magnified_outfile(dataptr dz) { int exit_status; int wc, windows_left; int vc, cc, written_whole_buffer = 0; int w_to_buf = dz->big_fsize/dz->wanted; float *bigbufend = dz->bigfbuf + dz->big_fsize; memmove((char *)dz->windowbuf[0],(char *)dz->flbufptr[0],(size_t)(dz->wanted * sizeof(float))); dz->flbufptr[0] = dz->bigfbuf; for(wc=0; wctotal_windows; wc++) { memmove((char *)dz->flbufptr[0],(char *)dz->windowbuf[0],(size_t)(dz->wanted * sizeof(float))); if((dz->flbufptr[0] += dz->wanted) >= bigbufend) { if(!written_whole_buffer) { for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2) dz->bigfbuf[vc] = 0.0F; /* ZERO AMPS IN WINDOW ONE */ } if((exit_status = write_exact_samps(dz->bigfbuf,dz->big_fsize,dz))<0) return(exit_status); if(!written_whole_buffer) /* RESTORE DATA IN WINDOW ONE */ memmove((char *)dz->bigfbuf,(char *)dz->windowbuf[0],(size_t)(dz->wanted * sizeof(float))); written_whole_buffer = 1; dz->flbufptr[0] = dz->bigfbuf; } } if(!written_whole_buffer) { for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2) dz->bigfbuf[vc] = 0.0F; /* ZERO AMPS IN WINDOW ONE */ if(dz->flbufptr[0] - dz->bigfbuf > 0) { if((exit_status = write_samps(dz->bigfbuf,dz->flbufptr[0] - dz->bigfbuf,dz))<0) return(exit_status); } } else { if((windows_left = dz->total_windows % w_to_buf)> 0) { if((exit_status = write_samps(dz->bigfbuf,windows_left * dz->wanted,dz))<0) return(exit_status); } } return(FINISHED); } /************************* READ_CUT_SAMPS ***************************/ int read_cut_samps(dataptr dz) { if(fgetfbufEx(dz->bigfbuf,dz->big_fsize,dz->ifd[0],0) < 0) { sprintf(errstr,"Window read failed: read_cut_samps().\n"); return(SYSTEM_ERROR); } return(FINISHED); }