A typo fixed in the OKI ADPCM codec
The V.17 modem has been modified, so it will not clear the most recent saved AGC value if long training is requested. The T.38 gateway codec now has fillin implemented properly
This commit is contained in:
parent
1eb4b79c15
commit
01052800c7
|
@ -26,8 +26,6 @@
|
|||
*
|
||||
* The actual OKI ADPCM encode and decode method is derived from freely
|
||||
* available code, whose exact origins seem uncertain.
|
||||
*
|
||||
* $Id: oki_adpcm.c,v 1.32 2009/02/10 13:06:46 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -153,7 +151,7 @@ static const float cutoff_coeffs[] =
|
|||
|
||||
static int16_t decode(oki_adpcm_state_t *s, uint8_t adpcm)
|
||||
{
|
||||
int16_t e;
|
||||
int16_t d;
|
||||
int16_t ss;
|
||||
int16_t linear;
|
||||
|
||||
|
@ -170,20 +168,20 @@ static int16_t decode(oki_adpcm_state_t *s, uint8_t adpcm)
|
|||
*/
|
||||
|
||||
ss = step_size[s->step_index];
|
||||
e = ss >> 3;
|
||||
d = ss >> 3;
|
||||
if (adpcm & 0x01)
|
||||
e += (ss >> 2);
|
||||
d += (ss >> 2);
|
||||
/*endif*/
|
||||
if (adpcm & 0x02)
|
||||
e += (ss >> 1);
|
||||
d += (ss >> 1);
|
||||
/*endif*/
|
||||
if (adpcm & 0x04)
|
||||
e += ss;
|
||||
d += ss;
|
||||
/*endif*/
|
||||
if (adpcm & 0x08)
|
||||
e = -e;
|
||||
d = -d;
|
||||
/*endif*/
|
||||
linear = s->last + e;
|
||||
linear = s->last + d;
|
||||
|
||||
/* Saturate the values to +/- 2^11 (supposed to be 12 bits) */
|
||||
if (linear > 2047)
|
||||
|
@ -206,32 +204,32 @@ static int16_t decode(oki_adpcm_state_t *s, uint8_t adpcm)
|
|||
|
||||
static uint8_t encode(oki_adpcm_state_t *s, int16_t linear)
|
||||
{
|
||||
int16_t e;
|
||||
int16_t d;
|
||||
int16_t ss;
|
||||
uint8_t adpcm;
|
||||
|
||||
ss = step_size[s->step_index];
|
||||
e = (linear >> 4) - s->last;
|
||||
d = (linear >> 4) - s->last;
|
||||
adpcm = (uint8_t) 0x00;
|
||||
if (e < 0)
|
||||
if (d < 0)
|
||||
{
|
||||
adpcm = (uint8_t) 0x08;
|
||||
e = -e;
|
||||
d = -d;
|
||||
}
|
||||
/*endif*/
|
||||
if (e >= ss)
|
||||
if (d >= ss)
|
||||
{
|
||||
adpcm |= (uint8_t) 0x04;
|
||||
e -= ss;
|
||||
d -= ss;
|
||||
}
|
||||
/*endif*/
|
||||
if (e >= (ss >> 1))
|
||||
if (d >= (ss >> 1))
|
||||
{
|
||||
adpcm |= (uint8_t) 0x02;
|
||||
e -= ss;
|
||||
d -= (ss >> 1);
|
||||
}
|
||||
/*endif*/
|
||||
if (e >= (ss >> 2))
|
||||
if (d >= (ss >> 2))
|
||||
adpcm |= (uint8_t) 0x01;
|
||||
/*endif*/
|
||||
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: t38_gateway.h,v 1.5 2009/11/07 08:58:58 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -35,7 +33,7 @@
|
|||
*/
|
||||
typedef struct
|
||||
{
|
||||
/*! Core T.38 IFP support */
|
||||
/*! \brief Core T.38 IFP support */
|
||||
t38_core_state_t t38;
|
||||
|
||||
/*! \brief TRUE if the NSF, NSC, and NSS are to be suppressed by altering
|
||||
|
@ -61,9 +59,10 @@ typedef struct
|
|||
{
|
||||
/*! \brief The FAX modem set for the audio side fo the gateway. */
|
||||
fax_modems_state_t modems;
|
||||
/*! \brief The current receive signal handler. Actual receiving hop between this
|
||||
/*! \brief The current receive signal handler. Actual receiving hops between this
|
||||
and a dummy receive routine. */
|
||||
span_rx_handler_t *base_rx_handler;
|
||||
span_rx_fillin_handler_t *base_rx_fillin_handler;
|
||||
} t38_gateway_audio_state_t;
|
||||
|
||||
/*!
|
||||
|
@ -144,6 +143,8 @@ typedef struct
|
|||
int supported_modems;
|
||||
/*! \brief TRUE if ECM FAX mode is allowed through the gateway. */
|
||||
int ecm_allowed;
|
||||
/*! \brief Required time between T.38 transmissions, in ms. */
|
||||
int ms_per_tx_chunk;
|
||||
|
||||
/*! \brief TRUE if in image data modem is to use short training. This usually
|
||||
follows image_data_mode, but in ECM mode T.30 defines recovery
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: v17rx.h,v 1.2.4.1 2009/12/24 16:52:30 steveu Exp $
|
||||
*/
|
||||
|
||||
#if !defined(_SPANDSP_PRIVATE_V17RX_H_)
|
||||
|
@ -30,10 +28,11 @@
|
|||
|
||||
/* 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
|
||||
|
||||
/*! Samples before the target position in the equalizer buffer */
|
||||
#define V17_EQUALIZER_PRE_LEN 8
|
||||
/*! Samples after the target position in the equalizer buffer */
|
||||
#define V17_EQUALIZER_POST_LEN 8
|
||||
#define V17_EQUALIZER_PRE_LEN 16
|
||||
|
||||
/*! The number of taps in the pulse shaping/bandpass filter */
|
||||
#define V17_RX_FILTER_STEPS 27
|
||||
|
@ -137,7 +136,7 @@ struct v17_rx_state_s
|
|||
int eq_step;
|
||||
/*! \brief Current write offset into the equalizer buffer. */
|
||||
int eq_put_step;
|
||||
/*! \brief Symbol counter to the next equalizer update. */
|
||||
/*! \brief Symbol count to the next equalizer update. */
|
||||
int eq_skip;
|
||||
|
||||
/*! \brief The current half of the baud. */
|
||||
|
@ -152,11 +151,11 @@ struct v17_rx_state_s
|
|||
/*! \brief The current delta factor for updating the equalizer coefficients. */
|
||||
float eq_delta;
|
||||
/*! \brief The adaptive equalizer coefficients. */
|
||||
complexi16_t eq_coeff[V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN];
|
||||
complexi16_t eq_coeff[V17_EQUALIZER_LEN];
|
||||
/*! \brief A saved set of adaptive equalizer coefficients for use after restarts. */
|
||||
complexi16_t eq_coeff_save[V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN];
|
||||
complexi16_t eq_coeff_save[V17_EQUALIZER_LEN];
|
||||
/*! \brief The equalizer signal buffer. */
|
||||
complexi16_t eq_buf[V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN];
|
||||
complexi16_t eq_buf[V17_EQUALIZER_LEN];
|
||||
|
||||
/*! Low band edge filter for symbol sync. */
|
||||
int32_t symbol_sync_low[2];
|
||||
|
@ -175,11 +174,11 @@ struct v17_rx_state_s
|
|||
/*! \brief The current delta factor for updating the equalizer coefficients. */
|
||||
float eq_delta;
|
||||
/*! \brief The adaptive equalizer coefficients. */
|
||||
complexf_t eq_coeff[V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN];
|
||||
complexf_t eq_coeff[V17_EQUALIZER_LEN];
|
||||
/*! \brief A saved set of adaptive equalizer coefficients for use after restarts. */
|
||||
complexf_t eq_coeff_save[V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN];
|
||||
complexf_t eq_coeff_save[V17_EQUALIZER_LEN];
|
||||
/*! \brief The equalizer signal buffer. */
|
||||
complexf_t eq_buf[V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN];
|
||||
complexf_t eq_buf[V17_EQUALIZER_LEN];
|
||||
|
||||
/*! Low band edge filter for symbol sync. */
|
||||
float symbol_sync_low[2];
|
||||
|
|
|
@ -287,7 +287,7 @@ SPAN_DECLARE_NONSTD(int) v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
|
|||
\param len The number of samples to fake.
|
||||
\return The number of samples unprocessed.
|
||||
*/
|
||||
SPAN_DECLARE(int) v17_rx_fillin(v17_rx_state_t *s, int len);
|
||||
SPAN_DECLARE_NONSTD(int) v17_rx_fillin(v17_rx_state_t *s, int len);
|
||||
|
||||
/*! Get a snapshot of the current equalizer coefficients.
|
||||
\brief Get a snapshot of the current equalizer coefficients.
|
||||
|
|
|
@ -22,8 +22,6 @@
|
|||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: t38_gateway.c,v 1.171.4.2 2009/12/19 10:44:10 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -106,7 +104,8 @@
|
|||
/* This is the target time per transmission chunk. The actual
|
||||
packet timing will sync to the data octets. */
|
||||
/*! The default number of milliseconds per transmitted IFP when sending bulk T.38 data */
|
||||
#define MS_PER_TX_CHUNK 30
|
||||
#define DEFAULT_MS_PER_TX_CHUNK 30
|
||||
|
||||
/*! The number of bytes which must be in the audio to T.38 HDLC buffer before we start
|
||||
outputting them as IFP messages. */
|
||||
#define HDLC_START_BUFFER_LEVEL 8
|
||||
|
@ -185,11 +184,15 @@ static void non_ecm_remove_fill_and_put_bit(void *user_data, int bit);
|
|||
static void non_ecm_push_residue(t38_gateway_state_t *s);
|
||||
static void tone_detected(void *user_data, int tone, int level, int delay);
|
||||
|
||||
static void set_rx_handler(t38_gateway_state_t *s, span_rx_handler_t *handler, void *user_data)
|
||||
static void set_rx_handler(t38_gateway_state_t *s, span_rx_handler_t *handler, span_rx_fillin_handler_t *fillin_handler, void *user_data)
|
||||
{
|
||||
if (s->audio.modems.rx_handler != span_dummy_rx)
|
||||
{
|
||||
s->audio.modems.rx_handler = handler;
|
||||
s->audio.modems.rx_fillin_handler = fillin_handler;
|
||||
}
|
||||
s->audio.base_rx_handler = handler;
|
||||
s->audio.base_rx_fillin_handler = fillin_handler;
|
||||
s->audio.modems.rx_user_data = user_data;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -211,6 +214,20 @@ static void set_next_tx_handler(t38_gateway_state_t *s, span_tx_handler_t *handl
|
|||
static void set_rx_active(t38_gateway_state_t *s, int active)
|
||||
{
|
||||
s->audio.modems.rx_handler = (active) ? s->audio.base_rx_handler : span_dummy_rx;
|
||||
s->audio.modems.rx_fillin_handler = (active) ? s->audio.base_rx_fillin_handler : span_dummy_rx_fillin;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int v17_v21_rx_fillin(void *user_data, int len)
|
||||
{
|
||||
t38_gateway_state_t *t;
|
||||
fax_modems_state_t *s;
|
||||
|
||||
t = (t38_gateway_state_t *) user_data;
|
||||
s = &t->audio.modems;
|
||||
v17_rx_fillin(&s->v17_rx, len);
|
||||
fsk_rx_fillin(&s->v21_rx, len);
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -227,7 +244,7 @@ static int v17_v21_rx(void *user_data, const int16_t amp[], int len)
|
|||
/* The fast modem has trained, so we no longer need to run the slow
|
||||
one in parallel. */
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->v17_rx));
|
||||
set_rx_handler(t, (span_rx_handler_t *) &v17_rx, &s->v17_rx);
|
||||
set_rx_handler(t, (span_rx_handler_t *) &v17_rx, (span_rx_fillin_handler_t *) &v17_rx_fillin, &s->v17_rx);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -235,7 +252,7 @@ static int v17_v21_rx(void *user_data, const int16_t amp[], int len)
|
|||
if (s->rx_signal_present)
|
||||
{
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
|
||||
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx);
|
||||
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &s->v21_rx);
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
|
@ -244,6 +261,19 @@ static int v17_v21_rx(void *user_data, const int16_t amp[], int len)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int v27ter_v21_rx_fillin(void *user_data, int len)
|
||||
{
|
||||
t38_gateway_state_t *t;
|
||||
fax_modems_state_t *s;
|
||||
|
||||
t = (t38_gateway_state_t *) user_data;
|
||||
s = &t->audio.modems;
|
||||
v27ter_rx_fillin(&s->v27ter_rx, len);
|
||||
fsk_rx_fillin(&s->v21_rx, len);
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
|
||||
{
|
||||
t38_gateway_state_t *t;
|
||||
|
@ -257,7 +287,7 @@ static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
|
|||
/* The fast modem has trained, so we no longer need to run the slow
|
||||
one in parallel. */
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->v27ter_rx));
|
||||
set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, &s->v27ter_rx);
|
||||
set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, (span_rx_fillin_handler_t *) &v27ter_v21_rx_fillin, &s->v27ter_rx);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -265,7 +295,7 @@ static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
|
|||
if (s->rx_signal_present)
|
||||
{
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
|
||||
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx);
|
||||
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &s->v21_rx);
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
|
@ -274,6 +304,19 @@ static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int v29_v21_rx_fillin(void *user_data, int len)
|
||||
{
|
||||
t38_gateway_state_t *t;
|
||||
fax_modems_state_t *s;
|
||||
|
||||
t = (t38_gateway_state_t *) user_data;
|
||||
s = &t->audio.modems;
|
||||
v29_rx_fillin(&s->v29_rx, len);
|
||||
fsk_rx_fillin(&s->v21_rx, len);
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int v29_v21_rx(void *user_data, const int16_t amp[], int len)
|
||||
{
|
||||
t38_gateway_state_t *t;
|
||||
|
@ -287,7 +330,7 @@ static int v29_v21_rx(void *user_data, const int16_t amp[], int len)
|
|||
/* The fast modem has trained, so we no longer need to run the slow
|
||||
one in parallel. */
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->v29_rx));
|
||||
set_rx_handler(t, (span_rx_handler_t *) &v29_rx, &s->v29_rx);
|
||||
set_rx_handler(t, (span_rx_handler_t *) &v29_rx, (span_rx_fillin_handler_t *) &v29_rx_fillin, &s->v29_rx);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -295,7 +338,7 @@ static int v29_v21_rx(void *user_data, const int16_t amp[], int len)
|
|||
if (s->rx_signal_present)
|
||||
{
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
|
||||
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx);
|
||||
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &s->v21_rx);
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
|
@ -651,7 +694,7 @@ static void edit_control_messages(t38_gateway_state_t *s, int from_modem, uint8_
|
|||
{
|
||||
case T30_DIS:
|
||||
/* Make sure the V.8 capability doesn't pass through. If it
|
||||
did then two V.34 capable FAX machines might start some
|
||||
did, two V.34 capable FAX machines might start some
|
||||
V.8 re-negotiation. */
|
||||
buf[3] &= ~DISBIT6;
|
||||
break;
|
||||
|
@ -827,7 +870,6 @@ static void monitor_control_messages(t38_gateway_state_t *s,
|
|||
if (len >= 6)
|
||||
{
|
||||
j = (buf[5] & (DISBIT7 | DISBIT6 | DISBIT5)) >> 4;
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Min bits test = 0x%X\n", buf[5]);
|
||||
s->core.min_row_bits = (s->core.fast_bit_rate*minimum_scan_line_times[j])/1000;
|
||||
}
|
||||
else
|
||||
|
@ -1468,7 +1510,7 @@ static void set_octets_per_data_packet(t38_gateway_state_t *s, int bit_rate)
|
|||
{
|
||||
int octets;
|
||||
|
||||
octets = MS_PER_TX_CHUNK*bit_rate/(8*1000);
|
||||
octets = s->core.ms_per_tx_chunk*bit_rate/(8*1000);
|
||||
if (octets < 1)
|
||||
octets = 1;
|
||||
/*endif*/
|
||||
|
@ -2029,23 +2071,23 @@ static int restart_rx_modem(t38_gateway_state_t *s)
|
|||
case T38_V17_RX:
|
||||
v17_rx_restart(&s->audio.modems.v17_rx, s->core.fast_bit_rate, s->core.short_train);
|
||||
v17_rx_set_put_bit(&s->audio.modems.v17_rx, put_bit_func, put_bit_user_data);
|
||||
set_rx_handler(s, (span_rx_handler_t *) &v17_v21_rx, s);
|
||||
set_rx_handler(s, &v17_v21_rx, &v17_v21_rx_fillin, s);
|
||||
s->core.fast_rx_active = T38_V17_RX;
|
||||
break;
|
||||
case T38_V27TER_RX:
|
||||
v27ter_rx_restart(&s->audio.modems.v27ter_rx, s->core.fast_bit_rate, FALSE);
|
||||
v27ter_rx_set_put_bit(&s->audio.modems.v27ter_rx, put_bit_func, put_bit_user_data);
|
||||
set_rx_handler(s, (span_rx_handler_t *) &v27ter_v21_rx, s);
|
||||
set_rx_handler(s, &v27ter_v21_rx, &v27ter_v21_rx_fillin, s);
|
||||
s->core.fast_rx_active = T38_V27TER_RX;
|
||||
break;
|
||||
case T38_V29_RX:
|
||||
v29_rx_restart(&s->audio.modems.v29_rx, s->core.fast_bit_rate, FALSE);
|
||||
v29_rx_set_put_bit(&s->audio.modems.v29_rx, put_bit_func, put_bit_user_data);
|
||||
set_rx_handler(s, (span_rx_handler_t *) &v29_v21_rx, s);
|
||||
set_rx_handler(s, &v29_v21_rx, &v29_v21_rx_fillin, s);
|
||||
s->core.fast_rx_active = T38_V29_RX;
|
||||
break;
|
||||
default:
|
||||
set_rx_handler(s, (span_rx_handler_t *) &fsk_rx, &(s->audio.modems.v21_rx));
|
||||
set_rx_handler(s, (span_rx_handler_t *) &fsk_rx, (span_rx_fillin_handler_t *) &fsk_rx_fillin, &(s->audio.modems.v21_rx));
|
||||
s->core.fast_rx_active = T38_NONE;
|
||||
break;
|
||||
}
|
||||
|
@ -2054,15 +2096,8 @@ static int restart_rx_modem(t38_gateway_state_t *s)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE_NONSTD(int) t38_gateway_rx(t38_gateway_state_t *s, int16_t amp[], int len)
|
||||
static void update_rx_timing(t38_gateway_state_t *s, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
#if defined(LOG_FAX_AUDIO)
|
||||
if (s->audio.modems.audio_rx_log >= 0)
|
||||
write(s->audio.modems.audio_rx_log, amp, len*sizeof(int16_t));
|
||||
/*endif*/
|
||||
#endif
|
||||
if (s->core.samples_to_timeout > 0)
|
||||
{
|
||||
if ((s->core.samples_to_timeout -= len) <= 0)
|
||||
|
@ -2096,6 +2131,19 @@ SPAN_DECLARE_NONSTD(int) t38_gateway_rx(t38_gateway_state_t *s, int16_t amp[], i
|
|||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE_NONSTD(int) t38_gateway_rx(t38_gateway_state_t *s, int16_t amp[], int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
#if defined(LOG_FAX_AUDIO)
|
||||
if (s->audio.modems.audio_rx_log >= 0)
|
||||
write(s->audio.modems.audio_rx_log, amp, len*sizeof(int16_t));
|
||||
/*endif*/
|
||||
#endif
|
||||
update_rx_timing(s, len);
|
||||
for (i = 0; i < len; i++)
|
||||
amp[i] = dc_restore(&(s->audio.modems.dc_restore), amp[i]);
|
||||
/*endfor*/
|
||||
|
@ -2106,7 +2154,28 @@ SPAN_DECLARE_NONSTD(int) t38_gateway_rx(t38_gateway_state_t *s, int16_t amp[], i
|
|||
|
||||
SPAN_DECLARE_NONSTD(int) t38_gateway_rx_fillin(t38_gateway_state_t *s, int len)
|
||||
{
|
||||
/* TODO: handle things properly */
|
||||
/* To mitigate the effect of lost packets on a packet network we should
|
||||
try to sustain the status quo. If there is no receive modem running, keep
|
||||
things that way. If there is a receive modem running, try to sustain its
|
||||
operation, without causing a phase hop, or letting its adaptive functions
|
||||
diverge. */
|
||||
#if defined(LOG_FAX_AUDIO)
|
||||
if (s->audio.modems.audio_rx_log >= 0)
|
||||
{
|
||||
int i;
|
||||
#if defined(_MSC_VER)
|
||||
int16_t *amp = (int16_t *) _alloca(sizeof(int16_t)*len);
|
||||
#else
|
||||
int16_t amp[len];
|
||||
#endif
|
||||
|
||||
vec_zeroi16(amp, len);
|
||||
write(s->modems.audio_rx_log, amp, len*sizeof(int16_t));
|
||||
}
|
||||
#endif
|
||||
update_rx_timing(s, len);
|
||||
/* TODO: handle the modems properly */
|
||||
s->audio.modems.rx_fillin_handler(s->audio.modems.rx_user_data, len);
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -2301,11 +2370,12 @@ SPAN_DECLARE(t38_gateway_state_t *) t38_gateway_init(t38_gateway_state_t *s,
|
|||
t38_gateway_t38_init(s, tx_packet_handler, tx_packet_user_data);
|
||||
|
||||
set_rx_active(s, TRUE);
|
||||
t38_gateway_set_supported_modems(s, T30_SUPPORT_V27TER | T30_SUPPORT_V29);
|
||||
t38_gateway_set_supported_modems(s, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17);
|
||||
t38_gateway_set_nsx_suppression(s, (const uint8_t *) "\x00\x00\x00", 3, (const uint8_t *) "\x00\x00\x00", 3);
|
||||
|
||||
s->core.to_t38.octets_per_data_packet = 1;
|
||||
s->core.ecm_allowed = TRUE;
|
||||
s->core.ms_per_tx_chunk = DEFAULT_MS_PER_TX_CHUNK;
|
||||
t38_non_ecm_buffer_init(&s->core.non_ecm_to_modem, FALSE, 0);
|
||||
restart_rx_modem(s);
|
||||
s->core.timed_mode = TIMED_MODE_STARTUP;
|
||||
|
|
|
@ -22,8 +22,6 @@
|
|||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: v17rx.c,v 1.153.4.6 2009/12/28 12:20:46 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -98,9 +96,6 @@
|
|||
/*! The 16 bit pattern used in the bridge section of the training sequence */
|
||||
#define V17_BRIDGE_WORD 0x8880
|
||||
|
||||
/*! The length of the equalizer buffer */
|
||||
#define V17_EQUALIZER_LEN (V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN)
|
||||
|
||||
enum
|
||||
{
|
||||
TRAINING_STAGE_NORMAL_OPERATION = 0,
|
||||
|
@ -233,6 +228,7 @@ static void equalizer_restore(v17_rx_state_t *s)
|
|||
|
||||
s->eq_put_step = RX_PULSESHAPER_COEFF_SETS*10/(3*2) - 1;
|
||||
s->eq_step = 0;
|
||||
s->eq_skip = 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -253,6 +249,7 @@ static void equalizer_reset(v17_rx_state_t *s)
|
|||
|
||||
s->eq_put_step = RX_PULSESHAPER_COEFF_SETS*10/(3*2) - 1;
|
||||
s->eq_step = 0;
|
||||
s->eq_skip = 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -565,7 +562,7 @@ static __inline__ void symbol_sync(v17_rx_state_t *s)
|
|||
Passband Timing Recovery in an All-Digital Modem Receiver
|
||||
IEEE TRANSACTIONS ON COMMUNICATIONS, VOL. COM-26, NO. 5, MAY 1978 */
|
||||
|
||||
/* This is slightly rearranged for figure 3b of the Godard paper, as this saves a couple of
|
||||
/* This is slightly rearranged from figure 3b of the Godard paper, as this saves a couple of
|
||||
maths operations */
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
/* TODO: The scalings used here need more thorough evaluation, to see if overflows are possible. */
|
||||
|
@ -579,12 +576,12 @@ static __inline__ void symbol_sync(v17_rx_state_t *s)
|
|||
s->symbol_sync_dc_filter[0] = v;
|
||||
/* A little integration will now filter away much of the HF noise */
|
||||
s->baud_phase -= p;
|
||||
if (abs(s->baud_phase) > 100*FP_FACTOR)
|
||||
v = labs(s->baud_phase);
|
||||
if (v > 100*FP_FACTOR)
|
||||
{
|
||||
if (s->baud_phase > 0)
|
||||
i = (s->baud_phase > 1000*FP_FACTOR) ? 15 : 1;
|
||||
else
|
||||
i = (s->baud_phase < -1000*FP_FACTOR) ? -15 : -1;
|
||||
i = (v > 1000*FP_FACTOR) ? 15 : 1;
|
||||
if (s->baud_phase < 0)
|
||||
i = -i;
|
||||
//printf("v = %10.5f %5d - %f %f %d %d\n", v, i, p, s->baud_phase, s->total_baud_timing_correction);
|
||||
s->eq_put_step += i;
|
||||
s->total_baud_timing_correction += i;
|
||||
|
@ -600,12 +597,12 @@ static __inline__ void symbol_sync(v17_rx_state_t *s)
|
|||
s->symbol_sync_dc_filter[0] = v;
|
||||
/* A little integration will now filter away much of the HF noise */
|
||||
s->baud_phase -= p;
|
||||
if (fabsf(s->baud_phase) > 100.0f)
|
||||
v = fabsf(s->baud_phase);
|
||||
if (v > 100.0f)
|
||||
{
|
||||
if (s->baud_phase > 0.0f)
|
||||
i = (s->baud_phase > 1000.0f) ? 15 : 1;
|
||||
else
|
||||
i = (s->baud_phase < -1000.0f) ? -15 : -1;
|
||||
i = (v > 1000.0f) ? 15 : 1;
|
||||
if (s->baud_phase < 0.0f)
|
||||
i = -i;
|
||||
//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;
|
||||
|
@ -732,18 +729,14 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
if (s->training_count == 100)
|
||||
{
|
||||
i = s->training_count;
|
||||
/* Avoid the possibility of a divide by zero */
|
||||
if (i)
|
||||
{
|
||||
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);
|
||||
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];
|
||||
}
|
||||
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);
|
||||
|
||||
|
@ -1219,7 +1212,7 @@ SPAN_DECLARE_NONSTD(int) v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) v17_rx_fillin(v17_rx_state_t *s, int len)
|
||||
SPAN_DECLARE_NONSTD(int) v17_rx_fillin(v17_rx_state_t *s, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -1343,15 +1336,14 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
|
|||
s->distances[0] = 0;
|
||||
s->trellis_ptr = 14;
|
||||
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Phase rates %f %f\n", dds_frequencyf(s->carrier_phase_rate), dds_frequencyf(s->carrier_phase_rate_save));
|
||||
s->carrier_phase = 0;
|
||||
power_meter_init(&(s->power), 4);
|
||||
|
||||
if (s->short_train)
|
||||
{
|
||||
s->carrier_phase_rate = s->carrier_phase_rate_save;
|
||||
s->agc_scaling = s->agc_scaling_save;
|
||||
equalizer_restore(s);
|
||||
s->agc_scaling = s->agc_scaling_save;
|
||||
/* Don't allow any frequency correction at all, until we start to pull the phase in. */
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
s->carrier_track_i = 0;
|
||||
|
@ -1366,18 +1358,19 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
|
|||
s->carrier_phase_rate = dds_phase_ratef(CARRIER_NOMINAL_FREQ);
|
||||
equalizer_reset(s);
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
s->agc_scaling_save = 0;
|
||||
//s->agc_scaling_save = 0;
|
||||
s->agc_scaling = (float) FP_FACTOR*32768.0f*0.0017f/RX_PULSESHAPER_GAIN;
|
||||
s->carrier_track_i = 5000;
|
||||
s->carrier_track_p = 40000;
|
||||
#else
|
||||
s->agc_scaling_save = 0.0f;
|
||||
//s->agc_scaling_save = 0.0f;
|
||||
s->agc_scaling = 0.0017f/RX_PULSESHAPER_GAIN;
|
||||
s->carrier_track_i = 5000.0f;
|
||||
s->carrier_track_p = 40000.0f;
|
||||
#endif
|
||||
}
|
||||
s->last_sample = 0;
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Phase rates %f %f\n", dds_frequencyf(s->carrier_phase_rate), dds_frequencyf(s->carrier_phase_rate_save));
|
||||
|
||||
/* Initialise the working data for symbol timing synchronisation */
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
|
@ -1432,8 +1425,13 @@ 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->agc_scaling = 0.0017f/RX_PULSESHAPER_GAIN;
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
s->agc_scaling_save = 0;
|
||||
s->agc_scaling = (float) FP_FACTOR*32768.0f*0.0017f/RX_PULSESHAPER_GAIN;
|
||||
#else
|
||||
s->agc_scaling_save = 0.0f;
|
||||
s->agc_scaling = 0.0017f/RX_PULSESHAPER_GAIN;
|
||||
#endif
|
||||
s->carrier_phase_rate_save = dds_phase_ratef(CARRIER_NOMINAL_FREQ);
|
||||
v17_rx_restart(s, bit_rate, s->short_train);
|
||||
return s;
|
||||
|
|
|
@ -22,8 +22,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: oki_adpcm_tests.c,v 1.37 2009/05/30 15:23:14 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -85,24 +83,33 @@ int main(int argc, char *argv[])
|
|||
int hist_out;
|
||||
oki_adpcm_state_t *oki_enc_state;
|
||||
oki_adpcm_state_t *oki_dec_state;
|
||||
oki_adpcm_state_t *oki_dec_state2;
|
||||
int xx;
|
||||
int total_pre_samples;
|
||||
int total_compressed_bytes;
|
||||
int total_post_samples;
|
||||
int successive_08_bytes;
|
||||
int successive_80_bytes;
|
||||
int encoded_fd;
|
||||
const char *encoded_file_name;
|
||||
const char *in_file_name;
|
||||
int log_encoded_data;
|
||||
int opt;
|
||||
|
||||
bit_rate = 32000;
|
||||
encoded_file_name = NULL;
|
||||
in_file_name = IN_FILE_NAME;
|
||||
log_encoded_data = FALSE;
|
||||
while ((opt = getopt(argc, argv, "2i:l")) != -1)
|
||||
while ((opt = getopt(argc, argv, "2d:i:l")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case '2':
|
||||
bit_rate = 24000;
|
||||
break;
|
||||
case 'd':
|
||||
encoded_file_name = optarg;
|
||||
break;
|
||||
case 'i':
|
||||
in_file_name = optarg;
|
||||
break;
|
||||
|
@ -116,24 +123,39 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
if ((inhandle = sf_open_telephony_read(in_file_name, 1)) == NULL)
|
||||
if (encoded_file_name)
|
||||
{
|
||||
fprintf(stderr, " Cannot open audio file '%s'\n", in_file_name);
|
||||
exit(2);
|
||||
if ((encoded_fd = open(encoded_file_name, O_RDONLY)) < 0)
|
||||
{
|
||||
fprintf(stderr, " Cannot open encoded file '%s'\n", encoded_file_name);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((inhandle = sf_open_telephony_read(in_file_name, 1)) == NULL)
|
||||
{
|
||||
fprintf(stderr, " Cannot open audio file '%s'\n", in_file_name);
|
||||
exit(2);
|
||||
}
|
||||
if ((oki_enc_state = oki_adpcm_init(NULL, bit_rate)) == NULL)
|
||||
{
|
||||
fprintf(stderr, " Cannot create encoder\n");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
if ((outhandle = sf_open_telephony_write(OUT_FILE_NAME, 1)) == NULL)
|
||||
{
|
||||
fprintf(stderr, " Cannot create audio file '%s'\n", OUT_FILE_NAME);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if ((oki_enc_state = oki_adpcm_init(NULL, bit_rate)) == NULL)
|
||||
if ((oki_dec_state = oki_adpcm_init(NULL, bit_rate)) == NULL)
|
||||
{
|
||||
fprintf(stderr, " Cannot create encoder\n");
|
||||
fprintf(stderr, " Cannot create decoder\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if ((oki_dec_state = oki_adpcm_init(NULL, bit_rate)) == NULL)
|
||||
if ((oki_dec_state2 = oki_adpcm_init(NULL, bit_rate)) == NULL)
|
||||
{
|
||||
fprintf(stderr, " Cannot create decoder\n");
|
||||
exit(2);
|
||||
|
@ -151,72 +173,125 @@ int main(int argc, char *argv[])
|
|||
total_pre_samples = 0;
|
||||
total_compressed_bytes = 0;
|
||||
total_post_samples = 0;
|
||||
while ((frames = sf_readf_short(inhandle, pre_amp, 159)))
|
||||
if (encoded_file_name)
|
||||
{
|
||||
total_pre_samples += frames;
|
||||
oki_bytes = oki_adpcm_encode(oki_enc_state, oki_data, pre_amp, frames);
|
||||
if (log_encoded_data)
|
||||
write(1, oki_data, oki_bytes);
|
||||
total_compressed_bytes += oki_bytes;
|
||||
dec_frames = oki_adpcm_decode(oki_dec_state, post_amp, oki_data, oki_bytes);
|
||||
total_post_samples += dec_frames;
|
||||
for (i = 0; i < frames; i++)
|
||||
/* Decode a file of OKI ADPCM code to a linear wave file */
|
||||
while ((oki_bytes = read(encoded_fd, oki_data, 80)) > 0)
|
||||
{
|
||||
history[hist_in++] = pre_amp[i];
|
||||
if (hist_in >= HIST_LEN)
|
||||
hist_in = 0;
|
||||
pre_energy += (double) pre_amp[i] * (double) pre_amp[i];
|
||||
total_compressed_bytes += oki_bytes;
|
||||
dec_frames = oki_adpcm_decode(oki_dec_state, post_amp, oki_data, oki_bytes);
|
||||
total_post_samples += dec_frames;
|
||||
for (i = 0; i < dec_frames; i++)
|
||||
{
|
||||
post_energy += (double) post_amp[i] * (double) post_amp[i];
|
||||
xx = post_amp[i] - history[hist_out++];
|
||||
if (hist_out >= HIST_LEN)
|
||||
hist_out = 0;
|
||||
diff_energy += (double) xx * (double) xx;
|
||||
}
|
||||
outframes = sf_writef_short(outhandle, post_amp, dec_frames);
|
||||
}
|
||||
for (i = 0; i < dec_frames; i++)
|
||||
{
|
||||
post_energy += (double) post_amp[i] * (double) post_amp[i];
|
||||
xx = post_amp[i] - history[hist_out++];
|
||||
if (hist_out >= HIST_LEN)
|
||||
hist_out = 0;
|
||||
diff_energy += (double) xx * (double) xx;
|
||||
//post_amp[i] = xx;
|
||||
}
|
||||
outframes = sf_writef_short(outhandle, post_amp, dec_frames);
|
||||
close(encoded_fd);
|
||||
}
|
||||
if (sf_close(inhandle) != 0)
|
||||
else
|
||||
{
|
||||
fprintf(stderr, " Cannot close audio file '%s'\n", in_file_name);
|
||||
exit(2);
|
||||
/* Perform a linear wave file -> OKI ADPCM -> linear wave file cycle. Along the way
|
||||
check the decoder resets on the sequence specified for this codec, and the gain
|
||||
and worst case sample distortion. */
|
||||
successive_08_bytes = 0;
|
||||
successive_80_bytes = 0;
|
||||
while ((frames = sf_readf_short(inhandle, pre_amp, 159)))
|
||||
{
|
||||
total_pre_samples += frames;
|
||||
oki_bytes = oki_adpcm_encode(oki_enc_state, oki_data, pre_amp, frames);
|
||||
if (log_encoded_data)
|
||||
write(1, oki_data, oki_bytes);
|
||||
total_compressed_bytes += oki_bytes;
|
||||
/* Look for a condition which is defined as something which should cause a reset of
|
||||
the decoder (48 samples of 0, 8, 0, 8, etc.), and verify that it really does. Use
|
||||
a second decode, which we feed byte by byte, for this. */
|
||||
for (i = 0; i < oki_bytes; i++)
|
||||
{
|
||||
oki_adpcm_decode(oki_dec_state2, post_amp, &oki_data[i], 1);
|
||||
if (oki_data[i] == 0x08)
|
||||
successive_08_bytes++;
|
||||
else
|
||||
successive_08_bytes = 0;
|
||||
if (oki_data[i] == 0x80)
|
||||
successive_80_bytes++;
|
||||
else
|
||||
successive_80_bytes = 0;
|
||||
if (successive_08_bytes == 24 || successive_80_bytes == 24)
|
||||
{
|
||||
if (oki_dec_state2->step_index != 0)
|
||||
{
|
||||
fprintf(stderr, "Decoder reset failure\n");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
dec_frames = oki_adpcm_decode(oki_dec_state, post_amp, oki_data, oki_bytes);
|
||||
total_post_samples += dec_frames;
|
||||
for (i = 0; i < frames; i++)
|
||||
{
|
||||
history[hist_in++] = pre_amp[i];
|
||||
if (hist_in >= HIST_LEN)
|
||||
hist_in = 0;
|
||||
pre_energy += (double) pre_amp[i] * (double) pre_amp[i];
|
||||
}
|
||||
for (i = 0; i < dec_frames; i++)
|
||||
{
|
||||
post_energy += (double) post_amp[i] * (double) post_amp[i];
|
||||
xx = post_amp[i] - history[hist_out++];
|
||||
if (hist_out >= HIST_LEN)
|
||||
hist_out = 0;
|
||||
diff_energy += (double) xx * (double) xx;
|
||||
//post_amp[i] = xx;
|
||||
}
|
||||
outframes = sf_writef_short(outhandle, post_amp, dec_frames);
|
||||
}
|
||||
printf("Pre samples: %d\n", total_pre_samples);
|
||||
printf("Compressed bytes: %d\n", total_compressed_bytes);
|
||||
printf("Post samples: %d\n", total_post_samples);
|
||||
|
||||
printf("Output energy is %f%% of input energy.\n", 100.0*post_energy/pre_energy);
|
||||
printf("Residual energy is %f%% of the total.\n", 100.0*diff_energy/post_energy);
|
||||
if (bit_rate == 32000)
|
||||
{
|
||||
if (fabs(1.0 - post_energy/pre_energy) > 0.01
|
||||
||
|
||||
fabs(diff_energy/post_energy) > 0.01)
|
||||
{
|
||||
printf("Tests failed.\n");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fabs(1.0 - post_energy/pre_energy) > 0.11
|
||||
||
|
||||
fabs(diff_energy/post_energy) > 0.05)
|
||||
{
|
||||
printf("Tests failed.\n");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
oki_adpcm_release(oki_enc_state);
|
||||
if (sf_close(inhandle) != 0)
|
||||
{
|
||||
fprintf(stderr, " Cannot close audio file '%s'\n", in_file_name);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
oki_adpcm_release(oki_dec_state);
|
||||
oki_adpcm_release(oki_dec_state2);
|
||||
if (sf_close(outhandle) != 0)
|
||||
{
|
||||
fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME);
|
||||
exit(2);
|
||||
}
|
||||
oki_adpcm_release(oki_enc_state);
|
||||
oki_adpcm_release(oki_dec_state);
|
||||
|
||||
printf("Pre samples: %d\n", total_pre_samples);
|
||||
printf("Compressed bytes: %d\n", total_compressed_bytes);
|
||||
printf("Post samples: %d\n", total_post_samples);
|
||||
|
||||
printf("Output energy is %f%% of input energy.\n", 100.0*post_energy/pre_energy);
|
||||
printf("Residual energy is %f%% of the total.\n", 100.0*diff_energy/post_energy);
|
||||
if (bit_rate == 32000)
|
||||
{
|
||||
if (fabs(1.0 - post_energy/pre_energy) > 0.05
|
||||
||
|
||||
fabs(diff_energy/post_energy) > 0.03)
|
||||
{
|
||||
printf("Tests failed.\n");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fabs(1.0 - post_energy/pre_energy) > 0.20
|
||||
||
|
||||
fabs(diff_energy/post_energy) > 0.10)
|
||||
{
|
||||
printf("Tests failed.\n");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Tests passed.\n");
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue