In creating a Java version of a couple of routines in fdmdv.c, I had
to do things a bit different, due to the pointers. But I did get rid
of the S[] arrays out of global memory and they now go in and out of
the stack. Attached is the essential bits. Not a big savings, but at
least you don't have 4K of memory sitting idle. I could do a lot with
4K back in the Z80 days :-)
So I converted that back to C to see if it might be useful for you.
/*
* LPF and pick peak part of freq estimate
*/
static float lpf_peak_pick(int pass, float *foffset, COMP S[], int nin) {
COMP s[MPILOTFFT];
COMP *pilot_lpf;
COMP *pilot_baseband;
int i, j, k;
if (pass == 1) {
pilot_lpf = pilot_lpf1;
pilot_baseband = pilot_baseband1;
} else {
pilot_lpf = pilot_lpf2;
pilot_baseband = pilot_baseband2;
}
// LPF cutoff 200Hz, so we can handle max +/- 200 Hz freq offset
for (i = 0; i < (NPILOTLPF - nin); i++) {
pilot_lpf[i] = pilot_lpf[nin + i];
}
for (i = (NPILOTLPF - nin), j = 0; i < NPILOTLPF; i++, j++) {
pilot_lpf[i].real = 0.0;
pilot_lpf[i].imag = 0.0;
for (k = 0; k < NPILOTCOEFF; k++) {
pilot_lpf[i] = cadd(pilot_lpf[i], fcmult(pilot_coeff[k], pilot_baseband[j + k]));
}
}
/*
* decimate to improve DFT resolution, window and DFT
* calc decimation rate given new sample rate is twice LPF freq
*/
int mpilot = (int) FS / (2 * 200); // 20
for (i = 0; i < MPILOTFFT; i++) {
s[i].real = 0.0;
s[i].imag = 0.0;
}
for (i = 0, j = 0; i < NPILOTLPF; i += mpilot, j++) {
s[j] = fcmult(hanning[i], pilot_lpf[i]);
}
kiss_fft(fft_pilot_cfg, (kiss_fft_cpx *) s, (kiss_fft_cpx *) S);
// peak pick and convert to Hz
float imax = 0.0;
float mag;
int ix = 0;
for (i = 0; i < MPILOTFFT; i++) {
mag = S[i].real * S[i].real + S[i].imag * S[i].imag;
if (mag > imax) {
imax = mag;
ix = i;
}
}
float r = (2.0 * 200.0) / (float) FFT_SIZE; // maps FFT bin to frequency in Hz
if (ix >= (FFT_SIZE / 2)) {
*foffset = (float) (ix - FFT_SIZE) * r;
} else {
*foffset = (float) ix * r;
}
return imax;
}
/*
* Estimate frequency offset of FDM signal using BPSK pilot. Note that this
* algorithm is quite sensitive to pilot tone level wrt other carriers, so
* test variations to the pilot amplitude carefully.
*/
static float rx_est_freq_offset(COMP rx_fdm[], int nin) {
COMP pilot[M + M / P];
COMP prev_pilot[M + M / P];
COMP S[MPILOTFFT];
float *foff1;
float *foff2;
int i, j;
// get pilot samples used for correlation/down conversion of rx signal
for (i = 0; i < nin; i++) {
pilot[i] = pilot_lut[pilot_lut_index++];
if (pilot_lut_index >= (M * 4)) {
pilot_lut_index = 0;
}
prev_pilot[i] = pilot_lut[prev_pilot_lut_index++];
if (prev_pilot_lut_index >= (M * 4)) {
prev_pilot_lut_index = 0;
}
}
/*
* Down convert latest M samples of pilot by multiplying by ideal
* BPSK pilot signal we have generated locally. The peak of the
* resulting signal is sensitive to the time shift between the
* received and local version of the pilot, so we do it twice at
* different time shifts and choose the maximum.
*/
for (i = 0; i < (NPILOTBASEBAND - nin); i++) { // 230 - 160 = 0..69
pilot_baseband1[i] = pilot_baseband1[i + nin];
pilot_baseband2[i] = pilot_baseband2[i + nin];
}
for (i = 0, j = (NPILOTBASEBAND - nin); i < nin; i++, j++) { // 70..159 (90)
pilot_baseband1[j] = cmult(rx_fdm[i], cconj(pilot[i]));
pilot_baseband2[j] = cmult(rx_fdm[i], cconj(prev_pilot[i]));
}
float freq1 = lpf_peak_pick(1, foff1, &S[0], nin);
float freq2 = lpf_peak_pick(2, foff2, &S[0], nin);
if (freq1 > freq2) {
return *foff1;
} else {
return *foff2;
}
}
------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
_______________________________________________
Freetel-codec2 mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freetel-codec2