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 */
|
double frame_last_phase; /* master's bit phase of last frame sync */
|
||||||
|
|
||||||
/* audio offset removal */
|
/* audio offset removal */
|
||||||
double offset_factor; /* filer alpha of high-pass filter */
|
double offset_last; /* last sample value of last frame */
|
||||||
double offset_y_last; /* last stored sample */
|
int offset_range; /* range of samples to ramp the offset */
|
||||||
|
|
||||||
/* measurements */
|
/* measurements */
|
||||||
int measure_speed; /* measure clock speed */
|
int measure_speed; /* measure clock speed */
|
||||||
|
|
|
@ -46,7 +46,6 @@
|
||||||
#define MAX_DISPLAY 1.4 /* something above speech level, no emphasis */
|
#define MAX_DISPLAY 1.4 /* something above speech level, no emphasis */
|
||||||
#define BITRATE 5280.0 /* bits per second */
|
#define BITRATE 5280.0 /* bits per second */
|
||||||
#define BLOCK_BITS 198 /* duration of one time slot including pause at beginning and end */
|
#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
|
#ifdef TEST_SCRAMBLE
|
||||||
jitter_t scrambler_test_jb;
|
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;
|
int rc = 0;
|
||||||
double size;
|
double size;
|
||||||
double RC, dt;
|
|
||||||
|
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init FSK for 'Sender'.\n");
|
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 */
|
/* 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);
|
rc = fsk_fm_init(&cnetz->fsk_demod, cnetz, cnetz->sender.samplerate, (double)BITRATE / (1.0 + clock_speed[0] / 1000000.0), demod);
|
||||||
if (rc < 0)
|
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 */
|
* shall not exceed according to ITU G.162 */
|
||||||
init_compandor(&cnetz->cstate, 8000, 5.0, 22.5);
|
init_compandor(&cnetz->cstate, 8000, 5.0, 22.5);
|
||||||
|
|
||||||
/* use this filter to compensate level changes between two subsequent audio chunks */
|
/* use duration of one bit to ramp level of last frame to current frame */
|
||||||
RC = 1.0 / (CUT_OFF_OFFSET * 2.0 *3.14);
|
cnetz->offset_range = ceil(cnetz->fsk_bitduration);
|
||||||
dt = 1.0 / cnetz->sender.samplerate;
|
|
||||||
cnetz->offset_factor = RC / (RC + dt);
|
|
||||||
|
|
||||||
#ifdef TEST_SCRAMBLE
|
#ifdef TEST_SCRAMBLE
|
||||||
rc = jitter_create(&scrambler_test_jb, cnetz->sender.samplerate / 5);
|
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;
|
sample_t *spl;
|
||||||
int pos, i;
|
int pos, i;
|
||||||
double x, y, x_last, y_last, factor;
|
int range;
|
||||||
|
double offset;
|
||||||
|
|
||||||
/* check if we still have a transaction
|
/* check if we still have a transaction
|
||||||
* this might not be true, if we just released transaction, but still
|
* 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)
|
if (!cnetz->trans_list)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* fix offset between speech blocks by using high pass filter */
|
/* ramp from level of last frame to level of current frame */
|
||||||
/* use first sample as previous sample, so we don't have a level jump between two subsequent audio chunks */
|
range = cnetz->offset_range;
|
||||||
x_last = speech_buffer[0];
|
offset = speech_buffer[0] - cnetz->offset_last;
|
||||||
y_last = cnetz->offset_y_last;
|
for (i = 0; i < range; i++) {
|
||||||
factor = cnetz->offset_factor;
|
speech_buffer[i] -= offset * (1.0 - (double)i / (double)range);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
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 */
|
/* 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 */
|
/* 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
|
* if debug is set to 1, debugging will start at program start
|
||||||
*/
|
*/
|
||||||
//#define DEBUG_DECODER
|
//#define DEBUG_DECODER
|
||||||
//static int debug = 0;
|
|
||||||
|
#ifdef DEBUG_DECODER
|
||||||
|
static int debug = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.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
|
#ifdef DEBUG_DECODER
|
||||||
char debug_filename[256];
|
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");
|
fsk->debug_fp = fopen(debug_filename, "w");
|
||||||
if (!fsk->debug_fp) {
|
if (!fsk->debug_fp) {
|
||||||
fprintf(stderr, "Failed to open decoder debug file '%s'!\n", debug_filename);
|
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;
|
sample_t threshold;
|
||||||
int i;
|
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 level range (level_min and level_max) and also
|
||||||
* get maximum slope (change_max) and where it was
|
* get maximum slope (change_max) and where it was
|
||||||
* (change_at) and what direction it went (change_positive)
|
* (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;
|
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 */
|
/* 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 */
|
/* 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];
|
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 */
|
/* just sample first bit in distributed mode */
|
||||||
if (fsk->cnetz->dsp_mode == DSP_MODE_SPK_V && fsk->bit_count == 0) {
|
if (fsk->cnetz->dsp_mode == DSP_MODE_SPK_V && fsk->bit_count == 0) {
|
||||||
if (fmod(fsk->bit_time, BITS_PER_SPK_BLOCK) < 1.5)
|
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;
|
fsk->next_bit -= fsk->bits_per_sample;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
#ifdef DEBUG_DECODER
|
|
||||||
if (debug)
|
|
||||||
fprintf(fsk->debug_fp, "\n");
|
|
||||||
#endif
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -580,7 +558,7 @@ done:
|
||||||
void fsk_fm_demod(fsk_fm_demod_t *fsk, sample_t *samples, int length)
|
void fsk_fm_demod(fsk_fm_demod_t *fsk, sample_t *samples, int length)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
double t;
|
double t = 0.0;
|
||||||
|
|
||||||
/* process signaling block, sample by sample */
|
/* process signaling block, sample by sample */
|
||||||
for (i = 0; i < length; i++) {
|
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)
|
if (fsk->bit_buffer_pos == fsk->bit_buffer_len)
|
||||||
fsk->bit_buffer_pos = 0;
|
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 */
|
/* for each sample process buffer */
|
||||||
if (fsk->cnetz->dsp_mode != DSP_MODE_SPK_V) {
|
if (fsk->cnetz->dsp_mode != DSP_MODE_SPK_V) {
|
||||||
if (fsk->demod_type == FSK_DEMOD_SLOPE)
|
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;
|
fsk->next_bit = 1.0 - fsk->bits_per_sample;
|
||||||
#ifdef DEBUG_DECODER
|
#ifdef DEBUG_DECODER
|
||||||
if (debug && fsk->bit_count)
|
if (debug && fsk->bit_count)
|
||||||
fprintf(fsk->debug_fp, "---- SPK(V) BLOCK START ----\n");
|
fprintf(fsk->debug_fp, "\n---- SPK(V) BLOCK START ----");
|
||||||
#endif
|
#endif
|
||||||
fsk->bit_count = 0;
|
fsk->bit_count = 0;
|
||||||
} else
|
} else
|
||||||
|
@ -622,13 +608,21 @@ void fsk_fm_demod(fsk_fm_demod_t *fsk, sample_t *samples, int length)
|
||||||
find_change_level(fsk);
|
find_change_level(fsk);
|
||||||
} else
|
} else
|
||||||
if (t >= 5.5 && t < 65.5) {
|
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 */
|
/* get audio for the duration of 60 bits */
|
||||||
/* prevent overflow, if speech_size != 0 and SPK_V
|
/* prevent overflow, if speech_size != 0 and SPK_V
|
||||||
* has been restarted. */
|
* has been restarted. */
|
||||||
if (fsk->speech_count < fsk->speech_size)
|
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
|
} else
|
||||||
if (t >= 65.5) {
|
if (t >= 65.5) {
|
||||||
|
#ifdef DEBUG_DECODER
|
||||||
|
if (debug && fsk->speech_count)
|
||||||
|
fprintf(fsk->debug_fp, " (stop recording speech)");
|
||||||
|
#endif
|
||||||
if (fsk->speech_count) {
|
if (fsk->speech_count) {
|
||||||
unshrink_speech(fsk->cnetz, fsk->speech_buffer, fsk->speech_count);
|
unshrink_speech(fsk->cnetz, fsk->speech_buffer, fsk->speech_count);
|
||||||
fsk->speech_count = 0;
|
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) {
|
if (fsk->bit_time >= BITS_PER_SUPERFRAME) {
|
||||||
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 */
|
/* another clock is used to measure actual super frame time */
|
||||||
fsk->bit_time_uncorrected += fsk->bits_per_sample;
|
fsk->bit_time_uncorrected += fsk->bits_per_sample;
|
||||||
if (fsk->bit_time_uncorrected >= BITS_PER_SUPERFRAME) {
|
if (fsk->bit_time_uncorrected >= BITS_PER_SUPERFRAME) {
|
||||||
|
|
Loading…
Reference in New Issue