]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Tweaks for spandsp
authorSteve Underwood <steveu@coppice.org>
Thu, 29 Mar 2012 15:33:11 +0000 (23:33 +0800)
committerSteve Underwood <steveu@coppice.org>
Thu, 29 Mar 2012 15:33:11 +0000 (23:33 +0800)
12 files changed:
libs/spandsp/src/spandsp/private/t38_terminal.h
libs/spandsp/src/spandsp/private/v22bis.h
libs/spandsp/src/spandsp/v22bis.h
libs/spandsp/src/t38_terminal.c
libs/spandsp/src/v22bis_rx.c
libs/spandsp/src/v22bis_tx.c
libs/spandsp/src/v29rx.c
libs/spandsp/src/v29tx_constellation_maps.h
libs/spandsp/src/v8.c
libs/spandsp/tests/Makefile.am
libs/spandsp/tests/fax_tester.c
libs/spandsp/tests/fax_tests.sh

index 4cd47df85bb5eeaccee9c3a896e610e419937d21..0bd75a6cfb453b2db6e3a6140c2d47e8fb360856 100644 (file)
@@ -32,8 +32,8 @@ typedef struct
 {
     /*! \brief Internet Aware FAX mode bit mask. */
     int iaf;
-    /*! \brief Required time between T.38 transmissions, in milliseconds. */
-    int ms_per_tx_chunk;
+    /*! \brief Required time between T.38 transmissions, in microseconds. */
+    int us_per_tx_chunk;
     /*! \brief Bit fields controlling the way data is packed into chunked for transmission. */
     int chunking_modes;
 
index 2561c8e03d5d07887a456bcb570f734df3ed9148..d5016430e9c47f38be5facf669249c58f3d65179 100644 (file)
 #if !defined(_SPANDSP_PRIVATE_V22BIS_H_)
 #define _SPANDSP_PRIVATE_V22BIS_H_
 
-/*! The length of the equalizer buffer */
-#define V22BIS_EQUALIZER_LEN        17
-/*! Samples before the target position in the equalizer buffer */
-#define V22BIS_EQUALIZER_PRE_LEN    8
+/*! The number of steps to the left and to the right of the target position in the equalizer buffer. */
+#define V22BIS_EQUALIZER_LEN        7
+/*! One less than a power of 2 >= (2*V22BIS_EQUALIZER_LEN + 1) */
+#define V22BIS_EQUALIZER_MASK       15
 
 /*! The number of taps in the transmit pulse shaping filter */
 #define V22BIS_TX_FILTER_STEPS      9
@@ -65,12 +65,6 @@ enum
     V22BIS_TX_TRAINING_STAGE_PARKED
 };
 
-#if defined(SPANDSP_USE_FIXED_POINT)
-extern const complexi16_t v22bis_constellation[16];
-#else
-extern const complexf_t v22bis_constellation[16];
-#endif
-
 /*!
     V.22bis modem descriptor. This defines the working state for a single instance
     of a V.22bis modem.
@@ -99,15 +93,10 @@ struct v22bis_state_s
     /* Receive section */
     struct
     {
-#if defined(SPANDSP_USE_FIXED_POINT)
-        /*! \brief The scaling factor accessed by the AGC algorithm. */
-        int16_t agc_scaling;
-        /*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
+        /*! \brief The route raised cosine (RRC) pulse shaping filter buffer. */
+#if defined(SPANDSP_USE_FIXED_POINTx)
         int16_t rrc_filter[V22BIS_RX_FILTER_STEPS];
 #else
-        /*! \brief The scaling factor accessed by the AGC algorithm. */
-        float agc_scaling;
-        /*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
         float rrc_filter[V22BIS_RX_FILTER_STEPS];
 #endif
         /*! \brief Current offset into the RRC pulse shaping filter buffer. */
@@ -127,27 +116,19 @@ struct v22bis_state_s
         /*! \brief >0 if a signal above the minimum is present. It may or may not be a V.22bis signal. */
         int signal_present;
 
+        /*! \brief A measure of how much mismatch there is between the real constellation,
+            and the decoded symbol positions. */
+        float training_error;
+
         /*! \brief The current phase of the carrier (i.e. the DDS parameter). */
         uint32_t carrier_phase;
         /*! \brief The update rate for the phase of the carrier (i.e. the DDS increment). */
         int32_t carrier_phase_rate;
-#if defined(SPANDSP_USE_FIXED_POINT)
-        /*! \brief A measure of how much mismatch there is between the real constellation,
-                   and the decoded symbol positions. */
-        int32_t training_error;
-        /*! \brief The proportional part of the carrier tracking filter. */
-        int32_t carrier_track_p;
-        /*! \brief The integral part of the carrier tracking filter. */
-        int32_t carrier_track_i;
-#else
-        /*! \brief A measure of how much mismatch there is between the real constellation,
-                   and the decoded symbol positions. */
-        float training_error;
+
         /*! \brief The proportional part of the carrier tracking filter. */
         float carrier_track_p;
         /*! \brief The integral part of the carrier tracking filter. */
         float carrier_track_i;
-#endif
 
         /*! \brief A callback function which may be enabled to report every symbol's
                    constellation position. */
@@ -162,23 +143,21 @@ struct v22bis_state_s
         int32_t carrier_on_power;
         /*! \brief The power meter level at which carrier off is declared. */
         int32_t carrier_off_power;
-
+        /*! \brief The scaling factor accessed by the AGC algorithm. */
+        float agc_scaling;
+    
         int constellation_state;
 
-#if defined(SPANDSP_USE_FIXED_POINT)
-        /*! \brief The current delta factor for updating the equalizer coefficients. */
-        int16_t eq_delta;
-        /*! \brief The adaptive equalizer coefficients. */
-        complexi16_t eq_coeff[V22BIS_EQUALIZER_LEN];
-        /*! \brief The equalizer signal buffer. */
-        complexi16_t eq_buf[V22BIS_EQUALIZER_LEN];
-#else
         /*! \brief The current delta factor for updating the equalizer coefficients. */
         float eq_delta;
+#if defined(SPANDSP_USE_FIXED_POINTx)
         /*! \brief The adaptive equalizer coefficients. */
-        complexf_t eq_coeff[V22BIS_EQUALIZER_LEN];
+        complexi_t eq_coeff[2*V22BIS_EQUALIZER_LEN + 1];
         /*! \brief The equalizer signal buffer. */
-        complexf_t eq_buf[V22BIS_EQUALIZER_LEN];
+        complexi_t eq_buf[V22BIS_EQUALIZER_MASK + 1];
+#else
+        complexf_t eq_coeff[2*V22BIS_EQUALIZER_LEN + 1];
+        complexf_t eq_buf[V22BIS_EQUALIZER_MASK + 1];
 #endif
         /*! \brief Current offset into the equalizer buffer. */
         int eq_step;
@@ -204,24 +183,11 @@ struct v22bis_state_s
     /* Transmit section */
     struct
     {
-#if defined(SPANDSP_USE_FIXED_POINT)
-        /*! \brief The guard tone level. */
-        int16_t guard_tone_gain;
-        /*! \brief The gain factor needed to achieve the specified output power. */
-        int16_t gain;
-        /*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
-        int16_t rrc_filter_re[V22BIS_TX_FILTER_STEPS];
-        int16_t rrc_filter_im[V22BIS_TX_FILTER_STEPS];
-#else
-        /*! \brief The guard tone level. */
-        float guard_tone_gain;
         /*! \brief The gain factor needed to achieve the specified output power. */
         float gain;
-        /*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
-        float rrc_filter_re[V22BIS_TX_FILTER_STEPS];
-        float rrc_filter_im[V22BIS_TX_FILTER_STEPS];
-#endif
 
+        /*! \brief The route raised cosine (RRC) pulse shaping filter buffer. */
+        complexf_t rrc_filter[2*V22BIS_TX_FILTER_STEPS];
         /*! \brief Current offset into the RRC pulse shaping filter buffer. */
         int rrc_filter_step;
 
@@ -243,6 +209,7 @@ struct v22bis_state_s
         uint32_t guard_phase;
         /*! \brief The update rate for the phase of the guard tone (i.e. the DDS increment). */
         int32_t guard_phase_rate;
+        float guard_level;
         /*! \brief The current fractional phase of the baud timing. */
         int baud_phase;
         /*! \brief The code number for the current position in the constellation. */
index 440118c7cbd7b1a674b96fdb84c2eb762c8e9fb3..073fb7135adb0b815eae6cbce2135528d0cdb2a8 100644 (file)
@@ -61,6 +61,8 @@ enum
 */
 typedef struct v22bis_state_s v22bis_state_t;
 
+extern const complexf_t v22bis_constellation[16];
+
 #if defined(__cplusplus)
 extern "C"
 {
@@ -86,11 +88,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx_fillin(v22bis_state_t *s, int len);
     \brief Get a snapshot of the current equalizer coefficients.
     \param coeffs The vector of complex coefficients.
     \return The number of coefficients in the vector. */
-#if defined(SPANDSP_USE_FIXED_POINT)
-SPAN_DECLARE(int) v22bis_rx_equalizer_state(v22bis_state_t *s, complexi16_t **coeffs);
-#else
 SPAN_DECLARE(int) v22bis_rx_equalizer_state(v22bis_state_t *s, complexf_t **coeffs);
-#endif
 
 /*! Get the current received carrier frequency.
     \param s The modem context.
index cf78c024cc16bfcc63bb44d2902e3d9518c30298..1a2c3eca2e998fbfd5ff3bd9ba3172ea5a70dd3c 100644 (file)
 #include "spandsp/private/t38_terminal.h"
 
 /* Settings suitable for paced transmission over a UDP transport */
-#define DEFAULT_MS_PER_TX_CHUNK                 30
+#define DEFAULT_US_PER_TX_CHUNK                 30000
 
 #define INDICATOR_TX_COUNT                      3
 #define DATA_TX_COUNT                           1
@@ -613,7 +613,8 @@ static void send_hdlc(void *user_data, const uint8_t *msg, int len)
     }
     else
     {
-        s->t38_fe.hdlc_tx.extra_bits = extra_bits_in_stuffed_frame(msg, len);
+        if (s->t38_fe.us_per_tx_chunk)
+            s->t38_fe.hdlc_tx.extra_bits = extra_bits_in_stuffed_frame(msg, len);
         bit_reverse(s->t38_fe.hdlc_tx.buf, msg, len);
         s->t38_fe.hdlc_tx.len = len;
         s->t38_fe.hdlc_tx.ptr = 0;
@@ -624,7 +625,7 @@ static void send_hdlc(void *user_data, const uint8_t *msg, int len)
 
 static __inline__ int bits_to_us(t38_terminal_state_t *s, int bits)
 {
-    if (s->t38_fe.ms_per_tx_chunk == 0  ||  s->t38_fe.tx_bit_rate == 0)
+    if (s->t38_fe.us_per_tx_chunk == 0  ||  s->t38_fe.tx_bit_rate == 0)
         return 0;
     /*endif*/
     return bits*1000000/s->t38_fe.tx_bit_rate;
@@ -634,9 +635,9 @@ static __inline__ int bits_to_us(t38_terminal_state_t *s, int bits)
 static void set_octets_per_data_packet(t38_terminal_state_t *s, int bit_rate)
 {
     s->t38_fe.tx_bit_rate = bit_rate;
-    if (s->t38_fe.ms_per_tx_chunk)
+    if (s->t38_fe.us_per_tx_chunk)
     {
-        s->t38_fe.octets_per_data_packet = s->t38_fe.ms_per_tx_chunk*bit_rate/(8*1000);
+        s->t38_fe.octets_per_data_packet = (s->t38_fe.us_per_tx_chunk/1000)*bit_rate/(8*1000);
         /* Make sure we have a positive number (i.e. we didn't truncate to zero). */
         if (s->t38_fe.octets_per_data_packet < 1)
             s->t38_fe.octets_per_data_packet = 1;
@@ -660,14 +661,12 @@ static int set_no_signal(t38_terminal_state_t *s)
             return delay;
         /*endif*/
         s->t38_fe.timed_step = T38_TIMED_STEP_NO_SIGNAL;
-#if 0
         if ((s->t38_fe.chunking_modes & T38_CHUNKING_SEND_2S_REGULAR_INDICATORS))
             s->t38_fe.timeout_tx_samples = s->t38_fe.next_tx_samples + us_to_samples(2000000);
         else
             s->t38_fe.timeout_tx_samples = 0;
         /*endif*/
-#endif
-        return s->t38_fe.ms_per_tx_chunk*1000;
+        return s->t38_fe.us_per_tx_chunk;
     }
     /*endif*/
     if ((delay = t38_core_send_indicator(&s->t38_fe.t38, T38_IND_NO_SIGNAL)) < 0)
@@ -685,12 +684,10 @@ static int stream_no_signal(t38_terminal_state_t *s)
     if ((delay = t38_core_send_indicator(&s->t38_fe.t38, 0x100 | T38_IND_NO_SIGNAL)) < 0)
         return delay;
     /*endif*/
-#if 0
     if (s->t38_fe.timeout_tx_samples  &&  s->t38_fe.next_tx_samples >= s->t38_fe.timeout_tx_samples)
         s->t38_fe.timed_step = T38_TIMED_STEP_NONE;
     /*endif*/
-#endif
-    return s->t38_fe.ms_per_tx_chunk*1000;
+    return s->t38_fe.us_per_tx_chunk;
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -717,20 +714,19 @@ static int stream_non_ecm(t38_terminal_state_t *s)
             }
             else
             {
-                delay = 75000;
+                if (fe->us_per_tx_chunk)
+                    delay = 75000;
+                /*endif*/
             }
             /*endif*/
             fe->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_2;
-#if 0
             fe->timeout_tx_samples = fe->next_tx_samples
                                    + us_to_samples(t38_core_send_training_delay(&fe->t38, fe->next_tx_indicator));
-#endif
             fe->next_tx_samples = fe->samples;
             break;
         case T38_TIMED_STEP_NON_ECM_MODEM_2:
             /* Switch on a fast modem, and give the training time to complete */
-#if 0
-            if ((s->t38_fe.chunking_modes & T38_CHUNKING_SEND_REGULAR_INDICATORS))
+            if ((fe->chunking_modes & T38_CHUNKING_SEND_REGULAR_INDICATORS))
             {
                 if ((delay = t38_core_send_indicator(&fe->t38, 0x100 | fe->next_tx_indicator)) < 0)
                     return delay;
@@ -738,10 +734,9 @@ static int stream_non_ecm(t38_terminal_state_t *s)
                 if (fe->next_tx_samples >= fe->timeout_tx_samples)
                     fe->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_3;
                 /*endif*/
-                return fe->ms_per_tx_chunk*1000;
+                return fe->us_per_tx_chunk;
             }
             /*endif*/
-#endif
             if ((delay = t38_core_send_indicator(&fe->t38, fe->next_tx_indicator)) < 0)
                 return delay;
             /*endif*/
@@ -760,7 +755,7 @@ static int stream_non_ecm(t38_terminal_state_t *s)
             if (len < fe->octets_per_data_packet)
             {
                 /* That's the end of the image data. */
-                if (s->t38_fe.ms_per_tx_chunk)
+                if (fe->us_per_tx_chunk)
                 {
                     /* Pad the end of the data with some zeros. If we just stop abruptly
                        at the end of the EOLs, some ATAs fail to clean up properly before
@@ -781,7 +776,7 @@ static int stream_non_ecm(t38_terminal_state_t *s)
                         return res;
                     /*endif*/
                     fe->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_5;
-                    delay = 0;
+                    front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE);
                     break;
                 }
                 /*endif*/
@@ -790,7 +785,9 @@ static int stream_non_ecm(t38_terminal_state_t *s)
             if ((res = t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_T4_NON_ECM_DATA, buf, len, T38_PACKET_CATEGORY_IMAGE_DATA)) < 0)
                 return res;
             /*endif*/
-            delay = bits_to_us(s, 8*len);
+            if (fe->us_per_tx_chunk)
+                delay = bits_to_us(s, 8*len);
+            /*endif*/
             break;
         case T38_TIMED_STEP_NON_ECM_MODEM_4:
             /* Send padding */
@@ -806,9 +803,8 @@ static int stream_non_ecm(t38_terminal_state_t *s)
                 fe->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_5;
                 /* Allow a bit more time than the data will take to play out, to ensure the far ATA does not
                    cut things short. */
-                delay = bits_to_us(s, 8*len);
-                if (s->t38_fe.ms_per_tx_chunk)
-                    delay += 60000;
+                if (fe->us_per_tx_chunk)
+                    delay = bits_to_us(s, 8*len) + 60000;
                 /*endif*/
                 front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE);
                 break;
@@ -818,12 +814,21 @@ static int stream_non_ecm(t38_terminal_state_t *s)
             if ((res = t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_T4_NON_ECM_DATA, buf, len, T38_PACKET_CATEGORY_IMAGE_DATA)) < 0)
                 return res;
             /*endif*/
-            delay = bits_to_us(s, 8*len);
+            if (fe->us_per_tx_chunk)
+                delay = bits_to_us(s, 8*len);
+            /*endif*/
             break;
         case T38_TIMED_STEP_NON_ECM_MODEM_5:
             /* This should not be needed, since the message above indicates the end of the signal, but it
                seems like it can improve compatibility with quirky implementations. */
-            return set_no_signal(s);
+            delay = set_no_signal(s);
+            if (fe->queued_timed_step != T38_TIMED_STEP_NONE)
+            {
+                fe->timed_step = fe->queued_timed_step;
+                fe->queued_timed_step = T38_TIMED_STEP_NONE;
+            }
+            /*endif*/
+            return delay;
         }
         /*endswitch*/
     }
