diff options
Diffstat (limited to 'src/bnetz/dsp.c')
-rw-r--r-- | src/bnetz/dsp.c | 100 |
1 files changed, 67 insertions, 33 deletions
diff --git a/src/bnetz/dsp.c b/src/bnetz/dsp.c index c360771..9e0e3fe 100644 --- a/src/bnetz/dsp.c +++ b/src/bnetz/dsp.c @@ -26,7 +26,7 @@ #include <errno.h> #include <math.h> #include "../libsample/sample.h" -#include "../libdebug/debug.h" +#include "../liblogging/logging.h" #include "../libmobile/call.h" #include "bnetz.h" #include "dsp.h" @@ -55,6 +55,7 @@ #define METERING_HZ 2900 /* metering pulse frequency */ #define TONE_DETECT_CNT 7 /* 70 milliseconds to detect continuous tone */ #define TONE_LOST_CNT 14 /* we use twice of the detect time, so we bridge a loss of "TONE_DETECT_CNT duration" */ +#define TONE_LEVEL_TH 0.20 /* threshold of low level to reject tone */ #define TONE_STDDEV_TH 0.2 /* threshold of bad quality (standard deviation) to reject tone */ /* carrier loss detection */ @@ -69,7 +70,7 @@ void dsp_init(void) { int i; - PDEBUG(DDSP, DEBUG_DEBUG, "Generating sine table for metering tone.\n"); + LOGP(DDSP, LOGL_DEBUG, "Generating sine table for metering tone.\n"); for (i = 0; i < 65536; i++) dsp_metering[i] = sin((double)i / 65536.0 * 2.0 * PI) * TX_PEAK_METER; } @@ -80,10 +81,10 @@ static void fsk_receive_bit(void *inst, int bit, double quality, double level); /* Init transceiver instance. */ int dsp_init_sender(bnetz_t *bnetz, double squelch_db) { - PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init DSP for 'Sender'.\n"); + LOGP_CHAN(DDSP, LOGL_DEBUG, "Init DSP for 'Sender'.\n"); if (TONE_DETECT_CNT > sizeof(bnetz->rx_tone_quality) / sizeof(bnetz->rx_tone_quality[0])) { - PDEBUG_CHAN(DDSP, DEBUG_ERROR, "buffer for tone quality is too small, please fix!\n"); + LOGP_CHAN(DDSP, LOGL_ERROR, "buffer for tone quality is too small, please fix!\n"); return -EINVAL; } @@ -93,15 +94,15 @@ int dsp_init_sender(bnetz_t *bnetz, double squelch_db) /* set modulation parameters */ sender_set_fm(&bnetz->sender, MAX_DEVIATION, MAX_MODULATION, SPEECH_DEVIATION, MAX_DISPLAY); - PDEBUG(DDSP, DEBUG_DEBUG, "Using FSK level of %.3f (%.3f KHz deviation @ 2000 Hz)\n", TX_PEAK_FSK, 4.0); + LOGP(DDSP, LOGL_DEBUG, "Using FSK level of %.3f (%.3f KHz deviation @ 2000 Hz)\n", TX_PEAK_FSK, 4.0); /* init fsk */ if (fsk_mod_init(&bnetz->fsk_mod, bnetz, fsk_send_bit, bnetz->sender.samplerate, BIT_RATE, F0, F1, TX_PEAK_FSK, 0, 0) < 0) { - PDEBUG_CHAN(DDSP, DEBUG_ERROR, "FSK init failed!\n"); + LOGP_CHAN(DDSP, LOGL_ERROR, "FSK init failed!\n"); return -EINVAL; } if (fsk_demod_init(&bnetz->fsk_demod, bnetz, fsk_receive_bit, bnetz->sender.samplerate, BIT_RATE, F0, F1, BIT_ADJUST) < 0) { - PDEBUG_CHAN(DDSP, DEBUG_ERROR, "FSK init failed!\n"); + LOGP_CHAN(DDSP, LOGL_ERROR, "FSK init failed!\n"); return -EINVAL; } @@ -123,7 +124,7 @@ int dsp_init_sender(bnetz_t *bnetz, double squelch_db) /* Cleanup transceiver instance. */ void dsp_cleanup_sender(bnetz_t *bnetz) { - PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Cleanup DSP for 'Sender'.\n"); + LOGP_CHAN(DDSP, LOGL_DEBUG, "Cleanup DSP for 'Sender'.\n"); fsk_mod_cleanup(&bnetz->fsk_mod); fsk_demod_cleanup(&bnetz->fsk_demod); @@ -147,7 +148,7 @@ static void fsk_receive_tone(bnetz_t *bnetz, int tone, int goodtone, double leve /* set duration to TONE_DETECT_CNT, because it took that long to detect the tone */ bnetz->tone_duration = TONE_DETECT_CNT; bnetz->tone_detected = tone; - PDEBUG_CHAN(DDSP, DEBUG_INFO, "Detecting continuous tone: F%d Level=%3.0f%% standard deviation=%.0f%% Quality=%3.0f%%\n", bnetz->tone_detected, level_avg * 100.0, level_stddev / level_avg * 100.0, quality_avg * 100.0); + LOGP_CHAN(DDSP, LOGL_INFO, "Detecting continuous tone: F%d Level=%3.0f%% (threshold %3.0f%%) standard deviation=%.0f%% (threshold=%.0f%%) Quality=%3.0f%%\n", bnetz->tone_detected, level_avg * 100.0, TONE_LEVEL_TH * 100.0, level_stddev / level_avg * 100.0, TONE_STDDEV_TH * 100.0, quality_avg * 100.0); bnetz_receive_tone(bnetz, bnetz->tone_detected); } } @@ -157,7 +158,7 @@ static void fsk_receive_tone(bnetz_t *bnetz, int tone, int goodtone, double leve bnetz->tone_count++; if (bnetz->tone_count == TONE_LOST_CNT) { /* subtract TONE_LOST_CNT from duration, because it took that long to detect loss of tone */ - PDEBUG_CHAN(DDSP, DEBUG_INFO, "Lost F%d tone after %.2f seconds.\n", bnetz->tone_detected, (double)(bnetz->tone_duration - TONE_LOST_CNT) / 100.0); + LOGP_CHAN(DDSP, LOGL_INFO, "Lost F%d tone after %.2f seconds.\n", bnetz->tone_detected, (double)(bnetz->tone_duration - TONE_LOST_CNT) / 100.0); bnetz->tone_detected = -1; bnetz_receive_tone(bnetz, -1); } @@ -169,7 +170,7 @@ static void fsk_receive_bit(void *inst, int bit, double quality, double level) { double level_avg, level_stddev, quality_avg; bnetz_t *bnetz = (bnetz_t *)inst; - int i; + int i, j; /* normalize FSK level */ level /= TX_PEAK_FSK; @@ -200,18 +201,19 @@ static void fsk_receive_bit(void *inst, int bit, double quality, double level) /* collect bits, and check for level and continuous tone */ bnetz->rx_tone = (bnetz->rx_tone << 1) | bit; - for (i = 0; i < TONE_DETECT_CNT; i++) { + for (i = 0, j = 0; i < TONE_DETECT_CNT; i++) { if (((bnetz->rx_tone >> i) & 1) != bit) - break; - if (bnetz->rx_tone_level[i] < 0.05) - break; + continue; + if (bnetz->rx_tone_level[i] < TONE_LEVEL_TH) + continue; + j++; } /* continuous tone detection: * 1. The quality must be good enough. * 2. All bits must be the same (continuous tone). */ - if (level_stddev / level_avg > TONE_STDDEV_TH || i < TONE_DETECT_CNT) + if (level_stddev / level_avg > TONE_STDDEV_TH || j < TONE_DETECT_CNT) fsk_receive_tone(bnetz, bit, 0, level_avg, level_stddev, quality_avg); else fsk_receive_tone(bnetz, bit, 1, level_avg, level_stddev, quality_avg); @@ -243,16 +245,15 @@ static void fsk_receive_bit(void *inst, int bit, double quality, double level) return; /* collect bits, and check for level */ - for (i = 0; i < 16; i++) { - if (bnetz->rx_telegramm_level[i] < 0.05) - break; + for (i = 0, j = 0; i < 16; i++) { + if (bnetz->rx_telegramm_level[i] >= TONE_LEVEL_TH) + j++; } - if (i == 16) - PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "FSK Valid bits: %d / %d Level: %.0f%% Stddev: %.0f%%\n", i, 16, level_avg * 100.0, level_stddev / level_avg * 100.0); + LOGP_CHAN(DDSP, LOGL_DEBUG, "FSK Valid bits: %d/%d Level: %.0f%% (threshold %.0f%%) Stddev: %.0f%% (threshold %.0f%%)\n", j, 16, level_avg * 100.0, TONE_LEVEL_TH * 100.0, level_stddev / level_avg * 100.0, TONE_STDDEV_TH * 100.0); /* drop any telegramm that is too bad */ - if (level_stddev / level_avg > TONE_STDDEV_TH || i < 16) + if (level_stddev / level_avg > TONE_STDDEV_TH || j < 16) return; /* update telegramm measurements */ @@ -260,7 +261,7 @@ static void fsk_receive_bit(void *inst, int bit, double quality, double level) display_measurements_update(bnetz->dmp_frame_stddev, level_stddev / level_avg * 100.0, 0.0); display_measurements_update(bnetz->dmp_frame_quality, quality_avg * 100.0, 0.0); - PDEBUG_CHAN(DDSP, DEBUG_INFO, "Telegramm RX Level: average=%.0f%% standard deviation=%.0f%% Quality: %.0f%%\n", level_avg * 100.0, level_stddev / level_avg * 100.0, quality_avg * 100.0); + LOGP_CHAN(DDSP, LOGL_INFO, "Telegramm RX Level: average=%.0f%% (threshold %.0f%%) standard deviation=%.0f%% (threshold %.0f%%) Quality: %.0f%%\n", level_avg * 100.0, TONE_LEVEL_TH * 100.0, level_stddev / level_avg * 100.0, TONE_STDDEV_TH * 100.0, quality_avg * 100.0); /* receive telegramm */ bnetz_receive_telegramm(bnetz, bnetz->rx_telegramm); @@ -274,10 +275,7 @@ void sender_receive(sender_t *sender, sample_t *samples, int length, double rf_l int pos; int i; - /* fsk/tone signal */ - fsk_demod_receive(&bnetz->fsk_demod, samples, length); - - /* process signal mute/loss, without signalling tone / FSK frames */ + /* process signal mute/loss, including removal of signalling tones / FSK frames */ switch (squelch(&bnetz->squelch, rf_level_db, (double)length / (double)bnetz->sender.samplerate)) { case SQUELCH_LOSS: bnetz_loss_indication(bnetz, LOSS_TIME); @@ -289,6 +287,9 @@ void sender_receive(sender_t *sender, sample_t *samples, int length, double rf_l break; } + /* fsk/tone signal */ + fsk_demod_receive(&bnetz->fsk_demod, samples, length); + if ((bnetz->dsp_mode == DSP_MODE_AUDIO || bnetz->dsp_mode == DSP_MODE_AUDIO_METER) && bnetz->callref) { int count; @@ -319,7 +320,7 @@ static int fsk_send_bit(void *inst) /* request frame */ bnetz->tx_telegramm = bnetz_get_telegramm(bnetz); if (!bnetz->tx_telegramm) { - PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Stop sending 'Telegramm'.\n"); + LOGP_CHAN(DDSP, LOGL_DEBUG, "Stop sending 'Telegramm'.\n"); return -1; } bnetz->tx_telegramm_pos = 0; @@ -360,7 +361,7 @@ static void metering_tone(bnetz_t *bnetz, sample_t *samples, int length) void sender_send(sender_t *sender, sample_t *samples, uint8_t *power, int length) { bnetz_t *bnetz = (bnetz_t *) sender; - int count; + int count, input_num; memset(power, 1, length); @@ -371,7 +372,13 @@ again: break; case DSP_MODE_AUDIO: case DSP_MODE_AUDIO_METER: - jitter_load(&bnetz->sender.dejitter, samples, length); + input_num = samplerate_upsample_input_num(&sender->srstate, length); + { + int16_t spl[input_num]; + jitter_load_samples(&sender->dejitter, (uint8_t *)spl, input_num, sizeof(*spl), jitter_conceal_s16, NULL); + int16_to_samples_speech(samples, spl, input_num); + } + samplerate_upsample(&sender->srstate, samples, input_num, samples, length); if (bnetz->dsp_mode == DSP_MODE_AUDIO_METER) metering_tone(bnetz, samples, length); break; @@ -389,7 +396,7 @@ again: } } -const char *bnetz_dsp_mode_name(enum dsp_mode mode) +static const char *bnetz_dsp_mode_name(enum dsp_mode mode) { static char invalid[16]; @@ -417,10 +424,37 @@ void bnetz_set_dsp_mode(bnetz_t *bnetz, enum dsp_mode mode) /* reset telegramm */ if (mode == DSP_MODE_TELEGRAMM && bnetz->dsp_mode != mode) { bnetz->tx_telegramm = 0; - fsk_mod_tx_reset(&bnetz->fsk_mod); + fsk_mod_reset(&bnetz->fsk_mod); } + if ((mode == DSP_MODE_AUDIO || mode == DSP_MODE_AUDIO_METER) && (bnetz->dsp_mode != DSP_MODE_AUDIO && bnetz->dsp_mode != DSP_MODE_AUDIO_METER)) + jitter_reset(&bnetz->sender.dejitter); - PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "DSP mode %s -> %s\n", bnetz_dsp_mode_name(bnetz->dsp_mode), bnetz_dsp_mode_name(mode)); + LOGP_CHAN(DDSP, LOGL_DEBUG, "DSP mode %s -> %s\n", bnetz_dsp_mode_name(bnetz->dsp_mode), bnetz_dsp_mode_name(mode)); bnetz->dsp_mode = mode; } +/* Receive audio from call instance. */ +void call_down_audio(void *decoder, void *decoder_priv, int callref, uint16_t sequence, uint8_t marker, uint32_t timestamp, uint32_t ssrc, uint8_t *payload, int payload_len) +{ + sender_t *sender; + bnetz_t *bnetz; + + for (sender = sender_head; sender; sender = sender->next) { + bnetz = (bnetz_t *) sender; + if (bnetz->callref == callref) + break; + } + if (!sender) + return; + + if (bnetz->dsp_mode == DSP_MODE_AUDIO + || bnetz->dsp_mode == DSP_MODE_AUDIO_METER) { + jitter_frame_t *jf; + jf = jitter_frame_alloc(decoder, decoder_priv, payload, payload_len, marker, sequence, timestamp, ssrc); + if (jf) + jitter_save(&bnetz->sender.dejitter, jf); + } +} + +void call_down_clock(void) {} + |