Correcting all levels and move all remaining integer samples to sample_t
The leves are based on the standards of each mobile network. They are adjusted to the specified frequency deviation now.
This commit is contained in:
parent
bd7ccc5fa0
commit
7e45f556ce
|
@ -54,7 +54,7 @@ A caller must not know the location of the phone anymore to reach the right base
|
||||||
<li>Channel spacing: 10 KHz and optionally 12.5 KHz
|
<li>Channel spacing: 10 KHz and optionally 12.5 KHz
|
||||||
<li>Voice modulation: FM
|
<li>Voice modulation: FM
|
||||||
<li>Signaling modulation: carrier FSK
|
<li>Signaling modulation: carrier FSK
|
||||||
<li>Frequency deviation: 2.5 KHz (FSK); 2.4 KHz (Voice)
|
<li>Frequency deviation: 2.5 KHz (FSK); 4 KHz (Voice)
|
||||||
<li>Mobile station transmit power: 50 mW up to 15 Watts
|
<li>Mobile station transmit power: 50 mW up to 15 Watts
|
||||||
<li>Base station transmit power: 25 Watts
|
<li>Base station transmit power: 25 Watts
|
||||||
<li>Features: Speech Compandor, Audio scrambling
|
<li>Features: Speech Compandor, Audio scrambling
|
||||||
|
|
|
@ -135,14 +135,14 @@ typedef struct amps {
|
||||||
goertzel_t sat_goertzel[5]; /* filter for SAT signal decoding */
|
goertzel_t sat_goertzel[5]; /* filter for SAT signal decoding */
|
||||||
sample_t *sat_filter_spl; /* array with sample buffer for supervisory detection */
|
sample_t *sat_filter_spl; /* array with sample buffer for supervisory detection */
|
||||||
int sat_filter_pos; /* current sample position in filter_spl */
|
int sat_filter_pos; /* current sample position in filter_spl */
|
||||||
double sat_phaseshift256[3]; /* how much the phase of sine wave changes per sample */
|
double sat_phaseshift65536[3]; /* how much the phase of sine wave changes per sample */
|
||||||
double sat_phase256; /* current phase */
|
double sat_phase65536; /* current phase */
|
||||||
int sat_detected; /* current detection state flag */
|
int sat_detected; /* current detection state flag */
|
||||||
int sat_detect_count; /* current number of consecutive detections/losses */
|
int sat_detect_count; /* current number of consecutive detections/losses */
|
||||||
int sig_detected; /* current detection state flag */
|
int sig_detected; /* current detection state flag */
|
||||||
int sig_detect_count; /* current number of consecutive detections/losses */
|
int sig_detect_count; /* current number of consecutive detections/losses */
|
||||||
double test_phaseshift256; /* how much the phase of sine wave changes per sample */
|
double test_phaseshift65536; /* how much the phase of sine wave changes per sample */
|
||||||
double test_phase256; /* current phase */
|
double test_phase65536; /* current phase */
|
||||||
|
|
||||||
transaction_t *trans_list; /* list of transactions */
|
transaction_t *trans_list; /* list of transactions */
|
||||||
|
|
||||||
|
|
|
@ -99,10 +99,13 @@
|
||||||
|
|
||||||
#define PI M_PI
|
#define PI M_PI
|
||||||
|
|
||||||
#define BANDWIDTH 20000.0 /* maximum bandwidth */
|
#define MAX_DEVIATION 8000.0
|
||||||
#define FSK_DEVIATION 32767.0 /* +-8 KHz */
|
#define MAX_MODULATION 10000.0
|
||||||
#define SAT_DEVIATION 8192.0 /* +-2 KHz */
|
#define DBM0_DEVIATION 2900.0 /* deviation of dBm0 at 1 kHz */
|
||||||
#define COMPANDOR_0DB 45000 /* works quite well */
|
#define COMPANDOR_0DB 1.0 /* A level of 0dBm (1.0) shall be unaccected */
|
||||||
|
#define FSK_DEVIATION (8000.0 / DBM0_DEVIATION) /* no emphasis */
|
||||||
|
#define SAT_DEVIATION (2000.0 / DBM0_DEVIATION) /* no emphasis */
|
||||||
|
#define MAX_DISPLAY (8000.0 / DBM0_DEVIATION) /* no emphasis */
|
||||||
#define BITRATE 10000
|
#define BITRATE 10000
|
||||||
#define SIG_TONE_CROSSINGS 2000 /* 2000 crossings are 100ms @ 10 KHz */
|
#define SIG_TONE_CROSSINGS 2000 /* 2000 crossings are 100ms @ 10 KHz */
|
||||||
#define SIG_TONE_MINBITS 950 /* minimum bit durations to detect signaling tone (1000 is perfect for 100 ms) */
|
#define SIG_TONE_MINBITS 950 /* minimum bit durations to detect signaling tone (1000 is perfect for 100 ms) */
|
||||||
|
@ -116,7 +119,7 @@
|
||||||
#define CUT_OFF_HIGHPASS 300.0 /* cut off frequency for high pass filter to remove dc level from sound card / sample */
|
#define CUT_OFF_HIGHPASS 300.0 /* cut off frequency for high pass filter to remove dc level from sound card / sample */
|
||||||
#define BEST_QUALITY 0.68 /* Best possible RX quality */
|
#define BEST_QUALITY 0.68 /* Best possible RX quality */
|
||||||
|
|
||||||
static int16_t ramp_up[256], ramp_down[256];
|
static sample_t ramp_up[256], ramp_down[256];
|
||||||
|
|
||||||
static double sat_freq[5] = {
|
static double sat_freq[5] = {
|
||||||
5970.0,
|
5970.0,
|
||||||
|
@ -126,8 +129,8 @@ static double sat_freq[5] = {
|
||||||
10000.0, /* signaling tone */
|
10000.0, /* signaling tone */
|
||||||
};
|
};
|
||||||
|
|
||||||
static int dsp_sine_sat[256];
|
static sample_t dsp_sine_sat[65536];
|
||||||
static int dsp_sine_test[256];
|
static sample_t dsp_sine_test[65536];
|
||||||
|
|
||||||
static uint8_t dsp_sync_check[0x800];
|
static uint8_t dsp_sync_check[0x800];
|
||||||
|
|
||||||
|
@ -138,10 +141,10 @@ void dsp_init(void)
|
||||||
double s;
|
double s;
|
||||||
|
|
||||||
PDEBUG(DDSP, DEBUG_DEBUG, "Generating sine table for SAT signal.\n");
|
PDEBUG(DDSP, DEBUG_DEBUG, "Generating sine table for SAT signal.\n");
|
||||||
for (i = 0; i < 256; i++) {
|
for (i = 0; i < 65536; i++) {
|
||||||
s = sin((double)i / 256.0 * 2.0 * PI);
|
s = sin((double)i / 65536.0 * 2.0 * PI);
|
||||||
dsp_sine_sat[i] = (int)(s * SAT_DEVIATION);
|
dsp_sine_sat[i] = s * SAT_DEVIATION;
|
||||||
dsp_sine_test[i] = (int)(s * FSK_DEVIATION);
|
dsp_sine_test[i] = s * FSK_DEVIATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sync checker */
|
/* sync checker */
|
||||||
|
@ -170,7 +173,7 @@ static void dsp_init_ramp(amps_t *amps)
|
||||||
else
|
else
|
||||||
c = sqrt(c);
|
c = sqrt(c);
|
||||||
#endif
|
#endif
|
||||||
ramp_down[i] = (int)(c * (double)amps->fsk_deviation);
|
ramp_down[i] = c * (double)amps->fsk_deviation;
|
||||||
ramp_up[i] = -ramp_down[i];
|
ramp_up[i] = -ramp_down[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -190,9 +193,8 @@ int dsp_init_sender(amps_t *amps, int tolerant)
|
||||||
|
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init DSP for transceiver.\n");
|
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init DSP for transceiver.\n");
|
||||||
|
|
||||||
/* set deviation and modulation parameters */
|
/* set modulation parameters */
|
||||||
amps->sender.bandwidth = BANDWIDTH;
|
sender_set_fm(&s->sender, MAX_DEVIATION, MAX_MODULATION, DBM0_DEVIATION, MAX_DISPLAY);
|
||||||
amps->sender.sample_deviation = 8000.0 / (double)FSK_DEVIATION;
|
|
||||||
|
|
||||||
if (amps->sender.samplerate < 96000) {
|
if (amps->sender.samplerate < 96000) {
|
||||||
PDEBUG(DDSP, DEBUG_ERROR, "Sample rate must be at least 96000 Hz to process FSK and SAT signals.\n");
|
PDEBUG(DDSP, DEBUG_ERROR, "Sample rate must be at least 96000 Hz to process FSK and SAT signals.\n");
|
||||||
|
@ -229,7 +231,7 @@ int dsp_init_sender(amps_t *amps, int tolerant)
|
||||||
amps->fsk_rx_window = spl;
|
amps->fsk_rx_window = spl;
|
||||||
|
|
||||||
/* create devation and ramp */
|
/* create devation and ramp */
|
||||||
amps->fsk_deviation = FSK_DEVIATION; /* be sure not to overflow 32767 */
|
amps->fsk_deviation = FSK_DEVIATION;
|
||||||
dsp_init_ramp(amps);
|
dsp_init_ramp(amps);
|
||||||
|
|
||||||
/* allocate ring buffer for SAT signal detection */
|
/* allocate ring buffer for SAT signal detection */
|
||||||
|
@ -245,15 +247,15 @@ int dsp_init_sender(amps_t *amps, int tolerant)
|
||||||
for (i = 0; i < 5; i++) {
|
for (i = 0; i < 5; i++) {
|
||||||
audio_goertzel_init(&s->sat_goertzel[i], sat_freq[i], amps->sender.samplerate);
|
audio_goertzel_init(&s->sat_goertzel[i], sat_freq[i], amps->sender.samplerate);
|
||||||
if (i < 3) {
|
if (i < 3) {
|
||||||
amps->sat_phaseshift256[i] = 256.0 / ((double)amps->sender.samplerate / sat_freq[i]);
|
amps->sat_phaseshift65536[i] = 65536.0 / ((double)amps->sender.samplerate / sat_freq[i]);
|
||||||
PDEBUG(DDSP, DEBUG_DEBUG, "sat_phaseshift256[%d] = %.4f\n", i, amps->sat_phaseshift256[i]);
|
PDEBUG(DDSP, DEBUG_DEBUG, "sat_phaseshift65536[%d] = %.4f\n", i, amps->sat_phaseshift65536[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sat_reset(amps, "Initial state");
|
sat_reset(amps, "Initial state");
|
||||||
|
|
||||||
/* test tone */
|
/* test tone */
|
||||||
amps->test_phaseshift256 = 256.0 / ((double)amps->sender.samplerate / 1000.0);
|
amps->test_phaseshift65536 = 65536.0 / ((double)amps->sender.samplerate / 1000.0);
|
||||||
PDEBUG(DDSP, DEBUG_DEBUG, "test_phaseshift256 = %.4f\n", amps->test_phaseshift256);
|
PDEBUG(DDSP, DEBUG_DEBUG, "test_phaseshift65536 = %.4f\n", amps->test_phaseshift65536);
|
||||||
|
|
||||||
/* be more tolerant when syncing */
|
/* be more tolerant when syncing */
|
||||||
amps->fsk_rx_sync_tolerant = tolerant;
|
amps->fsk_rx_sync_tolerant = tolerant;
|
||||||
|
@ -401,7 +403,7 @@ again:
|
||||||
//printf("pos=%d length=%d copy=%d\n", pos, length, copy);
|
//printf("pos=%d length=%d copy=%d\n", pos, length, copy);
|
||||||
for (i = 0; i < copy; i++) {
|
for (i = 0; i < copy; i++) {
|
||||||
#ifdef DEBUG_ENCODER
|
#ifdef DEBUG_ENCODER
|
||||||
puts(debug_amplitude((double)spl[pos] / 32767.0));
|
puts(debug_amplitude((double)spl[pos]));
|
||||||
#endif
|
#endif
|
||||||
*samples++ = spl[pos++];
|
*samples++ = spl[pos++];
|
||||||
}
|
}
|
||||||
|
@ -422,26 +424,19 @@ done:
|
||||||
static void sat_encode(amps_t *amps, sample_t *samples, int length)
|
static void sat_encode(amps_t *amps, sample_t *samples, int length)
|
||||||
{
|
{
|
||||||
double phaseshift, phase;
|
double phaseshift, phase;
|
||||||
int32_t sample;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
phaseshift = amps->sat_phaseshift256[amps->sat];
|
phaseshift = amps->sat_phaseshift65536[amps->sat];
|
||||||
phase = amps->sat_phase256;
|
phase = amps->sat_phase65536;
|
||||||
|
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
sample = *samples;
|
*samples++ += dsp_sine_sat[(uint16_t)phase];
|
||||||
sample += dsp_sine_sat[(uint8_t)phase];
|
|
||||||
if (sample > 32767)
|
|
||||||
sample = 32767;
|
|
||||||
else if (sample < -32767)
|
|
||||||
sample = -32767;
|
|
||||||
*samples++ = sample;
|
|
||||||
phase += phaseshift;
|
phase += phaseshift;
|
||||||
if (phase >= 256)
|
if (phase >= 65536)
|
||||||
phase -= 256;
|
phase -= 65536;
|
||||||
}
|
}
|
||||||
|
|
||||||
amps->sat_phase256 = phase;
|
amps->sat_phase65536 = phase;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_tone_encode(amps_t *amps, sample_t *samples, int length)
|
static void test_tone_encode(amps_t *amps, sample_t *samples, int length)
|
||||||
|
@ -449,17 +444,17 @@ static void test_tone_encode(amps_t *amps, sample_t *samples, int length)
|
||||||
double phaseshift, phase;
|
double phaseshift, phase;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
phaseshift = amps->test_phaseshift256;
|
phaseshift = amps->test_phaseshift65536;
|
||||||
phase = amps->test_phase256;
|
phase = amps->test_phase65536;
|
||||||
|
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
*samples++ = dsp_sine_test[(uint8_t)phase];
|
*samples++ = dsp_sine_test[(uint16_t)phase];
|
||||||
phase += phaseshift;
|
phase += phaseshift;
|
||||||
if (phase >= 256)
|
if (phase >= 65536)
|
||||||
phase -= 256;
|
phase -= 65536;
|
||||||
}
|
}
|
||||||
|
|
||||||
amps->test_phase256 = phase;
|
amps->test_phase65536 = phase;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Provide stream of audio toward radio unit */
|
/* Provide stream of audio toward radio unit */
|
||||||
|
@ -735,9 +730,9 @@ static void sat_decode(amps_t *amps, sample_t *samples, int length)
|
||||||
if (quality[1] < 0)
|
if (quality[1] < 0)
|
||||||
quality[1] = 0;
|
quality[1] = 0;
|
||||||
|
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_NOTICE, "SAT level %.2f%% quality %.0f%%\n", result[0] * 32767.0 / SAT_DEVIATION / 0.63662 * 100.0, quality[0] * 100.0);
|
PDEBUG_CHAN(DDSP, DEBUG_NOTICE, "SAT level %.2f%% quality %.0f%%\n", result[0] / SAT_DEVIATION / 0.63662 * 100.0, quality[0] * 100.0);
|
||||||
if (amps->sender.loopback || debuglevel == DEBUG_DEBUG) {
|
if (amps->sender.loopback || debuglevel == DEBUG_DEBUG) {
|
||||||
PDEBUG_CHAN(DDSP, debuglevel, "Signaling Tone level %.2f%% quality %.0f%%\n", result[2] * 32767.0 / FSK_DEVIATION / 0.63662 * 100.0, quality[1] * 100.0);
|
PDEBUG_CHAN(DDSP, debuglevel, "Signaling Tone level %.2f%% quality %.0f%%\n", result[2] / FSK_DEVIATION / 0.63662 * 100.0, quality[1] * 100.0);
|
||||||
}
|
}
|
||||||
if (quality[0] > SAT_QUALITY) {
|
if (quality[0] > SAT_QUALITY) {
|
||||||
if (amps->sat_detected == 0) {
|
if (amps->sat_detected == 0) {
|
||||||
|
|
|
@ -33,12 +33,12 @@ typedef struct anetz {
|
||||||
int fsk_filter_pos; /* current sample position in filter_spl */
|
int fsk_filter_pos; /* current sample position in filter_spl */
|
||||||
int tone_detected; /* what tone has been detected */
|
int tone_detected; /* what tone has been detected */
|
||||||
int tone_count; /* how long has that tone been detected */
|
int tone_count; /* how long has that tone been detected */
|
||||||
double tone_phaseshift256; /* how much the phase of sine wave changes per sample */
|
double tone_phaseshift65536; /* how much the phase of sine wave changes per sample */
|
||||||
double tone_phase256; /* current phase */
|
double tone_phase65536; /* current phase */
|
||||||
double page_gain; /* factor to raise the paging tones */
|
double page_gain; /* factor to raise the paging tones */
|
||||||
int page_sequence; /* if set, use paging tones in sequence rather than parallel */
|
int page_sequence; /* if set, use paging tones in sequence rather than parallel */
|
||||||
double paging_phaseshift256[4];/* how much the phase of sine wave changes per sample */
|
double paging_phaseshift65536[4];/* how much the phase of sine wave changes per sample */
|
||||||
double paging_phase256[4]; /* current phase */
|
double paging_phase65536[4]; /* current phase */
|
||||||
int paging_tone; /* current tone (0..3) in sequenced mode */
|
int paging_tone; /* current tone (0..3) in sequenced mode */
|
||||||
int paging_count; /* current sample count of tone in seq. mode */
|
int paging_count; /* current sample count of tone in seq. mode */
|
||||||
int paging_transition; /* set to number of samples during transition */
|
int paging_transition; /* set to number of samples during transition */
|
||||||
|
|
118
src/anetz/dsp.c
118
src/anetz/dsp.c
|
@ -35,8 +35,12 @@
|
||||||
#define PI 3.1415927
|
#define PI 3.1415927
|
||||||
|
|
||||||
/* signaling */
|
/* signaling */
|
||||||
#define BANDWIDTH 15000.0 /* maximum bandwidth */
|
#define MAX_DEVIATION 15000.0
|
||||||
#define TX_PEAK_TONE 8192.0 /* peak amplitude for all tones */
|
#define MAX_MODULATION 4000.0
|
||||||
|
#define DBM0_DEVIATION 10500.0 /* deviation of dBm0 at 1 kHz */
|
||||||
|
#define TX_PEAK_TONE (10500.0 / DBM0_DEVIATION) /* 10.5 kHz, no emphasis */
|
||||||
|
#define TX_PEAK_PAGE (15000.0 / DBM0_DEVIATION) /* 15 kHz, no emphasis */
|
||||||
|
#define MAX_DISPLAY (15000.0 / DBM0_DEVIATION) /* 15 kHz, no emphasis */
|
||||||
#define CHUNK_DURATION 0.010 /* 10 ms */
|
#define CHUNK_DURATION 0.010 /* 10 ms */
|
||||||
|
|
||||||
// FIXME: how long until we detect a tone?
|
// FIXME: how long until we detect a tone?
|
||||||
|
@ -53,7 +57,8 @@ static double fsk_tones[2] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* table for fast sine generation */
|
/* table for fast sine generation */
|
||||||
sample_t dsp_sine_tone[256];
|
static sample_t dsp_sine_tone[65536];
|
||||||
|
static sample_t dsp_sine_page[65536];
|
||||||
|
|
||||||
/* global init for audio processing */
|
/* global init for audio processing */
|
||||||
void dsp_init(void)
|
void dsp_init(void)
|
||||||
|
@ -62,14 +67,10 @@ void dsp_init(void)
|
||||||
double s;
|
double s;
|
||||||
|
|
||||||
PDEBUG(DDSP, DEBUG_DEBUG, "Generating sine tables.\n");
|
PDEBUG(DDSP, DEBUG_DEBUG, "Generating sine tables.\n");
|
||||||
for (i = 0; i < 256; i++) {
|
for (i = 0; i < 65536; i++) {
|
||||||
s = sin((double)i / 256.0 * 2.0 * PI);
|
s = sin((double)i / 65536.0 * 2.0 * PI);
|
||||||
dsp_sine_tone[i] = (int)(s * TX_PEAK_TONE);
|
dsp_sine_tone[i] = s * TX_PEAK_TONE;
|
||||||
}
|
dsp_sine_page[i] = s * TX_PEAK_PAGE;
|
||||||
|
|
||||||
if (TX_PEAK_TONE > 32767.0) {
|
|
||||||
fprintf(stderr, "TX_PEAK_TONE definition too high, please fix!\n");
|
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,15 +83,10 @@ int dsp_init_sender(anetz_t *anetz, double page_gain, int page_sequence)
|
||||||
|
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init DSP for 'Sender'.\n");
|
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init DSP for 'Sender'.\n");
|
||||||
|
|
||||||
/* set deviation and modulation parameters */
|
/* set modulation parameters */
|
||||||
anetz->sender.bandwidth = BANDWIDTH;
|
sender_set_fm(&anetz->sender, MAX_DEVIATION * page_gain, MAX_MODULATION, DBM0_DEVIATION, MAX_DISPLAY);
|
||||||
anetz->sender.sample_deviation = 11000.0 / (double)TX_PEAK_TONE;
|
|
||||||
|
|
||||||
anetz->page_gain = page_gain;
|
anetz->page_gain = page_gain;
|
||||||
if (page_gain * TX_PEAK_TONE > 32767.0) {
|
|
||||||
page_gain = 32767.0 / TX_PEAK_TONE;
|
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_NOTICE, "Highest possible gain of paging tones is %.1f dB.\n", log10(page_gain) * 20);
|
|
||||||
}
|
|
||||||
anetz->page_sequence = page_sequence;
|
anetz->page_sequence = page_sequence;
|
||||||
|
|
||||||
audio_init_loss(&anetz->sender.loss, LOSS_INTERVAL, anetz->sender.loss_volume, LOSS_TIME);
|
audio_init_loss(&anetz->sender.loss, LOSS_INTERVAL, anetz->sender.loss_volume, LOSS_TIME);
|
||||||
|
@ -109,8 +105,8 @@ int dsp_init_sender(anetz_t *anetz, double page_gain, int page_sequence)
|
||||||
for (i = 0; i < 2; i++)
|
for (i = 0; i < 2; i++)
|
||||||
audio_goertzel_init(&anetz->fsk_tone_goertzel[i], fsk_tones[i], anetz->sender.samplerate);
|
audio_goertzel_init(&anetz->fsk_tone_goertzel[i], fsk_tones[i], anetz->sender.samplerate);
|
||||||
tone = fsk_tones[(anetz->sender.loopback == 0) ? 0 : 1];
|
tone = fsk_tones[(anetz->sender.loopback == 0) ? 0 : 1];
|
||||||
anetz->tone_phaseshift256 = 256.0 / ((double)anetz->sender.samplerate / tone);
|
anetz->tone_phaseshift65536 = 65536.0 / ((double)anetz->sender.samplerate / tone);
|
||||||
PDEBUG(DDSP, DEBUG_DEBUG, "TX %.0f Hz phaseshift = %.4f\n", tone, anetz->tone_phaseshift256);
|
PDEBUG(DDSP, DEBUG_DEBUG, "TX %.0f Hz phaseshift = %.4f\n", tone, anetz->tone_phaseshift65536);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -169,19 +165,19 @@ static void fsk_decode_chunk(anetz_t *anetz, sample_t *spl, int max)
|
||||||
/* show quality of tone */
|
/* show quality of tone */
|
||||||
if (anetz->sender.loopback) {
|
if (anetz->sender.loopback) {
|
||||||
/* adjust level, so we get peak of sine curve */
|
/* adjust level, so we get peak of sine curve */
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_NOTICE, "Tone %.0f: Level=%3.0f%% Quality=%3.0f%%\n", fsk_tones[1], level / 0.63662 * 100.0 * 32768.0 / TX_PEAK_TONE, result[1] / level * 100.0);
|
PDEBUG_CHAN(DDSP, DEBUG_NOTICE, "Tone %.0f: Level=%3.0f%% Quality=%3.0f%%\n", fsk_tones[1], level / 0.63662 * 100.0 / TX_PEAK_TONE, result[1] / level * 100.0);
|
||||||
}
|
}
|
||||||
if (level / 0.63 > 0.05 && result[0] / level > 0.5)
|
if (level / 0.63 > 0.05 && result[0] / level > 0.5)
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_INFO, "Tone %.0f: Level=%3.0f%% Quality=%3.0f%%\n", fsk_tones[0], level / 0.63662 * 100.0 * 32768.0 / TX_PEAK_TONE, result[0] / level * 100.0);
|
PDEBUG_CHAN(DDSP, DEBUG_INFO, "Tone %.0f: Level=%3.0f%% Quality=%3.0f%%\n", fsk_tones[0], level / 0.63662 * 100.0 / TX_PEAK_TONE, result[0] / level * 100.0);
|
||||||
|
|
||||||
/* adjust level, so we get peak of sine curve */
|
/* adjust level, so we get peak of sine curve */
|
||||||
/* indicate detected tone */
|
/* indicate detected tone */
|
||||||
if (level / 0.63 > 0.05 && result[0] / level > 0.5)
|
if (level / 0.63 > 0.05 && result[0] / level > 0.5)
|
||||||
fsk_receive_tone(anetz, 0, 1, level / 0.63662 * 32768.0 / TX_PEAK_TONE);
|
fsk_receive_tone(anetz, 0, 1, level / 0.63662 / TX_PEAK_TONE);
|
||||||
else if (level / 0.63 > 0.05 && result[1] / level > 0.5)
|
else if (level / 0.63 > 0.05 && result[1] / level > 0.5)
|
||||||
fsk_receive_tone(anetz, 1, 1, level / 0.63662 * 32768.0 / TX_PEAK_TONE);
|
fsk_receive_tone(anetz, 1, 1, level / 0.63662 / TX_PEAK_TONE);
|
||||||
else
|
else
|
||||||
fsk_receive_tone(anetz, -1, 0, level / 0.63662 * 32768.0 / TX_PEAK_TONE);
|
fsk_receive_tone(anetz, -1, 0, level / 0.63662 / TX_PEAK_TONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process received audio stream from radio unit. */
|
/* Process received audio stream from radio unit. */
|
||||||
|
@ -230,42 +226,36 @@ void dsp_set_paging(anetz_t *anetz, double *freq)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++) {
|
||||||
anetz->paging_phaseshift256[i] = 256.0 / ((double)anetz->sender.samplerate / freq[i]);
|
anetz->paging_phaseshift65536[i] = 65536.0 / ((double)anetz->sender.samplerate / freq[i]);
|
||||||
anetz->paging_phase256[i] = 0;
|
anetz->paging_phase65536[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate audio stream of 4 simultanious paging tones. Keep phase for next call of function.
|
/* Generate audio stream of 4 simultanious paging tones. Keep phase for next call of function.
|
||||||
* Use TX_PEAK_TONE*page_gain for all tones, which gives peak of 1/4th for each individual tone. */
|
* Use TX_PEAK_PAGE*page_gain for all tones, which gives peak of 1/4th for each individual tone. */
|
||||||
static void fsk_paging_tone(anetz_t *anetz, sample_t *samples, int length)
|
static void fsk_paging_tone(anetz_t *anetz, sample_t *samples, int length)
|
||||||
{
|
{
|
||||||
double phaseshift[4], phase[4];
|
double *phaseshift, *phase;
|
||||||
int i;
|
int i;
|
||||||
double sample;
|
double sample;
|
||||||
|
|
||||||
for (i = 0; i < 4; i++) {
|
phaseshift = anetz->paging_phaseshift65536;
|
||||||
phaseshift[i] = anetz->paging_phaseshift256[i];
|
phase = anetz->paging_phase65536;
|
||||||
phase[i] = anetz->paging_phase256[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
sample = (int32_t)dsp_sine_tone[(uint8_t)phase[0]]
|
sample = dsp_sine_page[(uint16_t)phase[0]]
|
||||||
+ (int32_t)dsp_sine_tone[(uint8_t)phase[1]]
|
+ dsp_sine_page[(uint16_t)phase[1]]
|
||||||
+ (int32_t)dsp_sine_tone[(uint8_t)phase[2]]
|
+ dsp_sine_page[(uint16_t)phase[2]]
|
||||||
+ (int32_t)dsp_sine_tone[(uint8_t)phase[3]];
|
+ dsp_sine_page[(uint16_t)phase[3]];
|
||||||
*samples++ = sample / 4.0 * anetz->page_gain;
|
*samples++ = sample / 4.0 * anetz->page_gain;
|
||||||
phase[0] += phaseshift[0];
|
phase[0] += phaseshift[0];
|
||||||
phase[1] += phaseshift[1];
|
phase[1] += phaseshift[1];
|
||||||
phase[2] += phaseshift[2];
|
phase[2] += phaseshift[2];
|
||||||
phase[3] += phaseshift[3];
|
phase[3] += phaseshift[3];
|
||||||
if (phase[0] >= 256) phase[0] -= 256;
|
if (phase[0] >= 65536) phase[0] -= 65536;
|
||||||
if (phase[1] >= 256) phase[1] -= 256;
|
if (phase[1] >= 65536) phase[1] -= 65536;
|
||||||
if (phase[2] >= 256) phase[2] -= 256;
|
if (phase[2] >= 65536) phase[2] -= 65536;
|
||||||
if (phase[3] >= 256) phase[3] -= 256;
|
if (phase[3] >= 65536) phase[3] -= 65536;
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < 4; i++) {
|
|
||||||
anetz->paging_phase256[i] = phase[i];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,14 +270,11 @@ static void fsk_paging_tone(anetz_t *anetz, sample_t *samples, int length)
|
||||||
*/
|
*/
|
||||||
static void fsk_paging_tone_sequence(anetz_t *anetz, sample_t *samples, int length, int numspl)
|
static void fsk_paging_tone_sequence(anetz_t *anetz, sample_t *samples, int length, int numspl)
|
||||||
{
|
{
|
||||||
double phaseshift[4], phase[4];
|
double *phaseshift, *phase;
|
||||||
int i;
|
|
||||||
int tone, count, transition;
|
int tone, count, transition;
|
||||||
|
|
||||||
for (i = 0; i < 4; i++) {
|
phaseshift = anetz->paging_phaseshift65536;
|
||||||
phaseshift[i] = anetz->paging_phaseshift256[i];
|
phase = anetz->paging_phase65536;
|
||||||
phase[i] = anetz->paging_phase256[i];
|
|
||||||
}
|
|
||||||
tone = anetz->paging_tone;
|
tone = anetz->paging_tone;
|
||||||
count = anetz->paging_count;
|
count = anetz->paging_count;
|
||||||
transition = anetz->paging_transition;
|
transition = anetz->paging_transition;
|
||||||
|
@ -295,21 +282,21 @@ static void fsk_paging_tone_sequence(anetz_t *anetz, sample_t *samples, int leng
|
||||||
while (length) {
|
while (length) {
|
||||||
/* use tone, but during transition of tones, keep phase 0 degrees (high level) until next tone reaches 0 degrees (high level) */
|
/* use tone, but during transition of tones, keep phase 0 degrees (high level) until next tone reaches 0 degrees (high level) */
|
||||||
if (!transition)
|
if (!transition)
|
||||||
*samples++ = dsp_sine_tone[(uint8_t)phase[tone]] * anetz->page_gain;
|
*samples++ = dsp_sine_page[(uint16_t)phase[tone]] * anetz->page_gain;
|
||||||
else {
|
else {
|
||||||
/* fade between old an new tone */
|
/* fade between old an new tone */
|
||||||
*samples++
|
*samples++
|
||||||
= (double)dsp_sine_tone[(uint8_t)phase[(tone - 1) & 3]] * (double)(transition - count) / (double)transition / 2.0 * anetz->page_gain
|
= (double)dsp_sine_page[(uint16_t)phase[(tone - 1) & 3]] * (double)(transition - count) / (double)transition / 2.0 * anetz->page_gain
|
||||||
+ (double)dsp_sine_tone[(uint8_t)phase[tone]] * (double)count / (double)transition / 2.0 * anetz->page_gain;
|
+ (double)dsp_sine_page[(uint16_t)phase[tone]] * (double)count / (double)transition / 2.0 * anetz->page_gain;
|
||||||
}
|
}
|
||||||
phase[0] += phaseshift[0];
|
phase[0] += phaseshift[0];
|
||||||
phase[1] += phaseshift[1];
|
phase[1] += phaseshift[1];
|
||||||
phase[2] += phaseshift[2];
|
phase[2] += phaseshift[2];
|
||||||
phase[3] += phaseshift[3];
|
phase[3] += phaseshift[3];
|
||||||
if (phase[0] >= 256) phase[0] -= 256;
|
if (phase[0] >= 65536) phase[0] -= 65536;
|
||||||
if (phase[1] >= 256) phase[1] -= 256;
|
if (phase[1] >= 65536) phase[1] -= 65536;
|
||||||
if (phase[2] >= 256) phase[2] -= 256;
|
if (phase[2] >= 65536) phase[2] -= 65536;
|
||||||
if (phase[3] >= 256) phase[3] -= 256;
|
if (phase[3] >= 65536) phase[3] -= 65536;
|
||||||
count++;
|
count++;
|
||||||
if (transition && count == transition) {
|
if (transition && count == transition) {
|
||||||
transition = 0;
|
transition = 0;
|
||||||
|
@ -327,9 +314,6 @@ static void fsk_paging_tone_sequence(anetz_t *anetz, sample_t *samples, int leng
|
||||||
length--;
|
length--;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 4; i++) {
|
|
||||||
anetz->paging_phase256[i] = phase[i];
|
|
||||||
}
|
|
||||||
anetz->paging_tone = tone;
|
anetz->paging_tone = tone;
|
||||||
anetz->paging_count = count;
|
anetz->paging_count = count;
|
||||||
anetz->paging_transition = transition;
|
anetz->paging_transition = transition;
|
||||||
|
@ -341,17 +325,17 @@ static void fsk_tone(anetz_t *anetz, sample_t *samples, int length)
|
||||||
double phaseshift, phase;
|
double phaseshift, phase;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
phaseshift = anetz->tone_phaseshift256;
|
phaseshift = anetz->tone_phaseshift65536;
|
||||||
phase = anetz->tone_phase256;
|
phase = anetz->tone_phase65536;
|
||||||
|
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
*samples++ = dsp_sine_tone[(uint8_t)phase];
|
*samples++ = dsp_sine_tone[(uint16_t)phase];
|
||||||
phase += phaseshift;
|
phase += phaseshift;
|
||||||
if (phase >= 256)
|
if (phase >= 65536)
|
||||||
phase -= 256;
|
phase -= 65536;
|
||||||
}
|
}
|
||||||
|
|
||||||
anetz->tone_phase256 = phase;
|
anetz->tone_phase65536 = phase;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Provide stream of audio toward radio unit */
|
/* Provide stream of audio toward radio unit */
|
||||||
|
|
|
@ -88,8 +88,8 @@ typedef struct bnetz {
|
||||||
int fsk_filter_qualidx; /* index of quality array above */
|
int fsk_filter_qualidx; /* index of quality array above */
|
||||||
int tone_detected; /* what tone has been detected */
|
int tone_detected; /* what tone has been detected */
|
||||||
int tone_count; /* how long has that tone been detected */
|
int tone_count; /* how long has that tone been detected */
|
||||||
double phaseshift256[2]; /* how much the phase of sine wave changes per sample */
|
double phaseshift65536[2]; /* how much the phase of sine wave changes per sample */
|
||||||
double phase256; /* current phase */
|
double phase65536; /* current phase */
|
||||||
int telegramm; /* set, if there is a valid telegram */
|
int telegramm; /* set, if there is a valid telegram */
|
||||||
sample_t *telegramm_spl; /* 16 * samples_per_bit */
|
sample_t *telegramm_spl; /* 16 * samples_per_bit */
|
||||||
int telegramm_pos; /* current sample position in telegramm_spl */
|
int telegramm_pos; /* current sample position in telegramm_spl */
|
||||||
|
|
|
@ -34,9 +34,19 @@
|
||||||
|
|
||||||
#define PI 3.1415927
|
#define PI 3.1415927
|
||||||
|
|
||||||
|
/* Notes on TX_PEAK_TONE level:
|
||||||
|
*
|
||||||
|
* At 2000 Hz the deviation shall be 4 kHz, so with emphasis the deviation
|
||||||
|
* at 1000 Hz would be theoretically 2 kHz. This is factor 0.714 below
|
||||||
|
* 2.8 kHz deviation we want at dBm0.
|
||||||
|
*/
|
||||||
|
|
||||||
/* signaling */
|
/* signaling */
|
||||||
#define BANDWIDTH 5000.0 /* maximum bandwidth */
|
#define MAX_DEVIATION 4000.0
|
||||||
#define TX_PEAK_TONE 5000.0 /* peak amplitude for all tones */
|
#define MAX_MODULATION 3000.0
|
||||||
|
#define DBM0_DEVIATION 2800.0 /* deviation of dBm0 at 1 kHz */
|
||||||
|
#define TX_PEAK_TONE (4000.0 / 2000.0 * 1000.0 / DBM0_DEVIATION)
|
||||||
|
#define MAX_DISPLAY 1.4 /* something above dBm0 */
|
||||||
#define BIT_DURATION 0.010 /* bit length: 10 ms */
|
#define BIT_DURATION 0.010 /* bit length: 10 ms */
|
||||||
#define FILTER_STEP 0.001 /* step every 1 ms */
|
#define FILTER_STEP 0.001 /* step every 1 ms */
|
||||||
#define METERING_HZ 2900 /* metering pulse frequency */
|
#define METERING_HZ 2900 /* metering pulse frequency */
|
||||||
|
@ -54,7 +64,7 @@ static double fsk_bits[2] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* table for fast sine generation */
|
/* table for fast sine generation */
|
||||||
static sample_t dsp_sine[256];
|
static sample_t dsp_sine[65536];
|
||||||
|
|
||||||
/* global init for FSK */
|
/* global init for FSK */
|
||||||
void dsp_init(void)
|
void dsp_init(void)
|
||||||
|
@ -62,13 +72,8 @@ void dsp_init(void)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
PDEBUG(DDSP, DEBUG_DEBUG, "Generating sine table.\n");
|
PDEBUG(DDSP, DEBUG_DEBUG, "Generating sine table.\n");
|
||||||
for (i = 0; i < 256; i++) {
|
for (i = 0; i < 65536; i++) {
|
||||||
dsp_sine[i] = (int)(sin((double)i / 256.0 * 2.0 * PI) * TX_PEAK_TONE);
|
dsp_sine[i] = sin((double)i / 65536.0 * 2.0 * PI) * TX_PEAK_TONE;
|
||||||
}
|
|
||||||
|
|
||||||
if (TX_PEAK_TONE > 32767.0) {
|
|
||||||
fprintf(stderr, "TX_PEAK_TONE definition too high, please fix!\n");
|
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,9 +90,8 @@ int dsp_init_sender(bnetz_t *bnetz)
|
||||||
|
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init DSP for 'Sender'.\n");
|
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init DSP for 'Sender'.\n");
|
||||||
|
|
||||||
/* set deviation and modulation parameters */
|
/* set modulation parameters */
|
||||||
bnetz->sender.bandwidth = BANDWIDTH;
|
sender_set_fm(&bnetz->sender, MAX_DEVIATION, MAX_MODULATION, DBM0_DEVIATION, MAX_DISPLAY);
|
||||||
bnetz->sender.sample_deviation = 1250.0 / (double)TX_PEAK_TONE; // FIXME: calc real value
|
|
||||||
|
|
||||||
audio_init_loss(&bnetz->sender.loss, LOSS_INTERVAL, bnetz->sender.loss_volume, LOSS_TIME);
|
audio_init_loss(&bnetz->sender.loss, LOSS_INTERVAL, bnetz->sender.loss_volume, LOSS_TIME);
|
||||||
|
|
||||||
|
@ -114,8 +118,8 @@ int dsp_init_sender(bnetz_t *bnetz)
|
||||||
/* count symbols */
|
/* count symbols */
|
||||||
for (i = 0; i < 2; i++) {
|
for (i = 0; i < 2; i++) {
|
||||||
audio_goertzel_init(&bnetz->fsk_goertzel[i], fsk_bits[i], bnetz->sender.samplerate);
|
audio_goertzel_init(&bnetz->fsk_goertzel[i], fsk_bits[i], bnetz->sender.samplerate);
|
||||||
bnetz->phaseshift256[i] = 256.0 / ((double)bnetz->sender.samplerate / fsk_bits[i]);
|
bnetz->phaseshift65536[i] = 65536.0 / ((double)bnetz->sender.samplerate / fsk_bits[i]);
|
||||||
PDEBUG(DDSP, DEBUG_DEBUG, "phaseshift[%d] = %.4f (must be arround 64 at 8000hz)\n", i, bnetz->phaseshift256[i]);
|
PDEBUG(DDSP, DEBUG_DEBUG, "phaseshift[%d] = %.4f (must be arround 64 at 8000hz)\n", i, bnetz->phaseshift65536[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -241,9 +245,9 @@ static inline void fsk_decode_step(bnetz_t *bnetz, int pos)
|
||||||
// FIXME: better threshold
|
// FIXME: better threshold
|
||||||
/* adjust level, so we get peak of sine curve */
|
/* adjust level, so we get peak of sine curve */
|
||||||
if (level / 0.63 > 0.05 && (softbit > 0.75 || softbit < 0.25)) {
|
if (level / 0.63 > 0.05 && (softbit > 0.75 || softbit < 0.25)) {
|
||||||
fsk_receive_tone(bnetz, bit, 1, level / 0.63662 * 32768.0 / TX_PEAK_TONE, quality);
|
fsk_receive_tone(bnetz, bit, 1, level / 0.63662 / TX_PEAK_TONE, quality);
|
||||||
} else
|
} else
|
||||||
fsk_receive_tone(bnetz, bit, 0, level / 0.63662 * 32768.0 / TX_PEAK_TONE, quality);
|
fsk_receive_tone(bnetz, bit, 0, level / 0.63662 / TX_PEAK_TONE, quality);
|
||||||
|
|
||||||
if (bnetz->fsk_filter_bit != bit) {
|
if (bnetz->fsk_filter_bit != bit) {
|
||||||
/* if we have a bit change, reset sample counter to one half bit duration */
|
/* if we have a bit change, reset sample counter to one half bit duration */
|
||||||
|
@ -256,7 +260,7 @@ static inline void fsk_decode_step(bnetz_t *bnetz, int pos)
|
||||||
printf("|%s|\n", debug_amplitude(quality);
|
printf("|%s|\n", debug_amplitude(quality);
|
||||||
#endif
|
#endif
|
||||||
/* adjust level, so we get peak of sine curve */
|
/* adjust level, so we get peak of sine curve */
|
||||||
fsk_receive_bit(bnetz, bit, level / 0.63662 * 32768.0 / TX_PEAK_TONE, quality);
|
fsk_receive_bit(bnetz, bit, level / 0.63662 / TX_PEAK_TONE, quality);
|
||||||
bnetz->fsk_filter_sample = 10;
|
bnetz->fsk_filter_sample = 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -308,17 +312,17 @@ static void fsk_tone(bnetz_t *bnetz, sample_t *samples, int length, int tone)
|
||||||
double phaseshift, phase;
|
double phaseshift, phase;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
phase = bnetz->phase256;
|
phase = bnetz->phase65536;
|
||||||
phaseshift = bnetz->phaseshift256[tone];
|
phaseshift = bnetz->phaseshift65536[tone];
|
||||||
|
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
*samples++ = dsp_sine[(uint8_t)phase];
|
*samples++ = dsp_sine[(uint16_t)phase];
|
||||||
phase += phaseshift;
|
phase += phaseshift;
|
||||||
if (phase >= 256)
|
if (phase >= 65536)
|
||||||
phase -= 256;
|
phase -= 65536;
|
||||||
}
|
}
|
||||||
|
|
||||||
bnetz->phase256 = phase;
|
bnetz->phase65536 = phase;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fsk_telegramm(bnetz_t *bnetz, sample_t *samples, int length)
|
static int fsk_telegramm(bnetz_t *bnetz, sample_t *samples, int length)
|
||||||
|
@ -342,17 +346,17 @@ next_telegramm:
|
||||||
bnetz->telegramm_pos = 0;
|
bnetz->telegramm_pos = 0;
|
||||||
spl = bnetz->telegramm_spl;
|
spl = bnetz->telegramm_spl;
|
||||||
/* render telegramm */
|
/* render telegramm */
|
||||||
phase = bnetz->phase256;
|
phase = bnetz->phase65536;
|
||||||
for (i = 0; i < 16; i++) {
|
for (i = 0; i < 16; i++) {
|
||||||
phaseshift = bnetz->phaseshift256[telegramm[i] == '1'];
|
phaseshift = bnetz->phaseshift65536[telegramm[i] == '1'];
|
||||||
for (j = 0; j < bnetz->samples_per_bit; j++) {
|
for (j = 0; j < bnetz->samples_per_bit; j++) {
|
||||||
*spl++ = dsp_sine[(uint8_t)phase];
|
*spl++ = dsp_sine[(uint16_t)phase];
|
||||||
phase += phaseshift;
|
phase += phaseshift;
|
||||||
if (phase >= 256)
|
if (phase >= 65536)
|
||||||
phase -= 256;
|
phase -= 65536;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bnetz->phase256 = phase;
|
bnetz->phase65536 = phase;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send audio from telegramm */
|
/* send audio from telegramm */
|
||||||
|
|
|
@ -43,9 +43,12 @@ extern int voice_deviation;
|
||||||
|
|
||||||
#define PI M_PI
|
#define PI M_PI
|
||||||
|
|
||||||
#define BANDWIDTH 5500.0 /* maximum bandwidth */
|
#define MAX_DEVIATION 4000.0
|
||||||
#define FSK_DEVIATION 10000
|
#define MAX_MODULATION 5280.0
|
||||||
#define COMPANDOR_0DB 30000
|
#define DBM0_DEVIATION 4000.0 /* deviation of dBm0 at 1 kHz */
|
||||||
|
#define COMPANDOR_0DB 1.0 /* A level of 0dBm (1.0) shall be unaccected */
|
||||||
|
#define FSK_DEVIATION (2500.0 / DBM0_DEVIATION) /* no emphasis */
|
||||||
|
#define MAX_DISPLAY 1.4 /* something above dBm0, 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) */
|
#define CUT_OFF_OFFSET 300.0 /* cut off frequency for offset filter (level correction between subsequent audio chunks) */
|
||||||
|
@ -76,7 +79,7 @@ static void dsp_init_ramp(cnetz_t *cnetz)
|
||||||
c = -sqrt(-c);
|
c = -sqrt(-c);
|
||||||
else
|
else
|
||||||
c = sqrt(c);
|
c = sqrt(c);
|
||||||
ramp_down[i] = (int)(c * (double)cnetz->fsk_deviation);
|
ramp_down[i] = c * (double)cnetz->fsk_deviation;
|
||||||
ramp_up[i] = -ramp_down[i];
|
ramp_up[i] = -ramp_down[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,9 +93,8 @@ int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], do
|
||||||
|
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init FSK for 'Sender'.\n");
|
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init FSK for 'Sender'.\n");
|
||||||
|
|
||||||
/* set deviation and modulation parameters */
|
/* set modulation parameters */
|
||||||
cnetz->sender.bandwidth = BANDWIDTH;
|
sender_set_fm(&cnetz->sender, MAX_DEVIATION, MAX_MODULATION, DBM0_DEVIATION, MAX_DISPLAY);
|
||||||
cnetz->sender.sample_deviation = 2500.0 / (double)FSK_DEVIATION;
|
|
||||||
|
|
||||||
if (measure_speed) {
|
if (measure_speed) {
|
||||||
cnetz->measure_speed = measure_speed;
|
cnetz->measure_speed = measure_speed;
|
||||||
|
@ -119,7 +121,7 @@ int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], do
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create devation and ramp */
|
/* create devation and ramp */
|
||||||
cnetz->fsk_deviation = FSK_DEVIATION; /* be sure not to overflow -32767 .. 32767 */
|
cnetz->fsk_deviation = FSK_DEVIATION;
|
||||||
dsp_init_ramp(cnetz);
|
dsp_init_ramp(cnetz);
|
||||||
cnetz->fsk_noise = noise;
|
cnetz->fsk_noise = noise;
|
||||||
|
|
||||||
|
@ -465,7 +467,7 @@ static int fsk_distributed_encode(cnetz_t *cnetz, const char *bits)
|
||||||
} while (phase < 256.0);
|
} while (phase < 256.0);
|
||||||
phase -= 256.0;
|
phase -= 256.0;
|
||||||
}
|
}
|
||||||
*marker = -32768; /* indicator for inserting speech */
|
*marker = 999; /* marker for inserting speech */
|
||||||
}
|
}
|
||||||
/* add 46 * (1+4+1 + 60) bits */
|
/* add 46 * (1+4+1 + 60) bits */
|
||||||
for (i = 0; i < 46; i++) {
|
for (i = 0; i < 46; i++) {
|
||||||
|
@ -556,7 +558,7 @@ static int fsk_distributed_encode(cnetz_t *cnetz, const char *bits)
|
||||||
} while (phase < 256.0);
|
} while (phase < 256.0);
|
||||||
phase -= 256.0;
|
phase -= 256.0;
|
||||||
}
|
}
|
||||||
*marker = -32768; /* indicator for inserting speech */
|
*marker = 999; /* marker for inserting speech */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* depending on the number of samples, return the number */
|
/* depending on the number of samples, return the number */
|
||||||
|
@ -706,7 +708,7 @@ again:
|
||||||
if (length - count < copy)
|
if (length - count < copy)
|
||||||
copy = length - count;
|
copy = length - count;
|
||||||
for (i = 0; i < copy; i++) {
|
for (i = 0; i < copy; i++) {
|
||||||
if (*spl == -32768) {
|
if (*spl == 999) {
|
||||||
/* marker found to insert new chunk of audio */
|
/* marker found to insert new chunk of audio */
|
||||||
jitter_load(&cnetz->sender.dejitter, speech_buffer, 100);
|
jitter_load(&cnetz->sender.dejitter, speech_buffer, 100);
|
||||||
/* 1. compress dynamics */
|
/* 1. compress dynamics */
|
||||||
|
@ -722,15 +724,9 @@ again:
|
||||||
pre_emphasis(&cnetz->estate, speech_buffer, speech_length);
|
pre_emphasis(&cnetz->estate, speech_buffer, speech_length);
|
||||||
/* change level */
|
/* change level */
|
||||||
if (voice_deviation != 1) {
|
if (voice_deviation != 1) {
|
||||||
int sample, j;
|
int j;
|
||||||
for (j = 0; j < speech_length; j++) {
|
for (j = 0; j < speech_length; j++)
|
||||||
sample = speech_buffer[j] * voice_deviation;
|
speech_buffer[j] *= (double)voice_deviation;
|
||||||
if (sample > 32767)
|
|
||||||
sample = 32767;
|
|
||||||
if (sample < -32768)
|
|
||||||
sample = -32768;
|
|
||||||
speech_buffer[j] = sample;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
speech_pos = 0;
|
speech_pos = 0;
|
||||||
}
|
}
|
||||||
|
@ -801,7 +797,7 @@ void unshrink_speech(cnetz_t *cnetz, sample_t *speech_buffer, int count)
|
||||||
factor = cnetz->offset_factor;
|
factor = cnetz->offset_factor;
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
/* change level */
|
/* change level */
|
||||||
x = speech_buffer[i] / voice_deviation;
|
x = speech_buffer[i] / (double)voice_deviation;
|
||||||
/* high-pass to remove low level frequencies, caused by level jump between audio chunks */
|
/* high-pass to remove low level frequencies, caused by level jump between audio chunks */
|
||||||
y = factor * (y_last + x - x_last);
|
y = factor * (y_last + x - x_last);
|
||||||
x_last = x;
|
x_last = x;
|
||||||
|
|
|
@ -148,7 +148,7 @@ int fsk_fm_init(fsk_fm_demod_t *fsk, cnetz_t *cnetz, int samplerate, double bitr
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
fsk->level_threshold = 655;
|
fsk->level_threshold = 0.1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -170,9 +170,10 @@ void fsk_fm_exit(fsk_fm_demod_t *fsk)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get levels, sync time and jitter from sync sequence or frame data */
|
/* get levels, sync time and jitter from sync sequence or frame data */
|
||||||
static inline void get_levels(fsk_fm_demod_t *fsk, int *_min, int *_max, int *_avg, int *_probes, int num, double *_time, double *_jitter)
|
static inline void get_levels(fsk_fm_demod_t *fsk, double *_min, double *_max, double *_avg, int *_probes, int num, double *_time, double *_jitter)
|
||||||
{
|
{
|
||||||
int min = 32767, max = -32768, avg = 0, count = 0, level;
|
int count = 0;
|
||||||
|
double min = 0, max = 0, avg = 0, level;
|
||||||
double time = 0, t, sync_average, sync_time, jitter = 0;
|
double time = 0, t, sync_average, sync_time, jitter = 0;
|
||||||
int bit_offset;
|
int bit_offset;
|
||||||
int i;
|
int i;
|
||||||
|
@ -192,19 +193,20 @@ static inline void get_levels(fsk_fm_demod_t *fsk, int *_min, int *_max, int *_a
|
||||||
if (t > BITS_PER_SUPERFRAME / 2)
|
if (t > BITS_PER_SUPERFRAME / 2)
|
||||||
t -= BITS_PER_SUPERFRAME;
|
t -= BITS_PER_SUPERFRAME;
|
||||||
//if (fsk->cnetz->dsp_mode == DSP_MODE_SPK_V)
|
//if (fsk->cnetz->dsp_mode == DSP_MODE_SPK_V)
|
||||||
// printf("%d: level=%d%% @%.2f difference=%.2f\n", bit_offset, level * 100 / 65536, fsk->change_when[(fsk->change_pos - 1 - i) & 0xff], t);
|
// printf("%d: level=%.0f%% @%.2f difference=%.2f\n", bit_offset, level * 100, fsk->change_when[(fsk->change_pos - 1 - i) & 0xff], t);
|
||||||
time += t;
|
time += t;
|
||||||
|
|
||||||
if (level < min)
|
if (i == 0 || level < min)
|
||||||
min = level;
|
min = level;
|
||||||
if (level > max)
|
if (i == 0 || level > max)
|
||||||
max = level;
|
max = level;
|
||||||
avg += level;
|
avg += level;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* should never happen */
|
||||||
if (!count) {
|
if (!count) {
|
||||||
*_min = *_max = *_avg = 0;
|
*_min = *_max = *_avg = 0.0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +221,7 @@ static inline void get_levels(fsk_fm_demod_t *fsk, int *_min, int *_max, int *_a
|
||||||
*_probes = count;
|
*_probes = count;
|
||||||
*_min = min;
|
*_min = min;
|
||||||
*_max = max;
|
*_max = max;
|
||||||
*_avg = avg / count;
|
*_avg = avg / (double)count;
|
||||||
|
|
||||||
if (_time) {
|
if (_time) {
|
||||||
// if (fsk->cnetz->dsp_mode == DSP_MODE_SPK_V)
|
// if (fsk->cnetz->dsp_mode == DSP_MODE_SPK_V)
|
||||||
|
@ -254,15 +256,16 @@ static inline void get_levels(fsk_fm_demod_t *fsk, int *_min, int *_max, int *_a
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void got_bit(fsk_fm_demod_t *fsk, int bit, int change_level)
|
static inline void got_bit(fsk_fm_demod_t *fsk, int bit, double change_level)
|
||||||
{
|
{
|
||||||
int min, max, avg, probes;
|
int probes;
|
||||||
|
double min, max, avg;
|
||||||
|
|
||||||
/* count bits, but do not exceed 4 bits per SPK block */
|
/* count bits, but do not exceed 4 bits per SPK block */
|
||||||
if (fsk->cnetz->dsp_mode == DSP_MODE_SPK_V) {
|
if (fsk->cnetz->dsp_mode == DSP_MODE_SPK_V) {
|
||||||
/* for first bit, we have only half of the modulation deviation, so we multiply level by two */
|
/* for first bit, we have only half of the modulation deviation, so we multiply level by two */
|
||||||
if (fsk->bit_count == 0)
|
if (fsk->bit_count == 0)
|
||||||
change_level *= 2;
|
change_level *= 2.0;
|
||||||
if (fsk->bit_count == 4)
|
if (fsk->bit_count == 4)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -284,20 +287,20 @@ static inline void got_bit(fsk_fm_demod_t *fsk, int bit, int change_level)
|
||||||
* for all other bits in the sync sequence.
|
* for all other bits in the sync sequence.
|
||||||
* after sync, the theshold is set to half of the average of
|
* after sync, the theshold is set to half of the average of
|
||||||
* all changes in the sync sequence */
|
* all changes in the sync sequence */
|
||||||
if (change_level) {
|
if (change_level > 0.0) {
|
||||||
fsk->level_threshold = (double)change_level / 2.0;
|
fsk->level_threshold = change_level / 2.0;
|
||||||
} else if ((fsk->rx_sync & 0x1f) == 0x00 || (fsk->rx_sync & 0x1f) == 0x1f) {
|
} else if ((fsk->rx_sync & 0x1f) == 0x00 || (fsk->rx_sync & 0x1f) == 0x1f) {
|
||||||
if (fsk->cnetz->dsp_mode != DSP_MODE_SPK_V)
|
if (fsk->cnetz->dsp_mode != DSP_MODE_SPK_V)
|
||||||
fsk->level_threshold = 655;
|
fsk->level_threshold = 0.01;
|
||||||
}
|
}
|
||||||
if (detect_sync(fsk->rx_sync)) {
|
if (detect_sync(fsk->rx_sync)) {
|
||||||
fsk->sync = FSK_SYNC_POSITIVE;
|
fsk->sync = FSK_SYNC_POSITIVE;
|
||||||
got_sync:
|
got_sync:
|
||||||
get_levels(fsk, &min, &max, &avg, &probes, 30, &fsk->sync_time, &fsk->sync_jitter);
|
get_levels(fsk, &min, &max, &avg, &probes, 30, &fsk->sync_time, &fsk->sync_jitter);
|
||||||
fsk->sync_level = (double)avg / 65535.0;
|
fsk->sync_level = avg / 2.0;
|
||||||
if (fsk->sync == FSK_SYNC_NEGATIVE)
|
if (fsk->sync == FSK_SYNC_NEGATIVE)
|
||||||
fsk->sync_level = -fsk->sync_level;
|
fsk->sync_level = -fsk->sync_level;
|
||||||
// printf("sync (change min=%d%% max=%d%% avg=%d%% sync_time=%.2f jitter=%.2f probes=%d)\n", min * 100 / 65535, max * 100 / 65535, avg * 100 / 65535, fsk->sync_time, fsk->sync_jitter, probes);
|
// printf("sync (change min=%.0f%% max=%.0f%% avg=%.0f%% sync_time=%.2f jitter=%.2f probes=%d)\n", min * 100, max * 100, avg * 100, fsk->sync_time, fsk->sync_jitter, probes);
|
||||||
fsk->level_threshold = (double)avg / 2.0;
|
fsk->level_threshold = (double)avg / 2.0;
|
||||||
fsk->rx_sync = 0;
|
fsk->rx_sync = 0;
|
||||||
fsk->rx_buffer_count = 0;
|
fsk->rx_buffer_count = 0;
|
||||||
|
@ -342,6 +345,10 @@ static inline void find_change(fsk_fm_demod_t *fsk)
|
||||||
change_at = -1;
|
change_at = -1;
|
||||||
change_positive = -1;
|
change_positive = -1;
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
*/
|
||||||
for (i = 0; i < fsk->bit_buffer_len; i++) {
|
for (i = 0; i < fsk->bit_buffer_len; i++) {
|
||||||
last_s = s;
|
last_s = s;
|
||||||
s = fsk->bit_buffer_spl[fsk->bit_buffer_pos++];
|
s = fsk->bit_buffer_spl[fsk->bit_buffer_pos++];
|
||||||
|
@ -417,7 +424,7 @@ void fsk_fm_demod(fsk_fm_demod_t *fsk, sample_t *samples, int length)
|
||||||
if (fsk->cnetz->dsp_mode != DSP_MODE_SPK_V) {
|
if (fsk->cnetz->dsp_mode != DSP_MODE_SPK_V) {
|
||||||
#ifdef DEBUG_DECODER
|
#ifdef DEBUG_DECODER
|
||||||
DEBUG_DECODER
|
DEBUG_DECODER
|
||||||
puts(debug_amplitude(samples[i] / 32768.0));
|
puts(debug_amplitude(samples[i]));
|
||||||
#endif
|
#endif
|
||||||
find_change(fsk);
|
find_change(fsk);
|
||||||
} else {
|
} else {
|
||||||
|
@ -441,7 +448,7 @@ void fsk_fm_demod(fsk_fm_demod_t *fsk, sample_t *samples, int length)
|
||||||
if (t >= 0.5 && t < 5.5) {
|
if (t >= 0.5 && t < 5.5) {
|
||||||
#ifdef DEBUG_DECODER
|
#ifdef DEBUG_DECODER
|
||||||
DEBUG_DECODER
|
DEBUG_DECODER
|
||||||
puts(debug_amplitude(samples[i] / 32768.0));
|
puts(debug_amplitude(samples[i]));
|
||||||
#endif
|
#endif
|
||||||
find_change(fsk);
|
find_change(fsk);
|
||||||
} else
|
} else
|
||||||
|
|
|
@ -24,7 +24,7 @@ typedef struct fsk_fm_demod {
|
||||||
int bit_buffer_len; /* number of samples in ring buffer */
|
int bit_buffer_len; /* number of samples in ring buffer */
|
||||||
int bit_buffer_half; /* half of ring buffer */
|
int bit_buffer_half; /* half of ring buffer */
|
||||||
int bit_buffer_pos; /* current position to write next sample */
|
int bit_buffer_pos; /* current position to write next sample */
|
||||||
int level_threshold; /* threshold for detection of next level change */
|
double level_threshold; /* threshold for detection of next level change */
|
||||||
double bits_per_sample; /* duration of one sample in bits */
|
double bits_per_sample; /* duration of one sample in bits */
|
||||||
double next_bit; /* count time to detect bits */
|
double next_bit; /* count time to detect bits */
|
||||||
int bit_count; /* counts bits, to match 4 bits at distributed signaling */
|
int bit_count; /* counts bits, to match 4 bits at distributed signaling */
|
||||||
|
@ -45,7 +45,7 @@ typedef struct fsk_fm_demod {
|
||||||
int rx_buffer_count; /* counter when receiving bits */
|
int rx_buffer_count; /* counter when receiving bits */
|
||||||
|
|
||||||
/* statistics */
|
/* statistics */
|
||||||
int change_levels[256]; /* ring buffer to store levels */
|
double change_levels[256]; /* ring buffer to store levels */
|
||||||
double change_when[256]; /* ring buffer to store time when level has changed */
|
double change_when[256]; /* ring buffer to store time when level has changed */
|
||||||
uint8_t change_pos; /* index for next write */
|
uint8_t change_pos; /* index for next write */
|
||||||
} fsk_fm_demod_t;
|
} fsk_fm_demod_t;
|
||||||
|
|
|
@ -36,22 +36,22 @@
|
||||||
#define TEST_1000HZ_DB 55.0
|
#define TEST_1000HZ_DB 55.0
|
||||||
|
|
||||||
/* sine wave for carrier to modulate to */
|
/* sine wave for carrier to modulate to */
|
||||||
static double carrier[256];
|
static double carrier[65536];
|
||||||
|
|
||||||
void scrambler_init(void)
|
void scrambler_init(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < 256; i++) {
|
for (i = 0; i < 65536; i++) {
|
||||||
/* our amplitude must be doubled, since we have one spectrum above and one below carrier */
|
/* our amplitude must be doubled, since we have one spectrum above and one below carrier */
|
||||||
carrier[i] = sin((double)i / 256.0 * 2 * PI) * 2.0;
|
carrier[i] = sin((double)i / 65536.0 * 2 * PI) * 2.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void scrambler_setup(scrambler_t *scrambler, int samplerate)
|
void scrambler_setup(scrambler_t *scrambler, int samplerate)
|
||||||
{
|
{
|
||||||
filter_lowpass_init(&scrambler->lp, CARRIER_HZ - FILTER_BELOW, samplerate, FILTER_TURNS);
|
filter_lowpass_init(&scrambler->lp, CARRIER_HZ - FILTER_BELOW, samplerate, FILTER_TURNS);
|
||||||
scrambler->carrier_phaseshift256 = 256.0 / ((double)samplerate / CARRIER_HZ);
|
scrambler->carrier_phaseshift65536 = 65536.0 / ((double)samplerate / CARRIER_HZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Modulate samples to carriere that is twice the mirror frequency.
|
/* Modulate samples to carriere that is twice the mirror frequency.
|
||||||
|
@ -63,18 +63,18 @@ void scrambler(scrambler_t *scrambler, sample_t *samples, int length)
|
||||||
double phaseshift, phase;
|
double phaseshift, phase;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
phaseshift = scrambler->carrier_phaseshift256;
|
phaseshift = scrambler->carrier_phaseshift65536;
|
||||||
phase = scrambler->carrier_phase256;
|
phase = scrambler->carrier_phase65536;
|
||||||
|
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
/* modulate samples to carrier */
|
/* modulate samples to carrier */
|
||||||
samples[i] *= carrier[((uint8_t)phase) & 0xff];
|
samples[i] *= carrier[(uint16_t)phase];
|
||||||
phase += phaseshift;
|
phase += phaseshift;
|
||||||
if (phase >= 256.0)
|
if (phase >= 65536.0)
|
||||||
phase -= 256.0;
|
phase -= 65536.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
scrambler->carrier_phase256 = phase;
|
scrambler->carrier_phase65536 = phase;
|
||||||
|
|
||||||
/* cut off carrier frequency and modulation above carrier frequency */
|
/* cut off carrier frequency and modulation above carrier frequency */
|
||||||
filter_process(&scrambler->lp, samples, length);
|
filter_process(&scrambler->lp, samples, length);
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include "../common/filter.h"
|
#include "../common/filter.h"
|
||||||
|
|
||||||
typedef struct scrambler {
|
typedef struct scrambler {
|
||||||
double carrier_phaseshift256; /* carrier phase shift per sample */
|
double carrier_phaseshift65536;/* carrier phase shift per sample */
|
||||||
double carrier_phase256; /* current phase of carrier frequency */
|
double carrier_phase65536; /* current phase of carrier frequency */
|
||||||
filter_t lp; /* filter to remove carrier frequency */
|
filter_t lp; /* filter to remove carrier frequency */
|
||||||
} scrambler_t;
|
} scrambler_t;
|
||||||
|
|
||||||
|
|
|
@ -1492,9 +1492,9 @@ void cnetz_decode_telegramm(cnetz_t *cnetz, const char *bits, double level, doub
|
||||||
telegramm.jitter = jitter;
|
telegramm.jitter = jitter;
|
||||||
|
|
||||||
if (bit_errors)
|
if (bit_errors)
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_INFO, "RX Level: %.0f%% Jitter: %.2f Sync Time: %.2f (TS %.2f) Bit errors: %d %s\n", fabs(level) * 32767.0 / cnetz->fsk_deviation * 100.0, jitter, sync_time, sync_time / 396.0, bit_errors, (level < 0) ? "NEGATIVE (phone's mode)" : "POSITIVE (base station's mode)");
|
PDEBUG_CHAN(DDSP, DEBUG_INFO, "RX Level: %.0f%% Jitter: %.2f Sync Time: %.2f (TS %.2f) Bit errors: %d %s\n", fabs(level) / cnetz->fsk_deviation * 100.0, jitter, sync_time, sync_time / 396.0, bit_errors, (level < 0) ? "NEGATIVE (phone's mode)" : "POSITIVE (base station's mode)");
|
||||||
else
|
else
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_INFO, "RX Level: %.0f%% Jitter: %.2f Sync Time: %.2f (TS %.2f) %s\n", fabs(level) * 32767.0 / cnetz->fsk_deviation * 100.0, jitter, sync_time, sync_time / 396.0, (level < 0) ? "NEGATIVE (phone's mode)" : "POSITIVE (base station's mode)");
|
PDEBUG_CHAN(DDSP, DEBUG_INFO, "RX Level: %.0f%% Jitter: %.2f Sync Time: %.2f (TS %.2f) %s\n", fabs(level) / cnetz->fsk_deviation * 100.0, jitter, sync_time, sync_time / 396.0, (level < 0) ? "NEGATIVE (phone's mode)" : "POSITIVE (base station's mode)");
|
||||||
|
|
||||||
if (cnetz->sender.loopback) {
|
if (cnetz->sender.loopback) {
|
||||||
PDEBUG(DFRAME, DEBUG_NOTICE, "Received Telegramm in loopback test mode (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name);
|
PDEBUG(DFRAME, DEBUG_NOTICE, "Received Telegramm in loopback test mode (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name);
|
||||||
|
|
|
@ -35,6 +35,23 @@
|
||||||
|
|
||||||
#define DISC_TIMEOUT 30
|
#define DISC_TIMEOUT 30
|
||||||
|
|
||||||
|
//#define DEBUG_LEVEL
|
||||||
|
|
||||||
|
#ifdef DEBUG_LEVEL
|
||||||
|
static double level_of(double *samples, int count)
|
||||||
|
{
|
||||||
|
double level = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
if (samples[i] > level)
|
||||||
|
level = samples[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* stream patterns/announcements */
|
/* stream patterns/announcements */
|
||||||
int16_t *test_spl = NULL;
|
int16_t *test_spl = NULL;
|
||||||
int16_t *ringback_spl = NULL;
|
int16_t *ringback_spl = NULL;
|
||||||
|
@ -221,7 +238,7 @@ static void get_test_patterns(int16_t *samples, int length)
|
||||||
if (pos >= size)
|
if (pos >= size)
|
||||||
*samples++ = 0;
|
*samples++ = 0;
|
||||||
else
|
else
|
||||||
*samples++ = spl[pos] >> 1;
|
*samples++ = spl[pos] >> 2;
|
||||||
if (++pos == max)
|
if (++pos == max)
|
||||||
pos = 0;
|
pos = 0;
|
||||||
}
|
}
|
||||||
|
@ -477,7 +494,8 @@ int call_init(const char *station_id, const char *audiodev, int samplerate, int
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* open sound device for call control */
|
/* open sound device for call control */
|
||||||
call.sound = sound_open(audiodev, NULL, NULL, 1, 0.0, samplerate, 3700.0, 0.0);
|
/* use +3.17 dBm0 (factor 1.44) for complete range of sound card */
|
||||||
|
call.sound = sound_open(audiodev, NULL, NULL, 1, 0.0, samplerate, 1.44, 4000.0);
|
||||||
if (!call.sound) {
|
if (!call.sound) {
|
||||||
PDEBUG(DSENDER, DEBUG_ERROR, "No sound device!\n");
|
PDEBUG(DSENDER, DEBUG_ERROR, "No sound device!\n");
|
||||||
|
|
||||||
|
@ -677,7 +695,6 @@ void process_call(int c)
|
||||||
default:
|
default:
|
||||||
jitter_load(&call.dejitter, samples, count);
|
jitter_load(&call.dejitter, samples, count);
|
||||||
}
|
}
|
||||||
samples_to_int16(spl, samples, count);
|
|
||||||
samples_list[0] = samples;
|
samples_list[0] = samples;
|
||||||
rc = sound_write(call.sound, samples_list, count, NULL, NULL, 1);
|
rc = sound_write(call.sound, samples_list, count, NULL, NULL, 1);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
|
@ -904,8 +921,6 @@ void call_in_release(int callref, int cause)
|
||||||
/* forward audio to MNCC or call instance */
|
/* forward audio to MNCC or call instance */
|
||||||
void call_tx_audio(int callref, sample_t *samples, int count)
|
void call_tx_audio(int callref, sample_t *samples, int count)
|
||||||
{
|
{
|
||||||
int16_t spl[count];
|
|
||||||
|
|
||||||
if (!callref)
|
if (!callref)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -920,6 +935,10 @@ void call_tx_audio(int callref, sample_t *samples, int count)
|
||||||
/* forward audio */
|
/* forward audio */
|
||||||
data->msg_type = ANALOG_8000HZ;
|
data->msg_type = ANALOG_8000HZ;
|
||||||
data->callref = callref;
|
data->callref = callref;
|
||||||
|
#ifdef DEBUG_LEVEL
|
||||||
|
double lev = level_of(samples, count);
|
||||||
|
printf(" mobil-level: %s%.4f\n", debug_db(lev), (20 * log10(lev)));
|
||||||
|
#endif
|
||||||
samples_to_int16((int16_t *)data->data, samples, count);
|
samples_to_int16((int16_t *)data->data, samples, count);
|
||||||
|
|
||||||
mncc_write(buf, sizeof(buf));
|
mncc_write(buf, sizeof(buf));
|
||||||
|
@ -934,6 +953,7 @@ void call_tx_audio(int callref, sample_t *samples, int count)
|
||||||
} else
|
} else
|
||||||
/* else, if no sound is used, send test tone to mobile */
|
/* else, if no sound is used, send test tone to mobile */
|
||||||
if (call.state == CALL_CONNECT) {
|
if (call.state == CALL_CONNECT) {
|
||||||
|
int16_t spl[count];
|
||||||
get_test_patterns(spl, count);
|
get_test_patterns(spl, count);
|
||||||
int16_to_samples(samples, spl, count);
|
int16_to_samples(samples, spl, count);
|
||||||
call_rx_audio(callref, samples, count);
|
call_rx_audio(callref, samples, count);
|
||||||
|
@ -953,6 +973,13 @@ void call_mncc_clock(void)
|
||||||
data->callref = process->callref;
|
data->callref = process->callref;
|
||||||
/* try to get patterns, else copy the samples we got */
|
/* try to get patterns, else copy the samples we got */
|
||||||
get_process_patterns(process, (int16_t *)data->data, 160);
|
get_process_patterns(process, (int16_t *)data->data, 160);
|
||||||
|
#ifdef DEBUG_LEVEL
|
||||||
|
sample_t samples[160];
|
||||||
|
int16_to_samples(samples, (int16_t *)data->data, 160);
|
||||||
|
double lev = level_of(samples, 160);
|
||||||
|
printf(" mobil-level: %s%.4f\n", debug_db(lev), (20 * log10(lev)));
|
||||||
|
samples_to_int16((int16_t *)data->data, samples, 160);
|
||||||
|
#endif
|
||||||
mncc_write(buf, sizeof(buf));
|
mncc_write(buf, sizeof(buf));
|
||||||
}
|
}
|
||||||
process = process->next;
|
process = process->next;
|
||||||
|
@ -978,6 +1005,10 @@ void call_mncc_recv(uint8_t *buf, int length)
|
||||||
if (is_process_pattern(data->callref))
|
if (is_process_pattern(data->callref))
|
||||||
return;
|
return;
|
||||||
int16_to_samples(samples, (int16_t *)data->data, count);
|
int16_to_samples(samples, (int16_t *)data->data, count);
|
||||||
|
#ifdef DEBUG_LEVEL
|
||||||
|
double lev = level_of(samples, count);
|
||||||
|
printf("festnetz-level: %s %.4f\n", debug_db(lev), (20 * log10(lev)));
|
||||||
|
#endif
|
||||||
call_rx_audio(data->callref, samples, count);
|
call_rx_audio(data->callref, samples, count);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,9 @@
|
||||||
/* Minimum level value to keep state */
|
/* Minimum level value to keep state */
|
||||||
#define ENVELOPE_MIN 0.001
|
#define ENVELOPE_MIN 0.001
|
||||||
|
|
||||||
|
/* Maximum level, to prevent sqrt_tab to overflow */
|
||||||
|
#define ENVELOPE_MAX 9.990
|
||||||
|
|
||||||
static double sqrt_tab[10000];
|
static double sqrt_tab[10000];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -43,7 +46,7 @@ static double sqrt_tab[10000];
|
||||||
* Hopefully this is correct
|
* Hopefully this is correct
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void init_compandor(compandor_t *state, int samplerate, double attack_ms, double recovery_ms, int unaffected_level)
|
void init_compandor(compandor_t *state, int samplerate, double attack_ms, double recovery_ms, double unaffected_level)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -95,6 +98,8 @@ void compress_audio(compandor_t *state, sample_t *samples, int num)
|
||||||
envelope = peak;
|
envelope = peak;
|
||||||
if (envelope < ENVELOPE_MIN)
|
if (envelope < ENVELOPE_MIN)
|
||||||
envelope = ENVELOPE_MIN;
|
envelope = ENVELOPE_MIN;
|
||||||
|
if (envelope > ENVELOPE_MAX)
|
||||||
|
envelope = ENVELOPE_MAX;
|
||||||
|
|
||||||
value = value / sqrt_tab[(int)(envelope / 0.001)];
|
value = value / sqrt_tab[(int)(envelope / 0.001)];
|
||||||
//if (i > 47000.0 && i < 48144)
|
//if (i > 47000.0 && i < 48144)
|
||||||
|
|
|
@ -15,7 +15,7 @@ typedef struct compandor {
|
||||||
} e;
|
} e;
|
||||||
} compandor_t;
|
} compandor_t;
|
||||||
|
|
||||||
void init_compandor(compandor_t *state, int samplerate, double attack_ms, double recovery_ms, int unaffected_level);
|
void init_compandor(compandor_t *state, int samplerate, double attack_ms, double recovery_ms, double unaffected_level);
|
||||||
void compress_audio(compandor_t *state, sample_t *samples, int num);
|
void compress_audio(compandor_t *state, sample_t *samples, int num);
|
||||||
void expand_audio(compandor_t *state, sample_t *samples, int num);
|
void expand_audio(compandor_t *state, sample_t *samples, int num);
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ void get_win_size(int *w, int *h);
|
||||||
void display_wave_init(sender_t *sender, int samplerate);
|
void display_wave_init(sender_t *sender, int samplerate);
|
||||||
void display_wave_on(int on);
|
void display_wave_on(int on);
|
||||||
void display_wave_limit_scroll(int on);
|
void display_wave_limit_scroll(int on);
|
||||||
void display_wave(sender_t *sender, sample_t *samples, int length);
|
void display_wave(sender_t *sender, sample_t *samples, int length, double range);
|
||||||
|
|
||||||
void display_iq_init(int samplerate);
|
void display_iq_init(int samplerate);
|
||||||
void display_iq_on(int on);
|
void display_iq_on(int on);
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include "sample.h"
|
#include "sample.h"
|
||||||
#include "sender.h"
|
#include "sender.h"
|
||||||
|
@ -110,10 +111,10 @@ void display_wave_limit_scroll(int on)
|
||||||
* HEIGHT is odd, so the center line's char is '-' (otherwise '_')
|
* HEIGHT is odd, so the center line's char is '-' (otherwise '_')
|
||||||
* (HEIGHT - 1) / 2 = 1, so the center line is drawn in line 1
|
* (HEIGHT - 1) / 2 = 1, so the center line is drawn in line 1
|
||||||
*
|
*
|
||||||
* y is in range of 0..5, so these are 5 steps, where 2 to 2.999 is the
|
* y is in range of 0..4, so these are 5 steps, where 2 is the
|
||||||
* center line. this is calculated by (HEIGHT * 2 - 1)
|
* center line. this is calculated by (HEIGHT * 2 - 1)
|
||||||
*/
|
*/
|
||||||
void display_wave(sender_t *sender, sample_t *samples, int length)
|
void display_wave(sender_t *sender, sample_t *samples, int length, double range)
|
||||||
{
|
{
|
||||||
dispwav_t *disp = &sender->dispwav;
|
dispwav_t *disp = &sender->dispwav;
|
||||||
int pos, max;
|
int pos, max;
|
||||||
|
@ -147,9 +148,16 @@ void display_wave(sender_t *sender, sample_t *samples, int length)
|
||||||
if (pos == width) {
|
if (pos == width) {
|
||||||
memset(&screen, ' ', sizeof(screen));
|
memset(&screen, ' ', sizeof(screen));
|
||||||
for (j = 0; j < width; j++) {
|
for (j = 0; j < width; j++) {
|
||||||
y = (32767 - (int32_t)buffer[j]) * (HEIGHT * 2 - 1) / 65536;
|
/* Input value is scaled to range -1 .. 1 and then substracted from 1,
|
||||||
|
* so the result ranges from 0 .. 2.
|
||||||
|
* HEIGHT-1 is multiplied with the range, so a HEIGHT of 3 would allow
|
||||||
|
* 0..4 (5 steps) and a HEIGHT of 11 would allow 0..20 (21 steps).
|
||||||
|
* We always use odd number of steps, so there will be a center between
|
||||||
|
* values.
|
||||||
|
*/
|
||||||
|
y = round((1.0 - buffer[j] / range) * (double)(HEIGHT - 1));
|
||||||
/* only display level, if it is in range */
|
/* only display level, if it is in range */
|
||||||
if (y >= 0 && y < HEIGHT * 2)
|
if (y >= 0 && y < HEIGHT * 2 - 1)
|
||||||
screen[y >> 1][j] = (y & 1) ? '_' : '-';
|
screen[y >> 1][j] = (y & 1) ? '_' : '-';
|
||||||
}
|
}
|
||||||
sprintf(screen[0], "(chan %d", sender->kanal);
|
sprintf(screen[0], "(chan %d", sender->kanal);
|
||||||
|
|
|
@ -25,10 +25,12 @@
|
||||||
|
|
||||||
#define PI M_PI
|
#define PI M_PI
|
||||||
|
|
||||||
#define TX_PEAK_DTMF 7000 /* single dtmf tone peak (note this is half to total peak) */
|
static double tx_peak_dtmf_low = 0.2818 / SPEECH_LEVEL; /* -11 dBm, relative to speech level */
|
||||||
#define DTMF_DURATION 0.100 /* duration in seconds */
|
static double tx_peak_dtmf_high = 0.3548 / SPEECH_LEVEL;/* -9 dBm, relative to speech level */
|
||||||
|
#define DTMF_DURATION 0.100 /* duration in seconds */
|
||||||
|
|
||||||
static double dsp_sine_dtmf[256];
|
static sample_t dsp_sine_dtmf_low[65536];
|
||||||
|
static sample_t dsp_sine_dtmf_high[65536];
|
||||||
|
|
||||||
void dtmf_init(dtmf_t *dtmf, int samplerate)
|
void dtmf_init(dtmf_t *dtmf, int samplerate)
|
||||||
{
|
{
|
||||||
|
@ -39,8 +41,10 @@ void dtmf_init(dtmf_t *dtmf, int samplerate)
|
||||||
dtmf->max = (int)((double)samplerate * DTMF_DURATION + 0.5);
|
dtmf->max = (int)((double)samplerate * DTMF_DURATION + 0.5);
|
||||||
|
|
||||||
// FIXME: do this globally and not per instance */
|
// FIXME: do this globally and not per instance */
|
||||||
for (i = 0; i < 256; i++)
|
for (i = 0; i < 65536; i++) {
|
||||||
dsp_sine_dtmf[i] = (int)(sin((double)i / 256.0 * 2.0 * PI) * TX_PEAK_DTMF);
|
dsp_sine_dtmf_low[i] = sin((double)i / 65536.0 * 2.0 * PI) * tx_peak_dtmf_low;
|
||||||
|
dsp_sine_dtmf_high[i] = sin((double)i / 65536.0 * 2.0 * PI) * tx_peak_dtmf_high;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set dtmf tone */
|
/* set dtmf tone */
|
||||||
|
@ -71,8 +75,8 @@ void dtmf_set_tone(dtmf_t *dtmf, char tone)
|
||||||
}
|
}
|
||||||
dtmf->tone = tone;
|
dtmf->tone = tone;
|
||||||
dtmf->pos = 0;
|
dtmf->pos = 0;
|
||||||
dtmf->phaseshift256[0] = 256.0 / ((double)dtmf->samplerate / f1);
|
dtmf->phaseshift65536[0] = 65536.0 / ((double)dtmf->samplerate / f1);
|
||||||
dtmf->phaseshift256[1] = 256.0 / ((double)dtmf->samplerate / f2);
|
dtmf->phaseshift65536[1] = 65536.0 / ((double)dtmf->samplerate / f2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate audio stream from DTMF tone. Keep phase for next call of function. */
|
/* Generate audio stream from DTMF tone. Keep phase for next call of function. */
|
||||||
|
@ -87,20 +91,20 @@ void dtmf_tone(dtmf_t *dtmf, sample_t *samples, int length)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
phaseshift = dtmf->phaseshift256;
|
phaseshift = dtmf->phaseshift65536;
|
||||||
phase = dtmf->phase256;
|
phase = dtmf->phase65536;
|
||||||
pos = dtmf->pos;
|
pos = dtmf->pos;
|
||||||
max = dtmf->max;
|
max = dtmf->max;
|
||||||
|
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
*samples++ = dsp_sine_dtmf[((uint8_t)phase[0]) & 0xff]
|
*samples++ = dsp_sine_dtmf_low[(uint16_t)phase[0]]
|
||||||
+ dsp_sine_dtmf[((uint8_t)phase[1]) & 0xff];
|
+ dsp_sine_dtmf_high[(uint16_t)phase[1]];
|
||||||
phase[0] += phaseshift[0];
|
phase[0] += phaseshift[0];
|
||||||
if (phase[0] >= 256)
|
if (phase[0] >= 65536)
|
||||||
phase[0] -= 256;
|
phase[0] -= 65536;
|
||||||
phase[1] += phaseshift[1];
|
phase[1] += phaseshift[1];
|
||||||
if (phase[1] >= 256)
|
if (phase[1] >= 65536)
|
||||||
phase[1] -= 256;
|
phase[1] -= 65536;
|
||||||
|
|
||||||
/* tone ends */
|
/* tone ends */
|
||||||
if (++pos == max) {
|
if (++pos == max) {
|
||||||
|
|
|
@ -4,8 +4,8 @@ typedef struct dtmf {
|
||||||
char tone; /* current tone to be played */
|
char tone; /* current tone to be played */
|
||||||
int pos; /* sample counter for tone */
|
int pos; /* sample counter for tone */
|
||||||
int max; /* max number of samples for tone duration */
|
int max; /* max number of samples for tone duration */
|
||||||
double phaseshift256[2]; /* how much the phase of sine wave changes per sample */
|
double phaseshift65536[2]; /* how much the phase of sine wave changes per sample */
|
||||||
double phase256[2]; /* current phase */
|
double phase65536[2]; /* current phase */
|
||||||
} dtmf_t;
|
} dtmf_t;
|
||||||
|
|
||||||
void dtmf_init(dtmf_t *dtmf, int samplerate);
|
void dtmf_init(dtmf_t *dtmf, int samplerate);
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include "sample.h"
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
#include "emphasis.h"
|
#include "emphasis.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
@ -29,7 +30,7 @@
|
||||||
|
|
||||||
#define CUT_OFF_H 100.0 /* cut-off frequency for high-pass filter */
|
#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(sample_t *samples, int num, int samplerate, double freq)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -37,7 +38,7 @@ static void gen_sine(double *samples, int num, int samplerate, double freq)
|
||||||
samples[i] = cos(2.0 * M_PI * freq / (double)samplerate * (double)i);
|
samples[i] = cos(2.0 * M_PI * freq / (double)samplerate * (double)i);
|
||||||
}
|
}
|
||||||
|
|
||||||
static double get_level(double *samples, int num)
|
static double get_level(sample_t *samples, int num)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
double envelope = 0;
|
double envelope = 0;
|
||||||
|
@ -52,7 +53,7 @@ static double get_level(double *samples, int num)
|
||||||
int init_emphasis(emphasis_t *state, int samplerate, double cut_off)
|
int init_emphasis(emphasis_t *state, int samplerate, double cut_off)
|
||||||
{
|
{
|
||||||
double factor;
|
double factor;
|
||||||
double test_samples[samplerate / 10];
|
sample_t test_samples[samplerate / 10];
|
||||||
|
|
||||||
memset(state, 0, sizeof(*state));
|
memset(state, 0, sizeof(*state));
|
||||||
|
|
||||||
|
@ -78,7 +79,7 @@ int init_emphasis(emphasis_t *state, int samplerate, double cut_off)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pre_emphasis(emphasis_t *state, double *samples, int num)
|
void pre_emphasis(emphasis_t *state, sample_t *samples, int num)
|
||||||
{
|
{
|
||||||
double x, y, x_last, factor, amp;
|
double x, y, x_last, factor, amp;
|
||||||
int i;
|
int i;
|
||||||
|
@ -101,7 +102,7 @@ void pre_emphasis(emphasis_t *state, double *samples, int num)
|
||||||
state->p.x_last = x_last;
|
state->p.x_last = x_last;
|
||||||
}
|
}
|
||||||
|
|
||||||
void de_emphasis(emphasis_t *state, double *samples, int num)
|
void de_emphasis(emphasis_t *state, sample_t *samples, int num)
|
||||||
{
|
{
|
||||||
double x, y, y_last, factor, amp;
|
double x, y, y_last, factor, amp;
|
||||||
int i;
|
int i;
|
||||||
|
@ -125,7 +126,7 @@ void de_emphasis(emphasis_t *state, double *samples, int num)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* high pass filter to remove DC and low frequencies */
|
/* high pass filter to remove DC and low frequencies */
|
||||||
void dc_filter(emphasis_t *state, double *samples, int num)
|
void dc_filter(emphasis_t *state, sample_t *samples, int num)
|
||||||
{
|
{
|
||||||
filter_process(&state->d.hp, samples, num);
|
filter_process(&state->d.hp, samples, num);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ typedef struct emphasis {
|
||||||
#define CUT_OFF_EMPHASIS_DEFAULT 300.0
|
#define CUT_OFF_EMPHASIS_DEFAULT 300.0
|
||||||
|
|
||||||
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, sample_t *samples, int num);
|
||||||
void de_emphasis(emphasis_t *state, double *samples, int num);
|
void de_emphasis(emphasis_t *state, sample_t *samples, int num);
|
||||||
void dc_filter(emphasis_t *state, double *samples, int num);
|
void dc_filter(emphasis_t *state, sample_t *samples, int num);
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include "sample.h"
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
|
|
||||||
#define PI M_PI
|
#define PI M_PI
|
||||||
|
@ -65,7 +66,7 @@ void filter_highpass_init(filter_t *bq, double frequency, int samplerate, int it
|
||||||
bq->b2 = (1 - K / Q + K * K) * norm;
|
bq->b2 = (1 - K / Q + K * K) * norm;
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter_process(filter_t *bq, double *samples, int length)
|
void filter_process(filter_t *bq, sample_t *samples, int length)
|
||||||
{
|
{
|
||||||
double a0, a1, a2, b1, b2;
|
double a0, a1, a2, b1, b2;
|
||||||
double *z1, *z2;
|
double *z1, *z2;
|
||||||
|
|
|
@ -9,6 +9,6 @@ typedef struct filter {
|
||||||
|
|
||||||
void filter_lowpass_init(filter_t *bq, double frequency, int samplerate, int iterations);
|
void filter_lowpass_init(filter_t *bq, double frequency, int samplerate, int iterations);
|
||||||
void filter_highpass_init(filter_t *bq, double frequency, int samplerate, int iterations);
|
void filter_highpass_init(filter_t *bq, double frequency, int samplerate, int iterations);
|
||||||
void filter_process(filter_t *bq, double *samples, int length);
|
void filter_process(filter_t *bq, sample_t *samples, int length);
|
||||||
|
|
||||||
#endif /* _FILTER_H */
|
#endif /* _FILTER_H */
|
||||||
|
|
|
@ -1,27 +1,64 @@
|
||||||
|
/* Sample definition
|
||||||
|
*
|
||||||
|
* (C) 2017 by Andreas Eversberg <jolly@eversberg.eu>
|
||||||
|
* All Rights Reserved
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "sample.h"
|
#include "sample.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A regular voice conversation takes place at this factor below the full range
|
||||||
|
* of 16 bits signed value:
|
||||||
|
*/
|
||||||
|
static double int_16_speech_level = SPEECH_LEVEL * 0.7079; /* 16 dBm below dBm0, which is about 3dBm below full 16 bit range */
|
||||||
|
|
||||||
|
/* A sample_t is a value that has virtually infinite precision but will also
|
||||||
|
* support high numbers. 'double' or 'float' types are sufficient.
|
||||||
|
*
|
||||||
|
* When using sample_t inside signal processing of each base station, the
|
||||||
|
* level of +- 1 is relative to the normal speach evenlope.
|
||||||
|
*
|
||||||
|
* When converting sample_t to int16_t, the level of +- 1 is reduced by factor.
|
||||||
|
* This way the speech may be louder before clipping happens.
|
||||||
|
*
|
||||||
|
* When using sample_t to modulate (SDR or sound card), the level is changed,
|
||||||
|
* so it represents the frequency deviation in Hz. The deviation of speech
|
||||||
|
* envelope is network dependant.
|
||||||
|
*/
|
||||||
|
|
||||||
void samples_to_int16(int16_t *spl, sample_t *samples, int length)
|
void samples_to_int16(int16_t *spl, sample_t *samples, int length)
|
||||||
{
|
{
|
||||||
|
int32_t value;
|
||||||
|
|
||||||
while (length--) {
|
while (length--) {
|
||||||
if (*samples > 32767.0)
|
value = *samples++ * int_16_speech_level * 32768.0;
|
||||||
*spl = 32767;
|
if (value > 32767.0)
|
||||||
else if (*samples < -32767.0)
|
*spl++ = 32767;
|
||||||
*spl = -32767;
|
else if (value < -32767.0)
|
||||||
|
*spl++ = -32767;
|
||||||
else
|
else
|
||||||
*spl = (uint16_t)(*samples);
|
*spl++ = (uint16_t)value;
|
||||||
samples++;
|
|
||||||
spl++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void int16_to_samples(sample_t *samples, int16_t *spl, int length)
|
void int16_to_samples(sample_t *samples, int16_t *spl, int length)
|
||||||
{
|
{
|
||||||
while (length--) {
|
while (length--) {
|
||||||
*samples = (double)(*spl);
|
*samples++ = (double)(*spl++) / 32767.0 / int_16_speech_level;
|
||||||
samples++;
|
|
||||||
spl++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
|
||||||
typedef double sample_t;
|
typedef double sample_t;
|
||||||
|
|
||||||
|
#define SPEECH_LEVEL 0.1585
|
||||||
|
|
||||||
void samples_to_int16(int16_t *spl, sample_t *samples, int length);
|
void samples_to_int16(int16_t *spl, sample_t *samples, int length);
|
||||||
void int16_to_samples(sample_t *samples, int16_t *spl, int length);
|
void int16_to_samples(sample_t *samples, int16_t *spl, int length);
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,7 @@ int samplerate_upsample(samplerate_t *state, sample_t *input, int input_num, sam
|
||||||
|
|
||||||
if (input == output) {
|
if (input == output) {
|
||||||
/* copy samples */
|
/* copy samples */
|
||||||
for (i = 0; i < input_num; i++)
|
for (i = 0; i < output_num; i++)
|
||||||
*output++ = samples[i];
|
*output++ = samples[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,6 @@ typedef struct sdr {
|
||||||
sdr_chan_t *chan; /* settings for all channels */
|
sdr_chan_t *chan; /* settings for all channels */
|
||||||
int paging_channel; /* if set, points to paging channel */
|
int paging_channel; /* if set, points to paging channel */
|
||||||
sdr_chan_t paging_chan; /* settings for extra paging channel */
|
sdr_chan_t paging_chan; /* settings for extra paging channel */
|
||||||
double spl_deviation; /* how to convert a sample step into deviation (Hz) */
|
|
||||||
int channels; /* number of frequencies */
|
int channels; /* number of frequencies */
|
||||||
double samplerate; /* IQ rate */
|
double samplerate; /* IQ rate */
|
||||||
double amplitude; /* amplitude of each carrier */
|
double amplitude; /* amplitude of each carrier */
|
||||||
|
@ -84,15 +83,19 @@ int sdr_init(const char *device_args, double rx_gain, double tx_gain, const char
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_frequency, double *rx_frequency, int channels, double paging_frequency, int samplerate, double bandwidth, double sample_deviation)
|
void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_frequency, double *rx_frequency, int channels, double paging_frequency, int samplerate, double max_deviation, double max_modulation)
|
||||||
{
|
{
|
||||||
sdr_t *sdr;
|
sdr_t *sdr;
|
||||||
|
double bandwidth;
|
||||||
double tx_center_frequency, rx_center_frequency;
|
double tx_center_frequency, rx_center_frequency;
|
||||||
int rc;
|
int rc;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
display_iq_init(samplerate);
|
display_iq_init(samplerate);
|
||||||
|
|
||||||
|
bandwidth = 2.0 * (max_deviation + max_modulation);
|
||||||
|
PDEBUG(DSDR, DEBUG_INFO, "Using Bandwidth of 2 * (%.1f + %.1f) = %.1f\n", max_deviation / 1000, max_modulation / 1000, bandwidth / 1000);
|
||||||
|
|
||||||
if (channels < 1) {
|
if (channels < 1) {
|
||||||
PDEBUG(DSDR, DEBUG_ERROR, "No channel given, please fix!\n");
|
PDEBUG(DSDR, DEBUG_ERROR, "No channel given, please fix!\n");
|
||||||
abort();
|
abort();
|
||||||
|
@ -105,7 +108,6 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
|
||||||
}
|
}
|
||||||
sdr->channels = channels;
|
sdr->channels = channels;
|
||||||
sdr->samplerate = samplerate;
|
sdr->samplerate = samplerate;
|
||||||
sdr->spl_deviation = sample_deviation;
|
|
||||||
sdr->amplitude = 0.4 / (double)channels; // FIXME: actual amplitude 0.1?
|
sdr->amplitude = 0.4 / (double)channels; // FIXME: actual amplitude 0.1?
|
||||||
|
|
||||||
/* special case where we use a paging frequency */
|
/* special case where we use a paging frequency */
|
||||||
|
@ -124,8 +126,8 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
|
||||||
PDEBUG(DSDR, DEBUG_INFO, "Frequency #%d: TX = %.6f MHz, RX = %.6f MHz\n", c, tx_frequency[c] / 1e6, rx_frequency[c] / 1e6);
|
PDEBUG(DSDR, DEBUG_INFO, "Frequency #%d: TX = %.6f MHz, RX = %.6f MHz\n", c, tx_frequency[c] / 1e6, rx_frequency[c] / 1e6);
|
||||||
sdr->chan[c].tx_frequency = tx_frequency[c];
|
sdr->chan[c].tx_frequency = tx_frequency[c];
|
||||||
sdr->chan[c].rx_frequency = rx_frequency[c];
|
sdr->chan[c].rx_frequency = rx_frequency[c];
|
||||||
filter_lowpass_init(&sdr->chan[c].rx_lp[0], bandwidth, samplerate, 1);
|
filter_lowpass_init(&sdr->chan[c].rx_lp[0], bandwidth / 2.0, samplerate, 1);
|
||||||
filter_lowpass_init(&sdr->chan[c].rx_lp[1], bandwidth, samplerate, 1);
|
filter_lowpass_init(&sdr->chan[c].rx_lp[1], bandwidth / 2.0, samplerate, 1);
|
||||||
}
|
}
|
||||||
if (sdr->paging_channel) {
|
if (sdr->paging_channel) {
|
||||||
PDEBUG(DSDR, DEBUG_INFO, "Paging Frequency: TX = %.6f MHz\n", paging_frequency / 1e6);
|
PDEBUG(DSDR, DEBUG_INFO, "Paging Frequency: TX = %.6f MHz\n", paging_frequency / 1e6);
|
||||||
|
@ -190,21 +192,21 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
|
||||||
PDEBUG(DSDR, DEBUG_INFO, "Using gain: TX %.1f dB, RX %.1f dB\n", sdr_tx_gain, sdr_rx_gain);
|
PDEBUG(DSDR, DEBUG_INFO, "Using gain: TX %.1f dB, RX %.1f dB\n", sdr_tx_gain, sdr_rx_gain);
|
||||||
|
|
||||||
if (sdr_write_iq_rx_wave) {
|
if (sdr_write_iq_rx_wave) {
|
||||||
rc = wave_create_record(&sdr->wave_rx_rec, sdr_write_iq_rx_wave, sdr->samplerate, 2);
|
rc = wave_create_record(&sdr->wave_rx_rec, sdr_write_iq_rx_wave, sdr->samplerate, 2, 1.0);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n");
|
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sdr_write_iq_tx_wave) {
|
if (sdr_write_iq_tx_wave) {
|
||||||
rc = wave_create_record(&sdr->wave_tx_rec, sdr_write_iq_tx_wave, sdr->samplerate, 2);
|
rc = wave_create_record(&sdr->wave_tx_rec, sdr_write_iq_tx_wave, sdr->samplerate, 2, 1.0);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n");
|
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sdr_read_iq_rx_wave) {
|
if (sdr_read_iq_rx_wave) {
|
||||||
rc = wave_create_playback(&sdr->wave_rx_play, sdr_read_iq_rx_wave, sdr->samplerate, 2);
|
rc = wave_create_playback(&sdr->wave_rx_play, sdr_read_iq_rx_wave, sdr->samplerate, 2, 1.0);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE playback instance!\n");
|
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE playback instance!\n");
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -269,7 +271,7 @@ int sdr_write(void *inst, sample_t **samples, int num, enum paging_signal __attr
|
||||||
/* modulate */
|
/* modulate */
|
||||||
for (s = 0, ss = 0; s < num; s++) {
|
for (s = 0, ss = 0; s < num; s++) {
|
||||||
/* deviation is defined by the sample value and the offset */
|
/* deviation is defined by the sample value and the offset */
|
||||||
dev = offset + (double)samples[c][s] * sdr->spl_deviation;
|
dev = offset + samples[c][s];
|
||||||
#ifdef FAST_SINE
|
#ifdef FAST_SINE
|
||||||
phase += 256.0 * dev / rate;
|
phase += 256.0 * dev / rate;
|
||||||
if (phase < 0.0)
|
if (phase < 0.0)
|
||||||
|
@ -294,20 +296,8 @@ int sdr_write(void *inst, sample_t **samples, int num, enum paging_signal __attr
|
||||||
if (sdr->wave_tx_rec.fp) {
|
if (sdr->wave_tx_rec.fp) {
|
||||||
sample_t spl[2][num], *spl_list[2] = { spl[0], spl[1] };
|
sample_t spl[2][num], *spl_list[2] = { spl[0], spl[1] };
|
||||||
for (s = 0, ss = 0; s < num; s++) {
|
for (s = 0, ss = 0; s < num; s++) {
|
||||||
if (buff[ss] >= 1.0)
|
spl[0][s] = buff[ss++];
|
||||||
spl[0][s] = 32767.0;
|
spl[1][s] = buff[ss++];
|
||||||
else if (buff[ss] <= -1.0)
|
|
||||||
spl[0][s] = -32767.0;
|
|
||||||
else
|
|
||||||
spl[0][s] = 32767.0 * buff[ss];
|
|
||||||
ss++;
|
|
||||||
if (buff[ss] >= 1.0)
|
|
||||||
spl[1][s] = 32767.0;
|
|
||||||
else if (buff[ss] <= -1.0)
|
|
||||||
spl[1][s] = -32767.0;
|
|
||||||
else
|
|
||||||
spl[1][s] = 32767.0 * buff[ss];
|
|
||||||
ss++;
|
|
||||||
}
|
}
|
||||||
wave_write(&sdr->wave_tx_rec, spl_list, num);
|
wave_write(&sdr->wave_tx_rec, spl_list, num);
|
||||||
}
|
}
|
||||||
|
@ -325,7 +315,7 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels)
|
||||||
{
|
{
|
||||||
sdr_t *sdr = (sdr_t *)inst;
|
sdr_t *sdr = (sdr_t *)inst;
|
||||||
float buff[num * 2];
|
float buff[num * 2];
|
||||||
double I[num], Q[num], i, q;
|
sample_t I[num], Q[num], i, q;
|
||||||
int count;
|
int count;
|
||||||
int c, s, ss;
|
int c, s, ss;
|
||||||
double phase, rot, last_phase, dev, rate;
|
double phase, rot, last_phase, dev, rate;
|
||||||
|
@ -341,20 +331,8 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels)
|
||||||
if (sdr->wave_rx_rec.fp) {
|
if (sdr->wave_rx_rec.fp) {
|
||||||
sample_t spl[2][count], *spl_list[2] = { spl[0], spl[1] };
|
sample_t spl[2][count], *spl_list[2] = { spl[0], spl[1] };
|
||||||
for (s = 0, ss = 0; s < count; s++) {
|
for (s = 0, ss = 0; s < count; s++) {
|
||||||
if (buff[ss] >= 1.0)
|
spl[0][s] = buff[ss++];
|
||||||
spl[0][s] = 32767.0;
|
spl[1][s] = buff[ss++];
|
||||||
else if (buff[ss] <= -1.0)
|
|
||||||
spl[0][s] = -32767.0;
|
|
||||||
else
|
|
||||||
spl[0][s] = 32767.0 * buff[ss];
|
|
||||||
ss++;
|
|
||||||
if (buff[ss] >= 1.0)
|
|
||||||
spl[1][s] = 32767.0;
|
|
||||||
else if (buff[ss] <= -1.0)
|
|
||||||
spl[1][s] = -32767.0;
|
|
||||||
else
|
|
||||||
spl[1][s] = 32767.0 * buff[ss];
|
|
||||||
ss++;
|
|
||||||
}
|
}
|
||||||
wave_write(&sdr->wave_rx_rec, spl_list, count);
|
wave_write(&sdr->wave_rx_rec, spl_list, count);
|
||||||
}
|
}
|
||||||
|
@ -362,8 +340,8 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels)
|
||||||
sample_t spl[2][count], *spl_list[2] = { spl[0], spl[1] };
|
sample_t spl[2][count], *spl_list[2] = { spl[0], spl[1] };
|
||||||
wave_read(&sdr->wave_rx_play, spl_list, count);
|
wave_read(&sdr->wave_rx_play, spl_list, count);
|
||||||
for (s = 0, ss = 0; s < count; s++) {
|
for (s = 0, ss = 0; s < count; s++) {
|
||||||
buff[ss++] = spl[0][s] / 32767.0;
|
buff[ss++] = spl[0][s];
|
||||||
buff[ss++] = spl[1][s] / 32767.0;
|
buff[ss++] = spl[1][s];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
display_iq(buff, count);
|
display_iq(buff, count);
|
||||||
|
@ -391,7 +369,7 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels)
|
||||||
else if (dev > 0.49)
|
else if (dev > 0.49)
|
||||||
dev -= 1.0;
|
dev -= 1.0;
|
||||||
dev *= rate;
|
dev *= rate;
|
||||||
samples[c][s] = dev / sdr->spl_deviation;
|
samples[c][s] = dev;
|
||||||
}
|
}
|
||||||
sdr->chan[c].rx_last_phase = last_phase;
|
sdr->chan[c].rx_last_phase = last_phase;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,8 +41,6 @@ int sender_create(sender_t *sender, int kanal, double sendefrequenz, double empf
|
||||||
sender->kanal = kanal;
|
sender->kanal = kanal;
|
||||||
sender->sendefrequenz = sendefrequenz;
|
sender->sendefrequenz = sendefrequenz;
|
||||||
sender->empfangsfrequenz = empfangsfrequenz;
|
sender->empfangsfrequenz = empfangsfrequenz;
|
||||||
sender->bandwidth = 4000; /* default is overwritten by dsp.c */
|
|
||||||
sender->sample_deviation = 0.2; /* default is overwritten by dsp.c */
|
|
||||||
strncpy(sender->audiodev, audiodev, sizeof(sender->audiodev) - 1);
|
strncpy(sender->audiodev, audiodev, sizeof(sender->audiodev) - 1);
|
||||||
sender->samplerate = samplerate;
|
sender->samplerate = samplerate;
|
||||||
sender->rx_gain = rx_gain;
|
sender->rx_gain = rx_gain;
|
||||||
|
@ -168,21 +166,21 @@ int sender_open_audio(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (master->write_rx_wave) {
|
if (master->write_rx_wave) {
|
||||||
rc = wave_create_record(&master->wave_rx_rec, master->write_rx_wave, master->samplerate, channels);
|
rc = wave_create_record(&master->wave_rx_rec, master->write_rx_wave, master->samplerate, channels, master->max_deviation);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n");
|
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n");
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (master->write_tx_wave) {
|
if (master->write_tx_wave) {
|
||||||
rc = wave_create_record(&master->wave_tx_rec, master->write_tx_wave, master->samplerate, channels);
|
rc = wave_create_record(&master->wave_tx_rec, master->write_tx_wave, master->samplerate, channels, master->max_deviation);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n");
|
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n");
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (master->read_rx_wave) {
|
if (master->read_rx_wave) {
|
||||||
rc = wave_create_playback(&master->wave_rx_play, master->read_rx_wave, master->samplerate, channels);
|
rc = wave_create_playback(&master->wave_rx_play, master->read_rx_wave, master->samplerate, channels, master->max_deviation);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE playback instance!\n");
|
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE playback instance!\n");
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -190,7 +188,7 @@ int sender_open_audio(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* open device */
|
/* open device */
|
||||||
master->audio = master->audio_open(master->audiodev, tx_f, rx_f, channels, paging_frequency, master->samplerate, master->bandwidth, master->sample_deviation);
|
master->audio = master->audio_open(master->audiodev, tx_f, rx_f, channels, paging_frequency, master->samplerate, master->max_deviation, master->max_modulation);
|
||||||
if (!master->audio) {
|
if (!master->audio) {
|
||||||
PDEBUG(DSENDER, DEBUG_ERROR, "No audio device!\n");
|
PDEBUG(DSENDER, DEBUG_ERROR, "No audio device!\n");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
@ -225,6 +223,17 @@ void sender_destroy(sender_t *sender)
|
||||||
jitter_destroy(&sender->dejitter);
|
jitter_destroy(&sender->dejitter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sender_set_fm(sender_t *sender, double max_deviation, double max_modulation, double dBm0_deviation, double max_display)
|
||||||
|
{
|
||||||
|
sender->max_deviation = max_deviation;
|
||||||
|
sender->max_modulation = max_modulation;
|
||||||
|
sender->dBm0_deviation = dBm0_deviation;
|
||||||
|
sender->max_display = max_display;
|
||||||
|
|
||||||
|
PDEBUG_CHAN(DSENDER, DEBUG_DEBUG, "Maxium deviation: %.1f kHz, Maximum modulation: %.1f kHz\n", max_deviation / 1000.0, max_modulation / 1000.0);
|
||||||
|
PDEBUG_CHAN(DSENDER, DEBUG_DEBUG, "Deviation at dBm0 (audio level): %.1f kHz\n", dBm0_deviation / 1000.0);
|
||||||
|
}
|
||||||
|
|
||||||
static void gain_samples(sample_t *samples, int length, double gain)
|
static void gain_samples(sample_t *samples, int length, double gain)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -278,12 +287,14 @@ cant_recover:
|
||||||
sender_send(inst, samples[i], count);
|
sender_send(inst, samples[i], count);
|
||||||
/* internal loopback: loop back TX audio to RX */
|
/* internal loopback: loop back TX audio to RX */
|
||||||
if (inst->loopback == 1) {
|
if (inst->loopback == 1) {
|
||||||
display_wave(inst, samples[i], count);
|
display_wave(inst, samples[i], count, inst->max_display);
|
||||||
sender_receive(inst, samples[i], count);
|
sender_receive(inst, samples[i], count);
|
||||||
}
|
}
|
||||||
/* do pre emphasis towards radio */
|
/* 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);
|
||||||
|
/* normal level to frequency deviation of dBm0 */
|
||||||
|
gain_samples(samples[i], count, inst->dBm0_deviation);
|
||||||
/* set paging signal */
|
/* set paging signal */
|
||||||
paging_signal[i] = inst->paging_signal;
|
paging_signal[i] = inst->paging_signal;
|
||||||
on[i] = inst->paging_on;
|
on[i] = inst->paging_on;
|
||||||
|
@ -328,6 +339,8 @@ transmit_later:
|
||||||
|
|
||||||
/* loop through all channels */
|
/* loop through all channels */
|
||||||
for (i = 0, inst = sender; inst; i++, inst = inst->slave) {
|
for (i = 0, inst = sender; inst; i++, inst = inst->slave) {
|
||||||
|
/* frequency deviation of dBm0 to normal level */
|
||||||
|
gain_samples(samples[i], count, 1.0 / inst->dBm0_deviation);
|
||||||
/* 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);
|
||||||
|
@ -337,7 +350,7 @@ transmit_later:
|
||||||
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, inst->max_display);
|
||||||
sender_receive(inst, samples[i], count);
|
sender_receive(inst, samples[i], count);
|
||||||
}
|
}
|
||||||
if (inst->loopback == 3)
|
if (inst->loopback == 3)
|
||||||
|
|
|
@ -31,8 +31,12 @@ typedef struct sender {
|
||||||
double sendefrequenz; /* transmitter frequency */
|
double sendefrequenz; /* transmitter frequency */
|
||||||
double empfangsfrequenz; /* receiver frequency */
|
double empfangsfrequenz; /* receiver frequency */
|
||||||
double ruffrequenz; /* special paging frequency used for B-Netz */
|
double ruffrequenz; /* special paging frequency used for B-Netz */
|
||||||
double bandwidth; /* max NF frequency to be transmitted unaffected by filtering */
|
|
||||||
double sample_deviation; /* frequency deviation of one sample step (after pre-emphasis) */
|
/* fm levels */
|
||||||
|
double max_deviation; /* max frequency deviation */
|
||||||
|
double max_modulation; /* max frequency modulated */
|
||||||
|
double dBm0_deviation; /* deviation of 1000 Hz reference tone at dBm0 */
|
||||||
|
double max_display; /* level of displaying wave form */
|
||||||
|
|
||||||
/* audio */
|
/* audio */
|
||||||
void *audio;
|
void *audio;
|
||||||
|
@ -85,6 +89,7 @@ extern int cant_recover;
|
||||||
|
|
||||||
int sender_create(sender_t *sender, int kanal, double sendefrequenz, double empfangsfrequenz, const char *audiodev, int samplerate, double rx_gain, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, int loopback, double loss_volume, enum paging_signal paging_signal);
|
int sender_create(sender_t *sender, int kanal, double sendefrequenz, double empfangsfrequenz, const char *audiodev, int samplerate, double rx_gain, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, int loopback, double loss_volume, enum paging_signal paging_signal);
|
||||||
void sender_destroy(sender_t *sender);
|
void sender_destroy(sender_t *sender);
|
||||||
|
void sender_set_fm(sender_t *sender, double max_deviation, double max_modulation, double dBm0_deviation, double max_display);
|
||||||
int sender_open_audio(void);
|
int sender_open_audio(void);
|
||||||
void process_sender_audio(sender_t *sender, int *quit, int latspl);
|
void process_sender_audio(sender_t *sender, int *quit, int latspl);
|
||||||
void sender_send(sender_t *sender, sample_t *samples, int count);
|
void sender_send(sender_t *sender, sample_t *samples, int count);
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
typedef struct sound {
|
typedef struct sound {
|
||||||
snd_pcm_t *phandle, *chandle;
|
snd_pcm_t *phandle, *chandle;
|
||||||
int pchannels, cchannels;
|
int pchannels, cchannels;
|
||||||
|
double spl_deviation; /* how much deviation is one sample step */
|
||||||
double paging_phaseshift; /* phase to shift every sample */
|
double paging_phaseshift; /* phase to shift every sample */
|
||||||
double paging_phase; /* current phase */
|
double paging_phase; /* current phase */
|
||||||
} sound_t;
|
} sound_t;
|
||||||
|
@ -131,7 +132,7 @@ static int sound_prepare(sound_t *sound)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *sound_open(const char *audiodev, double __attribute__((unused)) *tx_frequency, double __attribute__((unused)) *rx_frequency, int channels, double __attribute__((unused)) paging_frequency, int samplerate, double __attribute__((unused)) bandwidth, double __attribute__((unused)) sample_deviation)
|
void *sound_open(const char *audiodev, double __attribute__((unused)) *tx_frequency, double __attribute__((unused)) *rx_frequency, int channels, double __attribute__((unused)) paging_frequency, int samplerate, double max_deviation, double __attribute__((unused)) max_modulation)
|
||||||
{
|
{
|
||||||
sound_t *sound;
|
sound_t *sound;
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -147,6 +148,7 @@ void *sound_open(const char *audiodev, double __attribute__((unused)) *tx_freque
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sound->spl_deviation = max_deviation / 32767.0;
|
||||||
sound->paging_phaseshift = 1.0 / ((double)samplerate / 1000.0);
|
sound->paging_phaseshift = 1.0 / ((double)samplerate / 1000.0);
|
||||||
|
|
||||||
rc = snd_pcm_open(&sound->phandle, audiodev, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
|
rc = snd_pcm_open(&sound->phandle, audiodev, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
|
||||||
|
@ -252,6 +254,7 @@ static void gen_paging_tone(sound_t *sound, int16_t *samples, int length, enum p
|
||||||
int sound_write(void *inst, sample_t **samples, int num, enum paging_signal *paging_signal, int *on, int channels)
|
int sound_write(void *inst, sample_t **samples, int num, enum paging_signal *paging_signal, int *on, int channels)
|
||||||
{
|
{
|
||||||
sound_t *sound = (sound_t *)inst;
|
sound_t *sound = (sound_t *)inst;
|
||||||
|
double spl_deviation = sound->spl_deviation;
|
||||||
int32_t value;
|
int32_t value;
|
||||||
int16_t buff[num << 1];
|
int16_t buff[num << 1];
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -263,7 +266,7 @@ int sound_write(void *inst, sample_t **samples, int num, enum paging_signal *pag
|
||||||
int16_t paging[num << 1];
|
int16_t paging[num << 1];
|
||||||
gen_paging_tone(sound, paging, num, paging_signal[0], on[0]);
|
gen_paging_tone(sound, paging, num, paging_signal[0], on[0]);
|
||||||
for (i = 0, ii = 0; i < num; i++) {
|
for (i = 0, ii = 0; i < num; i++) {
|
||||||
value = samples[0][i];
|
value = samples[0][i] / spl_deviation;
|
||||||
if (value > 32767)
|
if (value > 32767)
|
||||||
value = 32767;
|
value = 32767;
|
||||||
else if (value < -32767)
|
else if (value < -32767)
|
||||||
|
@ -273,13 +276,13 @@ int sound_write(void *inst, sample_t **samples, int num, enum paging_signal *pag
|
||||||
}
|
}
|
||||||
} else if (channels == 2) {
|
} else if (channels == 2) {
|
||||||
for (i = 0, ii = 0; i < num; i++) {
|
for (i = 0, ii = 0; i < num; i++) {
|
||||||
value = samples[0][i];
|
value = samples[0][i] / spl_deviation;
|
||||||
if (value > 32767)
|
if (value > 32767)
|
||||||
value = 32767;
|
value = 32767;
|
||||||
else if (value < -32767)
|
else if (value < -32767)
|
||||||
value = -32767;
|
value = -32767;
|
||||||
buff[ii++] = value;
|
buff[ii++] = value;
|
||||||
value = samples[1][i];
|
value = samples[1][i] / spl_deviation;
|
||||||
if (value > 32767)
|
if (value > 32767)
|
||||||
value = 32767;
|
value = 32767;
|
||||||
else if (value < -32767)
|
else if (value < -32767)
|
||||||
|
@ -288,7 +291,7 @@ int sound_write(void *inst, sample_t **samples, int num, enum paging_signal *pag
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (i = 0, ii = 0; i < num; i++) {
|
for (i = 0, ii = 0; i < num; i++) {
|
||||||
value = samples[0][i];
|
value = samples[0][i] / spl_deviation;
|
||||||
if (value > 32767)
|
if (value > 32767)
|
||||||
value = 32767;
|
value = 32767;
|
||||||
else if (value < -32767)
|
else if (value < -32767)
|
||||||
|
@ -300,7 +303,7 @@ int sound_write(void *inst, sample_t **samples, int num, enum paging_signal *pag
|
||||||
} else {
|
} else {
|
||||||
/* one channel */
|
/* one channel */
|
||||||
for (i = 0, ii = 0; i < num; i++) {
|
for (i = 0, ii = 0; i < num; i++) {
|
||||||
value = samples[0][i];
|
value = samples[0][i] / spl_deviation;
|
||||||
if (value > 32767)
|
if (value > 32767)
|
||||||
value = 32767;
|
value = 32767;
|
||||||
else if (value < -32767)
|
else if (value < -32767)
|
||||||
|
@ -328,6 +331,7 @@ int sound_write(void *inst, sample_t **samples, int num, enum paging_signal *pag
|
||||||
int sound_read(void *inst, sample_t **samples, int num, int channels)
|
int sound_read(void *inst, sample_t **samples, int num, int channels)
|
||||||
{
|
{
|
||||||
sound_t *sound = (sound_t *)inst;
|
sound_t *sound = (sound_t *)inst;
|
||||||
|
double spl_deviation = sound->spl_deviation;
|
||||||
int16_t buff[num << 1];
|
int16_t buff[num << 1];
|
||||||
int32_t spl;
|
int32_t spl;
|
||||||
int in, rc;
|
int in, rc;
|
||||||
|
@ -361,17 +365,17 @@ int sound_read(void *inst, sample_t **samples, int num, int channels)
|
||||||
for (i = 0, ii = 0; i < rc; i++) {
|
for (i = 0, ii = 0; i < rc; i++) {
|
||||||
spl = buff[ii++];
|
spl = buff[ii++];
|
||||||
spl += buff[ii++];
|
spl += buff[ii++];
|
||||||
samples[0][i] = (sample_t)spl;
|
samples[0][i] = (double)spl * spl_deviation;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (i = 0, ii = 0; i < rc; i++) {
|
for (i = 0, ii = 0; i < rc; i++) {
|
||||||
samples[0][i] = (sample_t)buff[ii++];
|
samples[0][i] = (double)buff[ii++] * spl_deviation;
|
||||||
samples[1][i] = (sample_t)buff[ii++];
|
samples[1][i] = (double)buff[ii++] * spl_deviation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (i = 0, ii = 0; i < rc; i++) {
|
for (i = 0, ii = 0; i < rc; i++) {
|
||||||
samples[0][i] = (sample_t)buff[ii++];
|
samples[0][i] = (double)buff[ii++] * spl_deviation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ struct fmt {
|
||||||
uint16_t bits_sample; /* bits per sample (one channel) */
|
uint16_t bits_sample; /* bits per sample (one channel) */
|
||||||
};
|
};
|
||||||
|
|
||||||
int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate, int channels)
|
int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate, int channels, double max_deviation)
|
||||||
{
|
{
|
||||||
/* RIFFxxxxWAVEfmt xxxx(fmt size)dataxxxx... */
|
/* RIFFxxxxWAVEfmt xxxx(fmt size)dataxxxx... */
|
||||||
char dummyheader[4 + 4 + 4 + 4 + 4 + sizeof(struct fmt) + 4 + 4];
|
char dummyheader[4 + 4 + 4 + 4 + 4 + sizeof(struct fmt) + 4 + 4];
|
||||||
|
@ -43,6 +43,7 @@ int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate, in
|
||||||
memset(rec, 0, sizeof(*rec));
|
memset(rec, 0, sizeof(*rec));
|
||||||
rec->samplerate = samplerate;
|
rec->samplerate = samplerate;
|
||||||
rec->channels = channels;
|
rec->channels = channels;
|
||||||
|
rec->max_deviation = max_deviation;
|
||||||
|
|
||||||
rec->fp = fopen(filename, "w");
|
rec->fp = fopen(filename, "w");
|
||||||
if (!rec->fp) {
|
if (!rec->fp) {
|
||||||
|
@ -58,7 +59,7 @@ int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate, in
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wave_create_playback(wave_play_t *play, const char *filename, int samplerate, int channels)
|
int wave_create_playback(wave_play_t *play, const char *filename, int samplerate, int channels, double max_deviation)
|
||||||
{
|
{
|
||||||
uint8_t buffer[256];
|
uint8_t buffer[256];
|
||||||
struct fmt fmt;
|
struct fmt fmt;
|
||||||
|
@ -68,6 +69,7 @@ int wave_create_playback(wave_play_t *play, const char *filename, int samplerate
|
||||||
|
|
||||||
memset(play, 0, sizeof(*play));
|
memset(play, 0, sizeof(*play));
|
||||||
play->channels = channels;
|
play->channels = channels;
|
||||||
|
play->max_deviation = max_deviation;
|
||||||
|
|
||||||
play->fp = fopen(filename, "r");
|
play->fp = fopen(filename, "r");
|
||||||
if (!play->fp) {
|
if (!play->fp) {
|
||||||
|
@ -196,6 +198,8 @@ error:
|
||||||
|
|
||||||
int wave_read(wave_play_t *play, sample_t **samples, int length)
|
int wave_read(wave_play_t *play, sample_t **samples, int length)
|
||||||
{
|
{
|
||||||
|
double max_deviation = play->max_deviation;
|
||||||
|
int16_t value; /* must be int16, so assembling bytes work */
|
||||||
uint8_t buff[2 * length * play->channels];
|
uint8_t buff[2 * length * play->channels];
|
||||||
int __attribute__((__unused__)) len;
|
int __attribute__((__unused__)) len;
|
||||||
int i, j, c;
|
int i, j, c;
|
||||||
|
@ -212,11 +216,12 @@ int wave_read(wave_play_t *play, sample_t **samples, int length)
|
||||||
if (!play->left)
|
if (!play->left)
|
||||||
printf("*** Finished reading WAVE file.\n");
|
printf("*** Finished reading WAVE file.\n");
|
||||||
|
|
||||||
/* read and correct endiness */
|
/* read and correct endianness */
|
||||||
len = fread(buff, 1, 2 * length * play->channels, play->fp);
|
len = fread(buff, 1, 2 * length * play->channels, play->fp);
|
||||||
for (i = 0, j = 0; i < length; i++) {
|
for (i = 0, j = 0; i < length; i++) {
|
||||||
for (c = 0; c < play->channels; c++) {
|
for (c = 0; c < play->channels; c++) {
|
||||||
samples[c][i] = (double)(buff[j] + (buff[j + 1] << 8));
|
value = buff[j] + (buff[j + 1] << 8);
|
||||||
|
samples[c][i] = (double)value / 32767.0 * max_deviation;
|
||||||
j += 2;
|
j += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,15 +231,16 @@ int wave_read(wave_play_t *play, sample_t **samples, int length)
|
||||||
|
|
||||||
int wave_write(wave_rec_t *rec, sample_t **samples, int length)
|
int wave_write(wave_rec_t *rec, sample_t **samples, int length)
|
||||||
{
|
{
|
||||||
|
double max_deviation = rec->max_deviation;
|
||||||
int32_t value;
|
int32_t value;
|
||||||
uint8_t buff[2 * length * rec->channels];
|
uint8_t buff[2 * length * rec->channels];
|
||||||
int __attribute__((__unused__)) len;
|
int __attribute__((__unused__)) len;
|
||||||
int i, j, c;
|
int i, j, c;
|
||||||
|
|
||||||
/* write and correct endiness */
|
/* write and correct endianness */
|
||||||
for (i = 0, j = 0; i < length; i++) {
|
for (i = 0, j = 0; i < length; i++) {
|
||||||
for (c = 0; c < rec->channels; c++) {
|
for (c = 0; c < rec->channels; c++) {
|
||||||
value = samples[c][i];
|
value = samples[c][i] / max_deviation * 32767.0;
|
||||||
if (value > 32767)
|
if (value > 32767)
|
||||||
value = 32767;
|
value = 32767;
|
||||||
else if (value < -32767)
|
else if (value < -32767)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
typedef struct wave_rec {
|
typedef struct wave_rec {
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int channels;
|
int channels;
|
||||||
|
double max_deviation;
|
||||||
int samplerate;
|
int samplerate;
|
||||||
uint32_t written; /* how much samples written */
|
uint32_t written; /* how much samples written */
|
||||||
} wave_rec_t;
|
} wave_rec_t;
|
||||||
|
@ -9,11 +10,12 @@ typedef struct wave_rec {
|
||||||
typedef struct wave_play {
|
typedef struct wave_play {
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int channels;
|
int channels;
|
||||||
|
double max_deviation;
|
||||||
uint32_t left; /* how much samples left */
|
uint32_t left; /* how much samples left */
|
||||||
} wave_play_t;
|
} wave_play_t;
|
||||||
|
|
||||||
int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate, int channels);
|
int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate, int channels, double max_deviation);
|
||||||
int wave_create_playback(wave_play_t *play, const char *filename, int samplerate, int channels);
|
int wave_create_playback(wave_play_t *play, const char *filename, int samplerate, int channels, double max_deviation);
|
||||||
int wave_read(wave_play_t *play, sample_t **samples, int length);
|
int wave_read(wave_play_t *play, sample_t **samples, int length);
|
||||||
int wave_write(wave_rec_t *rec, sample_t **samples, int length);
|
int wave_write(wave_rec_t *rec, sample_t **samples, int length);
|
||||||
void wave_destroy_record(wave_rec_t *rec);
|
void wave_destroy_record(wave_rec_t *rec);
|
||||||
|
|
120
src/nmt/dsp.c
120
src/nmt/dsp.c
|
@ -34,23 +34,36 @@
|
||||||
|
|
||||||
#define PI M_PI
|
#define PI M_PI
|
||||||
|
|
||||||
/* Notes on frequency deviation of supervidory signal:
|
/* Notes on TX_PEAK_FSK level:
|
||||||
*
|
*
|
||||||
* The FSK deviation at 1500 Hz is 3.5 KHz. If we use a level of 10000
|
* This deviation is -2.2db below the dBm0 deviation.
|
||||||
* The supervisory deviation shall be 0.3 KHz: 10000 / 3.5 * 0.3 = 857
|
*
|
||||||
* Supervisory is raised by pre-emphasis by factor 2.68 (4015 / 1500),
|
* At 1800 Hz the deviation shall be 4.2 kHz, so with emphasis the deviation
|
||||||
* so we need to lower it: 857 / 2.68 = 320
|
* at 1000 Hz would be theoretically 2.333 kHz. This is factor 0.777 below
|
||||||
|
* 3 kHz deviation we want at dBm0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Notes on TX_PEAK_SUPER (supervisory signal) level:
|
||||||
|
*
|
||||||
|
* This level has 0.3 kHz deviation at 4015 Hz.
|
||||||
|
*
|
||||||
|
* Same calculation as above, but now we want 0.3 kHz deviation after emphasis,
|
||||||
|
* so we calculate what we would need at 1000 Hz in relation to 3 kHz
|
||||||
|
* deviation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* signaling */
|
/* signaling */
|
||||||
#define BANDWIDTH 6000.0 /* maximum bandwidth FIXME */
|
#define MAX_DEVIATION 4700.0
|
||||||
#define COMPANDOR_0DB 32767 /* works quite well */
|
#define MAX_MODULATION 4055.0
|
||||||
#define TX_PEAK_FSK 10000.0 /* peak amplitude of signaling FSK +-3.5 KHz @ 1500 Hz */
|
#define DBM0_DEVIATION 3000.0 /* deviation of dBm0 at 1 kHz */
|
||||||
#define TX_PEAK_SUPER (TX_PEAK_FSK / 3.5 * 0.3 / 2.68) /* peak amplitude of supervisory signal +-0.3 KHz @ 4015 Hz */
|
#define COMPANDOR_0DB 1.0 /* A level of 0dBm (1.0) shall be unaccected */
|
||||||
|
#define TX_PEAK_FSK (4200.0 / 1800.0 * 1000.0 / DBM0_DEVIATION)
|
||||||
|
#define TX_PEAK_SUPER (300.0 / 4015.0 * 1000.0 / DBM0_DEVIATION)
|
||||||
|
#define MAX_DISPLAY 1.4 /* something above dBm0 */
|
||||||
#define BIT_RATE 1200 /* baud rate */
|
#define BIT_RATE 1200 /* baud rate */
|
||||||
#define STEPS_PER_BIT 10 /* step every 1/12000 sec */
|
#define FILTER_STEPS 0.1 /* step every 1/12000 sec */
|
||||||
#define DIALTONE_HZ 425.0 /* dial tone frequency */
|
#define DIALTONE_HZ 425.0 /* dial tone frequency */
|
||||||
#define TX_PEAK_DIALTONE 16000.0 /* dial tone peak */
|
#define TX_PEAK_DIALTONE 0.5 /* dial tone peak FIXME */
|
||||||
#define SUPER_DURATION 0.25 /* duration of supervisory signal measurement */
|
#define SUPER_DURATION 0.25 /* duration of supervisory signal measurement */
|
||||||
#define SUPER_DETECT_COUNT 4 /* number of measures to detect supervisory signal */
|
#define SUPER_DETECT_COUNT 4 /* number of measures to detect supervisory signal */
|
||||||
#define MUTE_DURATION 0.280 /* a tiny bit more than two frames */
|
#define MUTE_DURATION 0.280 /* a tiny bit more than two frames */
|
||||||
|
@ -71,9 +84,9 @@ static double super_freq[5] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* table for fast sine generation */
|
/* table for fast sine generation */
|
||||||
static double dsp_tone_bit[2][2][256]; /* polarity, bit, phase */
|
static sample_t dsp_tone_bit[2][2][65536]; /* polarity, bit, phase */
|
||||||
static double dsp_sine_super[256];
|
static sample_t dsp_sine_super[65536];
|
||||||
static double dsp_sine_dialtone[256];
|
static sample_t dsp_sine_dialtone[65536];
|
||||||
|
|
||||||
/* global init for FSK */
|
/* global init for FSK */
|
||||||
void dsp_init(void)
|
void dsp_init(void)
|
||||||
|
@ -82,8 +95,8 @@ void dsp_init(void)
|
||||||
double s;
|
double s;
|
||||||
|
|
||||||
PDEBUG(DDSP, DEBUG_DEBUG, "Generating sine table for supervisory signal.\n");
|
PDEBUG(DDSP, DEBUG_DEBUG, "Generating sine table for supervisory signal.\n");
|
||||||
for (i = 0; i < 256; i++) {
|
for (i = 0; i < 65536; i++) {
|
||||||
s = sin((double)i / 256.0 * 2.0 * PI);
|
s = sin((double)i / 65536.0 * 2.0 * PI);
|
||||||
/* supervisor sine */
|
/* supervisor sine */
|
||||||
dsp_sine_super[i] = s * TX_PEAK_SUPER;
|
dsp_sine_super[i] = s * TX_PEAK_SUPER;
|
||||||
/* dialtone sine */
|
/* dialtone sine */
|
||||||
|
@ -92,7 +105,7 @@ void dsp_init(void)
|
||||||
dsp_tone_bit[0][1][i] = s * TX_PEAK_FSK;
|
dsp_tone_bit[0][1][i] = s * TX_PEAK_FSK;
|
||||||
dsp_tone_bit[1][1][i] = -s * TX_PEAK_FSK;
|
dsp_tone_bit[1][1][i] = -s * TX_PEAK_FSK;
|
||||||
/* bit(0) 1.5 cycles */
|
/* bit(0) 1.5 cycles */
|
||||||
s = sin((double)i / 256.0 * 3.0 * PI);
|
s = sin((double)i / 65536.0 * 3.0 * PI);
|
||||||
dsp_tone_bit[0][0][i] = s * TX_PEAK_FSK;
|
dsp_tone_bit[0][0][i] = s * TX_PEAK_FSK;
|
||||||
dsp_tone_bit[1][0][i] = -s * TX_PEAK_FSK;
|
dsp_tone_bit[1][0][i] = -s * TX_PEAK_FSK;
|
||||||
}
|
}
|
||||||
|
@ -115,9 +128,8 @@ int dsp_init_sender(nmt_t *nmt)
|
||||||
|
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init DSP for Transceiver.\n");
|
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init DSP for Transceiver.\n");
|
||||||
|
|
||||||
/* set deviation and modulation parameters */
|
/* set modulation parameters */
|
||||||
nmt->sender.bandwidth = BANDWIDTH;
|
sender_set_fm(&nmt->sender, MAX_DEVIATION, MAX_MODULATION, DBM0_DEVIATION, MAX_DISPLAY);
|
||||||
nmt->sender.sample_deviation = 2500.0 / (double)TX_PEAK_FSK; // FIXME: calc real value
|
|
||||||
|
|
||||||
PDEBUG(DDSP, DEBUG_DEBUG, "Using FSK level of %.0f (3.5 KHz deviation @ 1500 Hz)\n", TX_PEAK_FSK);
|
PDEBUG(DDSP, DEBUG_DEBUG, "Using FSK level of %.0f (3.5 KHz deviation @ 1500 Hz)\n", TX_PEAK_FSK);
|
||||||
PDEBUG(DDSP, DEBUG_DEBUG, "Using Supervisory level of %.0f (0.3 KHz deviation @ 4015 Hz)\n", TX_PEAK_SUPER);
|
PDEBUG(DDSP, DEBUG_DEBUG, "Using Supervisory level of %.0f (0.3 KHz deviation @ 4015 Hz)\n", TX_PEAK_SUPER);
|
||||||
|
@ -166,22 +178,22 @@ int dsp_init_sender(nmt_t *nmt)
|
||||||
/* count symbols */
|
/* count symbols */
|
||||||
for (i = 0; i < 2; i++)
|
for (i = 0; i < 2; i++)
|
||||||
audio_goertzel_init(&nmt->fsk_goertzel[i], fsk_freq[i], nmt->sender.samplerate);
|
audio_goertzel_init(&nmt->fsk_goertzel[i], fsk_freq[i], nmt->sender.samplerate);
|
||||||
nmt->fsk_phaseshift256 = 256.0 / nmt->fsk_samples_per_bit;
|
nmt->fsk_phaseshift65536 = 65536.0 / nmt->fsk_samples_per_bit;
|
||||||
PDEBUG(DDSP, DEBUG_DEBUG, "fsk_phaseshift = %.4f\n", nmt->fsk_phaseshift256);
|
PDEBUG(DDSP, DEBUG_DEBUG, "fsk_phaseshift = %.4f\n", nmt->fsk_phaseshift65536);
|
||||||
|
|
||||||
/* count supervidory tones */
|
/* count supervidory tones */
|
||||||
for (i = 0; i < 5; i++) {
|
for (i = 0; i < 5; i++) {
|
||||||
audio_goertzel_init(&nmt->super_goertzel[i], super_freq[i], nmt->sender.samplerate);
|
audio_goertzel_init(&nmt->super_goertzel[i], super_freq[i], nmt->sender.samplerate);
|
||||||
if (i < 4) {
|
if (i < 4) {
|
||||||
nmt->super_phaseshift256[i] = 256.0 / ((double)nmt->sender.samplerate / super_freq[i]);
|
nmt->super_phaseshift65536[i] = 65536.0 / ((double)nmt->sender.samplerate / super_freq[i]);
|
||||||
PDEBUG(DDSP, DEBUG_DEBUG, "super_phaseshift[%d] = %.4f\n", i, nmt->super_phaseshift256[i]);
|
PDEBUG(DDSP, DEBUG_DEBUG, "super_phaseshift[%d] = %.4f\n", i, nmt->super_phaseshift65536[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
super_reset(nmt);
|
super_reset(nmt);
|
||||||
|
|
||||||
/* dial tone */
|
/* dial tone */
|
||||||
nmt->dial_phaseshift256 = 256.0 / ((double)nmt->sender.samplerate / DIALTONE_HZ);
|
nmt->dial_phaseshift65536 = 65536.0 / ((double)nmt->sender.samplerate / DIALTONE_HZ);
|
||||||
PDEBUG(DDSP, DEBUG_DEBUG, "dial_phaseshift = %.4f\n", nmt->dial_phaseshift256);
|
PDEBUG(DDSP, DEBUG_DEBUG, "dial_phaseshift = %.4f\n", nmt->dial_phaseshift65536);
|
||||||
|
|
||||||
/* dtmf */
|
/* dtmf */
|
||||||
dtmf_init(&nmt->dtmf, 8000);
|
dtmf_init(&nmt->dtmf, 8000);
|
||||||
|
@ -305,9 +317,8 @@ static inline void fsk_decode_step(nmt_t *nmt, int pos)
|
||||||
|
|
||||||
level = audio_level(spl, max);
|
level = audio_level(spl, max);
|
||||||
/* limit level to prevent division by zero */
|
/* limit level to prevent division by zero */
|
||||||
if (level < 0.01)
|
if (level < 0.001)
|
||||||
level = 0.01;
|
level = 0.001;
|
||||||
// level = 0.63662 / 2.0;
|
|
||||||
|
|
||||||
audio_goertzel(nmt->fsk_goertzel, spl, max, pos, result, 2);
|
audio_goertzel(nmt->fsk_goertzel, spl, max, pos, result, 2);
|
||||||
|
|
||||||
|
@ -353,9 +364,9 @@ static inline void fsk_decode_step(nmt_t *nmt, int pos)
|
||||||
printf("|%s|\n", debug_amplitude(quality));
|
printf("|%s|\n", debug_amplitude(quality));
|
||||||
#endif
|
#endif
|
||||||
/* adjust level, so a peak level becomes 100% */
|
/* adjust level, so a peak level becomes 100% */
|
||||||
fsk_receive_bit(nmt, bit, quality, level / 0.63662 * 32768.0 / TX_PEAK_FSK);
|
fsk_receive_bit(nmt, bit, quality, level / 0.63662 / TX_PEAK_FSK);
|
||||||
if (nmt->dms_call)
|
if (nmt->dms_call)
|
||||||
fsk_receive_bit_dms(nmt, bit, quality, level / 0.63662 * 32768.0 / TX_PEAK_FSK);
|
fsk_receive_bit_dms(nmt, bit, quality, level / 0.63662 / TX_PEAK_FSK);
|
||||||
nmt->fsk_filter_sample = 10;
|
nmt->fsk_filter_sample = 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -368,26 +379,19 @@ static void super_decode(nmt_t *nmt, sample_t *samples, int length)
|
||||||
audio_goertzel(&nmt->super_goertzel[nmt->supervisory - 1], samples, length, 0, &result[0], 1);
|
audio_goertzel(&nmt->super_goertzel[nmt->supervisory - 1], samples, length, 0, &result[0], 1);
|
||||||
audio_goertzel(&nmt->super_goertzel[4], samples, length, 0, &result[1], 1); /* noise floor detection */
|
audio_goertzel(&nmt->super_goertzel[4], samples, length, 0, &result[1], 1); /* noise floor detection */
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* normalize levels */
|
|
||||||
result[0] *= 32768.0 / TX_PEAK_SUPER / 0.63662;
|
|
||||||
result[1] *= 32768.0 / TX_PEAK_SUPER / 0.63662;
|
|
||||||
printf("signal=%.4f noise=%.4f\n", result[0], result[1]);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
quality = (result[0] - result[1]) / result[0];
|
quality = (result[0] - result[1]) / result[0];
|
||||||
if (quality < 0)
|
if (quality < 0)
|
||||||
quality = 0;
|
quality = 0;
|
||||||
|
|
||||||
if (nmt->state == STATE_ACTIVE)
|
if (nmt->state == STATE_ACTIVE)
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_NOTICE, "Supervisory level %.0f%% quality %.0f%%\n", result[0] / 0.63662 * 32768.0 / TX_PEAK_SUPER * 100.0, quality * 100.0);
|
PDEBUG_CHAN(DDSP, DEBUG_NOTICE, "Supervisory level %.0f%% quality %.0f%%\n", result[0] / 0.63662 / TX_PEAK_SUPER * 100.0, quality * 100.0);
|
||||||
if (quality > 0.5) {
|
if (quality > 0.5) {
|
||||||
if (nmt->super_detected == 0) {
|
if (nmt->super_detected == 0) {
|
||||||
nmt->super_detect_count++;
|
nmt->super_detect_count++;
|
||||||
if (nmt->super_detect_count == SUPER_DETECT_COUNT) {
|
if (nmt->super_detect_count == SUPER_DETECT_COUNT) {
|
||||||
nmt->super_detected = 1;
|
nmt->super_detected = 1;
|
||||||
nmt->super_detect_count = 0;
|
nmt->super_detect_count = 0;
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Supervisory signal detected with level=%.0f%%, quality=%.0f%%.\n", result[0] / 0.63662 * 32768.0 / TX_PEAK_SUPER * 100.0, quality * 100.0);
|
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Supervisory signal detected with level=%.0f%%, quality=%.0f%%.\n", result[0] / 0.63662 / TX_PEAK_SUPER * 100.0, quality * 100.0);
|
||||||
nmt_rx_super(nmt, 1, quality);
|
nmt_rx_super(nmt, 1, quality);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
|
@ -497,21 +501,21 @@ int fsk_render_frame(nmt_t *nmt, const char *frame, int length, sample_t *sample
|
||||||
int count = 0, i;
|
int count = 0, i;
|
||||||
|
|
||||||
polarity = nmt->fsk_polarity;
|
polarity = nmt->fsk_polarity;
|
||||||
phaseshift = nmt->fsk_phaseshift256;
|
phaseshift = nmt->fsk_phaseshift65536;
|
||||||
phase = nmt->fsk_phase256;
|
phase = nmt->fsk_phase65536;
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
bit = (frame[i] == '1');
|
bit = (frame[i] == '1');
|
||||||
do {
|
do {
|
||||||
*sample++ = dsp_tone_bit[polarity][bit][(uint8_t)phase];
|
*sample++ = dsp_tone_bit[polarity][bit][(uint16_t)phase];
|
||||||
count++;
|
count++;
|
||||||
phase += phaseshift;
|
phase += phaseshift;
|
||||||
} while (phase < 256.0);
|
} while (phase < 65536.0);
|
||||||
phase -= 256.0;
|
phase -= 65536.0;
|
||||||
/* flip polarity when we have 1.5 sine waves */
|
/* flip polarity when we have 1.5 sine waves */
|
||||||
if (bit == 0)
|
if (bit == 0)
|
||||||
polarity = 1 - polarity;
|
polarity = 1 - polarity;
|
||||||
}
|
}
|
||||||
nmt->fsk_phase256 = phase;
|
nmt->fsk_phase65536 = phase;
|
||||||
nmt->fsk_polarity = polarity;
|
nmt->fsk_polarity = polarity;
|
||||||
|
|
||||||
/* return number of samples created for frame */
|
/* return number of samples created for frame */
|
||||||
|
@ -570,17 +574,17 @@ static void super_encode(nmt_t *nmt, sample_t *samples, int length)
|
||||||
double phaseshift, phase;
|
double phaseshift, phase;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
phaseshift = nmt->super_phaseshift256[nmt->supervisory - 1];
|
phaseshift = nmt->super_phaseshift65536[nmt->supervisory - 1];
|
||||||
phase = nmt->super_phase256;
|
phase = nmt->super_phase65536;
|
||||||
|
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
*samples++ += dsp_sine_super[(uint8_t)phase];
|
*samples++ += dsp_sine_super[(uint16_t)phase];
|
||||||
phase += phaseshift;
|
phase += phaseshift;
|
||||||
if (phase >= 256)
|
if (phase >= 65536)
|
||||||
phase -= 256;
|
phase -= 65536;
|
||||||
}
|
}
|
||||||
|
|
||||||
nmt->super_phase256 = phase;
|
nmt->super_phase65536 = phase;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate audio stream from dial tone. Keep phase for next call of function. */
|
/* Generate audio stream from dial tone. Keep phase for next call of function. */
|
||||||
|
@ -589,17 +593,17 @@ static void dial_tone(nmt_t *nmt, sample_t *samples, int length)
|
||||||
double phaseshift, phase;
|
double phaseshift, phase;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
phaseshift = nmt->dial_phaseshift256;
|
phaseshift = nmt->dial_phaseshift65536;
|
||||||
phase = nmt->dial_phase256;
|
phase = nmt->dial_phase65536;
|
||||||
|
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
*samples++ = dsp_sine_dialtone[(uint8_t)phase];
|
*samples++ = dsp_sine_dialtone[(uint16_t)phase];
|
||||||
phase += phaseshift;
|
phase += phaseshift;
|
||||||
if (phase >= 256)
|
if (phase >= 65536)
|
||||||
phase -= 256;
|
phase -= 65536;
|
||||||
}
|
}
|
||||||
|
|
||||||
nmt->dial_phase256 = phase;
|
nmt->dial_phase65536 = phase;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Provide stream of audio toward radio unit */
|
/* Provide stream of audio toward radio unit */
|
||||||
|
|
|
@ -1452,7 +1452,7 @@ void nmt_receive_frame(nmt_t *nmt, const char *bits, double quality, double leve
|
||||||
frame_t frame;
|
frame_t frame;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_INFO, "RX Level: %.0f%% Quality=%.0f\n", level * 100.0 + 0.5, quality * 100.0 + 0.5);
|
PDEBUG_CHAN(DDSP, DEBUG_INFO, "RX Level: %.0f%% Quality=%.0f\n", level * 100.0, quality * 100.0);
|
||||||
|
|
||||||
rc = decode_frame(&frame, bits, (nmt->sender.loopback) ? MTX_TO_XX : XX_TO_MTX, (nmt->state == STATE_MT_PAGING));
|
rc = decode_frame(&frame, bits, (nmt->sender.loopback) ? MTX_TO_XX : XX_TO_MTX, (nmt->state == STATE_MT_PAGING));
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
|
|
|
@ -113,12 +113,12 @@ typedef struct nmt {
|
||||||
double fsk_filter_quality[256];/* quality infos */
|
double fsk_filter_quality[256];/* quality infos */
|
||||||
sample_t *super_filter_spl; /* array with sample buffer for supervisory detection */
|
sample_t *super_filter_spl; /* array with sample buffer for supervisory detection */
|
||||||
int super_filter_pos; /* current sample position in filter_spl */
|
int super_filter_pos; /* current sample position in filter_spl */
|
||||||
double super_phaseshift256[4]; /* how much the phase of sine wave changes per sample */
|
double super_phaseshift65536[4];/* how much the phase of sine wave changes per sample */
|
||||||
double super_phase256; /* current phase */
|
double super_phase65536; /* current phase */
|
||||||
double dial_phaseshift256; /* how much the phase of sine wave changes per sample */
|
double dial_phaseshift65536; /* how much the phase of sine wave changes per sample */
|
||||||
double dial_phase256; /* current phase */
|
double dial_phase65536; /* current phase */
|
||||||
double fsk_phaseshift256; /* how much the phase of fsk synbol changes per sample */
|
double fsk_phaseshift65536; /* how much the phase of fsk synbol changes per sample */
|
||||||
double fsk_phase256; /* current phase */
|
double fsk_phase65536; /* current phase */
|
||||||
sample_t *frame_spl; /* samples to store a complete rendered frame */
|
sample_t *frame_spl; /* samples to store a complete rendered frame */
|
||||||
int frame_size; /* total size of sample buffer */
|
int frame_size; /* total size of sample buffer */
|
||||||
int frame_length; /* current length of data in sample buffer */
|
int frame_length; /* current length of data in sample buffer */
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
#define SAMPLERATE 48000
|
#define SAMPLERATE 48000
|
||||||
|
|
||||||
static double get_level(double *samples)
|
static double get_level(sample_t *samples)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
double envelope = 0;
|
double envelope = 0;
|
||||||
|
@ -24,7 +24,7 @@ static double get_level(double *samples)
|
||||||
return envelope;
|
return envelope;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_samples(double *samples, double freq)
|
static void gen_samples(sample_t *samples, double freq)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
double value;
|
double value;
|
||||||
|
@ -39,7 +39,7 @@ int main(void)
|
||||||
{
|
{
|
||||||
emphasis_t estate;
|
emphasis_t estate;
|
||||||
double cut_off = CUT_OFF_EMPHASIS_DEFAULT;
|
double cut_off = CUT_OFF_EMPHASIS_DEFAULT;
|
||||||
double samples[SAMPLERATE];
|
sample_t samples[SAMPLERATE];
|
||||||
double level;
|
double level;
|
||||||
double i;
|
double i;
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
#define SAMPLERATE 48000
|
#define SAMPLERATE 48000
|
||||||
|
|
||||||
static double get_level(double *samples)
|
static double get_level(sample_t *samples)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
double envelope = 0;
|
double envelope = 0;
|
||||||
|
@ -23,7 +23,7 @@ static double get_level(double *samples)
|
||||||
return envelope;
|
return envelope;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_samples(double *samples, double freq)
|
static void gen_samples(sample_t *samples, double freq)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
double value;
|
double value;
|
||||||
|
@ -38,7 +38,7 @@ int main(void)
|
||||||
{
|
{
|
||||||
filter_t filter_low;
|
filter_t filter_low;
|
||||||
filter_t filter_high;
|
filter_t filter_high;
|
||||||
double samples[SAMPLERATE];
|
sample_t samples[SAMPLERATE];
|
||||||
double level;
|
double level;
|
||||||
int iter = 2;
|
int iter = 2;
|
||||||
int i;
|
int i;
|
||||||
|
|
Loading…
Reference in New Issue