@@ -858,22 +863,19 @@ static int stream_hdlc(t38_terminal_state_t *s)
             }
             else
             {
-                delay = 75000;
+                delay = (fe->us_per_tx_chunk)  ?  75000  :  0;
             }
             /*endif*/
             fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_2;
-#if 0
             fe->timeout_tx_samples = fe->next_tx_samples
                                    + us_to_samples(t38_core_send_training_delay(&fe->t38, fe->next_tx_indicator))
                                    + us_to_samples(t38_core_send_flags_delay(&fe->t38, fe->next_tx_indicator))
                                    + us_to_samples(delay);
-#endif
             fe->next_tx_samples = fe->samples;
             break;
         case T38_TIMED_STEP_HDLC_MODEM_2:
             /* Send HDLC preambling */
-#if 0
-            if ((s->t38_fe.chunking_modes & T38_CHUNKING_SEND_REGULAR_INDICATORS))
+            if ((fe->chunking_modes & T38_CHUNKING_SEND_REGULAR_INDICATORS))
             {
                 if ((delay = t38_core_send_indicator(&fe->t38, 0x100 | fe->next_tx_indicator)) < 0)
                     return delay;
@@ -881,10 +883,9 @@ static int stream_hdlc(t38_terminal_state_t *s)
                 if (fe->next_tx_samples >= fe->timeout_tx_samples)
                     fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_3;
                 /*endif*/
-                return fe->ms_per_tx_chunk*1000;
+                return fe->us_per_tx_chunk;
             }
             /*endif*/
-#endif
             if ((delay = t38_core_send_indicator(&fe->t38, fe->next_tx_indicator)) < 0)
                 return delay;
             /*endif*/
@@ -897,7 +898,7 @@ static int stream_hdlc(t38_terminal_state_t *s)
             if (fe->octets_per_data_packet >= i)
             {
                 /* The last part of an HDLC frame */
-                if (fe->chunking_modes & T38_CHUNKING_MERGE_FCS_WITH_DATA)
+                if ((fe->chunking_modes & T38_CHUNKING_MERGE_FCS_WITH_DATA))
                 {
                     /* Copy the data, as we might be about to refill the buffer it is in */
                     memcpy(buf, &fe->hdlc_tx.buf[fe->hdlc_tx.ptr], i);
@@ -911,41 +912,41 @@ static int stream_hdlc(t38_terminal_state_t *s)
                     fe->hdlc_tx.len = 0;
                     front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE);
                     /* The above step should have got the next HDLC step ready - either another frame, or an instruction to stop transmission. */
-                    if (fe->hdlc_tx.len < 0)
+                    if (fe->hdlc_tx.len >= 0)
                     {
-                        data_fields[1].field_type = T38_FIELD_HDLC_FCS_OK_SIG_END;
+                        data_fields[1].field_type = T38_FIELD_HDLC_FCS_OK;
                         data_fields[1].field = NULL;
                         data_fields[1].field_len = 0;
-                        category = (s->t38_fe.current_tx_data_type == T38_DATA_V21)  ?  T38_PACKET_CATEGORY_CONTROL_DATA_END  :  T38_PACKET_CATEGORY_IMAGE_DATA_END;
+                        category = (fe->current_tx_data_type == T38_DATA_V21)  ?  T38_PACKET_CATEGORY_CONTROL_DATA  :  T38_PACKET_CATEGORY_IMAGE_DATA;
                         if ((res = t38_core_send_data_multi_field(&fe->t38, fe->current_tx_data_type, data_fields, 2, category)) < 0)
                             return res;
                         /*endif*/
-                        fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_5;
-                        /* We add a bit of extra time here, as with some implementations
-                           the carrier falling too abruptly causes data loss. */
+                        fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_3;
                         delay = bits_to_us(s, i*8 + fe->hdlc_tx.extra_bits);
-                        if (s->t38_fe.ms_per_tx_chunk)
-                            delay += 100000;
-                        /*endif*/
-                        front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE);
                     }
                     else
                     {
-                        data_fields[1].field_type = T38_FIELD_HDLC_FCS_OK;
+                        data_fields[1].field_type = T38_FIELD_HDLC_FCS_OK_SIG_END;
                         data_fields[1].field = NULL;
                         data_fields[1].field_len = 0;
-                        category = (s->t38_fe.current_tx_data_type == T38_DATA_V21)  ?  T38_PACKET_CATEGORY_CONTROL_DATA  :  T38_PACKET_CATEGORY_IMAGE_DATA;
+                        category = (fe->current_tx_data_type == T38_DATA_V21)  ?  T38_PACKET_CATEGORY_CONTROL_DATA_END  :  T38_PACKET_CATEGORY_IMAGE_DATA_END;
                         if ((res = t38_core_send_data_multi_field(&fe->t38, fe->current_tx_data_type, data_fields, 2, category)) < 0)
                             return res;
                         /*endif*/
-                        fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_3;
+                        fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_5;
+                        /* We add a bit of extra time here, as with some implementations
+                           the carrier falling too abruptly causes data loss. */
                         delay = bits_to_us(s, i*8 + fe->hdlc_tx.extra_bits);
+                        if (fe->us_per_tx_chunk)
+                            delay += 100000;
+                        /*endif*/
+                        front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE);
                     }
                     /*endif*/
                     break;
                 }
                 /*endif*/
-                category = (s->t38_fe.current_tx_data_type == T38_DATA_V21)  ?  T38_PACKET_CATEGORY_CONTROL_DATA  :  T38_PACKET_CATEGORY_IMAGE_DATA;
+                category = (fe->current_tx_data_type == T38_DATA_V21)  ?  T38_PACKET_CATEGORY_CONTROL_DATA  :  T38_PACKET_CATEGORY_IMAGE_DATA;
                 if ((res = t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_HDLC_DATA, &fe->hdlc_tx.buf[fe->hdlc_tx.ptr], i, category)) < 0)
                     return res;
                 /*endif*/
@@ -954,7 +955,7 @@ static int stream_hdlc(t38_terminal_state_t *s)
             else
             {
                 i = fe->octets_per_data_packet;
-                category = (s->t38_fe.current_tx_data_type == T38_DATA_V21)  ?  T38_PACKET_CATEGORY_CONTROL_DATA  :  T38_PACKET_CATEGORY_IMAGE_DATA;
+                category = (fe->current_tx_data_type == T38_DATA_V21)  ?  T38_PACKET_CATEGORY_CONTROL_DATA  :  T38_PACKET_CATEGORY_IMAGE_DATA;
                 if ((res = t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_HDLC_DATA, &fe->hdlc_tx.buf[fe->hdlc_tx.ptr], i, category)) < 0)
                     return res;
                 /*endif*/
@@ -970,10 +971,28 @@ static int stream_hdlc(t38_terminal_state_t *s)
             fe->hdlc_tx.len = 0;
             front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE);
             /* The above step should have got the next HDLC step ready - either another frame, or an instruction to stop transmission. */
-            if (fe->hdlc_tx.len < 0)
+            if (fe->hdlc_tx.len >= 0)
+            {
+                if (fe->hdlc_tx.len == 0)
+                {
+                    /* Now, how did we get here? We have finished a frame, but have no new frame to
+                       send, and no end of transmission condition. */
+                    span_log(&s->logging, SPAN_LOG_FLOW, "No new frame or end transmission condition.\n");
+                }
+                /*endif*/
+                /* Finish the current frame off, and prepare for the next one. */
+                category = (fe->current_tx_data_type == T38_DATA_V21)  ?  T38_PACKET_CATEGORY_CONTROL_DATA  :  T38_PACKET_CATEGORY_IMAGE_DATA;
+                if ((res = t38_core_send_data(&fe->t38, previous, T38_FIELD_HDLC_FCS_OK, NULL, 0, category)) < 0)
+                    return res;
+                /*endif*/
+                fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_3;
+                /* We should now wait enough time for everything to clear through an analogue modem at the far end. */
+                delay = bits_to_us(s, fe->hdlc_tx.extra_bits);
+            }
+            else
             {
                 /* End of transmission */
-                category = (s->t38_fe.current_tx_data_type == T38_DATA_V21)  ?  T38_PACKET_CATEGORY_CONTROL_DATA_END  :  T38_PACKET_CATEGORY_IMAGE_DATA_END;
+                category = (fe->current_tx_data_type == T38_DATA_V21)  ?  T38_PACKET_CATEGORY_CONTROL_DATA_END  :  T38_PACKET_CATEGORY_IMAGE_DATA_END;
                 if ((res = t38_core_send_data(&fe->t38, previous, T38_FIELD_HDLC_FCS_OK_SIG_END, NULL, 0, category)) < 0)
                     return res;
                 /*endif*/
@@ -981,33 +1000,24 @@ static int stream_hdlc(t38_terminal_state_t *s)
                 /* We add a bit of extra time here, as with some implementations
                    the carrier falling too abruptly causes data loss. */
                 delay = bits_to_us(s, fe->hdlc_tx.extra_bits);
-                if (s->t38_fe.ms_per_tx_chunk)
+                if (fe->us_per_tx_chunk)
                     delay += 100000;
                 /*endif*/
                 front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE);
-                break;
-            }
-            /*endif*/
-            if (fe->hdlc_tx.len == 0)
-            {
-                /* Now, how did we get here? We have finished a frame, but have no new frame to
-                   send, and no end of transmission condition. */
-                span_log(&s->logging, SPAN_LOG_FLOW, "No new frame or end transmission condition.\n");
             }
             /*endif*/
-            /* Finish the current frame off, and prepare for the next one. */
-            category = (s->t38_fe.current_tx_data_type == T38_DATA_V21)  ?  T38_PACKET_CATEGORY_CONTROL_DATA  :  T38_PACKET_CATEGORY_IMAGE_DATA;
-            if ((res = t38_core_send_data(&fe->t38, previous, T38_FIELD_HDLC_FCS_OK, NULL, 0, category)) < 0)
-                return res;
-            /*endif*/
-            fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_3;
-            /* We should now wait enough time for everything to clear through an analogue modem at the far end. */
-            delay = bits_to_us(s, fe->hdlc_tx.extra_bits);
             break;
         case T38_TIMED_STEP_HDLC_MODEM_5:
             /* Note that some boxes do not like us sending a T38_FIELD_HDLC_SIG_END at this point.
                A T38_IND_NO_SIGNAL should always be OK. */
-            return set_no_signal(s);
+            delay = set_no_signal(s);
+            if (fe->queued_timed_step != T38_TIMED_STEP_NONE)
+            {
+                fe->timed_step = fe->queued_timed_step;
+                fe->queued_timed_step = T38_TIMED_STEP_NONE;
+            }
+            /*endif*/
+            return delay;
         }
         /*endswitch*/
     }
@@ -1035,7 +1045,7 @@ static int stream_ced(t38_terminal_state_t *s)
             if ((delay = t38_core_send_indicator(&fe->t38, T38_IND_NO_SIGNAL)) < 0)
                 return delay;
             /*endif*/
-            delay = 200000;
+            delay = (fe->us_per_tx_chunk)  ?  200000  :  0;
             fe->next_tx_samples = fe->samples;
             break;
         case T38_TIMED_STEP_CED_2:
@@ -1048,7 +1058,7 @@ static int stream_ced(t38_terminal_state_t *s)
             break;
         case T38_TIMED_STEP_CED_3:
             /* End of CED */
-            fe->timed_step = T38_TIMED_STEP_NONE;
+            fe->timed_step = fe->queued_timed_step;
             front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE);
             return 0;
         }
@@ -1078,17 +1088,15 @@ static int stream_cng(t38_terminal_state_t *s)
             if ((delay = t38_core_send_indicator(&fe->t38, T38_IND_NO_SIGNAL)) < 0)
                 return delay;
             /*endif*/
-            delay = 200000;
+            delay = (fe->us_per_tx_chunk)  ?  200000  :  0;
             fe->next_tx_samples = fe->samples;
             break;
         case T38_TIMED_STEP_CNG_2:
             /* Initial short delay over. Send the CNG indicator. CNG persists until something
                coming the other way interrupts it, or a long timeout controlled by the T.30 engine
                expires. */
-            fe->timed_step = T38_TIMED_STEP_NONE;
-            if ((delay = t38_core_send_indicator(&fe->t38, T38_IND_CNG)) < 0)
-                return delay;
-            /*endif*/
+            delay = t38_core_send_indicator(&fe->t38, T38_IND_CNG);
+            fe->timed_step = fe->queued_timed_step;
             fe->current_tx_data_type = T38_DATA_NONE;
             return delay;
         }
@@ -1123,7 +1131,7 @@ SPAN_DECLARE(int) t38_terminal_send_timeout(t38_terminal_state_t *s, int samples
     /*endif*/
     /* Wait until the right time comes along, unless we are working in "no delays" mode, while talking to an
        IAF terminal. */
-    if (fe->ms_per_tx_chunk  &&  fe->samples < fe->next_tx_samples)
+    if (fe->us_per_tx_chunk  &&  fe->samples < fe->next_tx_samples)
         return FALSE;
     /*endif*/
     /* Its time to send something */
@@ -1175,22 +1183,26 @@ static void set_rx_type(void *user_data, int type, int bit_rate, int short_train
 
 static void start_tx(t38_terminal_front_end_state_t *fe, int use_hdlc)
 {
+    int step;
+
     /* The actual transmission process depends on whether we are sending at a paced manner,
        for interaction with a traditional FAX machine, or streaming as fast as we can, normally
        over a TCP connection to a machine directly connected to the internet. */
-    if (fe->ms_per_tx_chunk)
+
+    step = (use_hdlc)  ?  T38_TIMED_STEP_HDLC_MODEM  :  T38_TIMED_STEP_NON_ECM_MODEM;
+    if (fe->timed_step == T38_TIMED_STEP_NONE)
     {
-        /* Start the paced packet transmission process. */
-        fe->timed_step = (use_hdlc)  ?  T38_TIMED_STEP_HDLC_MODEM  :  T38_TIMED_STEP_NON_ECM_MODEM;
-        if (fe->next_tx_samples < fe->samples)
-            fe->next_tx_samples = fe->samples;
-        /*endif*/
+        fe->queued_timed_step = T38_TIMED_STEP_NONE;
+        fe->timed_step = step;
     }
     else
     {
-        /* Start the fast streaming transmission process. */
+        fe->queued_timed_step = step;
     }
     /*endif*/
+    if (fe->next_tx_samples < fe->samples)
+        fe->next_tx_samples = fe->samples;
+    /*endif*/
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -1217,8 +1229,21 @@ static void set_tx_type(void *user_data, int type, int bit_rate, int short_train
         fe->current_tx_data_type = T38_DATA_NONE;
         break;
     case T30_MODEM_PAUSE:
-        fe->next_tx_samples = fe->samples + ms_to_samples(short_train);
-        fe->timed_step = T38_TIMED_STEP_PAUSE;
+        if (s->t38_fe.us_per_tx_chunk)
+            fe->next_tx_samples = fe->samples + ms_to_samples(short_train);
+        else
+            fe->next_tx_samples = fe->samples;
+        /*endif*/
+        if (fe->timed_step == T38_TIMED_STEP_NONE)
+        {
+            fe->queued_timed_step = T38_TIMED_STEP_NONE;
+            fe->timed_step = T38_TIMED_STEP_PAUSE;
+        }
+        else
+        {
+            fe->queued_timed_step = T38_TIMED_STEP_PAUSE;
+        }
+        /*endif*/
         fe->current_tx_data_type = T38_DATA_NONE;
         break;
     case T30_MODEM_CED:
@@ -1316,7 +1341,7 @@ SPAN_DECLARE(void) t38_terminal_set_config(t38_terminal_state_t *s, int config)
         t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_CONTROL_DATA_END, 1);
         t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_IMAGE_DATA, 1);
         t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_IMAGE_DATA_END, 1);
-        s->t38_fe.ms_per_tx_chunk = 0;
+        s->t38_fe.us_per_tx_chunk = 0;
         s->t38_fe.chunking_modes &= ~T38_CHUNKING_SEND_REGULAR_INDICATORS;
         s->t38_fe.chunking_modes |= T38_CHUNKING_MERGE_FCS_WITH_DATA;
     }
@@ -1334,7 +1359,7 @@ SPAN_DECLARE(void) t38_terminal_set_config(t38_terminal_state_t *s, int config)
         t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_CONTROL_DATA_END, DATA_END_TX_COUNT);
         t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_IMAGE_DATA, DATA_TX_COUNT);
         t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_IMAGE_DATA_END, DATA_END_TX_COUNT);
-        s->t38_fe.ms_per_tx_chunk = DEFAULT_MS_PER_TX_CHUNK;
+        s->t38_fe.us_per_tx_chunk = DEFAULT_US_PER_TX_CHUNK;
         if ((config & (T38_TERMINAL_OPTION_REGULAR_INDICATORS | T38_TERMINAL_OPTION_2S_REPEATING_INDICATORS)))
             s->t38_fe.chunking_modes |= T38_CHUNKING_SEND_REGULAR_INDICATORS;
         else
