C-Netz: Improved RX speech quality and decoder debugging
This commit is contained in:
parent
059d4f25b1
commit
89e3b89758
|
@ -127,8 +127,8 @@ struct cnetz {
|
|||
double frame_last_phase; /* master's bit phase of last frame sync */
|
||||
|
||||
/* audio offset removal */
|
||||
double offset_factor; /* filer alpha of high-pass filter */
|
||||
double offset_y_last; /* last stored sample */
|
||||
double offset_last; /* last sample value of last frame */
|
||||
int offset_range; /* range of samples to ramp the offset */
|
||||
|
||||
/* measurements */
|
||||
int measure_speed; /* measure clock speed */
|
||||
|
|
|
@ -46,7 +46,6 @@
|
|||
#define MAX_DISPLAY 1.4 /* something above speech level, no emphasis */
|
||||
#define BITRATE 5280.0 /* bits per second */
|
||||
#define BLOCK_BITS 198 /* duration of one time slot including pause at beginning and end */
|
||||
#define CUT_OFF_OFFSET 300.0 /* cut off frequency for offset filter (level correction between subsequent audio chunks) */
|
||||
|
||||
#ifdef TEST_SCRAMBLE
|
||||
jitter_t scrambler_test_jb;
|
||||
|
@ -103,7 +102,6 @@ int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], en
|
|||
{
|
||||
int rc = 0;
|
||||
double size;
|
||||
double RC, dt;
|
||||
|
||||
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init FSK for 'Sender'.\n");
|
||||
|
||||
|
@ -150,7 +148,7 @@ int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], en
|
|||
}
|
||||
|
||||
/* reinit the sample rate to shrink/expand audio */
|
||||
init_samplerate(&cnetz->sender.srstate, 8000.0, (double)cnetz->sender.samplerate / 1.1, 3300.0); /* 66 <-> 60 */
|
||||
init_samplerate(&cnetz->sender.srstate, 8000.0, (double)cnetz->sender.samplerate / (1.1 / (1.0 + clock_speed[0] / 1000000.0)), 3300.0); /* 66 <-> 60 */
|
||||
|
||||
rc = fsk_fm_init(&cnetz->fsk_demod, cnetz, cnetz->sender.samplerate, (double)BITRATE / (1.0 + clock_speed[0] / 1000000.0), demod);
|
||||
if (rc < 0)
|
||||
|
@ -170,10 +168,8 @@ int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], en
|
|||
* shall not exceed according to ITU G.162 */
|
||||
init_compandor(&cnetz->cstate, 8000, 5.0, 22.5);
|
||||
|
||||
/* use this filter to compensate level changes between two subsequent audio chunks */
|
||||
RC = 1.0 / (CUT_OFF_OFFSET * 2.0 *3.14);
|
||||
dt = 1.0 / cnetz->sender.samplerate;
|
||||
cnetz->offset_factor = RC / (RC + dt);
|
||||
/* use duration of one bit to ramp level of last frame to current frame */
|
||||
cnetz->offset_range = ceil(cnetz->fsk_bitduration);
|
||||
|
||||
#ifdef TEST_SCRAMBLE
|
||||
rc = jitter_create(&scrambler_test_jb, cnetz->sender.samplerate / 5);
|
||||
|
@ -821,7 +817,8 @@ void unshrink_speech(cnetz_t *cnetz, sample_t *speech_buffer, int count)
|
|||
{
|
||||
sample_t *spl;
|
||||
int pos, i;
|
||||
double x, y, x_last, y_last, factor;
|
||||
int range;
|
||||
double offset;
|
||||
|
||||
/* check if we still have a transaction
|
||||
* this might not be true, if we just released transaction, but still
|
||||
|
@ -830,21 +827,13 @@ void unshrink_speech(cnetz_t *cnetz, sample_t *speech_buffer, int count)
|
|||
if (!cnetz->trans_list)
|
||||
return;
|
||||
|
||||
/* fix offset between speech blocks by using high pass filter */
|
||||
/* use first sample as previous sample, so we don't have a level jump between two subsequent audio chunks */
|
||||
x_last = speech_buffer[0];
|
||||
y_last = cnetz->offset_y_last;
|
||||
factor = cnetz->offset_factor;
|
||||
for (i = 0; i < count; i++) {
|
||||
/* change level */
|
||||
x = speech_buffer[i];
|
||||
/* high-pass to remove low level frequencies, caused by level jump between audio chunks */
|
||||
y = factor * (y_last + x - x_last);
|
||||
x_last = x;
|
||||
y_last = y;
|
||||
speech_buffer[i] = y;
|
||||
/* ramp from level of last frame to level of current frame */
|
||||
range = cnetz->offset_range;
|
||||
offset = speech_buffer[0] - cnetz->offset_last;
|
||||
for (i = 0; i < range; i++) {
|
||||
speech_buffer[i] -= offset * (1.0 - (double)i / (double)range);
|
||||
}
|
||||
cnetz->offset_y_last = y_last;
|
||||
cnetz->offset_last = speech_buffer[count - 1];
|
||||
|
||||
/* 4. de-emphasis is done by cnetz code, not by common code */
|
||||
/* de-emphasis is only used when scrambler is off, see FTZ 171 TR 60 Clause 4 */
|
||||
|
|
|
@ -121,7 +121,10 @@
|
|||
* if debug is set to 1, debugging will start at program start
|
||||
*/
|
||||
//#define DEBUG_DECODER
|
||||
//static int debug = 0;
|
||||
|
||||
#ifdef DEBUG_DECODER
|
||||
static int debug = 0;
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
@ -182,7 +185,7 @@ int fsk_fm_init(fsk_fm_demod_t *fsk, cnetz_t *cnetz, int samplerate, double bitr
|
|||
|
||||
#ifdef DEBUG_DECODER
|
||||
char debug_filename[256];
|
||||
sprintf(debug_filename, "/tmp/debug_decoder_channel_%d.txt", cnetz->sender.kanal);
|
||||
sprintf(debug_filename, "/tmp/debug_decoder_channel_%s.txt", cnetz->sender.kanal);
|
||||
fsk->debug_fp = fopen(debug_filename, "w");
|
||||
if (!fsk->debug_fp) {
|
||||
fprintf(stderr, "Failed to open decoder debug file '%s'!\n", debug_filename);
|
||||
|
@ -414,17 +417,6 @@ static inline void find_change_slope(fsk_fm_demod_t *fsk)
|
|||
sample_t threshold;
|
||||
int i;
|
||||
|
||||
#ifdef DEBUG_DECODER
|
||||
/* show deviation of middle sample in windows (in a range of bandwidth) */
|
||||
if (debug) {
|
||||
fprintf(fsk->debug_fp, "%s",
|
||||
debug_amplitude(
|
||||
fsk->bit_buffer_spl[(fsk->bit_buffer_pos + fsk->bit_buffer_half) % fsk->bit_buffer_len]
|
||||
)
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* get level range (level_min and level_max) and also
|
||||
* get maximum slope (change_max) and where it was
|
||||
* (change_at) and what direction it went (change_positive)
|
||||
|
@ -492,10 +484,6 @@ static inline void find_change_slope(fsk_fm_demod_t *fsk)
|
|||
}
|
||||
fsk->next_bit -= fsk->bits_per_sample;
|
||||
|
||||
#ifdef DEBUG_DECODER
|
||||
if (debug)
|
||||
fprintf(fsk->debug_fp, "\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* find bit change by looking at zero crossing */
|
||||
|
@ -507,12 +495,6 @@ static inline void find_change_level(fsk_fm_demod_t *fsk)
|
|||
/* get bit in the middle of the buffer */
|
||||
s = fsk->bit_buffer_spl[(fsk->bit_buffer_pos + fsk->bit_buffer_half) % fsk->bit_buffer_len];
|
||||
|
||||
#ifdef DEBUG_DECODER
|
||||
/* show deviation */
|
||||
if (debug)
|
||||
fprintf(fsk->debug_fp, "%s", debug_amplitude(s));
|
||||
#endif
|
||||
|
||||
/* just sample first bit in distributed mode */
|
||||
if (fsk->cnetz->dsp_mode == DSP_MODE_SPK_V && fsk->bit_count == 0) {
|
||||
if (fmod(fsk->bit_time, BITS_PER_SPK_BLOCK) < 1.5)
|
||||
|
@ -569,10 +551,6 @@ static inline void find_change_level(fsk_fm_demod_t *fsk)
|
|||
fsk->next_bit -= fsk->bits_per_sample;
|
||||
|
||||
done:
|
||||
#ifdef DEBUG_DECODER
|
||||
if (debug)
|
||||
fprintf(fsk->debug_fp, "\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -580,7 +558,7 @@ done:
|
|||
void fsk_fm_demod(fsk_fm_demod_t *fsk, sample_t *samples, int length)
|
||||
{
|
||||
int i;
|
||||
double t;
|
||||
double t = 0.0;
|
||||
|
||||
/* process signaling block, sample by sample */
|
||||
for (i = 0; i < length; i++) {
|
||||
|
@ -590,6 +568,14 @@ void fsk_fm_demod(fsk_fm_demod_t *fsk, sample_t *samples, int length)
|
|||
if (fsk->bit_buffer_pos == fsk->bit_buffer_len)
|
||||
fsk->bit_buffer_pos = 0;
|
||||
|
||||
#ifdef DEBUG_DECODER
|
||||
/* show deviation of center sample in window */
|
||||
if (debug)
|
||||
fprintf(fsk->debug_fp, "%s", debug_amplitude(fsk->bit_buffer_spl[(fsk->bit_buffer_pos + fsk->bit_buffer_half) % fsk->bit_buffer_len]));
|
||||
if (debug && fmod(fsk->bit_time - fsk->bits_per_sample, 1.0) > fmod(fsk->bit_time, 1.0))
|
||||
fprintf(fsk->debug_fp, " -bitchange-");
|
||||
#endif
|
||||
|
||||
/* for each sample process buffer */
|
||||
if (fsk->cnetz->dsp_mode != DSP_MODE_SPK_V) {
|
||||
if (fsk->demod_type == FSK_DEMOD_SLOPE)
|
||||
|
@ -611,7 +597,7 @@ void fsk_fm_demod(fsk_fm_demod_t *fsk, sample_t *samples, int length)
|
|||
fsk->next_bit = 1.0 - fsk->bits_per_sample;
|
||||
#ifdef DEBUG_DECODER
|
||||
if (debug && fsk->bit_count)
|
||||
fprintf(fsk->debug_fp, "---- SPK(V) BLOCK START ----\n");
|
||||
fprintf(fsk->debug_fp, "\n---- SPK(V) BLOCK START ----");
|
||||
#endif
|
||||
fsk->bit_count = 0;
|
||||
} else
|
||||
|
@ -622,13 +608,21 @@ void fsk_fm_demod(fsk_fm_demod_t *fsk, sample_t *samples, int length)
|
|||
find_change_level(fsk);
|
||||
} else
|
||||
if (t >= 5.5 && t < 65.5) {
|
||||
#ifdef DEBUG_DECODER
|
||||
if (debug && !fsk->speech_count)
|
||||
fprintf(fsk->debug_fp, " (start recording speech)");
|
||||
#endif
|
||||
/* get audio for the duration of 60 bits */
|
||||
/* prevent overflow, if speech_size != 0 and SPK_V
|
||||
* has been restarted. */
|
||||
if (fsk->speech_count < fsk->speech_size)
|
||||
fsk->speech_buffer[fsk->speech_count++] = samples[i];
|
||||
fsk->speech_buffer[fsk->speech_count++] = fsk->bit_buffer_spl[(fsk->bit_buffer_pos + fsk->bit_buffer_half) % fsk->bit_buffer_len];
|
||||
} else
|
||||
if (t >= 65.5) {
|
||||
#ifdef DEBUG_DECODER
|
||||
if (debug && fsk->speech_count)
|
||||
fprintf(fsk->debug_fp, " (stop recording speech)");
|
||||
#endif
|
||||
if (fsk->speech_count) {
|
||||
unshrink_speech(fsk->cnetz, fsk->speech_buffer, fsk->speech_count);
|
||||
fsk->speech_count = 0;
|
||||
|
@ -641,6 +635,10 @@ void fsk_fm_demod(fsk_fm_demod_t *fsk, sample_t *samples, int length)
|
|||
if (fsk->bit_time >= BITS_PER_SUPERFRAME) {
|
||||
fsk->bit_time -= BITS_PER_SUPERFRAME;
|
||||
}
|
||||
#ifdef DEBUG_DECODER
|
||||
if (debug && samples)
|
||||
fprintf(fsk->debug_fp, "\n");
|
||||
#endif
|
||||
/* another clock is used to measure actual super frame time */
|
||||
fsk->bit_time_uncorrected += fsk->bits_per_sample;
|
||||
if (fsk->bit_time_uncorrected >= BITS_PER_SUPERFRAME) {
|
||||
|
|
Loading…
Reference in New Issue