aboutsummaryrefslogtreecommitdiffstats
path: root/src/bnetz/dsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bnetz/dsp.c')
-rw-r--r--src/bnetz/dsp.c100
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) {}
+