blob: 4151b331bb70182b929430b2fe914aeb8f1c2f02 [file] [log] [blame]
/*---------------------------------------------------------------------------*
* frontobj.c *
* *
* Copyright 2007, 2008 Nuance Communciations, Inc. *
* *
* Licensed under the Apache License, Version 2.0 (the 'License'); *
* you may not use this file except in compliance with the License. *
* *
* You may obtain a copy of the License at *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an 'AS IS' BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* *
*---------------------------------------------------------------------------*/
#include <stdlib.h>
#if defined(__cplusplus) && defined(_MSC_VER)
extern "C"
{
#include <string.h>
}
#else
#include <string.h>
#endif
#ifndef _RTT
#include <stdio.h>
#endif
#ifdef unix
#include <unistd.h>
#endif
#ifndef POSIX
#include <memory.h>
#endif
#include <assert.h>
#include "front.h"
#include "portable.h"
#include "sh_down.h"
#define DEBUG 0
static void hamming_window(fftdata *ham, int win_len);
static front_wave *create_wave_object(void);
static void delete_wave_object(front_wave *waveobj);
static void setup_wave_object(front_wave *waveobj, front_parameters *parameters);
static void clear_wave_object(front_wave *waveobj);
static front_freq *create_freq_object(void);
static void delete_freq_object(front_freq *freqobj);
static void setup_freq_object(front_freq *freqobj, front_parameters *parameters, int mel_dim);
static void reset_freq_object(front_freq *freqobj);
static void clear_freq_object(front_freq *freqobj);
static front_cep *create_cep_object(void);
static void delete_cep_object(front_cep *cepobj);
static void setup_cep_object(front_cep *cepobj, front_parameters *parameters,
size_t num_fb, size_t mel_dim);
static void reset_cep_object(front_cep *cepobj);
static void clear_cep_object(front_cep *cepobj);
front_config *create_config_object(void)
{
front_config *config;
config = (front_config *) CALLOC_CLR(1,
sizeof(front_config), "cfront.front_config");
return config;
}
/*******************************************************************************
** FUNCTION: setup_config_object
**
** DESCRIPTION: Set up the front end using the paramteters. This function
** configures the member Wave, Freq and Cep objects, by calling their
** create and setup
** functions.
**
** ARGUMENTS:
**
** RETURNS: pointer to config object
**
*******************************************************************************/
void setup_config_object(front_config *config, front_parameters *parameters)
{
ASSERT(config);
ASSERT(parameters);
/* Create and configure sub-components */
config->waveobj = create_wave_object();
config->freqobj = create_freq_object();
config->cepobj = create_cep_object();
setup_wave_object(config->waveobj, parameters);
setup_freq_object(config->freqobj, parameters, parameters->mel_dim);
setup_cep_object(config->cepobj, parameters, config->freqobj->nf,
parameters->mel_dim);
return;
}
void clear_config_object(front_config *config)
{
ASSERT(config);
clear_wave_object(config->waveobj);
clear_freq_object(config->freqobj);
clear_cep_object(config->cepobj);
delete_wave_object(config->waveobj);
config->waveobj = NULL;
delete_freq_object(config->freqobj);
config->freqobj = NULL;
delete_cep_object(config->cepobj);
config->cepobj = NULL;
return;
}
void delete_config_object(front_config *config)
{
ASSERT(config);
FREE((char *) config);
return;
}
front_channel *create_channel_object(void)
{
front_channel *channel;
channel = (front_channel *) CALLOC_CLR(1,
sizeof(front_channel), "cfront.channel");
return channel;
}
void delete_channel_object(front_channel *channel)
{
ASSERT(channel);
FREE((char *) channel);
}
void setup_channel_object(
front_channel *channel, front_wave *waveobj,
front_freq *freqobj, front_cep *cepobj)
{
ASSERT(channel);
ASSERT(waveobj);
ASSERT(freqobj);
ASSERT(cepobj);
channel->prebuff = (fftdata *) CALLOC(freqobj->window_length + 1,
sizeof(fftdata), "cfront.prebuff");
channel->prerefbuff = (fftdata *) CALLOC(freqobj->window_length + 1,
sizeof(fftdata), "cfront.prerefbuff");
channel->buff_size = freqobj->window_length + 1;
/* Create gain normalization object, and space for filter bank storage. BP */
channel->num_freq = freqobj->nf;
channel->filterbank = (cepdata *) CALLOC(channel->num_freq,
sizeof(cepdata), "cfront.filterbank");
channel->filterbankref = (cepdata *) CALLOC(channel->num_freq,
sizeof(cepdata), "cfront.filterbankref");
channel->mel_dim = cepobj->mel_dim;
channel->cep = (cepdata *) CALLOC((Q2 + 1) * (channel->mel_dim + 1),
sizeof(cepdata), "cfront.cep");
channel->rasta = (cepdata *) CALLOC((channel->mel_dim + 1),
sizeof(cepdata), "cfront.rasta");
channel->framdata = (featdata *) CALLOC(3 * (channel->mel_dim + 1),
sizeof(featdata), "cfront.chan_framdata");
if (freqobj->do_spectral_sub)
{
/* Spectral subtraction requires estimate of BG levels. This is currently
estimated on the first config->spectral_sub_frame_dur frames, which are
assumed to be in silence. The channel means are estimated when the
frame count is reached, and is_valid is set, in
estimate_spectral_sub_means. Spectral subtraction is turned on with
config->do_spectral_sub.
*/
channel->spectral_sub = (spectral_sub_info *) CALLOC_CLR(1,
sizeof(spectral_sub_info), "cfront.spectral_sub_info");
channel->spectral_sub->sub_vector = (cepdata *) CALLOC(NUM_MEL_FREQS,
sizeof(cepdata), "cfront.spectral_sub_vector");
channel->spectral_sub->frame_dur = cepobj->spectral_sub_frame_dur;
channel->spectral_sub->scale = cepobj->spec_sub_scale;
}
ASSERT(freqobj->frame_period > 0);
channel->frame_delay = DELTA + (freqobj->window_length / freqobj->frame_period) - 1;
channel->forget_factor = cepobj->forget_factor;
reset_channel_object(channel);
return;
}
void clear_channel_object(front_channel *channel)
{
ASSERT(channel);
FREE((char *) channel->prebuff);
channel->prebuff = NULL;
FREE((char *) channel->prerefbuff);
channel->prerefbuff = NULL;
FREE((char *) channel->filterbank);
channel->filterbank = NULL;
FREE((char *) channel->filterbankref);
channel->filterbankref = NULL;
FREE((char *) channel->cep);
channel->cep = NULL;
FREE((char *) channel->rasta);
channel->rasta = NULL;
FREE((char *) channel->framdata);
channel->framdata = NULL;
if (channel->spectral_sub)
{
FREE((char *) channel->spectral_sub->sub_vector);
FREE((char *) channel->spectral_sub);
channel->spectral_sub = NULL;
}
channel->buff_size = 0;
return;
}
/* Replacement fns for reset_std_channel */
void reset_channel_object(front_channel *channel)
{
size_t ii;
ASSERT(channel);
#if DEBUG
log_report("Channel reset\n");
#endif
memset(channel->cep, 0x00, Q2 *(channel->mel_dim + 1) * sizeof(float));
memset(channel->prebuff, 0x00, channel->buff_size * sizeof(fftdata));
memset(channel->prerefbuff, 0x00, channel->buff_size * sizeof(fftdata));
channel->lastx = 0;
for (ii = 0; ii <= channel->mel_dim; ii++)
channel->rasta[ii] = 0;
if (channel->spectral_sub)
{
channel->spectral_sub->is_valid = False;
for (ii = 0; ii < NUM_MEL_FREQS; ii++)
channel->spectral_sub->sub_vector[ii] = (cepdata) 0.0;
}
channel->frame_count = 0;
return;
}
/******************************************************************************
** WAVE OBJECT
*******************************************************************************/
static front_wave *create_wave_object(void)
{
front_wave *waveobj;
waveobj = (front_wave *) CALLOC_CLR(1, sizeof(front_wave), "cfront.waveobj");
return waveobj;
}
static void delete_wave_object(front_wave *waveobj)
{
ASSERT(waveobj);
FREE((char *) waveobj);
return;
}
static void setup_wave_object(front_wave *waveobj, front_parameters *parameters)
{
ASSERT(waveobj);
ASSERT(parameters);
waveobj->samplerate = parameters->samplerate;
/* Be careful about the value of COEFDATA_SHIFT - it should be <16.
During preemphasis the data is shifted up by COEFDATA_SHIFT too.
*/
waveobj->pre_mel = (coefdata) fixed_point_convert(parameters->pre_mel,
COEFDATA_SHIFT);
waveobj->high_clip = parameters->high_clip;
waveobj->low_clip = parameters->low_clip;
waveobj->max_per10000_clip = parameters->max_per10000_clip;
waveobj->max_dc_offset = parameters->max_dc_offset;
waveobj->high_noise_level_bit = parameters->high_noise_level_bit;
waveobj->low_speech_level_bit = parameters->low_speech_level_bit;
waveobj->min_samples = parameters->min_samples;
return;
}
static void clear_wave_object(front_wave *waveobj)
{
ASSERT(waveobj);
return;
}
/******************************************************************************
** FREQUENCY OBJECT
*******************************************************************************/
static front_freq *create_freq_object(void)
{
front_freq *freqobj;
freqobj = (front_freq *) CALLOC_CLR(1,
sizeof(front_freq), "cfront.freqobj");
freqobj->fc = &freqobj->fcb[1];
freqobj->lognp = 4;
reset_freq_object(freqobj);
return freqobj;
}
static void delete_freq_object(front_freq *freqobj)
{
ASSERT(freqobj);
FREE((char *) freqobj);
return;
}
static void setup_freq_object(front_freq *freqobj,
front_parameters *parameters, int mel_dim)
{
int fmax, i, j, high_cut, bandwidth;
float t, finc, f;
ASSERT(freqobj);
ASSERT(parameters);
ASSERT(FRAMERATE > 0);
ASSERT(parameters->samplerate);
freqobj->framerate = FRAMERATE;
freqobj->frame_period = parameters->samplerate / freqobj->framerate;
freqobj->samplerate = parameters->samplerate;
freqobj->window_length = (int)(parameters->window_factor * freqobj->frame_period);
freqobj->low_cut = parameters->low_cut;
freqobj->high_cut = parameters->high_cut;
freqobj->do_spectral_sub = parameters->do_spectral_sub;
freqobj->do_filterbank_input = parameters->do_filterbank_input;
freqobj->do_filterbank_dump = parameters->do_filterbank_dump;
freqobj->num_fb_to_use = parameters->num_fb_to_use;
freqobj->do_nonlinear_filter = True; /* on by default */
freqobj->spectrum_filter_num = 0;
freqobj->warp_scale = parameters->warp_scale; /*## */
freqobj->piecewise_start = parameters->piecewise_start; /*## */
if (freqobj->high_cut > 0)
high_cut = freqobj->high_cut;
else
high_cut = parameters->samplerate / 2;
bandwidth = parameters->samplerate / 2;
ASSERT(bandwidth != 0);
freqobj->np = 1 << freqobj->lognp; /* fft sizing */
while (freqobj->np < freqobj->window_length)
freqobj->np *= 2, freqobj->lognp++;
while (freqobj->np < 128)
freqobj->np *= 2, freqobj->lognp++;
if (freqobj->np > NP)
SERVICE_ERROR(FFT_TOO_SMALL);
/* Change the values of the peakpick forward and backward coefficients
to compensate for sample rate. */
t = (float) exp(log((double)parameters->peakpickup)
* ((double)parameters->samplerate / (double)11025)
/ ((double)freqobj->np / (double)256));
freqobj->peakpickup = (fftdata) fixed_point_convert(t, COEFDATA_SHIFT);
t = (float) exp(log((double)parameters->peakpickdown)
* ((double)parameters->samplerate / (double)11025)
/ ((double)freqobj->np / (double)256));
freqobj->peakpickdown = (fftdata) fixed_point_convert(t, COEFDATA_SHIFT);
#if BIGGER_WINDOW
freqobj->window_length = freqobj->np;
#endif
configure_fft(&freqobj->fft, freqobj->np);
freqobj->ns = freqobj->np / 2 + 1;
fmax = bandwidth;
finc = (float)parameters->samplerate / (float)freqobj->np;
/* finc= fmax/freqobj->ns; */
freqobj->cut_off_below = (int)(((long)freqobj->low_cut * freqobj->np) / (2.0 * bandwidth));
freqobj->cut_off_above = (int)(((long)high_cut * freqobj->np) / (2.0 * bandwidth));
freqobj->fc[-1] = (fftdata) freqobj->low_cut; /* 1st channel at cutoff */
i = ((int)freqobj->low_cut + 50) / 100 + 1; /* other channels at x00Hz */
for (freqobj->nf = 0; i <= 10; i++, freqobj->nf++)
freqobj->fc[freqobj->nf] = (fftdata)(100 * i); /* 100 Hz */
for (f = 1000.; f <= high_cut; freqobj->nf++)
{
f *= (float)1.1; /* 10% */
freqobj->fc[freqobj->nf] = (fftdata) fixed_round(f); /* 10 % */
}
freqobj->nf--;
if ((freqobj->fc[freqobj->nf] + freqobj->fc[freqobj->nf-1]) / 2. > high_cut)
freqobj->nf--;
freqobj->fc[freqobj->nf] = (fftdata) high_cut;
freqobj->fc[freqobj->nf+1] = (fftdata) high_cut;
#if DEBUG
write_frames(freqobj->nf + 1, 1, freqobj->fc, D_FLOAT);
#endif
for (i = 0; i <= freqobj->cut_off_below; i++)
freqobj->framp[i] = 0;
freqobj->fcscl[0] = 0;
freqobj->fcmid[0] = freqobj->cut_off_below;
f = (freqobj->cut_off_below + 1) * finc;
for (i = 0, j = freqobj->cut_off_below + 1; i <= freqobj->nf; i++)
{
freqobj->fcscl[i+1] = (fftdata) 0.0;
for (; f < freqobj->fc[i] && f < (float) high_cut; f += finc, j++)
{
t = (f - freqobj->fc[i-1]) / (freqobj->fc[i] - freqobj->fc[i-1]);
freqobj->framp[j] = (fftdata) fixed_point_convert(t, RAMP_SHIFT); /* scale it up by 12 bits, (16 - 4) */
freqobj->fcscl[i] += (fftdata) SHIFT_UP(1, RAMP_SHIFT) - freqobj->framp[j]; /* scale it up by 12 bits as well () */
freqobj->fcscl[i+1] += freqobj->framp[j]; /* scale it up by 12 bits as well () */
}
if (j > freqobj->cut_off_above)
freqobj->fcmid[i+1] = freqobj->cut_off_above;
else
freqobj->fcmid[i+1] = j;
}
/* Put in a check to validate the range of fcscl[] for fixed point f/e
*/
#if DEBUG
write_frames(freqobj->nf, 1, freqobj->fcmid, D_LONG);
write_frames(freqobj->nf, 1, freqobj->fcscl, D_LONG);
write_frames(freqobj->ns, 1, freqobj->framp, D_LONG);
#endif
if (mel_dim > freqobj->nf)
SERVICE_ERROR(BAD_COSINE_TRANSFORM);
if (freqobj->nf > NF)
SERVICE_ERROR(BAD_COSINE_TRANSFORM);
/* Weighting function construction */
freqobj->ham = (fftdata *) CALLOC(freqobj->window_length + 1,
sizeof(fftdata), "cfront.ham");
hamming_window(freqobj->ham, freqobj->window_length);
/* Sine tables for FFT */
#if DEBUG
#define log_report printf
log_report("fc\n");
write_scaled_frames(freqobj->nf + 1, 1, freqobj->fc, D_FIXED, 1);
log_report("framp\n");
write_scaled_frames(freqobj->ns, 1, freqobj->framp, D_FIXED, 1);
#endif
create_spectrum_filter(freqobj, parameters->spectrum_filter_freq,
parameters->spectrum_filter_spread);
if (freqobj->spectrum_filter_num == 0)
clear_spectrum_filter(freqobj);
return;
}
static void hamming_window(fftdata *ham, int win_len)
/*
** add Hamming window on speech data */
{
int i;
double f;
double coef;
f = (2 * M_PI) / win_len;
for (i = 0; i <= win_len; i++)
{
coef = 0.54 - 0.46 * cos(f * (double)i);
ham[i] = (fftdata) fixed_point_convert((float)coef,
HALF_FFTDATA_SIZE - 1);
}
return;
}
static void clear_freq_object(front_freq *freqobj)
{
ASSERT(freqobj);
if (freqobj->ham)
{
FREE((char *)freqobj->ham);
freqobj->ham = NULL;
}
unconfigure_fft(&freqobj->fft);
if (freqobj->spectrum_filter_num > 0)
clear_spectrum_filter(freqobj);
return;
}
static void reset_freq_object(front_freq *freqobj)
{
ASSERT(freqobj);
return;
}
/******************************************************************************
** CEPSTRAL OBJECT
*******************************************************************************/
static front_cep *create_cep_object(void)
{
front_cep *cepobj;
cepobj = (front_cep *) CALLOC_CLR(1, sizeof(front_cep), "cfront.cepobj");
return cepobj;
}
static void delete_cep_object(front_cep *cepobj)
{
ASSERT(cepobj);
FREE((char *) cepobj);
return;
}
static void setup_cep_object(front_cep *cepobj, front_parameters *parameters,
size_t num_fb, size_t mel_dim)
{
float f;
size_t i, j;
ASSERT(cepobj);
ASSERT(parameters);
cepobj->mel_dim = mel_dim;
cepobj->do_dd_mel = parameters->do_dd_mel;
cepobj->do_skip_even_frames = parameters->do_skip_even_frames;
cepobj->do_smooth_c0 = parameters->do_smooth_c0;
cepobj->sv6_margin = parameters->sv6_margin;
cepobj->forget_factor = parameters->forget_factor;
cepobj->spectral_sub_frame_dur = parameters->spectral_sub_frame_dur;
cepobj->spec_sub_scale = (coefdata) fixed_point_convert(
parameters->spec_sub_scale, COEFDATA_SHIFT);
cepobj->lpc_order = parameters->lpc_order;
cepobj->mel_offset = (cepdata *) CALLOC(MEL_FREQ_ARRAY_SIZE,
sizeof(cepdata), "cfront.mel_offset");
cepobj->mel_loop = (cepdata *) CALLOC(MEL_FREQ_ARRAY_SIZE,
sizeof(cepdata), "cfront.mel_loop");
cepobj->melA_scale = (cepdata *) CALLOC(cepobj->mel_dim + 1,
sizeof(cepdata), "cfront.melA_scale");
cepobj->dmelA_scale = (cepdata *) CALLOC(cepobj->mel_dim + 1,
sizeof(cepdata), "cfront.dmelA_scale");
cepobj->ddmelA_scale = (cepdata *) CALLOC(cepobj->mel_dim + 1,
sizeof(cepdata), "cfront.ddmelA_scale");
cepobj->melB_scale = (cepdata *) CALLOC(cepobj->mel_dim + 1,
sizeof(cepdata), "cfront.melB_scale");
cepobj->dmelB_scale = (cepdata *) CALLOC(cepobj->mel_dim + 1,
sizeof(cepdata), "cfront.dmelB_scale");
cepobj->ddmelB_scale = (cepdata *) CALLOC(cepobj->mel_dim + 1,
sizeof(cepdata), "cfront.ddmelB_scale");
cepobj->rastaA_scale = (cepdata *) CALLOC(cepobj->mel_dim + 1,
sizeof(cepdata), "cfront.rastaA_scale");
cepobj->rastaB_scale = (cepdata *) CALLOC(cepobj->mel_dim + 1,
sizeof(cepdata), "cfront.rastaB_scale");
cepobj->do_scales = True; /* Hack so default scalings are loaded */
for (i = 0; i < MEL_FREQ_ARRAY_SIZE; ++i)
{
cepobj->mel_offset[i] = (cepdata) parameters->mel_offset[i];
cepobj->mel_loop[i] = (cepdata) parameters->mel_loop[i];
}
for (i = 0; i <= cepobj->mel_dim; ++i)
{
cepobj->melA_scale[i] = (cepdata) parameters->melA_scale[i];
cepobj->dmelA_scale[i] = (cepdata) parameters->dmelA_scale[i];
cepobj->ddmelA_scale[i] = (cepdata) parameters->ddmelA_scale[i];
cepobj->melB_scale[i] = (cepdata) parameters->melB_scale[i];
cepobj->dmelB_scale[i] = (cepdata) parameters->dmelB_scale[i];
cepobj->ddmelB_scale[i] = (cepdata) parameters->ddmelB_scale[i];
cepobj->rastaA_scale[i] = (cepdata) parameters->rastaA_scale[i];
cepobj->rastaB_scale[i] = (cepdata) parameters->rastaB_scale[i];
cepobj->melA_scale[i] = (cepdata) fixed_point_convert((float) parameters->melA_scale[i],
BYTERANGE_SHIFT);
cepobj->dmelA_scale[i] = (cepdata) fixed_point_convert((float) parameters->dmelA_scale[i],
BYTERANGE_SHIFT);
cepobj->ddmelA_scale[i] = (cepdata) fixed_point_convert((float) parameters->ddmelA_scale[i],
BYTERANGE_SHIFT);
cepobj->melB_scale[i] = (cepdata) fixed_point_convert((float) parameters->melB_scale[i],
BYTERANGE_SHIFT + LOG_SCALE_SHIFT);
cepobj->dmelB_scale[i] = (cepdata) fixed_point_convert((float) parameters->dmelB_scale[i],
BYTERANGE_SHIFT + LOG_SCALE_SHIFT);
cepobj->ddmelB_scale[i] = (cepdata) fixed_point_convert((float) parameters->ddmelB_scale[i],
BYTERANGE_SHIFT + LOG_SCALE_SHIFT);
cepobj->rastaA_scale[i] = (cepdata) fixed_point_convert((float) parameters->rastaA_scale[i],
BYTERANGE_SHIFT);
cepobj->rastaB_scale[i] = (cepdata) fixed_point_convert((float) parameters->rastaB_scale[i],
BYTERANGE_SHIFT + LOG_SCALE_SHIFT);
}
/* Now allocate space for the cosine matrix. Previously fixed. */
f = (float)(M_PI / num_fb);
cepobj->cs = (cepdata *) CALLOC(num_fb * num_fb, sizeof(cepdata), "cfront.cosine_matrix");
for (i = 0; i < num_fb; ++i)
{
for (j = 0; j < num_fb; ++j) /* TODO: fixedpt cosine matrix */
cepobj->cs[i*(num_fb)+j] = (cepdata) fixed_point_convert(
(float)(cos((double)(i * (j + .5) * f)) / num_fb),
COSINE_TABLE_SHIFT); /* balanced after icostrans */
}
create_lookup_log(&cepobj->logtab, 12); /* TODO: rename 12 as macro */
reset_cep_object(cepobj);
return;
}
static void reset_cep_object(front_cep *cepobj)
{
ASSERT(cepobj);
return;
}
static void clear_cep_object(front_cep *cepobj)
{
ASSERT(cepobj);
if (cepobj->melA_scale)
FREE((char*)cepobj->melA_scale);
cepobj->melA_scale = NULL; /* Set to null in either case, for simplicity */
if (cepobj->dmelA_scale)
FREE((char*)cepobj->dmelA_scale);
cepobj->dmelA_scale = NULL;
if (cepobj->ddmelA_scale)
FREE((char*)cepobj->ddmelA_scale);
cepobj->ddmelA_scale = NULL;
if (cepobj->melB_scale)
FREE((char*)cepobj->melB_scale);
cepobj->melB_scale = NULL;
if (cepobj->dmelB_scale)
FREE((char*)cepobj->dmelB_scale);
cepobj->dmelB_scale = NULL;
if (cepobj->ddmelB_scale)
FREE((char*)cepobj->ddmelB_scale);
cepobj->ddmelB_scale = NULL;
if (cepobj->rastaA_scale)
FREE((char*)cepobj->rastaA_scale);
cepobj->rastaA_scale = NULL;
if (cepobj->rastaB_scale)
FREE((char*)cepobj->rastaB_scale);
cepobj->rastaB_scale = NULL;
if (cepobj->cs)
FREE((char *) cepobj->cs);
cepobj->cs = NULL;
if (cepobj->mel_offset)
FREE((char*)cepobj->mel_offset);
cepobj->mel_offset = NULL;
if (cepobj->mel_loop)
FREE((char*)cepobj->mel_loop);
cepobj->mel_loop = NULL;
destroy_lookup_log(&cepobj->logtab);
return;
}