]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
The FAX modem receive synchronisation algorithms have been changed to prevent
authorSteve Underwood <steveu@coppice.org>
Thu, 11 Oct 2012 12:16:45 +0000 (20:16 +0800)
committerSteve Underwood <steveu@coppice.org>
Thu, 11 Oct 2012 12:16:45 +0000 (20:16 +0800)
occasional false recognition of a fast modem when its really the V.21 modem.
This was sometimes messing up T.38 gateway operation.

libs/spandsp/src/spandsp/dds.h
libs/spandsp/src/spandsp/private/v17rx.h
libs/spandsp/src/spandsp/private/v27ter_rx.h
libs/spandsp/src/spandsp/private/v29rx.h
libs/spandsp/src/v17rx.c
libs/spandsp/src/v22bis_rx.c
libs/spandsp/src/v27ter_rx.c
libs/spandsp/src/v29rx.c

index 10bf99fdf759e2872c58c64e494dc64d64ad2eb5..c4b8b6bb134f5a20f10e663b874cb4b2eb0f909b 100644 (file)
@@ -28,6 +28,9 @@
 #if !defined(_SPANDSP_DDS_H_)
 #define _SPANDSP_DDS_H_
 
+#define DDS_PHASE_RATE(frequency) (int32_t) ((frequency)*65536.0f*65536.0f/SAMPLE_RATE)
+#define DDS_PHASE(angle) (int32_t) ((uint32_t) (((angle < 0.0f)  ?  (360.0f + angle)  :  angle)*65536.0f*65536.0f/360.0f))
+
 #if defined(__cplusplus)
 extern "C"
 {
index a9682900107a92a25a36e616783a64f1d79699ac..f25007e9eadc2e68d11c82d8aa69af78add9c2e0 100644 (file)
 /* Target length for the equalizer is about 63 taps, to deal with the worst stuff
    in V.56bis. */
 /*! The length of the equalizer buffer */
-//#define V17_EQUALIZER_LEN           33
-#define V17_EQUALIZER_LEN           17
+#define V17_EQUALIZER_LEN           33
+
 /*! Samples before the target position in the equalizer buffer */
-//#define V17_EQUALIZER_PRE_LEN       16
-#define V17_EQUALIZER_PRE_LEN       8
+#define V17_EQUALIZER_PRE_LEN       16
 
 /*! The number of taps in the pulse shaping/bandpass filter */
 #define V17_RX_FILTER_STEPS         27
@@ -72,7 +71,7 @@ struct v17_rx_state_s
                routine. */
     void *qam_user_data;
 
-#if defined(SPANDSP_USE_FIXED_POINTx)
+#if defined(SPANDSP_USE_FIXED_POINT)
     /*! \brief The scaling factor assessed by the AGC algorithm. */
     int16_t agc_scaling;
     /*! \brief The previous value of agc_scaling, needed to reuse old training. */
@@ -202,10 +201,10 @@ struct v17_rx_state_s
                This is only for performance analysis purposes. */
     int total_baud_timing_correction;
 
-    /*! \brief Starting phase angles for the coarse carrier aquisition step. */
-    int32_t start_angles[2];
-    /*! \brief History list of phase angles for the coarse carrier aquisition step. */
-    int32_t angles[16];
+    /*! \brief The previous symbol phase angles for the coarse carrier aquisition step. */
+    int32_t last_angles[2];
+    /*! \brief History list of phase angle differences for the coarse carrier aquisition step. */
+    int32_t diff_angles[16];
 
     /*! \brief A pointer to the current space map. There is a space map for
                each trellis state. */
@@ -219,7 +218,7 @@ struct v17_rx_state_s
     int full_path_to_past_state_locations[V17_TRELLIS_STORAGE_DEPTH][8];
     /*! \brief The trellis. */
     int past_state_locations[V17_TRELLIS_STORAGE_DEPTH][8];
-#if defined(SPANDSP_USE_FIXED_POINTx)
+#if defined(SPANDSP_USE_FIXED_POINT)
     /*! \brief Euclidean distances (actually the squares of the distances)
                from the last states of the trellis. */
     uint32_t distances[8];
index 92bf937d833fc8ea29287aff7d732f2b01a5d3ed..e10781f72e6bda097cd8a6fbb2be047c25a8d36e 100644 (file)
@@ -183,10 +183,11 @@ struct v27ter_rx_state_s
                This is only for performance analysis purposes. */
     int total_baud_timing_correction;
 
-    /*! \brief Starting phase angles for the coarse carrier aquisition step. */
-    int32_t start_angles[2];
-    /*! \brief History list of phase angles for the coarse carrier aquisition step. */
-    int32_t angles[16];
+    /*! \brief The previous symbol phase angles for the coarse carrier aquisition step. */
+    int32_t last_angles[2];
+    /*! \brief History list of phase angle differences for the coarse carrier aquisition step. */
+    int32_t diff_angles[16];
+
     /*! \brief Error and flow logging control */
     logging_state_t logging;
 };