@@ -1401,6 +1426,7 @@ static int t38_terminal_t38_fe_restart(t38_terminal_state_t *t)
     s->next_tx_samples = 0;
 
     s->hdlc_tx.ptr = 0;
+    s->hdlc_tx.extra_bits = 0;
 
     return 0;
 }
@@ -1424,6 +1450,7 @@ static int t38_terminal_t38_fe_init(t38_terminal_state_t *t,
 
     s->rx_signal_present = FALSE;
     s->timed_step = T38_TIMED_STEP_NONE;
+    s->queued_timed_step = T38_TIMED_STEP_NONE;
     //s->iaf = T30_IAF_MODE_T37 | T30_IAF_MODE_T38;
     s->iaf = T30_IAF_MODE_T38;
 
@@ -1432,6 +1459,7 @@ static int t38_terminal_t38_fe_init(t38_terminal_state_t *t,
     s->chunking_modes = T38_CHUNKING_ALLOW_TEP_TIME;
 
     s->hdlc_tx.ptr = 0;
+    s->hdlc_tx.extra_bits = 0;
 
     return 0;
 }
index 199611a0987d87cf87eb603efa1444f883f84773..55c540d53ef527b2e23303fe6b8a58b86380f458 100644 (file)
@@ -69,9 +69,9 @@
 #include "spandsp/private/logging.h"
 #include "spandsp/private/v22bis.h"
 
-#if defined(SPANDSP_USE_FIXED_POINT)
-#include "v22bis_rx_1200_fixed_rrc.h"
-#include "v22bis_rx_2400_fixed_rrc.h"
+#if defined(SPANDSP_USE_FIXED_POINTx)
+#include "v22bis_rx_1200_floating_rrc.h"
+#include "v22bis_rx_2400_floating_rrc.h"
 #else
 #include "v22bis_rx_1200_floating_rrc.h"
 #include "v22bis_rx_2400_floating_rrc.h"
 
 #define ms_to_symbols(t)        (((t)*600)/1000)
 
-#if defined(SPANDSP_USE_FIXED_POINT)
-#define FP_FACTOR                       4096
-#define FP_SHIFT_FACTOR                 12
-#endif
-
 /*! The adaption rate coefficient for the equalizer */
 #define EQUALIZER_DELTA         0.25f
 /*! The number of phase shifted coefficient set for the pulse shaping/bandpass filter */
@@ -172,28 +167,24 @@ void v22bis_report_status_change(v22bis_state_t *s, int status)
 }
 /*- End of function --------------------------------------------------------*/
 
-#if defined(SPANDSP_USE_FIXED_POINT)
-SPAN_DECLARE(int) v22bis_rx_equalizer_state(v22bis_state_t *s, complexi16_t **coeffs)
-#else
 SPAN_DECLARE(int) v22bis_rx_equalizer_state(v22bis_state_t *s, complexf_t **coeffs)
-#endif
 {
     *coeffs = s->rx.eq_coeff;
-    return V22BIS_EQUALIZER_LEN;
+    return 2*V22BIS_EQUALIZER_LEN + 1;
 }
 /*- End of function --------------------------------------------------------*/
 
 void v22bis_equalizer_coefficient_reset(v22bis_state_t *s)
 {
     /* Start with an equalizer based on everything being perfect */
-#if defined(SPANDSP_USE_FIXED_POINT)
-    cvec_zeroi16(s->rx.eq_coeff, V22BIS_EQUALIZER_LEN);
-    s->rx.eq_coeff[V22BIS_EQUALIZER_PRE_LEN] = complex_seti16(FP_Q_4_12(3.0), FP_Q_4_12(0.0));
-    s->rx.eq_delta = 32768.0f*EQUALIZER_DELTA/V22BIS_EQUALIZER_LEN;
+#if defined(SPANDSP_USE_FIXED_POINTx)
+    cvec_zeroi16(s->rx.eq_coeff, 2*V22BIS_EQUALIZER_LEN + 1);
+    s->rx.eq_coeff[V22BIS_EQUALIZER_LEN] = complex_seti16(3*FP_FACTOR, 0*FP_FACTOR);
+    s->rx.eq_delta = 32768.0f*EQUALIZER_DELTA/(2*V22BIS_EQUALIZER_LEN + 1);
 #else
-    cvec_zerof(s->rx.eq_coeff, V22BIS_EQUALIZER_LEN);
-    s->rx.eq_coeff[V22BIS_EQUALIZER_PRE_LEN] = complex_setf(3.0f, 0.0f);
-    s->rx.eq_delta = EQUALIZER_DELTA/V22BIS_EQUALIZER_LEN;
+    cvec_zerof(s->rx.eq_coeff, 2*V22BIS_EQUALIZER_LEN + 1);
+    s->rx.eq_coeff[V22BIS_EQUALIZER_LEN] = complex_setf(3.0f, 0.0f);
+    s->rx.eq_delta = EQUALIZER_DELTA/(2*V22BIS_EQUALIZER_LEN + 1);
 #endif
 }
 /*- End of function --------------------------------------------------------*/
@@ -201,68 +192,63 @@ void v22bis_equalizer_coefficient_reset(v22bis_state_t *s)
 static void equalizer_reset(v22bis_state_t *s)
 {
     v22bis_equalizer_coefficient_reset(s);
-#if defined(SPANDSP_USE_FIXED_POINT)
-    cvec_zeroi16(s->rx.eq_buf, V22BIS_EQUALIZER_LEN);
+#if defined(SPANDSP_USE_FIXED_POINTx)
+    cvec_zeroi16(s->rx.eq_buf, V22BIS_EQUALIZER_MASK + 1);
 #else
-    cvec_zerof(s->rx.eq_buf, V22BIS_EQUALIZER_LEN);
+    cvec_zerof(s->rx.eq_buf, V22BIS_EQUALIZER_MASK + 1);
 #endif
     s->rx.eq_put_step = 20 - 1;
     s->rx.eq_step = 0;
 }
 /*- End of function --------------------------------------------------------*/
 
-#if defined(SPANDSP_USE_FIXED_POINT)
-static __inline__ complexi16_t equalizer_get(v22bis_state_t *s)
+static complexf_t equalizer_get(v22bis_state_t *s)
 {
-    complexi32_t zz;
-    complexi16_t z;
+    int i;
+    int p;
+    complexf_t z;
+    complexf_t z1;
 
     /* Get the next equalized value. */
-    zz = cvec_circular_dot_prodi16(s->rx.eq_buf, s->rx.eq_coeff, V22BIS_EQUALIZER_LEN, s->rx.eq_step);
-    z.re = zz.re >> FP_SHIFT_FACTOR;
-    z.im = zz.im >> FP_SHIFT_FACTOR;
+    z = complex_setf(0.0f, 0.0f);
+    p = s->rx.eq_step - 1;
+    for (i = 0;  i < 2*V22BIS_EQUALIZER_LEN + 1;  i++)
+    {
+        p = (p - 1) & V22BIS_EQUALIZER_MASK;
+        z1 = complex_mulf(&s->rx.eq_coeff[i], &s->rx.eq_buf[p]);
+        z = complex_addf(&z, &z1);
+    }
     return z;
 }
-#else
-static __inline__ complexf_t equalizer_get(v22bis_state_t *s)
-{
-    /* Get the next equalized value. */
-    return cvec_circular_dot_prodf(s->rx.eq_buf, s->rx.eq_coeff, V22BIS_EQUALIZER_LEN, s->rx.eq_step);
-}
-#endif
 /*- End of function --------------------------------------------------------*/
 
-#if defined(SPANDSP_USE_FIXED_POINT)
-static void tune_equalizer(v22bis_state_t *s, const complexi16_t *z, const complexi16_t *target)
-{
-    complexi16_t err;
-
-    /* Find the x and y mismatch from the exact constellation position. */
-    err.re = target->re*FP_FACTOR - z->re;
-    err.im = target->im*FP_FACTOR - z->im;
-    err.re = ((int32_t) err.re*s->rx.eq_delta) >> 15;
-    err.im = ((int32_t) err.im*s->rx.eq_delta) >> 15;
-    cvec_circular_lmsi16(s->rx.eq_buf, s->rx.eq_coeff, V22BIS_EQUALIZER_LEN, s->rx.eq_step, &err);
-}
-#else
 static void tune_equalizer(v22bis_state_t *s, const complexf_t *z, const complexf_t *target)
 {
-    complexf_t err;
+    int i;
+    int p;
+    complexf_t ez;
+    complexf_t z1;
 
     /* Find the x and y mismatch from the exact constellation position. */
-    err = complex_subf(target, z);
-    err.re *= s->rx.eq_delta;
-    err.im *= s->rx.eq_delta;
-    cvec_circular_lmsf(s->rx.eq_buf, s->rx.eq_coeff, V22BIS_EQUALIZER_LEN, s->rx.eq_step, &err);
+    ez = complex_subf(target, z);
+    ez.re *= s->rx.eq_delta;
+    ez.im *= s->rx.eq_delta;
+
+    p = s->rx.eq_step - 1;
+    for (i = 0;  i < 2*V22BIS_EQUALIZER_LEN + 1;  i++)
+    {
+        p = (p - 1) & V22BIS_EQUALIZER_MASK;
+        z1 = complex_conjf(&s->rx.eq_buf[p]);
+        z1 = complex_mulf(&ez, &z1);
+        s->rx.eq_coeff[i] = complex_addf(&s->rx.eq_coeff[i], &z1);
+        /* If we don't leak a little bit we seem to get some wandering adaption */
+        s->rx.eq_coeff[i].re *= 0.9999f;
+        s->rx.eq_coeff[i].im *= 0.9999f;
+    }
 }
-#endif
 /*- End of function --------------------------------------------------------*/
 
-#if defined(SPANDSP_USE_FIXED_POINT)
-static __inline__ void track_carrier(v22bis_state_t *s, const complexi16_t *z, const complexi16_t *target)
-#else
 static __inline__ void track_carrier(v22bis_state_t *s, const complexf_t *z, const complexf_t *target)
