00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef _VrSYNCCORR_H_
00019 #define _VrSYNCCORR_H_
00020
00021 #define SIZE 4096
00022 #define MAX_RESULTS_SIZE 10000
00023
00024 #include <VrDecimatingSigProc.h>
00025 #include <fstream>
00026 #if defined (ENABLE_MMX)
00027 #include <VrMMX.h>
00028 #endif
00029
00030
00031
00032
00033 struct corr_result {
00034 float value;
00035 VrSampleIndex index;
00036 };
00037
00038
00039 template<class iType>
00040 class VrSyncCorr : public VrDecimatingSigProc<iType,char> {
00041 protected:
00042
00043 float result, old_result, *sqr, weight_sign;
00044 u_int first, first_high, first_low, current, mask;
00045 int step_size, skip, differential_offset;
00046 int low_interval, high_interval, best_period;
00047 int corr_count, pattern_length, pattern_count, corr_init;
00048 int window_size, excess_samples, numTaps, struct_size;
00049 float freq;
00050 virtual void get_filter_output(iType*,int,int,VrComplex*,int);
00051 VrComplex *filter_results;
00052 VrComplex phase_corr_incr, phase_bump, phase_offset;
00053 VrComplex* filter_taps;
00054 #if defined (ENABLE_MMX)
00055 mmxTaps* processedTaps;
00056 #endif
00057
00058 public:
00059 virtual void set_window(int w) {window_size = w;}
00060 virtual void set_period(int p) {best_period = p;}
00061 virtual void increment_input_ptr(int i) {differential_offset+=i;}
00062 virtual const char *name() { return "VrSyncCorr"; }
00063 virtual int forecast(VrSampleRange output,
00064 VrSampleRange inputs[]);
00065 virtual int work(VrSampleRange output, void *o[],
00066 VrSampleRange inputs[], void *i[]);
00067 virtual void initialize();
00068 VrSyncCorr(int, int, int, float);
00069 ~VrSyncCorr();
00070 };
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 template<class iType> int
00094 VrSyncCorr<iType>::work(VrSampleRange output, void *ao[],
00095 VrSampleRange inputs[], void *ai[])
00096 {
00097 iType **i = (iType **)ai;
00098 char **o = (char **)ao;
00099 struct corr_result best, *out_ptr;
00100 int size = output.size;
00101 float x, y, sign, *sqr;
00102 int current, output_time, step_size, number_outputs;
00103 float max, min;
00104 VrSampleIndex max_loc, min_loc;
00105 VrSampleIndex offset = inputs[0].index;
00106
00107 iType *input_ptr;
00108 VrComplex *f_results;
00109
00110 input_ptr = i[0];
00111 out_ptr = (struct corr_result*) o[0];
00112 f_results = filter_results;
00113
00114
00115 output_time = 0;
00116 number_outputs = window_size * size / step_size + 5;
00117 get_filter_output(input_ptr, output_time, number_outputs, f_results, step_size);
00118
00119 while(size-->0) {
00120
00121 x = real(*f_results);
00122 y = imag(*f_results++);
00123 sign = (float) (2 * (x>0.0))-1;
00124
00125 sqr[(current)&mask] = sign*(x*x + y*y);
00126
00127 if (corr_init) {
00128
00129 pattern_count++;
00130 if (pattern_count == 1){
00131 old_result = 0.0;
00132 weight_sign = -1.0;
00133 max = 0.0;
00134 min = 0.0;
00135 }
00136 if (pattern_count == low_interval + 1){
00137 weight_sign = 1.0;
00138 }
00139 if (pattern_count == low_interval + high_interval + 1) {
00140 weight_sign = -1.0;
00141 }
00142
00143 old_result += weight_sign * sign * (x*x + y*y);
00144 current++;
00145
00146 if (pattern_count == pattern_length){
00147 pattern_count = 0;
00148 corr_init = 0;
00149 first = current-pattern_length;
00150 first_high = first + low_interval;
00151 first_low = first_high + high_interval;
00152 }
00153 } else {
00154
00155 result = old_result;
00156
00157 result += sqr[(first++)&mask];
00158 result -= (2 * sqr[(first_high++)&mask]);
00159 result += (2 * sqr[(first_low++)&mask]);
00160 result -= sqr[(current)&mask];
00161
00162 if (result > max) {
00163 max = result;
00164 max_loc = (current - (pattern_length/2)) * step_size;
00165 }
00166 if (result < min) {
00167 min = result;
00168 min_loc = (current - (pattern_length/2)) * step_size;
00169 }
00170
00171 current++;
00172
00173 old_result = result;
00174 }
00175 if (max >= -min) {
00176 best.value = max;
00177 best.index = max_loc + offset;
00178 }
00179 else {
00180 best.value = min;
00181 best.index = min_loc + offset;
00182 }
00183 }
00184 *out_ptr++ = best;
00185 return output.size;
00186 }
00187
00188 template<class iType> void
00189 VrSyncCorr<iType>::get_filter_output(iType *inputArray, int output_time,
00190 int num_outputs, VrComplex *result_array, int decimation)
00191 {
00192 VrComplex result = 0;
00193 unsigned int size = num_outputs;
00194
00195 VrComplex phase_correction;
00196 phase_correction=pow(phase_corr_incr, output_time) * phase_offset;
00197
00198 for (;size>0;size--,inputArray+=decimation) {
00199 result = 0;
00200
00201 #if defined (ENABLE_MMX)
00202 if(processedTaps->mmxReady())
00203 result = processedTaps->mmxCVDProduct(inputArray);
00204 else
00205 #endif
00206 {
00207 VrComplex *taps_tmp = filter_taps;
00208 for (int j=0; j < numTaps; j++)
00209 result += taps_tmp[j] * inputArray[j];
00210 }
00211
00212 phase_correction *= phase_corr_incr;
00213 result *= phase_correction;
00214 *result_array++ = result;
00215 }
00216 }
00217
00218 template<class iType>
00219 VrSyncCorr<iType>::VrSyncCorr(int dec, int step, int num_taps, float center_freq)
00220 :VrDecimatingSigProc<iType,char>(1,dec)
00221 {
00222 numTaps = num_taps;
00223 freq = center_freq;
00224 step_size = step;
00225 struct_size = sizeof(struct corr_result);
00226
00227 }
00228
00229 template<class iType> int
00230 VrSyncCorr<iType>::forecast(VrSampleRange output,
00231 VrSampleRange inputs[]) {
00232
00233 for(unsigned int i=0;i<numberInputs;i++) {
00234 inputs[i].index=output.index*best_period+ differential_offset;
00235 inputs[i].size=output.size*decimation + window_size + 2*excess_samples;
00236
00237
00238 }
00239 return 0;
00240 }
00241
00242
00243 template<class iType>
00244 void VrSyncCorr<iType>::initialize()
00245 {
00246
00247 sqr = new float[SIZE];
00248 mask = (u_int) (SIZE-1);
00249 differential_offset = 0;
00250 excess_samples = 0;
00251
00252
00253
00254
00255 first = 0;
00256 first_high = (int) (2.0 * nominal_samples_per_symbol / (float) step_size);
00257 first_low = (int) (6.0 * nominal_samples_per_symbol / (float) step_size);
00258
00259 current = 0;
00260 corr_init = 1;
00261 corr_count = 0;
00262
00263 pattern_length = (int) (8.0 * nominal_samples_per_symbol / (float) step_size)/2*2;
00264 excess_samples = pattern_length / 2 * step_size;
00265 pattern_count = 0;
00266
00267 filter_results = new VrComplex[MAX_RESULTS_SIZE];
00268 history = excess_samples;
00269
00270
00271 window_size = source_rate / sync_rate / 10;
00272 best_period = (int) (nominal_samples_per_symbol * symbols_per_period);
00273
00274 }
00275
00276 template<class iType>
00277 VrSyncCorr<iType>::~VrSyncCorr()
00278 {
00279 delete sqr;
00280 delete filter_results;
00281 }
00282
00283 #endif
00284
00285
00286
00287
00288
00289
00290
00291
00292