static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; SilenceRemoveContext *s = ctx->priv; int i, j, threshold, ret = 0; int nbs, nb_samples_read, nb_samples_written; double *obuf, *ibuf = (double *)in->data[0]; AVFrame *out; nb_samples_read = nb_samples_written = 0; switch (s->mode) { case SILENCE_TRIM: silence_trim: nbs = in->nb_samples - nb_samples_read / inlink->channels; if (!nbs) break; for (i = 0; i < nbs; i++) { threshold = 0; for (j = 0; j < inlink->channels; j++) { threshold |= compute_rms(s, ibuf[j]) > s->start_threshold; } if (threshold) { for (j = 0; j < inlink->channels; j++) { update_rms(s, *ibuf); s->start_holdoff[s->start_holdoff_end++] = *ibuf++; nb_samples_read++; } if (s->start_holdoff_end >= s->start_duration * inlink->channels) { if (++s->start_found_periods >= s->start_periods) { s->mode = SILENCE_TRIM_FLUSH; goto silence_trim_flush; } s->start_holdoff_offset = 0; s->start_holdoff_end = 0; } } else { s->start_holdoff_end = 0; for (j = 0; j < inlink->channels; j++) update_rms(s, ibuf[j]); ibuf += inlink->channels; nb_samples_read += inlink->channels; } } break; case SILENCE_TRIM_FLUSH: silence_trim_flush: nbs = s->start_holdoff_end - s->start_holdoff_offset; nbs -= nbs % inlink->channels; if (!nbs) break; out = ff_get_audio_buffer(inlink, nbs / inlink->channels); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); } memcpy(out->data[0], &s->start_holdoff[s->start_holdoff_offset], nbs * sizeof(double)); s->start_holdoff_offset += nbs; ret = ff_filter_frame(outlink, out); if (s->start_holdoff_offset == s->start_holdoff_end) { s->start_holdoff_offset = 0; s->start_holdoff_end = 0; s->mode = SILENCE_COPY; goto silence_copy; } break; case SILENCE_COPY: silence_copy: nbs = in->nb_samples - nb_samples_read / inlink->channels; if (!nbs) break; out = ff_get_audio_buffer(inlink, nbs); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); } obuf = (double *)out->data[0]; if (s->stop_periods) { for (i = 0; i < nbs; i++) { threshold = 1; for (j = 0; j < inlink->channels; j++) threshold &= compute_rms(s, ibuf[j]) > s->stop_threshold; if (threshold && s->stop_holdoff_end && !s->leave_silence) { s->mode = SILENCE_COPY_FLUSH; flush(out, outlink, &nb_samples_written, &ret); goto silence_copy_flush; } else if (threshold) { for (j = 0; j < inlink->channels; j++) { update_rms(s, *ibuf); *obuf++ = *ibuf++; nb_samples_read++; nb_samples_written++; } } else if (!threshold) { for (j = 0; j < inlink->channels; j++) { update_rms(s, *ibuf); if (s->leave_silence) { *obuf++ = *ibuf; nb_samples_written++; } s->stop_holdoff[s->stop_holdoff_end++] = *ibuf++; nb_samples_read++; } if (s->stop_holdoff_end >= s->stop_duration * inlink->channels) { if (++s->stop_found_periods >= s->stop_periods) { s->stop_holdoff_offset = 0; s->stop_holdoff_end = 0; if (!s->restart) { s->mode = SILENCE_STOP; flush(out, outlink, &nb_samples_written, &ret); goto silence_stop; } else { s->stop_found_periods = 0; s->start_found_periods = 0; s->start_holdoff_offset = 0; s->start_holdoff_end = 0; clear_rms(s); s->mode = SILENCE_TRIM; flush(out, outlink, &nb_samples_written, &ret); goto silence_trim; } } s->mode = SILENCE_COPY_FLUSH; flush(out, outlink, &nb_samples_written, &ret); goto silence_copy_flush; } } } flush(out, outlink, &nb_samples_written, &ret); } else { memcpy(obuf, ibuf, sizeof(double) * nbs * inlink->channels); ret = ff_filter_frame(outlink, out); } break; case SILENCE_COPY_FLUSH: silence_copy_flush: nbs = s->stop_holdoff_end - s->stop_holdoff_offset; nbs -= nbs % inlink->channels; if (!nbs) break; out = ff_get_audio_buffer(inlink, nbs / inlink->channels); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); } memcpy(out->data[0], &s->stop_holdoff[s->stop_holdoff_offset], nbs * sizeof(double)); s->stop_holdoff_offset += nbs; ret = ff_filter_frame(outlink, out); if (s->stop_holdoff_offset == s->stop_holdoff_end) { s->stop_holdoff_offset = 0; s->stop_holdoff_end = 0; s->mode = SILENCE_COPY; goto silence_copy; } break; case SILENCE_STOP: silence_stop: break; } av_frame_free(&in); return ret; }
/* Return number of samples processed in isamp and osamp. */ static int sox_silence_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf, size_t *isamp, size_t *osamp) { priv_t * silence = (priv_t *) effp->priv; int threshold; size_t i, j; size_t nrOfTicks, /* sometimes wide, sometimes non-wide samples */ nrOfInSamplesRead, nrOfOutSamplesWritten; /* non-wide samples */ nrOfInSamplesRead = 0; nrOfOutSamplesWritten = 0; switch (silence->mode) { case SILENCE_TRIM: /* Reads and discards all input data until it detects a * sample that is above the specified threshold. Turns on * copy mode when detected. * Need to make sure and copy input in groups of "channels" to * prevent getting buffers out of sync. * nrOfTicks counts wide samples here. */ silence_trim: nrOfTicks = min((*isamp-nrOfInSamplesRead), (*osamp-nrOfOutSamplesWritten)) / effp->in_signal.channels; for(i = 0; i < nrOfTicks; i++) { threshold = 0; for (j = 0; j < effp->in_signal.channels; j++) { threshold |= aboveThreshold(effp, compute_rms(effp, ibuf[j]), silence->start_threshold, silence->start_unit); } if (threshold) { /* Add to holdoff buffer */ for (j = 0; j < effp->in_signal.channels; j++) { update_rms(effp, *ibuf); silence->start_holdoff[ silence->start_holdoff_end++] = *ibuf++; nrOfInSamplesRead++; } if (silence->start_holdoff_end >= silence->start_duration) { if (++silence->start_found_periods >= silence->start_periods) { silence->mode = SILENCE_TRIM_FLUSH; goto silence_trim_flush; } /* Trash holdoff buffer since its not * needed. Start looking again. */ silence->start_holdoff_offset = 0; silence->start_holdoff_end = 0; } } else /* !above Threshold */ { silence->start_holdoff_end = 0; for (j = 0; j < effp->in_signal.channels; j++) { update_rms(effp, ibuf[j]); } ibuf += effp->in_signal.channels; nrOfInSamplesRead += effp->in_signal.channels; } } /* for nrOfTicks */ break; case SILENCE_TRIM_FLUSH: /* nrOfTicks counts non-wide samples here. */ silence_trim_flush: nrOfTicks = min((silence->start_holdoff_end - silence->start_holdoff_offset), (*osamp-nrOfOutSamplesWritten)); nrOfTicks -= nrOfTicks % effp->in_signal.channels; for(i = 0; i < nrOfTicks; i++) { *obuf++ = silence->start_holdoff[silence->start_holdoff_offset++]; nrOfOutSamplesWritten++; } /* If fully drained holdoff then switch to copy mode */ if (silence->start_holdoff_offset == silence->start_holdoff_end) { silence->start_holdoff_offset = 0; silence->start_holdoff_end = 0; silence->mode = SILENCE_COPY; goto silence_copy; } break; case SILENCE_COPY: /* Attempts to copy samples into output buffer. * * Case B: * If not looking for silence to terminate copy then * blindly copy data into output buffer. * * Case A: * * Case 1a: * If previous silence was detect then see if input sample is * above threshold. If found then flush out hold off buffer * and copy over to output buffer. * * Case 1b: * If no previous silence detect then see if input sample * is above threshold. If found then copy directly * to output buffer. * * Case 2: * If not above threshold then silence is detect so * store in hold off buffer and do not write to output * buffer. Even though it wasn't put in output * buffer, inform user that input was consumed. * * If hold off buffer is full after this then stop * copying data and discard data in hold off buffer. * * Special leave_silence logic: * * During this mode, go ahead and copy input * samples to output buffer instead of holdoff buffer * Then also short ciruit any flushes that would occur * when non-silence is detect since samples were already * copied. This has the effect of always leaving * holdoff[] amount of silence but deleting any * beyond that amount. * * nrOfTicks counts wide samples here. */ silence_copy: nrOfTicks = min((*isamp-nrOfInSamplesRead), (*osamp-nrOfOutSamplesWritten)) / effp->in_signal.channels; if (silence->stop) { /* Case A */ for(i = 0; i < nrOfTicks; i++) { threshold = 1; for (j = 0; j < effp->in_signal.channels; j++) { threshold &= aboveThreshold(effp, compute_rms(effp, ibuf[j]), silence->stop_threshold, silence->stop_unit); } /* Case 1a * If above threshold, check to see if we where holding * off previously. If so then flush this buffer. * We haven't incremented any pointers yet so nothing * is lost. * * If user wants to leave_silence, then we * were already copying the data and so no * need to flush the old data. Just resume * copying as if we were not holding off. */ if (threshold && silence->stop_holdoff_end && !silence->leave_silence) { silence->mode = SILENCE_COPY_FLUSH; goto silence_copy_flush; } /* Case 1b */ else if (threshold) { /* Not holding off so copy into output buffer */ for (j = 0; j < effp->in_signal.channels; j++) { update_rms(effp, *ibuf); *obuf++ = *ibuf++; nrOfInSamplesRead++; nrOfOutSamplesWritten++; } } /* Case 2 */ else if (!threshold) { /* Add to holdoff buffer */ for (j = 0; j < effp->in_signal.channels; j++) { update_rms(effp, *ibuf); if (silence->leave_silence) { *obuf++ = *ibuf; nrOfOutSamplesWritten++; } silence->stop_holdoff[ silence->stop_holdoff_end++] = *ibuf++; nrOfInSamplesRead++; } /* Check if holdoff buffer is greater than duration */ if (silence->stop_holdoff_end >= silence->stop_duration) { /* Increment found counter and see if this * is the last period. If so then exit. */ if (++silence->stop_found_periods >= silence->stop_periods) { silence->stop_holdoff_offset = 0; silence->stop_holdoff_end = 0; if (!silence->restart) { *isamp = nrOfInSamplesRead; *osamp = nrOfOutSamplesWritten; silence->mode = SILENCE_STOP; /* Return SOX_EOF since no more processing */ return (SOX_EOF); } else { silence->stop_found_periods = 0; silence->start_found_periods = 0; silence->start_holdoff_offset = 0; silence->start_holdoff_end = 0; clear_rms(effp); silence->mode = SILENCE_TRIM; goto silence_trim; } } else { /* Flush this buffer and start * looking again. */ silence->mode = SILENCE_COPY_FLUSH; goto silence_copy_flush; } break; } /* Filled holdoff buffer */ } /* Detected silence */ } /* For # of samples */ } /* Trimming off backend */ else /* !(silence->stop) */ { /* Case B */ memcpy(obuf, ibuf, sizeof(sox_sample_t)*nrOfTicks* effp->in_signal.channels); nrOfInSamplesRead += (nrOfTicks*effp->in_signal.channels); nrOfOutSamplesWritten += (nrOfTicks*effp->in_signal.channels); } break; case SILENCE_COPY_FLUSH: /* nrOfTicks counts non-wide samples here. */ silence_copy_flush: nrOfTicks = min((silence->stop_holdoff_end - silence->stop_holdoff_offset), (*osamp-nrOfOutSamplesWritten)); nrOfTicks -= nrOfTicks % effp->in_signal.channels; for(i = 0; i < nrOfTicks; i++) { *obuf++ = silence->stop_holdoff[silence->stop_holdoff_offset++]; nrOfOutSamplesWritten++; } /* If fully drained holdoff then return to copy mode */ if (silence->stop_holdoff_offset == silence->stop_holdoff_end) { silence->stop_holdoff_offset = 0; silence->stop_holdoff_end = 0; silence->mode = SILENCE_COPY; goto silence_copy; } break; case SILENCE_STOP: /* This code can't be reached. */ nrOfInSamplesRead = *isamp; break; } *isamp = nrOfInSamplesRead; *osamp = nrOfOutSamplesWritten; return (SOX_SUCCESS); }
void comb_filter( spx_sig_t *exc, /*decoded excitation*/ spx_sig_t *new_exc, /*enhanced excitation*/ spx_coef_t *ak, /*LPC filter coefs*/ int p, /*LPC order*/ int nsf, /*sub-frame size*/ int pitch, /*pitch period*/ spx_word16_t *pitch_gain, /*pitch gain (3-tap)*/ spx_word16_t comb_gain, /*gain of comb filter*/ CombFilterMem *mem ) { int i; spx_word16_t exc_energy=0, new_exc_energy=0; spx_word16_t gain; spx_word16_t step; spx_word16_t fact; /*Compute excitation amplitude prior to enhancement*/ exc_energy = compute_rms(exc, nsf); /*for (i=0;i<nsf;i++) exc_energy+=((float)exc[i])*exc[i];*/ /*Some gain adjustment if pitch is too high or if unvoiced*/ #ifdef FIXED_POINT { spx_word16_t g = gain_3tap_to_1tap(pitch_gain)+gain_3tap_to_1tap(mem->last_pitch_gain); if (g > 166) comb_gain = MULT16_16_Q15(DIV32_16(SHL(165,15),g), comb_gain); if (g < 64) comb_gain = MULT16_16_Q15(SHL(g, 9), comb_gain); } #else { float g=0; g = GAIN_SCALING_1*.5*(gain_3tap_to_1tap(pitch_gain)+gain_3tap_to_1tap(mem->last_pitch_gain)); if (g>1.3) comb_gain*=1.3/g; if (g<.5) comb_gain*=2.*g; } #endif step = DIV32(COMB_STEP, nsf); fact=0; /*Apply pitch comb-filter (filter out noise between pitch harmonics)*/ for (i=0;i<nsf;i++) { spx_word32_t exc1, exc2; fact += step; exc1 = SHL(MULT16_32_Q15(SHL(pitch_gain[0],7),exc[i-pitch+1]) + MULT16_32_Q15(SHL(pitch_gain[1],7),exc[i-pitch]) + MULT16_32_Q15(SHL(pitch_gain[2],7),exc[i-pitch-1]) , 2); exc2 = SHL(MULT16_32_Q15(SHL(mem->last_pitch_gain[0],7),exc[i-mem->last_pitch+1]) + MULT16_32_Q15(SHL(mem->last_pitch_gain[1],7),exc[i-mem->last_pitch]) + MULT16_32_Q15(SHL(mem->last_pitch_gain[2],7),exc[i-mem->last_pitch-1]),2); new_exc[i] = exc[i] + MULT16_32_Q15(comb_gain,MULT16_32_Q15(fact,exc1) + MULT16_32_Q15(SUB16(COMB_STEP,fact), exc2)); } mem->last_pitch_gain[0] = pitch_gain[0]; mem->last_pitch_gain[1] = pitch_gain[1]; mem->last_pitch_gain[2] = pitch_gain[2]; mem->last_pitch = pitch; /*Amplitude after enhancement*/ new_exc_energy = compute_rms(new_exc, nsf); if (exc_energy > new_exc_energy) exc_energy = new_exc_energy; gain = DIV32_16(SHL(exc_energy,15),1+new_exc_energy); #ifdef FIXED_POINT if (gain < 16384) gain = 16384; #else if (gain < .5) gain=.5; #endif #ifdef FIXED_POINT for (i=0;i<nsf;i++) { mem->smooth_gain = MULT16_16_Q15(31457,mem->smooth_gain) + MULT16_16_Q15(1311,gain); new_exc[i] = MULT16_32_Q15(mem->smooth_gain, new_exc[i]); } #else for (i=0;i<nsf;i++) { mem->smooth_gain = .96*mem->smooth_gain + .04*gain; new_exc[i] *= mem->smooth_gain; } #endif }
int main(int argc, char* argv[]) { int verbose; sf_file in=NULL, out=NULL; int n1_traces; int n1_headers; char* header_format=NULL; sf_datatype typehead; /* kls do I need to add this? sf_datatype typein; */ float* fheader=NULL; float* intrace=NULL; float* outtrace=NULL; float* bandlimittrace=NULL; float* rmsall=NULL; float* rmsband=NULL; float* scalars=NULL; float* sum_of_scalars=NULL; int indx_time; int itrace=0; int ntaper; int numxstart; int numtstart; float* taper; char **list_of_floats; float* xstart; float* tstart; int indx_of_offset; float offset; float d1; float o1; float time_start; int itime_start; int itime_stop; int indx_taper; float wagc; int lenagc; float fmin=5; float fmax=95; float finc=5; int num_centerfreq; int firstlive; int lastlive; float pnoise; kiss_fftr_cfg cfg,icfg; sf_complex *fft1; sf_complex *fft2; int nfft; int nf; float df; float scale; int ifreq; float cntrfreq; /*****************************/ /* initialize verbose switch */ /*****************************/ sf_init (argc,argv); if(!sf_getint("verbose",&verbose))verbose=1; /* \n flag to control amount of print 0 terse, 1 informative, 2 chatty, 3 debug */ sf_warning("verbose=%d",verbose); /******************************************/ /* input and output data are stdin/stdout */ /******************************************/ if(verbose>0)fprintf(stderr,"read in file name\n"); in = sf_input ("in"); if(verbose>0)fprintf(stderr,"read out file name\n"); out = sf_output ("out"); if (!sf_histint(in,"n1_traces",&n1_traces)) sf_error("input data not define n1_traces"); if (!sf_histint(in,"n1_headers",&n1_headers)) sf_error("input data does not define n1_headers"); header_format=sf_histstring(in,"header_format"); if(strcmp (header_format,"native_int")==0) typehead=SF_INT; else typehead=SF_FLOAT; if(verbose>0)fprintf(stderr,"allocate headers. n1_headers=%d\n",n1_headers); fheader = sf_floatalloc(n1_headers); /* allocate intrace and outtrace after initialize fft and make them padded */ /* maybe I should add some validation that n1== n1_traces+n1_headers+2 and the record length read in the second word is consistent with n1. */ /**********************************************************/ /* end code block for standard tah Trace And Header setup */ /* continue with any sf_puthist this tah program calls to */ /* add to the history file */ /**********************************************************/ /* put the history from the input file to the output */ sf_fileflush(out,in); /********************************************************/ /* continue initialization specific to this tah program */ /********************************************************/ /* segy_init gets the list header keys required by segykey function */ segy_init(n1_headers,in); if(0==1) { /* infuture may want to have offset dependent agc design start time */ /* get the mute parameters */ if(NULL==(list_of_floats=sf_getnstring("xstart",&numxstart))){ xstart=NULL; sf_error("xstart is a required parameter in sftahagc"); } else { xstart=sf_floatalloc(numxstart); if(!sf_getfloats("xstart",xstart,numxstart))sf_error("unable to read xstart"); } if(NULL==(list_of_floats=sf_getnstring("tstart",&numtstart))){ tstart=NULL; sf_error("xstart is a required parameter in sftahagc"); } else { tstart=sf_floatalloc(numtstart); if(!sf_getfloats("tstart",tstart,numtstart))sf_error("unable to read tstart"); } if(numxstart!=numtstart)sf_error("bad mute parameters: numxstart!=numtstart"); if(!sf_getint("ntaper",&ntaper))ntaper=12; } /* \n length of the taper on the stack mute */ /* is this of use for agc? taper=sf_floatalloc(ntaper); for(indx_time=0; indx_time<ntaper; indx_time++){ float val_sin=sin((indx_time+1)*SF_PI/(2*ntaper)); taper[indx_time]=val_sin*val_sin; } */ indx_of_offset=segykey("offset"); if (!sf_histfloat(in,"d1",&d1)) sf_error("input data does not define d1"); if (!sf_histfloat(in,"o1",&o1)) sf_error("input data does not define o1"); /* check wagc for reasonableness. I input 250 (not .25 and ,250) */ if(!sf_getfloat("wagc",&wagc))wagc=-1; /* \n length of the agc window in seconds */ if(wagc<0)sf_error("wagc is a required parameter in sftahagc"); lenagc=wagc/d1+1.5; /* length of the agc window in samples */ if (!sf_getfloat("pnoise", &pnoise)) pnoise = 0.01; /* relative additive noise level */ if (!sf_getfloat("fmin",&fmin))fmin=5; /* minimum frequency band */ if (!sf_getfloat("fmax",&fmax))fmax=95; /* maximum frequency band */ if (!sf_getfloat("finc",&finc))finc=5; /* frequency band increment */ /* initialize kiss_fft kls */ nfft = kiss_fft_next_fast_size(n1_traces+200); nf = nfft/2+1; df = 1./(nfft*d1); scale = 1./nfft; cfg = kiss_fftr_alloc(nfft,0,NULL,NULL); icfg = kiss_fftr_alloc(nfft,1,NULL,NULL); fft1 = sf_complexalloc(nf); fft2 = sf_complexalloc(nf); if(verbose>0)fprintf(stderr,"fmax=%f\n",(nf-1)*df); /* allocate input and output traces with enough padding for ffts */ if(verbose>0) fprintf(stderr,"allocate padded intrace. n1_traces=%d nfft=%d\n", n1_traces, nfft); intrace =sf_floatalloc(nfft); /* must be padded for input to fft */ bandlimittrace=sf_floatalloc(nfft); /* must be padded for input to fft */ outtrace= sf_floatalloc(n1_traces); rmsall =sf_floatalloc(n1_traces); rmsband =sf_floatalloc(n1_traces); scalars =sf_floatalloc(n1_traces); sum_of_scalars=sf_floatalloc(n1_traces); num_centerfreq=(fmax-fmin)/finc+1.95; if(fabs(fmax-(fmin+(num_centerfreq-1)*finc))>.01){ fprintf(stderr,"*************************************\n"); fprintf(stderr,"*************************************\n"); fprintf(stderr,"*************************************\n"); fprintf(stderr,"fmin-fmax is not a multiple of finc\n"); fprintf(stderr,"fmin=%f, fmax=%f, finc=%f\n",fmin,fmax,finc); fprintf(stderr,"*************************************\n"); fprintf(stderr,"*************************************\n"); sf_error("illegal combination of fmin,fmax,fminc"); } /***************************/ /* start trace loop */ /***************************/ if(verbose>0)fprintf(stderr,"start trace loop\n"); itrace=0; while (!(get_tah(intrace, fheader, n1_traces, n1_headers, in))){ if(verbose>1 || (verbose==1 && itrace<5)){ fprintf(stderr,"process tah %d in sftahagc\n",itrace); } /********************/ /* process the tah. */ /********************/ if(typehead == SF_INT)offset=((int *)fheader)[indx_of_offset]; else offset=((float*)fheader)[indx_of_offset]; /* maybe latter add agc design start time intlin(numxstart,xstart,tstart, tstart[0],tstart[numxstart-1],1, &offset,&time_start); if(time_start<o1)time_start=o1; itime_start=(int)(((time_start-o1)/d1)+.5); */ /* find firstlive and lastlive */ if(verbose>2)fprintf(stderr,"find firstlive and lastlive\n"); for (firstlive=0; firstlive<n1_traces; firstlive++){ if(intrace[firstlive] != 0) break; } for (lastlive=n1_traces-1;lastlive>=0; lastlive--){ if(intrace[lastlive] != 0) break; } /* kls need to catch a zero trace */ if(verbose>2) fprintf(stderr,"firstlive=%d, lastlive=%d\n",firstlive,lastlive); /* zero the padded area on the input trace */ for (indx_time=n1_traces; indx_time<nfft; indx_time++){ intrace[indx_time]=0; } /********************************************************/ /* apply the SPECtral BALancing: */ /* 1 compute the input trace rms in agclen gates */ /* 2 fft to frequency domain */ /* 3 for each frequency band */ /* 3.1 extract (ramp) the frequency band */ /* 3.2 convert freqency band to time, */ /* 3.3 compute the rms of the frequency band */ /* 3.4 agc scalars 1/(freq_band_rms + whitenoise*rms) */ /* 3.3 agc the frequency band */ /* 3.4 sum to output */ /* 3.5 sum scalars to sum of scalars */ /* 4 divide by the sum of scalars */ /********************************************************/ compute_rms(intrace, rmsall, lenagc, n1_traces, firstlive, lastlive); /* scale rms by whitenoise factor */ if(verbose>2)fprintf(stderr,"put_tah rmsall\n"); if(0) put_tah(intrace, fheader, n1_traces, n1_headers, out); if(0) put_tah(rmsall, fheader, n1_traces, n1_headers, out); for (indx_time=0; indx_time<n1_traces; indx_time++){ rmsall[indx_time]*=(1.0/num_centerfreq); } if(verbose>2)fprintf(stderr,"fftr\n"); kiss_fftr(cfg, intrace, (kiss_fft_cpx*) fft1); /* zero the output trace and the sum_of_scalars */ for (indx_time=0; indx_time<n1_traces; indx_time++){ outtrace[indx_time]=0.0; sum_of_scalars[indx_time]=0.0; } for (cntrfreq=fmin; cntrfreq<=fmax; cntrfreq+=finc){ if(verbose>2)fprintf(stderr,"cntrfreq=%f\n",cntrfreq); /* zero frequencies before the band */ for (ifreq=0; ifreq<(int)((cntrfreq-finc)/df); ifreq++){ fft2[ifreq]=0.0; } /* triangular weight the selected frequency band */ for (ifreq=(int)((cntrfreq-finc)/df); ifreq<(int)((cntrfreq+finc)/df) && ifreq<nf; ifreq++){ float weight; if(ifreq>0){ weight=(1.0-fabs(ifreq*df-cntrfreq)/finc)/nfft; fft2[ifreq]=weight*fft1[ifreq]; } } /* zero frequencies larger than the band */ for (ifreq=(int)((cntrfreq+finc)/df); ifreq<nf; ifreq++){ fft2[ifreq]=0.0; } /* inverse fft back to time domain */ if(verbose>2)fprintf(stderr,"fftri\n"); kiss_fftri(icfg,(kiss_fft_cpx*) fft2, bandlimittrace); /* apply agc to the bandlimittrace and sum scalars to sum_of_scalars */ if(verbose>2)fprintf(stderr,"agc_apply\n"); compute_rms(bandlimittrace, rmsband, lenagc, n1_traces, firstlive, lastlive); if(verbose>2)fprintf(stderr,"sum to ouput\n"); for (indx_time=0; indx_time<n1_traces; indx_time++){ /* old poor scalars[indx_time]=1.0/ (rmsband[indx_time]+pnoise*rmsall[indx_time]); */ if(1)scalars[indx_time]=rmsband[indx_time]/ (rmsband[indx_time]*rmsband[indx_time]+ pnoise*rmsall[indx_time]*rmsall[indx_time]); else scalars[indx_time]=1.0; } for (indx_time=0; indx_time<n1_traces; indx_time++){ bandlimittrace[indx_time]*=scalars[indx_time]; outtrace[indx_time]+=bandlimittrace[indx_time]; } for (indx_time=0; indx_time<n1_traces; indx_time++){ sum_of_scalars[indx_time]+=scalars[indx_time]; } if(0) put_tah(bandlimittrace, fheader, n1_traces, n1_headers, out); if(0) put_tah(rmsband, fheader, n1_traces, n1_headers, out); if(0) put_tah(scalars, fheader, n1_traces, n1_headers, out); } if(0)put_tah(sum_of_scalars, fheader, n1_traces, n1_headers, out); if(1){ /* divide output by sum of scalars */ for (indx_time=0; indx_time<n1_traces; indx_time++){ outtrace[indx_time]/=sum_of_scalars[indx_time]; } } if (1) put_tah(outtrace, fheader, n1_traces, n1_headers, out); itrace++; } exit(0); }
/* DIFF: was gto_fit_rxyscale */ static int geo_fit_linear( geomap_fit_t* const fit, surface_t* const sx1, surface_t* const sy1, const size_t ncoord, const coord_t* const input, const coord_t* const ref, const double* const weights, double* const residual_x, double* const residual_y, stimage_error_t* error) { bbox_t bbox; double sw = 0.0; coord_t sr = {0.0, 0.0}; coord_t si = {0.0, 0.0}; coord_t r0 = {0.0, 0.0}; coord_t i0 = {0.0, 0.0}; double sxrxr = 0.0; double syryr = 0.0; double syrxi = 0.0; double sxryi = 0.0; double sxrxi = 0.0; double syryi = 0.0; double num = 0.0; double denom = 0.0; double theta = 0.0; double ctheta = 0.0; double stheta = 0.0; coord_t cthetac = {0.0, 0.0}; coord_t sthetac = {0.0, 0.0}; double xmag = 0.0; double ymag = 0.0; size_t i = 0; int status = 1; assert(fit); assert(sx1); assert(sy1); assert(input); assert(ref); assert(weights); assert(residual_x); assert(residual_y); surface_free(sx1); surface_free(sy1); bbox_copy(&fit->bbox, &bbox); bbox_make_nonsingular(&bbox); /* Compute the sums required to determine the offsets */ compute_sums(ncoord, input, ref, weights, &sw, &si, &sr); if (sw < 3.0) { if (fit->projection == geomap_proj_none) { stimage_error_set_message( error, "Too few data points for X and Y fits."); } else { stimage_error_set_message( error, "Too few data points for XI and ETA fits."); } goto exit; } r0.x = sr.x / sw; r0.y = sr.y / sw; i0.x = si.x / sw; i0.y = si.y / sw; for (i = 0; i < ncoord; ++i) { sxrxr += weights[i] * (ref[i].x - r0.x) * (ref[i].x - r0.x); syryr += weights[i] * (ref[i].y - r0.y) * (ref[i].y - r0.y); syrxi += weights[i] * (ref[i].y - r0.y) * (input[i].x - i0.x); sxryi += weights[i] * (ref[i].x - r0.x) * (input[i].y - i0.y); sxrxi += weights[i] * (ref[i].x - r0.x) * (input[i].x - i0.x); syryi += weights[i] * (ref[i].y - r0.y) * (input[i].y - i0.y); } /* Compute the rotation angle */ num = 2.0 * (sxrxr * syrxi * syryi - syryr * sxrxi * sxryi); denom = syryr * (sxrxi - sxryi) * (sxrxi + sxryi) - \ sxrxr * (syrxi + syryi) * (syrxi - syryi); if (double_approx_equal(num, 0.0) && double_approx_equal(denom, 0.0)) { theta = 0.0; } else { theta = atan2(num, denom) / 2.0; if (theta < 0.0) { theta += M_PI * 2.0; } } ctheta = cos(theta); stheta = sin(theta); /* Compute the X magnification factor */ num = sxrxi * ctheta - sxryi * stheta; denom = sxrxr; if (denom <= 0.0) { xmag = 1.0; } else { xmag = num / denom; } /* Compute the Y magnification factor */ num = syrxi * stheta + syryi * ctheta; denom = syryr; if (denom <= 0.0) { ymag = 1.0; } else { ymag = num / denom; } /* Compute the polynomial coefficients */ cthetac.x = xmag * ctheta; sthetac.x = ymag * stheta; sthetac.y = xmag * stheta; cthetac.x = ymag * ctheta; /* Compute the X and Y fit coefficients */ if (compute_surface_coefficients( fit->function, &bbox, &i0, &r0, &cthetac, &sthetac, sx1, sy1, error)) goto exit; /* Compute the residuals */ if (compute_residuals( sx1, sy1, ncoord, input, ref, residual_x, residual_y, error)) goto exit; /* Compute the number of zero-weighted points */ fit->n_zero_weighted = count_zero_weighted(ncoord, weights); /* Compute the rms of the x and y fits */ compute_rms( ncoord, weights, residual_x, residual_y, &fit->xrms, &fit->yrms); fit->ncoord = ncoord; status = 0; exit: return status; }
/* DIFF: was geo_mrejectd */ static int geo_fit_reject( geomap_fit_t* const fit, surface_t* const sx1, surface_t* const sy1, surface_t* const sx2, surface_t* const sy2, int* const has_sx2, int* const has_sy2, const size_t ncoord, const coord_t* const input, const coord_t* const ref, const double* const weights, double* const residual_x, double* const residual_y, stimage_error_t* error) { double* tweights = NULL; size_t nreject = 0; size_t niter = 0; double cutx = 0.0; double cuty = 0.0; size_t i = 0; int status = 1; assert(fit); assert(sx1); assert(sy1); assert(sx2); assert(sy2); assert(input); assert(ref); assert(weights); assert(residual_x); assert(residual_y); assert(error); tweights = malloc_with_error(ncoord * sizeof(double), error); if (tweights == NULL) goto exit; if (fit->rej != NULL) { free(fit->rej); } fit->rej = malloc_with_error(ncoord * sizeof(int), error); if (fit->rej == NULL) goto exit; fit->nreject = 0; /* Initialize the temporary weights array and the number of rejected points */ for (i = 0; i < ncoord; ++i) { tweights[i] = weights[i]; } do { /* while (niter < fit->maxiter) */ /* Compute the rejection limits */ if (ncoord - fit->n_zero_weighted > 1) { cutx = fit->reject * \ sqrt(fit->xrms / (double)(ncoord - fit->n_zero_weighted - 1)); cuty = fit->reject * \ sqrt(fit->yrms / (double)(ncoord - fit->n_zero_weighted - 1)); } else { cutx = MAX_DOUBLE; cuty = MAX_DOUBLE; } /* Reject points from the fit */ for (i = 0; i < ncoord; ++i) { if (tweights[i] > 0.0 && ((abs(residual_x[i]) > cutx) || abs(residual_y[i]) > cuty)) { tweights[i] = 0.0; ++nreject; assert(nreject < ncoord); fit->rej[nreject] = i; } } if ((long)nreject - (long)fit->nreject <= 0) { break; } fit->nreject = nreject; /* Compute the number of deleted points */ fit->n_zero_weighted = count_zero_weighted(ncoord, weights); /* Recompute the X and Y fit */ switch (fit->fit_geometry) { case geomap_fit_rotate: if (geo_fit_theta( fit, sx1, sy1, ncoord, input, ref, tweights, residual_x, residual_y, error)) goto exit; break; case geomap_fit_rscale: if (geo_fit_magnify( fit, sx1, sy1, ncoord, input, ref, tweights, residual_x, residual_y, error)) goto exit; break; case geomap_fit_rxyscale: if (geo_fit_linear( fit, sx1, sy1, ncoord, input, ref, tweights, residual_x, residual_y, error)) goto exit; break; default: if (geo_fit_xy( fit, sx1, sx2, ncoord, 1, input, ref, has_sx2, tweights, residual_x, error) || geo_fit_xy( fit, sy1, sy2, ncoord, 0, input, ref, has_sy2, tweights, residual_y, error)) goto exit; break; } /* Compute the X and Y fit rms */ compute_rms( ncoord, tweights, residual_x, residual_y, &fit->xrms, &fit->yrms); ++niter; } while (niter < fit->maxiter); status = 0; exit: free(tweights); return status; }