Add global DC-Filter and remove all individual DC-Filters

This commit is contained in:
Andreas Eversberg 2017-01-28 18:18:44 +01:00
parent 71e556e7ff
commit bd7ccc5fa0
9 changed files with 32 additions and 58 deletions

View File

@ -450,7 +450,7 @@ int amps_create(int channel, enum amps_chan_type chan_type, const char *audiodev
} }
/* init audio processing */ /* init audio processing */
rc = dsp_init_sender(amps, (de_emphasis == 0), tolerant); rc = dsp_init_sender(amps, tolerant);
if (rc < 0) { if (rc < 0) {
PDEBUG(DAMPS, DEBUG_ERROR, "Failed to init audio processing!\n"); PDEBUG(DAMPS, DEBUG_ERROR, "Failed to init audio processing!\n");
goto error; goto error;

View File

@ -178,12 +178,11 @@ static void dsp_init_ramp(amps_t *amps)
static void sat_reset(amps_t *amps, const char *reason); static void sat_reset(amps_t *amps, const char *reason);
/* Init FSK of transceiver */ /* Init FSK of transceiver */
int dsp_init_sender(amps_t *amps, int high_pass, int tolerant) int dsp_init_sender(amps_t *amps, int tolerant)
{ {
sample_t *spl; sample_t *spl;
int i; int i;
int rc; int rc;
double RC, dt;
int half; int half;
/* attack (3ms) and recovery time (13.5ms) according to amps specs */ /* attack (3ms) and recovery time (13.5ms) according to amps specs */
@ -256,14 +255,6 @@ int dsp_init_sender(amps_t *amps, int high_pass, int tolerant)
amps->test_phaseshift256 = 256.0 / ((double)amps->sender.samplerate / 1000.0); amps->test_phaseshift256 = 256.0 / ((double)amps->sender.samplerate / 1000.0);
PDEBUG(DDSP, DEBUG_DEBUG, "test_phaseshift256 = %.4f\n", amps->test_phaseshift256); PDEBUG(DDSP, DEBUG_DEBUG, "test_phaseshift256 = %.4f\n", amps->test_phaseshift256);
/* use this filter to remove dc level for 0-crossing detection
* if we have de-emphasis, we don't need it, so high_pass is not set. */
if (high_pass) {
RC = 1.0 / (CUT_OFF_HIGHPASS * 2.0 *3.14);
dt = 1.0 / amps->sender.samplerate;
amps->highpass_factor = RC / (RC + dt);
}
/* be more tolerant when syncing */ /* be more tolerant when syncing */
amps->fsk_rx_sync_tolerant = tolerant; amps->fsk_rx_sync_tolerant = tolerant;
@ -808,8 +799,7 @@ static void sender_receive_audio(amps_t *amps, sample_t *samples, int length)
int max, pos; int max, pos;
int i; int i;
/* SAT detection */ /* SAT / signalling tone detection */
max = amps->sat_samples; max = amps->sat_samples;
spl = amps->sat_filter_spl; spl = amps->sat_filter_spl;
pos = amps->sat_filter_pos; pos = amps->sat_filter_pos;
@ -853,25 +843,10 @@ static void sender_receive_audio(amps_t *amps, sample_t *samples, int length)
void sender_receive(sender_t *sender, sample_t *samples, int length) void sender_receive(sender_t *sender, sample_t *samples, int length)
{ {
amps_t *amps = (amps_t *) sender; amps_t *amps = (amps_t *) sender;
double x, y, x_last, y_last, factor;
int i;
/* high pass filter to remove 0-level /* dc filter required for FSK decoding and tone detection */
* if factor is not set, we should already have 0-level. */ if (amps->de_emphasis)
factor = amps->highpass_factor; dc_filter(&amps->estate, samples, length);
if (factor) {
x_last = amps->highpass_x_last;
y_last = amps->highpass_y_last;
for (i = 0; i < length; i++) {
x = (double)samples[i];
y = factor * (y_last + x - x_last);
x_last = x;
y_last = y;
samples[i] = y;
}
amps->highpass_x_last = x_last;
amps->highpass_y_last = y_last;
}
switch (amps->dsp_mode) { switch (amps->dsp_mode) {
case DSP_MODE_OFF: case DSP_MODE_OFF:

View File

@ -1,6 +1,6 @@
void dsp_init(void); void dsp_init(void);
int dsp_init_sender(amps_t *amps, int high_pass, int tolerant); int dsp_init_sender(amps_t *amps, int tolerant);
void dsp_cleanup_sender(amps_t *amps); void dsp_cleanup_sender(amps_t *amps);
void amps_set_dsp_mode(amps_t *amps, enum dsp_mode mode, int frame_length); void amps_set_dsp_mode(amps_t *amps, enum dsp_mode mode, int frame_length);

View File

@ -812,6 +812,8 @@ void unshrink_speech(cnetz_t *cnetz, sample_t *speech_buffer, int count)
/* 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 */
if (cnetz->de_emphasis)
dc_filter(&cnetz->estate, speech_buffer, count);
if (cnetz->de_emphasis && !cnetz->scrambler) if (cnetz->de_emphasis && !cnetz->scrambler)
de_emphasis(&cnetz->estate, speech_buffer, count); de_emphasis(&cnetz->estate, speech_buffer, count);
/* 3. descramble */ /* 3. descramble */

View File

@ -27,7 +27,7 @@
#define PI M_PI #define PI M_PI
#define CUT_OFF_H 300.0 /* cut-off frequency for high-pass filters */ #define CUT_OFF_H 100.0 /* cut-off frequency for high-pass filter */
static void gen_sine(double *samples, int num, int samplerate, double freq) static void gen_sine(double *samples, int num, int samplerate, double freq)
{ {
@ -106,8 +106,6 @@ void de_emphasis(emphasis_t *state, double *samples, int num)
double x, y, y_last, factor, amp; double x, y, y_last, factor, amp;
int i; int i;
filter_process(&state->d.hp, samples, num);
y_last = state->d.y_last; y_last = state->d.y_last;
factor = state->d.factor; factor = state->d.factor;
amp = state->d.amp; amp = state->d.amp;
@ -126,3 +124,9 @@ void de_emphasis(emphasis_t *state, double *samples, int num)
state->d.y_last = y_last; state->d.y_last = y_last;
} }
/* high pass filter to remove DC and low frequencies */
void dc_filter(emphasis_t *state, double *samples, int num)
{
filter_process(&state->d.hp, samples, num);
}

View File

@ -17,4 +17,5 @@ typedef struct emphasis {
int init_emphasis(emphasis_t *state, int samplerate, double cut_off); int init_emphasis(emphasis_t *state, int samplerate, double cut_off);
void pre_emphasis(emphasis_t *state, double *samples, int num); void pre_emphasis(emphasis_t *state, double *samples, int num);
void de_emphasis(emphasis_t *state, double *samples, int num); void de_emphasis(emphasis_t *state, double *samples, int num);
void dc_filter(emphasis_t *state, double *samples, int num);

View File

@ -30,30 +30,26 @@
* audio level calculation * audio level calculation
*/ */
/* return average value (rectified value), that can be 0..1 */ /* Return average value (rectified value)
* The input must not have any dc offset!
* For a perfect rectangualr wave, the result would equal the peak level.
* For a sine wave the result would be factor (2 / PI) below peak level.
*/
double audio_level(sample_t *samples, int length) double audio_level(sample_t *samples, int length)
{ {
double bias; double level, sk;
double level;
int sk;
int n; int n;
/* calculate bias */
bias = 0;
for (n = 0; n < length; n++)
bias += samples[n];
bias = bias / length;
/* level calculation */ /* level calculation */
level = 0; level = 0;
for (n = 0; n < length; n++) { for (n = 0; n < length; n++) {
sk = samples[n] - bias; sk = samples[n];
if (sk < 0) if (sk < 0)
level -= (double)sk; level -= (double)sk;
if (sk > 0) if (sk > 0)
level += (double)sk; level += (double)sk;
} }
level = level / (double)length / 32767.0; level = level / (double)length;
return level; return level;
} }
@ -79,17 +75,10 @@ void audio_goertzel_init(goertzel_t *goertzel, double freq, int samplerate)
*/ */
void audio_goertzel(goertzel_t *goertzel, sample_t *samples, int length, int offset, double *result, int k) void audio_goertzel(goertzel_t *goertzel, sample_t *samples, int length, int offset, double *result, int k)
{ {
double bias;
double sk, sk1, sk2; double sk, sk1, sk2;
double cos2pik; double cos2pik;
int i, n; int i, n;
/* calculate bias to remove DC */
bias = 0;
for (n = 0; n < length; n++)
bias += samples[n];
bias = bias / length;
/* we do goertzel */ /* we do goertzel */
for (i = 0; i < k; i++) { for (i = 0; i < k; i++) {
sk = 0; sk = 0;
@ -98,7 +87,7 @@ void audio_goertzel(goertzel_t *goertzel, sample_t *samples, int length, int off
cos2pik = goertzel[i].coeff; cos2pik = goertzel[i].coeff;
/* note: after 'length' cycles, offset is restored to its initial value */ /* note: after 'length' cycles, offset is restored to its initial value */
for (n = 0; n < length; n++) { for (n = 0; n < length; n++) {
sk = (cos2pik * sk1) - sk2 + samples[offset++] - bias; sk = (cos2pik * sk1) - sk2 + samples[offset++];
sk2 = sk1; sk2 = sk1;
sk1 = sk; sk1 = sk;
if (offset == length) if (offset == length)

View File

@ -281,7 +281,7 @@ cant_recover:
display_wave(inst, samples[i], count); display_wave(inst, samples[i], count);
sender_receive(inst, samples[i], count); sender_receive(inst, samples[i], count);
} }
/* do pre emphasis towards radio, not wave_write */ /* do pre emphasis towards radio */
if (inst->pre_emphasis) if (inst->pre_emphasis)
pre_emphasis(&inst->estate, samples[i], count); pre_emphasis(&inst->estate, samples[i], count);
/* set paging signal */ /* set paging signal */
@ -331,9 +331,11 @@ transmit_later:
/* rx gain */ /* rx gain */
if (inst->rx_gain != 1.0) if (inst->rx_gain != 1.0)
gain_samples(samples[i], count, inst->rx_gain); gain_samples(samples[i], count, inst->rx_gain);
/* do de emphasis from radio (then write_wave/wave_read), receive audio, process echo test */ /* do filter and de-emphasis from radio receive audio, process echo test */
if (inst->de_emphasis) if (inst->de_emphasis) {
dc_filter(&inst->estate, samples[i], count);
de_emphasis(&inst->estate, samples[i], count); de_emphasis(&inst->estate, samples[i], count);
}
if (inst->loopback != 1) { if (inst->loopback != 1) {
display_wave(inst, samples[i], count); display_wave(inst, samples[i], count);
sender_receive(inst, samples[i], count); sender_receive(inst, samples[i], count);

View File

@ -64,6 +64,7 @@ int main(void)
for (i = 31.25; i < 4001; i = i * sqrt(sqrt(2.0))) { for (i = 31.25; i < 4001; i = i * sqrt(sqrt(2.0))) {
gen_samples(samples, (double)i); gen_samples(samples, (double)i);
dc_filter(&estate, samples, SAMPLERATE);
de_emphasis(&estate, samples, SAMPLERATE); de_emphasis(&estate, samples, SAMPLERATE);
level = get_level(samples); level = get_level(samples);
printf("%s%.0f Hz: %.1f dB", debug_db(level), i, level2db(level)); printf("%s%.0f Hz: %.1f dB", debug_db(level), i, level2db(level));