index 17e900582e621a03cd29bceab9849705b6d462ff..385c787dd62c1ff172330cc6b57110353d2c09ec 100644 (file)
@@ -184,10 +184,10 @@ struct v29_rx_state_s
                This is only for performance analysis purposes. */
     int total_baud_timing_correction;
 
-    /*! \brief Starting phase angles for the coarse carrier aquisition step. */
-    int32_t start_angles[2];
-    /*! \brief History list of phase angles for the coarse carrier aquisition step. */
-    int32_t angles[16];
+    /*! \brief The previous symbol phase angles for the coarse carrier aquisition step. */
+    int32_t last_angles[2];
+    /*! \brief History list of phase angle differences for the coarse carrier aquisition step. */
+    int32_t diff_angles[16];
 
     /*! \brief The position of the current symbol in the constellation, used for
                differential decoding. */
index 9d692a154887ff1af00b3fc77aa251f6b44e4003..b275270b4961322f5938bca7c5747ed65fc6760d 100644 (file)
@@ -718,9 +718,9 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
         if (++s->training_count >= 100)
         {
             /* Record the current phase angle */
-            s->angles[0] =
-            s->start_angles[0] = arctan2(z.im, z.re);
             s->training_stage = TRAINING_STAGE_LOG_PHASE;
+            vec_zeroi32(s->diff_angles, 16);
+            s->last_angles[0] = arctan2(z.im, z.re);
 #if defined(SPANDSP_USE_FIXED_POINTx)
             if (s->agc_scaling_save == 0)
                 s->agc_scaling_save = s->agc_scaling;
@@ -740,16 +740,16 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
             /* We should already know the accurate carrier frequency. All we need to sort
                out is the phase. */
             /* Check if we just saw A or B */
-            if ((uint32_t) (angle - s->start_angles[0]) < 0x80000000U)
+            if ((uint32_t) (angle - s->last_angles[0]) < 0x80000000U)
             {
-                angle = s->start_angles[0];
-                s->angles[0] = 0xC0000000 + 219937506;
-                s->angles[1] = 0x80000000 + 219937506;
+                angle = s->last_angles[0];
+                s->last_angles[0] = 0xC0000000 + 219937506;
+                s->last_angles[1] = 0x80000000 + 219937506;
             }
             else
             {
-                s->angles[0] = 0x80000000 + 219937506;
-                s->angles[1] = 0xC0000000 + 219937506;
+                s->last_angles[0] = 0x80000000 + 219937506;
+                s->last_angles[1] = 0xC0000000 + 219937506;
             }
             /* Make a step shift in the phase, to pull it into line. We need to rotate the equalizer
                buffer, as well as the carrier phase, for this to play out nicely. */
@@ -775,8 +775,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
         }
         else
         {
-            s->angles[1] =
-            s->start_angles[1] = angle;
+            s->last_angles[1] = angle;
             s->training_stage = TRAINING_STAGE_WAIT_FOR_CDBA;
         }
         break;