-#endif
 {
     float error;
 
@@ -350,69 +336,40 @@ static int decode_baudx(v22bis_state_t *s, int nearest)
 
 static __inline__ void symbol_sync(v22bis_state_t *s)
 {
-#if defined(SPANDSP_USE_FIXED_POINT)
-    int32_t p;
-    int32_t q;
-    complexi16_t zz;
-    complexi16_t a;
-    complexi16_t b;
-    complexi16_t c;
-#else
     float p;
     float q;
     complexf_t zz;
     complexf_t a;
     complexf_t b;
     complexf_t c;
-#endif
-    int aa[3];
-    int i;
-    int j;
 
     /* This routine adapts the position of the half baud samples entering the equalizer. */
 
     /* Perform a Gardner test for baud alignment on the three most recent samples. */
-    for (i = 0, j = s->rx.eq_step;  i < 3;  i++)
-    {
-        if (--j < 0)
-            j = V22BIS_EQUALIZER_LEN - 1;
-        aa[i] = j;
-    }
     if (s->rx.sixteen_way_decisions)
     {
-        p = s->rx.eq_buf[aa[2]].re - s->rx.eq_buf[aa[0]].re;
-        p *= s->rx.eq_buf[aa[1]].re;
+        p = s->rx.eq_buf[(s->rx.eq_step - 3) & V22BIS_EQUALIZER_MASK].re
+          - s->rx.eq_buf[(s->rx.eq_step - 1) & V22BIS_EQUALIZER_MASK].re;
+        p *= s->rx.eq_buf[(s->rx.eq_step - 2) & V22BIS_EQUALIZER_MASK].re;
 
-        q = s->rx.eq_buf[aa[2]].im - s->rx.eq_buf[aa[0]].im;
-        q *= s->rx.eq_buf[aa[1]].im;
+        q = s->rx.eq_buf[(s->rx.eq_step - 3) & V22BIS_EQUALIZER_MASK].im
+        - s->rx.eq_buf[(s->rx.eq_step - 1) & V22BIS_EQUALIZER_MASK].im;
+        q *= s->rx.eq_buf[(s->rx.eq_step - 2) & V22BIS_EQUALIZER_MASK].im;
     }
     else
     {
         /* Rotate the points to the 45 degree positions, to maximise the effectiveness of
            the Gardner algorithm. This is particularly significant at the start of operation
            to pull things in quickly. */
-#if defined(SPANDSP_USE_FIXED_POINT)
-        zz = complex_seti16(FP_Q_6_10(0.894427), FP_Q_6_10(0.44721f));
-        a = complex_muli16(&s->rx.eq_buf[aa[2]], &zz);
-        b = complex_muli16(&s->rx.eq_buf[aa[1]], &zz);
-        c = complex_muli16(&s->rx.eq_buf[aa[0]], &zz);
-        p = (a.re - c.re)*b.re;
-        q = (a.im - c.im)*b.im;
-#else
         zz = complex_setf(0.894427, 0.44721f);
-        a = complex_mulf(&s->rx.eq_buf[aa[2]], &zz);
-        b = complex_mulf(&s->rx.eq_buf[aa[1]], &zz);
-        c = complex_mulf(&s->rx.eq_buf[aa[0]], &zz);
+        a = complex_mulf(&s->rx.eq_buf[(s->rx.eq_step - 3) & V22BIS_EQUALIZER_MASK], &zz);
+        b = complex_mulf(&s->rx.eq_buf[(s->rx.eq_step - 2) & V22BIS_EQUALIZER_MASK], &zz);
+        c = complex_mulf(&s->rx.eq_buf[(s->rx.eq_step - 1) & V22BIS_EQUALIZER_MASK], &zz);
         p = (a.re - c.re)*b.re;
         q = (a.im - c.im)*b.im;
-#endif
     }
 
-#if defined(SPANDSP_USE_FIXED_POINT)
-    s->rx.gardner_integrate += (p + q > 0)  ?  s->rx.gardner_step  :  -s->rx.gardner_step;
-#else
     s->rx.gardner_integrate += (p + q > 0.0f)  ?  s->rx.gardner_step  :  -s->rx.gardner_step;
-#endif
 
     if (abs(s->rx.gardner_integrate) >= 16)
     {
@@ -429,21 +386,11 @@ static __inline__ void symbol_sync(v22bis_state_t *s)
 }
 /*- End of function --------------------------------------------------------*/
 
-#if defined(SPANDSP_USE_FIXED_POINT)
-static void process_half_baud(v22bis_state_t *s, const complexi16_t *sample)
-#else
 static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
-#endif
 {
-#if defined(SPANDSP_USE_FIXED_POINT)
-    complexi16_t z;
-    complexi16_t zz;
-    const complexi16_t *target;
-#else
     complexf_t z;
     complexf_t zz;
     const complexf_t *target;
-#endif
     int re;
     int im;
     int nearest;
@@ -456,8 +403,7 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
     /* Add a sample to the equalizer's circular buffer, but don't calculate anything
        at this time. */
     s->rx.eq_buf[s->rx.eq_step] = z;
-    if (++s->rx.eq_step >= V22BIS_EQUALIZER_LEN)
-        s->rx.eq_step = 0;
+    s->rx.eq_step = (s->rx.eq_step + 1) & V22BIS_EQUALIZER_MASK;
 
     /* On alternate insertions we have a whole baud and must process it. */
     if ((s->rx.baud_phase ^= 1))
@@ -470,18 +416,6 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
     /* Find the constellation point */
     if (s->rx.sixteen_way_decisions)
     {
-#if defined(SPANDSP_USE_FIXED_POINT)
-        re = (int) (z.re + FP_Q_6_10(3.0f));
-        if (re > 5)
-            re = 5;
-        else if (re < 0)
-            re = 0;
-        im = (int) (z.im + FP_Q_6_10(3.0f));
-        if (im > 5)
-            im = 5;
-        else if (im < 0)
-            im = 0;
-#else
         re = (int) (z.re + 3.0f);
         if (re > 5)
             re = 5;
@@ -492,19 +426,13 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
             im = 5;
         else if (im < 0)
             im = 0;
-#endif
         nearest = space_map_v22bis[re][im];
     }
     else
     {
         /* Rotate to 45 degrees, to make the slicing trivial */
-#if defined(SPANDSP_USE_FIXED_POINT)
-        zz = complex_seti16(FP_Q_4_12(0.894427), FP_Q_4_12(0.44721f));
-        zz = complex_muli16(&z, &zz);
-#else
         zz = complex_setf(0.894427, 0.44721f);
         zz = complex_mulf(&z, &zz);
-#endif
         nearest = 0x01;
         if (zz.re < 0.0f)
             nearest |= 0x04;
@@ -562,7 +490,10 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
                error could be higher. */
             s->rx.gardner_step = 4;
             s->rx.pattern_repeats = 0;
-            s->rx.training = (s->calling_party)  ?  V22BIS_RX_TRAINING_STAGE_UNSCRAMBLED_ONES  :  V22BIS_RX_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
+            if (s->calling_party)
+                s->rx.training = V22BIS_RX_TRAINING_STAGE_UNSCRAMBLED_ONES;
+            else
+                s->rx.training = V22BIS_RX_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
             /* Be pessimistic and see what the handshake brings */
             s->negotiated_bit_rate = 1200;
             break;
@@ -764,21 +695,12 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
 {
     int i;
     int step;
-#if defined(SPANDSP_USE_FIXED_POINT)
-    complexi16_t z;
-    complexi16_t zz;
-    complexi16_t sample;
-    int32_t ii;
-    int32_t qq;
-    float vv;
-#else
     complexf_t z;
     complexf_t zz;
+    int32_t power;
     complexf_t sample;
     float ii;
     float qq;
-#endif
-    int32_t power;
 
     for (i = 0;  i < len;  i++)
     {
@@ -795,7 +717,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
         if (s->calling_party)
         {
 #if defined(SPANDSP_USE_FIXED_POINT)
-            ii = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_2400_re[6], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step) >> 15;
+            ii = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_2400_re[6], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step);
 #else
             ii = vec_circular_dot_prodf(s->rx.rrc_filter, rx_pulseshaper_2400_re[6], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step);
 #endif
@@ -803,7 +725,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
         else
         {
 #if defined(SPANDSP_USE_FIXED_POINT)
-            ii = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_1200_re[6], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step) >> 15;
+            ii = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_1200_re[6], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step);
 #else
             ii = vec_circular_dot_prodf(s->rx.rrc_filter, rx_pulseshaper_1200_re[6], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step);
 #endif
@@ -831,25 +753,11 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
         {
             /* Only spend effort processing this data if the modem is not
                parked, after a training failure. */
-#if defined(SPANDSP_USE_FIXED_POINT)
-            z = dds_complexi16(&s->rx.carrier_phase, s->rx.carrier_phase_rate);
-#else
             z = dds_complexf(&s->rx.carrier_phase, s->rx.carrier_phase_rate);
-#endif
             if (s->rx.training == V22BIS_RX_TRAINING_STAGE_SYMBOL_ACQUISITION)
             {
                 /* Only AGC during the initial symbol acquisition, and then lock the gain. */
-#if defined(SPANDSP_USE_FIXED_POINT)
-                vv = 0.18f*3.60f/sqrtf(power);
-                if (vv > 32767.0f)
-                    s->rx.agc_scaling = 32767;
-                else if (vv > -32768.0f)
-                    s->rx.agc_scaling = -32768;
-                else
-                    s->rx.agc_scaling = vv;
-#else
                 s->rx.agc_scaling = 0.18f*3.60f/sqrtf(power);
-#endif
             }
             /* Put things into the equalization buffer at T/2 rate. The Gardner algorithm
                will fiddle the step to align this with the symbols. */
@@ -866,8 +774,8 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
                 if (s->calling_party)
                 {
 #if defined(SPANDSP_USE_FIXED_POINT)
-                    ii = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_2400_re[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step) >> 15;
-                    qq = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_2400_im[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step) >> 15;
+                    ii = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_2400_re[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step);
+                    qq = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_2400_im[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step);
 #else
                     ii = vec_circular_dot_prodf(s->rx.rrc_filter, rx_pulseshaper_2400_re[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step);
                     qq = vec_circular_dot_prodf(s->rx.rrc_filter, rx_pulseshaper_2400_im[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step);
@@ -876,20 +784,15 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
                 else
                 {
 #if defined(SPANDSP_USE_FIXED_POINT)
-                    ii = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_1200_re[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step) >> 15;
-                    qq = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_1200_im[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step) >> 15;
+                    ii = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_1200_re[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step);
+                    qq = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_1200_im[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step);
 #else
                     ii = vec_circular_dot_prodf(s->rx.rrc_filter, rx_pulseshaper_1200_re[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step);
                     qq = vec_circular_dot_prodf(s->rx.rrc_filter, rx_pulseshaper_1200_im[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step);
 #endif
                 }
-#if defined(SPANDSP_USE_FIXED_POINT)
-                sample.re = ((int32_t) ii*s->rx.agc_scaling) >> 10;
-                sample.im = ((int32_t) qq*s->rx.agc_scaling) >> 10;
-#else
                 sample.re = ii*s->rx.agc_scaling;
                 sample.im = qq*s->rx.agc_scaling;
-#endif
                 /* Shift to baseband - since this is done in a full complex form, the
                    result is clean, and requires no further filtering apart from the
                    equalizer. */
@@ -914,7 +817,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx_fillin(v22bis_state_t *s, int len)
         return 0;
     for (i = 0;  i < len;  i++)
     {
-#if defined(SPANDSP_USE_FIXED_POINT)
+#if defined(SPANDSP_USE_FIXED_POINTx)
         dds_advance(&s->rx.carrier_phase, s->rx.carrier_phase_rate);
 #else
         dds_advancef(&s->rx.carrier_phase, s->rx.carrier_phase_rate);
@@ -927,7 +830,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx_fillin(v22bis_state_t *s, int len)
 
 int v22bis_rx_restart(v22bis_state_t *s)
 {
-#if defined(SPANDSP_USE_FIXED_POINT)
+#if defined(SPANDSP_USE_FIXED_POINTx)
     vec_zeroi16(s->rx.rrc_filter, sizeof(s->rx.rrc_filter)/sizeof(s->rx.rrc_filter[0]));
 #else
     vec_zerof(s->rx.rrc_filter, sizeof(s->rx.rrc_filter)/sizeof(s->rx.rrc_filter[0]));
@@ -958,13 +861,8 @@ int v22bis_rx_restart(v22bis_state_t *s)
     s->rx.training_error = 0.0f;
     s->rx.total_baud_timing_correction = 0;
     /* We want the carrier to pull in faster on the answerer side, as it has very little time to adapt. */
-#if defined(SPANDSP_USE_FIXED_POINT)
-    s->rx.carrier_track_i = (s->calling_party)  ?  8000  :  40000;
-    s->rx.carrier_track_p = 8000000;
-#else
     s->rx.carrier_track_i = (s->calling_party)  ?  8000.0f  :  40000.0f;
     s->rx.carrier_track_p = 8000000.0f;
-#endif
 
     s->negotiated_bit_rate = 1200;
 
index 7501800c3fc8947df63df70f0526fe9caba36109..39ad4dd24099b8699b464512dc4c1e6339c40556 100644 (file)
@@ -62,7 +62,7 @@
 #include "spandsp/private/logging.h"
 #include "spandsp/private/v22bis.h"
 
-#if defined(SPANDSP_USE_FIXED_POINT)
+#if defined(SPANDSP_USE_FIXED_POINTx)
 #include "v22bis_tx_fixed_rrc.h"
 #else
 #include "v22bis_tx_floating_rrc.h"
@@ -246,28 +246,24 @@ static const int phase_steps[4] =
     1, 0, 2, 3
 };
 
-#if defined(SPANDSP_USE_FIXED_POINT)
-const complexi16_t v22bis_constellation[16] =
-#else
 const complexf_t v22bis_constellation[16] =
-#endif
 {
-    { 1,  1},
-    { 3,  1},     /* 1200bps 00 */
-    { 1,  3},
-    { 3,  3},
-    {-1,  1},
-    {-1,  3},     /* 1200bps 01 */
-    {-3,  1},
-    {-3,  3},
-    {-1, -1},
-    {-3, -1},     /* 1200bps 10 */
-    {-1, -3},
-    {-3, -3},
-    { 1, -1},
-    { 1, -3},     /* 1200bps 11 */
-    { 3, -1},
-    { 3, -3}
+    { 1.0f,  1.0f},
+    { 3.0f,  1.0f},     /* 1200bps 00 */
+    { 1.0f,  3.0f},
+    { 3.0f,  3.0f},
+    {-1.0f,  1.0f},
+    {-1.0f,  3.0f},     /* 1200bps 01 */
+    {-3.0f,  1.0f},
+    {-3.0f,  3.0f},
+    {-1.0f, -1.0f},
+    {-3.0f, -1.0f},     /* 1200bps 10 */
+    {-1.0f, -3.0f},
+    {-3.0f, -3.0f},
+    { 1.0f, -1.0f},
+    { 1.0f, -3.0f},     /* 1200bps 11 */
+    { 3.0f, -1.0f},
+    { 3.0f, -3.0f}
 };
 
 static int fake_get_bit(void *user_data)
@@ -312,17 +308,9 @@ static __inline__ int get_scrambled_bit(v22bis_state_t *s)
 }
 /*- End of function --------------------------------------------------------*/
 
-#if defined(SPANDSP_USE_FIXED_POINT)
-static complexi16_t training_get(v22bis_state_t *s)
-#else
 static complexf_t training_get(v22bis_state_t *s)
-#endif
 {
-#if defined(SPANDSP_USE_FIXED_POINT)
-    static const complexi16_t zero = {0, 0};
-#else
-    static const complexf_t zero = {0.0f, 0.0f};
-#endif
+    complexf_t z;
     int bits;
 
     /* V.22bis training sequence */
@@ -341,17 +329,20 @@ static complexf_t training_get(v22bis_state_t *s)
     case V22BIS_TX_TRAINING_STAGE_INITIAL_SILENCE:
         /* Silence */
         s->tx.constellation_state = 0;
-        return zero;
+        z = complex_setf(0.0f, 0.0f);
+        break;
     case V22BIS_TX_TRAINING_STAGE_U11:
         /* Send continuous unscrambled ones at 1200bps (i.e. 270 degree phase steps). */
         /* Only the answering modem sends unscrambled ones. It is the first thing exchanged between the modems. */
         s->tx.constellation_state = (s->tx.constellation_state + phase_steps[3]) & 3;
-        return v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
+        z = v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
+        break;
     case V22BIS_TX_TRAINING_STAGE_U0011:
         /* Continuous unscrambled double dibit 00 11 at 1200bps. This is termed the S1 segment in
            the V.22bis spec. It is only sent to request or accept 2400bps mode, and lasts 100+-3ms. After this
            timed burst, we unconditionally change to sending scrambled ones at 1200bps. */
         s->tx.constellation_state = (s->tx.constellation_state + phase_steps[3*(s->tx.training_count & 1)]) & 3;
+        z = v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
         if (++s->tx.training_count >= ms_to_symbols(100))
         {
             span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting S11 after U0011\n");
@@ -366,7 +357,7 @@ static complexf_t training_get(v22bis_state_t *s)
                 s->tx.training = V22BIS_TX_TRAINING_STAGE_TIMED_S11;
             }
         }
-        return v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
+        break;
     case V22BIS_TX_TRAINING_STAGE_TIMED_S11:
         /* A timed period of scrambled ones at 1200bps. */
         if (++s->tx.training_count >= ms_to_symbols(756))
@@ -392,7 +383,8 @@ static complexf_t training_get(v22bis_state_t *s)
         bits = scramble(s, 1);
         bits = (bits << 1) | scramble(s, 1);
         s->tx.constellation_state = (s->tx.constellation_state + phase_steps[bits]) & 3;
-        return v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
+        z = v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
+        break;
     case V22BIS_TX_TRAINING_STAGE_S1111:
         /* Scrambled ones at 2400bps. We send a timed 200ms burst, and switch to normal operation at 2400bps */
         bits = scramble(s, 1);
@@ -400,6 +392,7 @@ static complexf_t training_get(v22bis_state_t *s)
         s->tx.constellation_state = (s->tx.constellation_state + phase_steps[bits]) & 3;
         bits = scramble(s, 1);
         bits = (bits << 1) | scramble(s, 1);
+        z = v22bis_constellation[(s->tx.constellation_state << 2) | bits];
         if (++s->tx.training_count >= ms_to_symbols(200))
         {
             /* We have completed training. Now handle some real work. */
@@ -409,23 +402,18 @@ static complexf_t training_get(v22bis_state_t *s)
             v22bis_report_status_change(s, SIG_STATUS_TRAINING_SUCCEEDED);
             s->tx.current_get_bit = s->get_bit;
         }
-        return v22bis_constellation[(s->tx.constellation_state << 2) | bits];
+        break;
+    case V22BIS_TX_TRAINING_STAGE_PARKED:
+    default:
+        z = complex_setf(0.0f, 0.0f);
+        break;
     }
-    return zero;
+    return z;
 }
 /*- End of function --------------------------------------------------------*/
 
-#if defined(SPANDSP_USE_FIXED_POINT)
-static complexi16_t getbaud(v22bis_state_t *s)
-#else
 static complexf_t getbaud(v22bis_state_t *s)
-#endif
 {
-#if defined(SPANDSP_USE_FIXED_POINT)
-    static const complexi16_t zero = {0, 0};
-#else
-    static const complexf_t zero = {0.0f, 0.0f};
-#endif
     int bits;
 
     if (s->tx.training)
@@ -440,7 +428,7 @@ static complexf_t getbaud(v22bis_state_t *s)
     if (s->tx.shutdown)
     {
         if (++s->tx.shutdown > 10)
-            return zero;
+            return complex_setf(0.0f, 0.0f);
     }
     /* The first two bits define the quadrant */
     bits = get_scrambled_bit(s);
@@ -462,18 +450,11 @@ static complexf_t getbaud(v22bis_state_t *s)
 
 SPAN_DECLARE_NONSTD(int) v22bis_tx(v22bis_state_t *s, int16_t amp[], int len)
 {
-#if defined(SPANDSP_USE_FIXED_POINT)
-    complexi16_t v;
-    complexi32_t x;
-    complexi32_t z;
-    int16_t iamp;
-#else
-    complexf_t v;
     complexf_t x;
     complexf_t z;
-    float famp;
-#endif
+    int i;
     int sample;
+    float famp;
 
     if (s->tx.shutdown > 10)
         return 0;
@@ -482,41 +463,28 @@ SPAN_DECLARE_NONSTD(int) v22bis_tx(v22bis_state_t *s, int16_t amp[], int len)
         if ((s->tx.baud_phase += 3) >= 40)
         {
             s->tx.baud_phase -= 40;
-            v = getbaud(s);
-            s->tx.rrc_filter_re[s->tx.rrc_filter_step] = v.re;
-            s->tx.rrc_filter_im[s->tx.rrc_filter_step] = v.im;
+            s->tx.rrc_filter[s->tx.rrc_filter_step] =
+            s->tx.rrc_filter[s->tx.rrc_filter_step + V22BIS_TX_FILTER_STEPS] = getbaud(s);
             if (++s->tx.rrc_filter_step >= V22BIS_TX_FILTER_STEPS)
                 s->tx.rrc_filter_step = 0;
         }
-#if defined(SPANDSP_USE_FIXED_POINT)
-        x.re = vec_circular_dot_prodi16(s->tx.rrc_filter_re, tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->tx.baud_phase], V22BIS_TX_FILTER_STEPS, s->tx.rrc_filter_step) >> 4;
-        x.im = vec_circular_dot_prodi16(s->tx.rrc_filter_im, tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->tx.baud_phase], V22BIS_TX_FILTER_STEPS, s->tx.rrc_filter_step) >> 4;
-        /* Now create and modulate the carrier */
-        z = dds_complexi32(&s->tx.carrier_phase, s->tx.carrier_phase_rate);
-        iamp = (x.re*z.re - x.im*z.im) >> 15;
-        iamp = (int16_t) (((int32_t) iamp*s->tx.gain) >> 11);
-        if (s->tx.guard_phase_rate  &&  (s->tx.rrc_filter_re[s->tx.rrc_filter_step] != 0  ||  s->tx.rrc_filter_im[s->tx.rrc_filter_step] != 0))
+        /* Root raised cosine pulse shaping at baseband */
+        x = complex_setf(0.0f, 0.0f);
+        for (i = 0;  i < V22BIS_TX_FILTER_STEPS;  i++)
         {
-            /* Add the guard tone */
-            iamp += dds_mod(&s->tx.guard_phase, s->tx.guard_phase_rate, s->tx.guard_tone_gain, 0);
+            x.re += tx_pulseshaper[39 - s->tx.baud_phase][i]*s->tx.rrc_filter[i + s->tx.rrc_filter_step].re;
+            x.im += tx_pulseshaper[39 - s->tx.baud_phase][i]*s->tx.rrc_filter[i + s->tx.rrc_filter_step].im;
         }
-        /* Don't bother saturating. We should never clip. */
-        amp[sample] = iamp;
-#else
-        /* Root raised cosine pulse shaping at baseband */
-        x.re = vec_circular_dot_prodf(s->tx.rrc_filter_re, tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->tx.baud_phase], V22BIS_TX_FILTER_STEPS, s->tx.rrc_filter_step);
-        x.im = vec_circular_dot_prodf(s->tx.rrc_filter_im, tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->tx.baud_phase], V22BIS_TX_FILTER_STEPS, s->tx.rrc_filter_step);
         /* Now create and modulate the carrier */
         z = dds_complexf(&(s->tx.carrier_phase), s->tx.carrier_phase_rate);
         famp = (x.re*z.re - x.im*z.im)*s->tx.gain;
-        if (s->tx.guard_phase_rate  &&  (s->tx.rrc_filter_re[s->tx.rrc_filter_step] != 0.0f  ||  s->tx.rrc_filter_im[s->tx.rrc_filter_step] != 0.0f))
+        if (s->tx.guard_phase_rate  &&  (s->tx.rrc_filter[s->tx.rrc_filter_step].re != 0.0f  ||  s->tx.rrc_filter[s->tx.rrc_filter_step].im != 0.0f))
         {
             /* Add the guard tone */
-            famp += dds_modf(&s->tx.guard_phase, s->tx.guard_phase_rate, s->tx.guard_tone_gain, 0);
+            famp += dds_modf(&(s->tx.guard_phase), s->tx.guard_phase_rate, s->tx.guard_level, 0);
         }
         /* Don't bother saturating. We should never clip. */
         amp[sample] = (int16_t) lfastrintf(famp);
-#endif
     }
     return sample;
 }
@@ -524,49 +492,34 @@ SPAN_DECLARE_NONSTD(int) v22bis_tx(v22bis_state_t *s, int16_t amp[], int len)
 
 SPAN_DECLARE(void) v22bis_tx_power(v22bis_state_t *s, float power)
 {
-    float sig_power;
-    float guard_tone_power;
-    float sig_gain;
-    float guard_tone_gain;
+    float l;
 
-    /* If is there is a guard tone we need to scale down the signal power a bit, so the aggregate of the signal
-       and guard tone power is the specified power. */
     if (s->tx.guard_phase_rate == dds_phase_ratef(550.0f))
     {
-        sig_power = power - 1.0f;
-        guard_tone_power = sig_power - 3.0f;
+        l = 1.6f*powf(10.0f, (power - 1.0f - DBM0_MAX_POWER)/20.0f);
+        s->tx.gain = l*32768.0f/(TX_PULSESHAPER_GAIN*3.0f);
+        l = powf(10.0f, (power - 1.0f - 3.0f - DBM0_MAX_POWER)/20.0f);
+        s->tx.guard_level = l*32768.0f;
     }
     else if(s->tx.guard_phase_rate == dds_phase_ratef(1800.0f))
     {
-        sig_power = power - 0.55f;
-        guard_tone_power = sig_power - 6.0f;
+        l = 1.6f*powf(10.0f, (power - 1.0f - 1.0f - DBM0_MAX_POWER)/20.0f);
+        s->tx.gain = l*32768.0f/(TX_PULSESHAPER_GAIN*3.0f);
+        l = powf(10.0f, (power - 1.0f - 6.0f - DBM0_MAX_POWER)/20.0f);
+        s->tx.guard_level = l*32768.0f;
     }
     else
     {
-        sig_power = power;
-        guard_tone_power = -9999.0f;
+        l = 1.6f*powf(10.0f, (power - DBM0_MAX_POWER)/20.0f);
+        s->tx.gain = l*32768.0f/(TX_PULSESHAPER_GAIN*3.0f);
+        s->tx.guard_level = 0;
     }
-    sig_gain = 0.4490f*powf(10.0f, (sig_power - DBM0_MAX_POWER)/20.0f)*32768.0f/TX_PULSESHAPER_GAIN;
-    guard_tone_gain = powf(10.0f, (guard_tone_power - DBM0_MAX_POWER)/20.0f)*32768.0f;
-#if defined(SPANDSP_USE_FIXED_POINT)
-    s->tx.gain = (int16_t) sig_gain;
-    s->tx.guard_tone_gain = (int16_t) guard_tone_gain;
-#else
-    s->tx.gain = sig_gain;
-    s->tx.guard_tone_gain = guard_tone_gain;
-#endif
 }
 /*- End of function --------------------------------------------------------*/
 
 static int v22bis_tx_restart(v22bis_state_t *s)
 {
-#if defined(SPANDSP_USE_FIXED_POINT)
-    vec_zeroi16(s->tx.rrc_filter_re, sizeof(s->tx.rrc_filter_re)/sizeof(s->tx.rrc_filter_re[0]));
-    vec_zeroi16(s->tx.rrc_filter_im, sizeof(s->tx.rrc_filter_im)/sizeof(s->tx.rrc_filter_im[0]));
-#else
-    vec_zerof(s->tx.rrc_filter_re, sizeof(s->tx.rrc_filter_re)/sizeof(s->tx.rrc_filter_re[0]));
-    vec_zerof(s->tx.rrc_filter_im, sizeof(s->tx.rrc_filter_im)/sizeof(s->tx.rrc_filter_im[0]));
-#endif
+    cvec_zerof(s->tx.rrc_filter, sizeof(s->tx.rrc_filter)/sizeof(s->tx.rrc_filter[0]));
     s->tx.rrc_filter_step = 0;
     s->tx.scramble_reg = 0;
     s->tx.scrambler_pattern_count = 0;
index db1a6c1253401c78ba7c983c302e43a3652586d9..cfc60aeabbc0243d20649f22502427c0c196f6b0 100644 (file)
@@ -230,13 +230,17 @@ static void equalizer_reset(v29_rx_state_t *s)
 {
     /* Start with an equalizer based on everything being perfect */
 #if defined(SPANDSP_USE_FIXED_POINT)
+    static const complexi16_t x = {3*FP_FACTOR, 0*FP_FACTOR};
+
     cvec_zeroi16(s->eq_coeff, V29_EQUALIZER_LEN);
-    s->eq_coeff[V29_EQUALIZER_PRE_LEN] = complex_seti16(3*FP_FACTOR, 0*FP_FACTOR);
+    s->eq_coeff[V29_EQUALIZER_PRE_LEN] = x;
     cvec_zeroi16(s->eq_buf, V29_EQUALIZER_LEN);
     s->eq_delta = 32768.0f*EQUALIZER_DELTA/V29_EQUALIZER_LEN;
 #else
+    static const complexf_t x = {3.0f, 0.0f};
+
     cvec_zerof(s->eq_coeff, V29_EQUALIZER_LEN);
-    s->eq_coeff[V29_EQUALIZER_PRE_LEN] = complex_setf(3.0f, 0.0f);
+    s->eq_coeff[V29_EQUALIZER_PRE_LEN] = x;
     cvec_zerof(s->eq_buf, V29_EQUALIZER_LEN);
     s->eq_delta = EQUALIZER_DELTA/V29_EQUALIZER_LEN;
 #endif
@@ -538,7 +542,7 @@ static __inline__ void symbol_sync(v29_rx_state_t *s)
         i = (v > 1000.0f)  ?  5  :  1;
         if (s->baud_phase < 0.0f)
             i = -i;
-        //printf("v = %10.5f %5d - %f %f %d %d\n", v, i, p, s->baud_phase, s->total_baud_timing_correction);
+        //printf("v = %10.5f %5d - %f %f %d\n", v, i, p, s->baud_phase, s->total_baud_timing_correction);
         s->eq_put_step += i;
         s->total_baud_timing_correction += i;
     }
@@ -645,8 +649,7 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
             if (i)
             {
                 j = i & 0xF;
-                ang = (s->angles[j] - s->start_angles[0])/i
-                    + (s->angles[j | 0x1] - s->start_angles[1])/i;
+                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, "Coarse carrier frequency %7.2f\n", dds_frequencyf(s->carrier_phase_rate));
@@ -719,11 +722,12 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
         if (++s->training_count >= V29_TRAINING_SEG_3_LEN - 48)
         {
             s->training_stage = TRAINING_STAGE_TRAIN_ON_CDCD_AND_TEST;
-            s->training_error = 0.0f;
 #if defined(SPANDSP_USE_FIXED_POINT)
+            s->training_error = 0;
             s->carrier_track_i = 200;
             s->carrier_track_p = 1000000;
 #else
+            s->training_error = 0.0f;
             s->carrier_track_i = 200.0f;
             s->carrier_track_p = 1000000.0f;
 #endif
@@ -946,10 +950,12 @@ SPAN_DECLARE_NONSTD(int) v29_rx(v29_rx_state_t *s, const int16_t amp[], int len)
            parked, after training failure. */
         s->eq_put_step -= RX_PULSESHAPER_COEFF_SETS;
         step = -s->eq_put_step;
-        if (step > RX_PULSESHAPER_COEFF_SETS - 1)
-            step = RX_PULSESHAPER_COEFF_SETS - 1;
         if (step < 0)
             step += RX_PULSESHAPER_COEFF_SETS;
+        if (step < 0)
+            step = 0;
+        else if (step > RX_PULSESHAPER_COEFF_SETS - 1)
+            step = RX_PULSESHAPER_COEFF_SETS - 1;
 #if defined(SPANDSP_USE_FIXED_POINT)
         v = vec_circular_dot_prodi16(s->rrc_filter, rx_pulseshaper_re[step], V29_RX_FILTER_STEPS, s->rrc_filter_step);
         sample.re = (v*s->agc_scaling) >> 15;
index f141b336bb39b94a40464cd0683beb527e1ceb72..01da53e71ff01ba0340dd24cab6de42b60fb4c4a 100644 (file)
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#if !defined(FP_SCALE)
-#if defined(SPANDSP_USE_FIXED_POINT)
-#define FP_SCALE(x)     ((int16_t) x)
-#else
-#define FP_SCALE(x)     (x)
-#endif
-#endif
-
 #if defined(SPANDSP_USE_FIXED_POINT)
 static const complexi16_t v29_abab_constellation[6] =
 #else
 static const complexf_t v29_abab_constellation[6] =
 #endif
 {
-    {FP_SCALE( 3.0f), FP_SCALE(-3.0f)},         /* 315deg high 9600 */
-    {FP_SCALE(-3.0f), FP_SCALE( 0.0f)},         /* 180deg low       */
-    {FP_SCALE( 1.0f), FP_SCALE(-1.0f)},         /* 315deg low 7200  */
-    {FP_SCALE(-3.0f), FP_SCALE( 0.0f)},         /* 180deg low       */
-    {FP_SCALE( 0.0f), FP_SCALE(-3.0f)},         /* 270deg low 4800  */
-    {FP_SCALE(-3.0f), FP_SCALE( 0.0f)}          /* 180deg low       */
+    { 3, -3},           /* 315deg high 9600 */
+    {-3,  0},           /* 180deg low       */
+    { 1, -1},           /* 315deg low 7200  */
+    {-3,  0},           /* 180deg low       */
+    { 0, -3},           /* 270deg low 4800  */
+    {-3,  0}            /* 180deg low       */
 };
 
 #if defined(SPANDSP_USE_FIXED_POINT)
@@ -52,12 +44,12 @@ static const complexi16_t v29_cdcd_constellation[6] =
 static const complexf_t v29_cdcd_constellation[6] =
 #endif
 {
-    {FP_SCALE( 3.0f), FP_SCALE( 0.0f)},         /*   0deg low 9600  */
-    {FP_SCALE(-3.0f), FP_SCALE( 3.0f)},         /* 135deg high      */
-    {FP_SCALE( 3.0f), FP_SCALE( 0.0f)},         /*   0deg low 7200  */
-    {FP_SCALE(-1.0f), FP_SCALE( 1.0f)},         /* 135deg low       */
-    {FP_SCALE( 3.0f), FP_SCALE( 0.0f)},         /*   0deg low 4800  */
-    {FP_SCALE( 0.0f), FP_SCALE( 3.0f)}          /*  90deg low       */
+    { 3,  0},           /*   0deg low 9600  */
+    {-3,  3},           /* 135deg high      */
+    { 3,  0},           /*   0deg low 7200  */
+    {-1,  1},           /* 135deg low       */
+    { 3,  0},           /*   0deg low 4800  */
+    { 0,  3}            /*  90deg low       */
 };
 
 #if defined(SPANDSP_USE_FIXED_POINT)
@@ -66,22 +58,22 @@ static const complexi16_t v29_9600_constellation[16] =
 static const complexf_t v29_9600_constellation[16] =
 #endif
 {
-    {FP_SCALE( 3.0f), FP_SCALE( 0.0f)},         /*   0deg low  */
-    {FP_SCALE( 1.0f), FP_SCALE( 1.0f)},         /*  45deg low  */
-    {FP_SCALE( 0.0f), FP_SCALE( 3.0f)},         /*  90deg low  */
-    {FP_SCALE(-1.0f), FP_SCALE( 1.0f)},         /* 135deg low  */
-    {FP_SCALE(-3.0f), FP_SCALE( 0.0f)},         /* 180deg low  */
-    {FP_SCALE(-1.0f), FP_SCALE(-1.0f)},         /* 225deg low  */
-    {FP_SCALE( 0.0f), FP_SCALE(-3.0f)},         /* 270deg low  */
-    {FP_SCALE( 1.0f), FP_SCALE(-1.0f)},         /* 315deg low  */
-    {FP_SCALE( 5.0f), FP_SCALE( 0.0f)},         /*   0deg high */
-    {FP_SCALE( 3.0f), FP_SCALE( 3.0f)},         /*  45deg high */
-    {FP_SCALE( 0.0f), FP_SCALE( 5.0f)},         /*  90deg high */
-    {FP_SCALE(-3.0f), FP_SCALE( 3.0f)},         /* 135deg high */
-    {FP_SCALE(-5.0f), FP_SCALE( 0.0f)},         /* 180deg high */
-    {FP_SCALE(-3.0f), FP_SCALE(-3.0f)},         /* 225deg high */
-    {FP_SCALE( 0.0f), FP_SCALE(-5.0f)},         /* 270deg high */
-    {FP_SCALE( 3.0f), FP_SCALE(-3.0f)}          /* 315deg high */
+    { 3,  0},           /*   0deg low  */
+    { 1,  1},           /*  45deg low  */
+    { 0,  3},           /*  90deg low  */
+    {-1,  1},           /* 135deg low  */
+    {-3,  0},           /* 180deg low  */
+    {-1, -1},           /* 225deg low  */
+    { 0, -3},           /* 270deg low  */
+    { 1, -1},           /* 315deg low  */
+    { 5,  0},           /*   0deg high */
+    { 3,  3},           /*  45deg high */
+    { 0,  5},           /*  90deg high */
+    {-3,  3},           /* 135deg high */
+    {-5,  0},           /* 180deg high */
+    {-3, -3},           /* 225deg high */
+    { 0, -5},           /* 270deg high */
+    { 3, -3}            /* 315deg high */
 };
 
 /*- End of file ------------------------------------------------------------*/
index 08a81dd7809cf397e428c0fa717c544a72689d5f..78f2904bac0eeb1a861e26ea3e668d889018ca87 100644 (file)
@@ -1024,9 +1024,9 @@ SPAN_DECLARE(int) v8_restart(v8_state_t *s, int calling_party, v8_parms_t *parms
     {
         /* Send the ANSam or ANSam/ tone */
         s->state = V8_CM_WAIT;
+        s->negotiation_timer = ms_to_samples(200 + 5000);
         v8_decode_init(s);
         modem_connect_tones_tx_init(&s->ansam_tx, s->parms.modem_connect_tone);
-        s->negotiation_timer = ms_to_samples(200 + 5000);
         s->modem_connect_tone_tx_on = ms_to_samples(75) + 1;
     }
 
index 05cccf139219dd0a19552c8f576ff39fd3b14096..401e8f41e636c2ddcef2168fc45dd66e22eee31e 100644 (file)
@@ -300,7 +300,7 @@ t38_core_tests_SOURCES = t38_core_tests.c
 t38_core_tests_LDADD = $(LIBDIR) -lspandsp
 
 t38_decode_SOURCES = t38_decode.c fax_utils.c pcap_parse.c udptl.c
-t38_decode_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp -lpcap
+t38_decode_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp
 
 t38_non_ecm_buffer_tests_SOURCES = t38_non_ecm_buffer_tests.c
 t38_non_ecm_buffer_tests_LDADD = $(LIBDIR) -lspandsp
index d6813a488d2ed89122d816d76b244a449fb716b2..79e8a09ae85c747e576b1ea4cecb2aff474483a5 100644 (file)
@@ -287,7 +287,7 @@ static void hdlc_rx_status(void *user_data, int status)
     faxtester_state_t *s;
 
     s = (faxtester_state_t *) user_data;
-    fprintf(stderr, "HDLC carrier status is %s (%d)\n", signal_status_to_str(status), status);
+    span_log(&s->logging, SPAN_LOG_FLOW, "HDLC carrier status is %s (%d)\n", signal_status_to_str(status), status);
     switch (status)
     {
     case SIG_STATUS_TRAINING_FAILED:
@@ -409,9 +409,7 @@ int faxtester_rx(faxtester_state_t *s, int16_t *amp, int len)
 int faxtester_tx(faxtester_state_t *s, int16_t *amp, int max_len)
 {
     int len;
-    int required_len;
     
-    required_len = max_len;
     len = 0;
     if (s->transmit)
     {
index a798ff8a6af46521f1fbe096571ae80fb753410e..bd29f3bf34fec9cb65ea587bfdb2efdeb3069202 100755 (executable)
@@ -18,8 +18,8 @@
 run_fax_test()
 {
     rm -f fax_tests_1.tif
-    echo -i ${FILE} ${OPTS}
-    ./fax_tests -i ${FILE} ${OPTS} >xyzzy 2>xyzzy2
+    echo -i ${FILE} ${OPTS} -i ${FILE}
+    ./fax_tests ${OPTS} -i ${FILE} >xyzzy 2>xyzzy2
     RETVAL=$?
     if [ $RETVAL != 0 ]
     then
@@ -28,7 +28,7 @@ run_fax_test()
     fi
     # Now use tiffcmp to check the results. It will return non-zero if any page images differ. The -t
     # option means the normal differences in tags will be ignored.
-    tiffcmp -t ${FILE} fax_tests_1.tif #>/dev/null
+    tiffcmp -t ${FILE} fax_tests.tif #>/dev/null
     RETVAL=$?
     if [ $RETVAL != 0 ]
     then
@@ -39,165 +39,106 @@ run_fax_test()
     echo tested ${FILE}
 }
 
-OPTS="-e"
+ITUTESTS_DIR=../test-data/itu/fax
 
-FILE="../itutests/fax/R8_385_A4.tif"
-run_fax_test
+for OPTS in "-p AA" "-p AA -e" "-p TT" "-p TT -e" "-p GG" "-p GG -e" "-p TG" "-p TG -e" "-p GT" "-p GT -e"
+do
+    FILE="${ITUTESTS_DIR}/R8_385_A4.tif"
+    run_fax_test
 
-FILE="../itutests/fax/R8_385_B4.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R8_385_B4.tif"
+    run_fax_test
 
-FILE="../itutests/fax/R8_385_A3.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R8_385_A3.tif"
+    run_fax_test
 
 
-FILE="../itutests/fax/R8_77_A4.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R8_77_A4.tif"
+    run_fax_test
 
-FILE="../itutests/fax/R8_77_B4.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R8_77_B4.tif"
+    run_fax_test
 
-FILE="../itutests/fax/R8_77_A3.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R8_77_A3.tif"
+    run_fax_test
 
 
-FILE="../itutests/fax/R8_154_A4.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R8_154_A4.tif"
+    run_fax_test
 
-FILE="../itutests/fax/R8_154_B4.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R8_154_B4.tif"
+    run_fax_test
 
-FILE="../itutests/fax/R8_154_A3.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R8_154_A3.tif"
+    run_fax_test
 
 
-FILE="../itutests/fax/R300_300_A4.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R300_300_A4.tif"
+    run_fax_test
 
-FILE="../itutests/fax/R300_300_B4.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R300_300_B4.tif"
+    run_fax_test
 
-FILE="../itutests/fax/R300_300_A3.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R300_300_A3.tif"
+    run_fax_test
 
 
-FILE="../itutests/fax/R300_600_A4.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R300_600_A4.tif"
+    run_fax_test
 
-FILE="../itutests/fax/R300_600_B4.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R300_600_B4.tif"
+    run_fax_test
 
-FILE="../itutests/fax/R300_600_A3.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R300_600_A3.tif"
+    run_fax_test
 
 
-FILE="../itutests/fax/R16_154_A4.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R16_154_A4.tif"
+    run_fax_test
 
-FILE="../itutests/fax/R16_154_B4.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R16_154_B4.tif"
+    run_fax_test
 
-FILE="../itutests/fax/R16_154_A3.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R16_154_A3.tif"
+    run_fax_test
 
 
-FILE="../itutests/fax/R16_800_A4.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R16_800_A4.tif"
+    run_fax_test
 
-FILE="../itutests/fax/R16_800_B4.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R16_800_B4.tif"
+    run_fax_test
 
-FILE="../itutests/fax/R16_800_A3.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R16_800_A3.tif"
+    run_fax_test
 
 
-FILE="../itutests/fax/R600_600_A4.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R600_600_A4.tif"
+    run_fax_test
 
-FILE="../itutests/fax/R600_600_B4.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R600_600_B4.tif"
+    run_fax_test
 
-FILE="../itutests/fax/R600_600_A3.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R600_600_A3.tif"
+    run_fax_test
 
 
-FILE="../itutests/fax/R600_1200_A4.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R600_1200_A4.tif"
+    run_fax_test
 
-FILE="../itutests/fax/R600_1200_B4.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R600_1200_B4.tif"
+    run_fax_test
 
-FILE="../itutests/fax/R600_1200_A3.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R600_1200_A3.tif"
+    run_fax_test
 
 
-FILE="../itutests/fax/R1200_1200_A4.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R1200_1200_A4.tif"
+    run_fax_test
 
-FILE="../itutests/fax/R1200_1200_B4.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R1200_1200_B4.tif"
+    run_fax_test
 
-FILE="../itutests/fax/R1200_1200_A3.tif"
-run_fax_test
-
-
-OPTS=""
-
-FILE="../itutests/fax/R8_385_A4.tif"
-run_fax_test
-
-FILE="../itutests/fax/R8_385_B4.tif"
-run_fax_test
-
-FILE="../itutests/fax/R8_385_A3.tif"
-run_fax_test
-
-
-FILE="../itutests/fax/R8_77_A4.tif"
-run_fax_test
-
-FILE="../itutests/fax/R8_77_B4.tif"
-run_fax_test
-
-FILE="../itutests/fax/R8_77_A3.tif"
-run_fax_test
-
-
-FILE="../itutests/fax/R8_154_A4.tif"
-run_fax_test
-
-FILE="../itutests/fax/R8_154_B4.tif"
-run_fax_test
-
-FILE="../itutests/fax/R8_154_A3.tif"
-run_fax_test
-
-
-FILE="../itutests/fax/R16_385_A4.tif"
-#run_fax_test
-
-FILE="../itutests/fax/R16_385_B4.tif"
-#run_fax_test
-
-FILE="../itutests/fax/R16_385_A3.tif"
-#run_fax_test
-
-
-FILE="../itutests/fax/R16_77_A4.tif"
-#run_fax_test
-
-FILE="../itutests/fax/R16_77_B4.tif"
-#run_fax_test
-
-FILE="../itutests/fax/R16_77_A3.tif"
-#run_fax_test
-
-
-FILE="../itutests/fax/R16_154_A4.tif"
-run_fax_test
-
-FILE="../itutests/fax/R16_154_B4.tif"
-run_fax_test
-
-FILE="../itutests/fax/R16_154_A3.tif"
-run_fax_test
+    FILE="${ITUTESTS_DIR}/R1200_1200_A3.tif"
+    run_fax_test
+done