DTTSPAGC newDttSPAgc (AGCMODE mode, COMPLEX * Vec, int BufSize, REAL Limit, REAL attack, REAL decay, REAL slope, REAL hangtime, REAL samprate, REAL MaxGain, REAL MinGain, REAL CurGain, char *tag) { DTTSPAGC a; a = (DTTSPAGC) safealloc (1, sizeof (dttspagc), tag); a->mode = mode; a->attack = (REAL) (1.0 - exp (-1000.0 / (attack * samprate))); a->one_m_attack = (REAL) exp (-1000.0 / (attack * samprate)); a->decay = (REAL) (1.0 - exp (-1000.0 / (decay * samprate))); a->one_m_decay = (REAL) exp (-1000.0 / (decay * samprate)); a->fastattack = (REAL) (1.0 - exp (-1000.0 / (0.2 * samprate))); a->one_m_fastattack = (REAL) exp (-1000.0 / (0.2 * samprate)); a->fastdecay = (REAL) (1.0 - exp (-1000.0 / (3.0 * samprate))); a->one_m_fastdecay = (REAL) exp (-1000.0 / (3.0 * samprate)); strcpy (a->tag, tag); a->mask = 2 * BufSize; a->hangindex = a->indx = 0; a->hangtime = hangtime * 0.001f; a->hangthresh = 0.0; a->sndx = (int) (samprate * attack * 0.003f); a->fastindx = (int)(0.002f*samprate); a->gain.fix = 10.0; a->slope = slope; a->gain.top = MaxGain; a->hangthresh = a->gain.bottom = MinGain; a->gain.fastnow = a->gain.old = a->gain.now = CurGain; a->gain.limit = Limit; a->buff = newCXB (BufSize, Vec, "agc in buffer"); a->circ = newvec_COMPLEX (a->mask, "circular agc buffer"); a->mask -= 1; a->fasthang = 0; a->fasthangtime = 0.1f*a->hangtime; return a; }
BLMS new_blms (CXB signal, REAL adaptation_rate, REAL leak_rate, int filter_type, int pbits) { BLMS tmp; tmp = (BLMS) safealloc (1, sizeof (_blocklms), "block lms"); tmp->delay_line = newvec_COMPLEX (256, "block lms delay line"); tmp->y = newvec_COMPLEX (256, "block lms output signal"); tmp->Yhat = newvec_COMPLEX (256, "block lms output transform"); tmp->Errhat = newvec_COMPLEX (256, "block lms Error transform"); tmp->error = newvec_COMPLEX (256, "block lms Error signal"); tmp->Xhat = newvec_COMPLEX (256, "block lms signal transform"); tmp->What = newvec_COMPLEX (256, "block lms filter transform"); tmp->Update = newvec_COMPLEX (256, "block lms update transform"); tmp->update = newvec_COMPLEX (256, "block lms update signal"); tmp->adaptation_rate = adaptation_rate; tmp->leak_rate = 1.0f - leak_rate; tmp->signal = signal; tmp->filter_type = filter_type; tmp->Xplan = fftwf_plan_dft_1d (256, (fftwf_complex *) tmp->delay_line, (fftwf_complex *) tmp->Xhat, FFTW_FORWARD, pbits); tmp->Yplan = fftwf_plan_dft_1d (256, (fftwf_complex *) tmp->Yhat, (fftwf_complex *) tmp->y, FFTW_BACKWARD, pbits); tmp->Errhatplan = fftwf_plan_dft_1d (256, (fftwf_complex *) tmp->error, (fftwf_complex *) tmp->Errhat, FFTW_FORWARD, pbits); tmp->UPDplan = fftwf_plan_dft_1d (256, (fftwf_complex *) tmp->Errhat, (fftwf_complex *) tmp->update, FFTW_BACKWARD, pbits); tmp->Wplan = fftwf_plan_dft_1d (256, (fftwf_complex *) tmp->update, (fftwf_complex *) tmp->Update, FFTW_FORWARD, pbits); return tmp; }
LMSR new_lmsr (CXB signal, int delay, REAL adaptation_rate, REAL leakage, int adaptive_filter_size, int filter_type) { LMSR lms = (LMSR) safealloc (1, sizeof (_lmsstate), "new_lmsr state"); lms->signal = signal; lms->signal_size = CXBsize (lms->signal); lms->delay = delay; lms->size = 512; lms->mask = lms->size - 1; lms->delay_line = newvec_COMPLEX (lms->size, "lmsr delay"); lms->adaptation_rate = adaptation_rate; lms->leakage = leakage; lms->adaptive_filter_size = adaptive_filter_size; lms->adaptive_filter = newvec_COMPLEX (128, "lmsr filter"); lms->filter_type = filter_type; lms->delay_line_ptr = 0; return lms; }
CXB newCXB (int size, COMPLEX * base, char *tag) { CXB p = (CXB) safealloc (1, sizeof (CXBuffer), tag); if (base) { CXBbase (p) = base; CXBmine (p) = FALSE; } else { CXBbase (p) = newvec_COMPLEX (size, "newCXB"); CXBmine (p) = TRUE; } CXBsize (p) = CXBwant (p) = size; CXBovlp (p) = CXBhave (p) = CXBdone (p) = 0; return p; }
DTTSPAGC newDttSPAgc (AGCMODE mode, COMPLEX *Vec, int BufSize, // Size of the input buffer REAL target, // The target voltage REAL attack, // Attack time constant in msec REAL decay, // Decay time constant in msec REAL slope, // Rate of change of gain after agc threshold is exceeded REAL hangtime, // Hang Time in msec where NO decay is allowed in the agc REAL samprate, // Sample Rate so time can be turned into sample number REAL MaxGain, // Maximum allowable gain REAL MinGain, // Minimum gain (can be -dB / less than 1.0 as in ALC or strong signals on receive REAL CurGain, // The initial gain setting char *tag) // String to emit when error conditions occur { DTTSPAGC a; a = (DTTSPAGC) safealloc (1, sizeof (dttspagc), tag); a->mode = mode; // Attack: decrease gain when input signal will produce an output signal above the target voltage // Decay: increase gain when input signal will produce an output signal below the target voltage // Compute exponential attack rate per sample from attack time and sampler rate. a->attack = (REAL) (1.0 - exp (-1000.0 / (attack * samprate))); // Compute 1.0 - attack time. a->one_m_attack = (REAL) (1.0 - a->attack); // Compute exponential decay rate per sample from attack time and sampler rate. a->decay = (REAL) (1.0 - exp (-1000.0 / (decay * samprate))); // Compute 1.0 - decay time. a->one_m_decay = (REAL) (1.0 - a->decay); // Our system has a two track agc response. The normal one found in most receive // systems is the determined from the calculations we just made. // Ours has a fast track agc which is designed to prevent large pulse signals from pushing // us into serious attack and wait for a long decay when the signal is short duration < 3 time constants for attack // Compute exponential fast attack rate per sample from fast attack time and sampler rate. a->fastattack = (REAL) (1.0 - exp (-1000.0 / (0.2 * samprate))); // Compute 1.0 - fast attack time. a->one_m_fastattack = (REAL) (1.0 - a->fastattack); // Compute exponential fast decay rate per sample from fast attack time and sampler rate. a->fastdecay = (REAL) (1.0 - exp (-1000.0 / (3.0 * samprate))); // Compute 1.0 - fast decay time. a->one_m_fastdecay = (REAL) (1.0 - a->fastdecay); // Save the error identification message strcpy (a->tag, tag); // This computes the index max for our circular buffer a->mask = 2 * BufSize - 1; // Hangtime: This is a period of NO allowed decay even though we need to increase gain to stay at target level // hangindex is used to compute how deep into the hang interval we are. a->hangindex = a->slowindx = 0; // Change hang time to hang length in samples using time and sample rate. a->hangtime = hangtime * 0.001f; //a->hangthresh = 0.0; // not neccessary? // We BEGIN applying decreasing gain 3 time constants ahead of the signals arrival to narrow the modulation // spread arising from modulating the signal with the agc gain. The index to application of computed gain // sndx and it is computed as number of samples in 3 attack time constants a->out_indx = (int) (samprate * attack * 0.003f); // We do the same anticipation in the fast channel but we only do two time constants. a->fastindx = (int)(0.0027f*samprate); // see update.c:SetRAGC() a->gain.fix = 10000.0; // Slope: The rate at which gain is decreased as signal strength increases after it exceeds the agc threshold // that is, after the required gain to reach the desired output level is LESS THAN the maximum allowable gain. a->slope = slope; // gain.top = Maxgain which is the maximum allowable gain. This determines the agc threshold a->gain.top = MaxGain; // gain.bottom = MinGain is the minimum allowable gain. If < 0dB or 1.0, then this is an attenuation. a->hangthresh = a->gain.bottom = MinGain; // Initialize the gain state to an initial value a->gain.fastnow = a->gain.old = a->gain.now = CurGain; // Set the target voltage. a->gain.target = target; // Given the vector of input samples, make a local complex buffer (struct to handle metadata associated with // the vector or array of samples a->buff = newCXB (BufSize, Vec, "agc in buffer"); // Use a circular buffer for efficiency in dealing with the anticipatory part of the agc algorithm a->circ = newvec_COMPLEX (2 * BufSize, "circular agc buffer"); // intialize fast hang index to 0 a->fasthang = 0; // Whatever the hangtime is for the slow channel, make the fast agc channel hangtime 10% of it a->fasthangtime = 0.1f*a->hangtime; return a; }
FiltOvSv newFiltOvSv(COMPLEX * coefs, int ncoef, int pbits) { int buflen, fftlen; FiltOvSv p; fftwf_plan pfwd, pinv; COMPLEX *zrvec, *zfvec, *zivec, *zovec; p = (FiltOvSv) safealloc(1, sizeof(filt_ov_sv), "new overlap/save filter"); buflen = nblock2(ncoef - 1), fftlen = 2 * buflen; zrvec = newvec_COMPLEX_fftw(fftlen, "raw signal vec in newFiltOvSv"); zfvec = newvec_COMPLEX_fftw(fftlen, "filter z vec in newFiltOvSv"); zivec = newvec_COMPLEX_fftw(fftlen, "signal in z vec in newFiltOvSv"); zovec = newvec_COMPLEX_fftw(fftlen, "signal out z vec in newFiltOvSv"); /* prepare frequency response from filter coefs */ { int i; COMPLEX *zcvec; fftwf_plan ptmp; zcvec = newvec_COMPLEX(fftlen, "temp filter z vec in newFiltOvSv"); //ptmp = fftw_create_plan(fftlen, FFTW_FORWARD, pbits); ptmp = fftwf_plan_dft_1d(fftlen, (fftwf_complex *) zcvec, (fftwf_complex *) zfvec, FFTW_FORWARD, pbits); #ifdef LHS for (i = 0; i < ncoef; i++) zcvec[i] = coefs[i]; #else for (i = 0; i < ncoef; i++) zcvec[fftlen - ncoef + i] = coefs[i]; #endif //fftw_one(ptmp, (fftw_complex *) zcvec, (fftw_complex *) zfvec); fftwf_execute(ptmp); fftwf_destroy_plan(ptmp); delvec_COMPLEX(zcvec); } /* prepare transforms for signal */ //pfwd = fftw_create_plan(fftlen, FFTW_FORWARD, pbits); //pinv = fftw_create_plan(fftlen, FFTW_BACKWARD, pbits); pfwd = fftwf_plan_dft_1d(fftlen, (fftwf_complex *) zrvec, (fftwf_complex *) zivec, FFTW_FORWARD, pbits); pinv = fftwf_plan_dft_1d(fftlen, (fftwf_complex *) zivec, (fftwf_complex *) zovec, FFTW_BACKWARD, pbits); /* stuff values */ p->buflen = buflen; p->fftlen = fftlen; p->zfvec = zfvec; p->zivec = zivec; p->zovec = zovec; p->zrvec = zrvec; p->pfwd = pfwd; p->pinv = pinv; p->scale = 1.0f / (REAL) fftlen; normalize_vec_COMPLEX (p->zfvec, p->fftlen, p->scale); return p; }