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