@@ -785,55 +784,32 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
         angle = arctan2(z.im, z.re);
         /* Look for the initial ABAB sequence to display a phase reversal, which will
            signal the start of the scrambled CDBA segment */
-        ang = angle - s->angles[(s->training_count - 1) & 0xF];
-        s->angles[(s->training_count + 1) & 0xF] = angle;
-
-        /* Do a coarse frequency adjustment about half way through the reversals, as if we wait until
-           the end, we might have rotated too far to correct properly. */
-        if (s->training_count == 100)
-        {
-            i = s->training_count;
-            j = i & 0xF;
-            ang = (s->angles[j] - s->start_angles[0])/i
-                + (s->angles[j | 0x1] - s->start_angles[1])/i;
-            s->carrier_phase_rate += 3*(ang/20);
-            //span_log(&s->logging, SPAN_LOG_FLOW, "Angles %x, %x, %x, %x, dist %d\n", s->angles[j], s->start_angles[0], s->angles[j | 0x1], s->start_angles[1], i);
-
-            s->start_angles[0] = s->angles[j];
-            s->start_angles[1] = s->angles[j | 0x1];
-            //span_log(&s->logging, SPAN_LOG_FLOW, "%d %d %d %d %d\n", s->angles[s->training_count & 0xF], s->start_angles[0], s->angles[(s->training_count | 0x1) & 0xF], s->start_angles[1], s->training_count);
-            span_log(&s->logging, SPAN_LOG_FLOW, "First coarse carrier frequency %7.2f (%d)\n", dds_frequencyf(s->carrier_phase_rate), s->training_count);
-
-        }
-        if ((ang > 0x40000000  ||  ang < -0x40000000)  &&  s->training_count >= 13)
+        i = s->training_count + 1;
+        ang = angle - s->last_angles[i & 1];
+        s->last_angles[i & 1] = angle;
+        s->diff_angles[i & 0xF] = s->diff_angles[(i - 2) & 0xF] + (ang >> 4);
+        if ((ang > DDS_PHASE(90.0f)  ||  ang < DDS_PHASE(-90.0f))  &&  s->training_count >= 13)
         {
             span_log(&s->logging, SPAN_LOG_FLOW, "We seem to have a reversal at symbol %d\n", s->training_count);
             /* We seem to have a phase reversal */
             /* Slam the carrier frequency into line, based on the total phase drift over the last
                section. Use the shift from the odd bits and the shift from the even bits to get
                better jitter suppression. */
-            /* TODO: We are supposed to deal with frequancy errors up to +-8Hz. Over 200+
-                     symbols that is more than half a cycle. We get confused an do crazy things.
-                     We can only cope with errors up to 5Hz right now. We need to implement
-                     greater tolerance to be compliant, although it doesn't really matter much
-                     these days. */
             /* Step back a few symbols so we don't get ISI distorting things. */
             i = (s->training_count - 8) & ~1;
             /* Avoid the possibility of a divide by zero */
-            if (i - 100 + 8)
+            if (i > 1)
             {
                 j = i & 0xF;
-                ang = (s->angles[j] - s->start_angles[0])/(i - 100 + 8)
-                    + (s->angles[j | 0x1] - s->start_angles[1])/(i - 100 + 8);
-                s->carrier_phase_rate += 3*(ang/20);
-                span_log(&s->logging, SPAN_LOG_FLOW, "Angles %x, %x, %x, %x, dist %d\n", s->angles[j], s->start_angles[0], s->angles[j | 0x1], s->start_angles[1], i);
+                ang = (s->diff_angles[j] + s->diff_angles[j | 0x1])/(i - 1);
+                s->carrier_phase_rate += 3*16*(ang/20);
+                span_log(&s->logging, SPAN_LOG_FLOW, "Angles %x, %x, dist %d\n", s->last_angles[0], s->last_angles[1], i);
             }
-            //span_log(&s->logging, SPAN_LOG_FLOW, "%d %d %d %d %d\n", s->angles[s->training_count & 0xF], s->start_angles[0], s->angles[(s->training_count | 0x1) & 0xF], s->start_angles[1], s->training_count);
-            span_log(&s->logging, SPAN_LOG_FLOW, "Second coarse carrier frequency %7.2f (%d)\n", dds_frequencyf(s->carrier_phase_rate), s->training_count);
+            span_log(&s->logging, SPAN_LOG_FLOW, "Coarse carrier frequency %7.2f (%d)\n", dds_frequencyf(s->carrier_phase_rate), s->training_count);
             /* Check if the carrier frequency is plausible */
-            if (s->carrier_phase_rate < dds_phase_ratef(CARRIER_NOMINAL_FREQ - 20.0f)
+            if (s->carrier_phase_rate < DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ - 20.0f)
                 ||
-                s->carrier_phase_rate > dds_phase_ratef(CARRIER_NOMINAL_FREQ + 20.0f))
+                s->carrier_phase_rate > DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ + 20.0f))
             {
                 span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
                 /* Park this modem */
@@ -1025,8 +1001,8 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
         /* Look for the initial ABAB sequence to display a phase reversal, which will
            signal the start of the scrambled CDBA segment */
         angle = arctan2(z.im, z.re);
-        ang = angle - s->angles[s->training_count & 1];
-        if (ang > 0x40000000  ||  ang < -0x40000000)
+        ang = angle - s->last_angles[s->training_count & 1];
+        if (ang > DDS_PHASE(90.0f)  ||  ang < DDS_PHASE(-90.0f))
         {
             /* We seem to have a phase reversal */
             /* We have just seen the first symbol of the scrambled sequence, so skip it. */
@@ -1507,8 +1483,8 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
 #endif
     if (short_train != 2)
         s->short_train = short_train;
-    memset(s->start_angles, 0, sizeof(s->start_angles));
-    memset(s->angles, 0, sizeof(s->angles));
+    memset(s->last_angles, 0, sizeof(s->last_angles));
+    memset(s->diff_angles, 0, sizeof(s->diff_angles));
 
     /* Initialise the TCM decoder parameters. */
     /* The accumulated distance vectors are set so state zero starts
@@ -1544,7 +1520,7 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
     }
     else
     {
-        s->carrier_phase_rate = dds_phase_ratef(CARRIER_NOMINAL_FREQ);
+        s->carrier_phase_rate = DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ);
         equalizer_reset(s);
 #if defined(SPANDSP_USE_FIXED_POINTx)
         s->agc_scaling_save = 0;
@@ -1618,7 +1594,7 @@ SPAN_DECLARE(v17_rx_state_t *) v17_rx_init(v17_rx_state_t *s, int bit_rate, put_
     s->short_train = FALSE;
     s->scrambler_tap = 18 - 1;
     v17_rx_signal_cutoff(s, -45.5f);
-    s->carrier_phase_rate_save = dds_phase_ratef(CARRIER_NOMINAL_FREQ);
+    s->carrier_phase_rate_save = DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ);
     v17_rx_restart(s, bit_rate, s->short_train);
     return s;
 }
index 41e307604232bb0f2c2b8da0c45afdb4dda7ab21..d124d7bcd8bb0eb9f8710762bf725658cca4c78d 100644 (file)
@@ -956,7 +956,7 @@ int v22bis_rx_restart(v22bis_state_t *s)
     s->rx.training_count = 0;
     s->rx.signal_present = FALSE;
 
-    s->rx.carrier_phase_rate = dds_phase_ratef((s->calling_party)  ?  2400.0f  :  1200.0f);
+    s->rx.carrier_phase_rate = (s->calling_party)  ?  DDS_PHASE_RATE(2400.0f)  :  DDS_PHASE_RATE(1200.0f);
     s->rx.carrier_phase = 0;
     power_meter_init(&s->rx.rx_power, 5);
     v22bis_rx_signal_cutoff(s, -45.5f);
index b38481b87a5ec4216165465e2041ce61396a40f5..a4a9f5eeb9499205b74fc1bfc5ef4af19b9c0582 100644 (file)
@@ -566,15 +566,14 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
         {
             s->gardner_step = 32;
             s->training_stage = TRAINING_STAGE_LOG_PHASE;
-            s->angles[0] =
-            s->start_angles[0] = arctan2(z.im, z.re);
+            vec_zeroi32(s->diff_angles, 16);
+            s->last_angles[0] = arctan2(z.im, z.re);
         }
         break;
     case TRAINING_STAGE_LOG_PHASE:
         /* Record the current alternate phase angle */
         target = &zero;
-        s->angles[1] =
-        s->start_angles[1] = arctan2(z.im, z.re);
+        s->last_angles[1] = arctan2(z.im, z.re);
         s->training_count = 1;
         s->training_stage = TRAINING_STAGE_WAIT_FOR_HOP;
         break;
@@ -583,9 +582,11 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
         angle = arctan2(z.im, z.re);
         /* Look for the initial ABAB sequence to display a phase reversal, which will
            signal the start of the scrambled ABAB segment */
-        ang = angle - s->angles[(s->training_count - 1) & 0xF];
-        s->angles[(s->training_count + 1) & 0xF] = angle;
-        if ((ang > 0x20000000  ||  ang < -0x20000000)  &&  s->training_count >= 3)
+        i = s->training_count + 1;
+        ang = angle - s->last_angles[i & 1];
+        s->last_angles[i & 1] = angle;
+        s->diff_angles[i & 0xF] = s->diff_angles[(i - 2) & 0xF] + (ang >> 4);
+        if ((ang > DDS_PHASE(45.0f)  ||  ang < DDS_PHASE(-45.0f))  &&  s->training_count >= 13)
         {
             /* We seem to have a phase reversal */
             /* Slam the carrier frequency into line, based on the total phase drift over the last
@@ -595,20 +596,20 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
             /* Step back a few symbols so we don't get ISI distorting things. */
             i = (s->training_count - 8) & ~1;
             /* Avoid the possibility of a divide by zero */
-            if (i)
+            if (i > 1)
             {
                 j = i & 0xF;
-                ang = (s->angles[j] - s->start_angles[0])/i + (s->angles[j | 0x1] - s->start_angles[1])/i;
+                ang = (s->diff_angles[j] + s->diff_angles[j | 0x1])/(i - 1);
                 if (s->bit_rate == 4800)
-                    s->carrier_phase_rate += ang/10;
+                    s->carrier_phase_rate += 16*(ang/10);
                 else
-                    s->carrier_phase_rate += 3*(ang/40);
+                    s->carrier_phase_rate += 3*16*(ang/40);
             }
             span_log(&s->logging, SPAN_LOG_FLOW, "Coarse carrier frequency %7.2f (%d)\n", dds_frequencyf(s->carrier_phase_rate), s->training_count);
             /* Check if the carrier frequency is plausible */
-            if (s->carrier_phase_rate < dds_phase_ratef(CARRIER_NOMINAL_FREQ - 20.0f)
+            if (s->carrier_phase_rate < DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ - 20.0f)
                 ||
-                s->carrier_phase_rate > dds_phase_ratef(CARRIER_NOMINAL_FREQ + 20.0f))
+                s->carrier_phase_rate > DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ + 20.0f))
             {
                 span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
                 /* Park this modem */
@@ -1065,7 +1066,7 @@ SPAN_DECLARE(int) v27ter_rx_restart(v27ter_rx_state_t *s, int bit_rate, int old_
     }
     else
     {
-        s->carrier_phase_rate = dds_phase_ratef(CARRIER_NOMINAL_FREQ);
+        s->carrier_phase_rate = DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ);
 #if defined(SPANDSP_USE_FIXED_POINT)
         s->agc_scaling = (float) (1024.0f*FP_FACTOR)*1.414f/283.0f;
 #else
index a8a1ed9c9455c7419fb398c69ee6ac10c9196ec8..dec0c1f27796cc9bb5123b907ebbe619b73be1bc 100644 (file)
@@ -600,8 +600,8 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
         {
             /* Record the current phase angle */
             s->training_stage = TRAINING_STAGE_LOG_PHASE;
-            s->angles[0] =
-            s->start_angles[0] = arctan2(z.im, z.re);
+            vec_zeroi32(s->diff_angles, 16);
+            s->last_angles[0] = arctan2(z.im, z.re);
 #if defined(SPANDSP_USE_FIXED_POINT)
             if (s->agc_scaling_save == 0)
                 s->agc_scaling_save = s->agc_scaling;
@@ -614,8 +614,7 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
     case TRAINING_STAGE_LOG_PHASE:
         /* Record the current alternate phase angle */
         target = &zero;
-        s->angles[1] =
-        s->start_angles[1] = arctan2(z.im, z.re);
+        s->last_angles[1] = arctan2(z.im, z.re);
         s->training_count = 1;
         s->training_stage = TRAINING_STAGE_WAIT_FOR_CDCD;
         break;
@@ -624,9 +623,11 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
         angle = arctan2(z.im, z.re);
         /* Look for the initial ABAB sequence to display a phase reversal, which will
            signal the start of the scrambled CDCD segment */
-        ang = angle - s->angles[(s->training_count - 1) & 0xF];
-        s->angles[(s->training_count + 1) & 0xF] = angle;
-        if ((ang > 0x20000000  ||  ang < -0x20000000)  &&  s->training_count >= 13)
+        i = s->training_count + 1;
+        ang = angle - s->last_angles[i & 1];
+        s->last_angles[i & 1] = angle;
+        s->diff_angles[i & 0xF] = s->diff_angles[(i - 2) & 0xF] + (ang >> 4);
+        if ((ang > DDS_PHASE(45.0f)  ||  ang < DDS_PHASE(-45.0f))  &&  s->training_count >= 13)
         {
             /* We seem to have a phase reversal */
             /* Slam the carrier frequency into line, based on the total phase drift over the last
@@ -636,17 +637,17 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
             /* Step back a few symbols so we don't get ISI distorting things. */
             i = (s->training_count - 8) & ~1;
             /* Avoid the possibility of a divide by zero */
-            if (i)
+            if (i > 1)
             {
                 j = i & 0xF;
-                ang = (s->angles[j] - s->start_angles[0])/i + (s->angles[j | 0x1] - s->start_angles[1])/i;
-                s->carrier_phase_rate += 3*(ang/20);
+                ang = (s->diff_angles[j] + s->diff_angles[j | 0x1])/(i - 1);
+                s->carrier_phase_rate += 3*16*(ang/20);
             }
             span_log(&s->logging, SPAN_LOG_FLOW, "Coarse carrier frequency %7.2f\n", dds_frequencyf(s->carrier_phase_rate));
             /* Check if the carrier frequency is plausible */
-            if (s->carrier_phase_rate < dds_phase_ratef(CARRIER_NOMINAL_FREQ - 20.0f)
+            if (s->carrier_phase_rate < DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ - 20.0f)
                 ||
-                s->carrier_phase_rate > dds_phase_ratef(CARRIER_NOMINAL_FREQ + 20.0f))
+                s->carrier_phase_rate > DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ + 20.0f))
             {
                 span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
                 /* Park this modem */
@@ -1111,7 +1112,7 @@ SPAN_DECLARE(int) v29_rx_restart(v29_rx_state_t *s, int bit_rate, int old_train)
     }
     else
     {
-        s->carrier_phase_rate = dds_phase_ratef(CARRIER_NOMINAL_FREQ);
+        s->carrier_phase_rate = DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ);
         equalizer_reset(s);
 #if defined(SPANDSP_USE_FIXED_POINT)
         s->agc_scaling_save = 0;