Browse Source

CTCSS or baseband audio on right channel

Some codec mode '1300C' preparation.
master
Jeroen Vreeken 3 years ago
parent
commit
b54474ec6a
10 changed files with 160 additions and 31 deletions
  1. +4
    -1
      Makefile.am
  2. +3
    -0
      analog_trx.c
  3. +5
    -5
      ctcss.c
  4. +22
    -13
      emphasis.c
  5. +77
    -0
      emphasis_test.c
  6. +1
    -0
      eth_ar/eth_ar.h
  7. +4
    -1
      freedv_eth.c
  8. +8
    -1
      freedv_eth.conf
  9. +7
    -2
      freedv_eth.h
  10. +29
    -8
      freedv_eth_txa.c

+ 4
- 1
Makefile.am View File

@ -12,7 +12,7 @@ nobase_include_HEADERS = eth_ar/eth_ar.h eth_ar/fprs.h
bin_PROGRAMS = analog_trx freedv_eth fprs2aprs_gate eth_ar_if fprs_request fprs_destination fprs_monitor
noinst_PROGRAMS = fprs_test
noinst_PROGRAMS = fprs_test emphasis_test
analog_trx_SOURCES = sound.c alaw.c dsp.c io.c interface.c analog_trx.c
analog_trx_LDADD = libeth_ar.la
@ -39,3 +39,6 @@ fprs_monitor_LDADD = libeth_ar.la
eth_ar_if_SOURCES = eth_ar_if.c
eth_ar_if_LDADD = libeth_ar.la
emphasis_test_SOURCES = emphasis_test.c emphasis.c
emphasis_test_LDFLAGS = -lm

+ 3
- 0
analog_trx.c View File

@ -475,6 +475,9 @@ int main(int argc, char **argv)
case CODEC2_MODE_700C:
rx_type = ETH_P_CODEC2_700C;
break;
case CODEC2_MODE_1300C:
rx_type = ETH_P_CODEC2_1300C;
break;
}
} else {
rx_codec = NULL;


+ 5
- 5
ctcss.c View File

@ -42,7 +42,7 @@ struct ctcss *ctcss_init(int rate, double f, double amp)
int i;
for (i = 0; i < ctcss->tone_nr; i++) {
ctcss->tone[i] = sin((2*M_PI * f * i) / (double)(rate)) * amp * 16535.0;
ctcss->tone[i] = sin((2*M_PI * f * i) / (double)(rate)) * amp * 32767.0;
}
return ctcss;
@ -66,10 +66,10 @@ int ctcss_add(struct ctcss *ctcss, int16_t *sound, int nr)
sample += ctcss->tone[ctcss->cur];
if (sample > 16535)
sample = 16535;
if (sample < -16536)
sample = -16536;
if (sample > 32767)
sample = 32767;
if (sample < -32768)
sample = -32768;
sound[i] = sample;


+ 22
- 13
emphasis.c View File

@ -19,8 +19,8 @@
#include "emphasis.h"
struct emphasis {
float prev_de;
int16_t prev_pre;
int16_t prev_de;
};
struct emphasis *emphasis_init(void)
@ -43,20 +43,27 @@ int emphasis_reset(struct emphasis *emphasis)
return 0;
}
// Set factor to 0.5 for 0db @ 3kHz (3kHz-4kHz is flattened)
// Set factor to 1.0 for 0db @ 1.5kHz (1.33kHz implementation)
#define AFACTOR_PRE 1.0
#define AFACTOR_DE (1.0/AFACTOR_PRE)
int emphasis_pre(struct emphasis *emphasis, int16_t *sound, int nr)
{
int i;
for (i = 0; i < nr; i++) {
long sample = sound[i];
float sample = sound[i];
sample -= emphasis->prev_pre;
emphasis->prev_pre = sound[i];
if (sample > 16535)
sample = 16535;
if (sample < -16536)
sample = -16536;
sample *= AFACTOR_PRE;
if (sample > 32767)
sample = 32767;
if (sample < -32768)
sample = -32768;
sound[i] = sample;
}
@ -69,16 +76,18 @@ int emphasis_de(struct emphasis *emphasis, int16_t *sound, int nr)
int i;
for (i = 0; i < nr; i++) {
long sample = sound[i];
float sample = sound[i];
sample += emphasis->prev_de;
if (sample > 16535)
sample = 16535;
if (sample < -16536)
sample = -16536;
emphasis->prev_de = sample;
sample *= AFACTOR_DE;
if (sample > 32767)
sample = 32767;
if (sample < -32768)
sample = -32768;
sound[i] = sample;
}


+ 77
- 0
emphasis_test.c View File

@ -0,0 +1,77 @@
/*
Copyright Jeroen Vreeken (jeroen@vreeken.net), 2017
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 "emphasis.h"
#include <math.h>
#include <string.h>
#include <stdio.h>
#define NR 8000
#define AMP (16384)
#define STEP 1.1394832
#define FREF 3000
double amp(int16_t *buf_out, int nr)
{
int i;
int amin = 0;
int amax = 0;
for (i = 0; i < nr; i++) {
if (buf_out[i] > amax)
amax = buf_out[i];
if (buf_out[i] < amin)
amin = buf_out[i];
}
double amp = 20*log10((amax - amin)/65536.0);
return amp;
}
int main(int argc, char **argv)
{
struct emphasis *emphasis = emphasis_init();
double f;
int16_t buf_in[NR];
int16_t buf_out[NR];
int i;
for (f = STEP; f < NR/2; f+= STEP) {
printf("%f %f", f, -20*log10((FREF/f)*(32768.0/AMP)));
for(i = 0; i < NR; i++) {
buf_in[i] = AMP * sin(((f * M_PI * 2.0) / NR) * i);
}
memcpy(buf_out, buf_in, sizeof(buf_out));
printf(" %f", amp(buf_out, NR));
emphasis_reset(emphasis);
emphasis_pre(emphasis, buf_out, NR);
printf(" %f", amp(buf_out, NR));
emphasis_reset(emphasis);
emphasis_de(emphasis, buf_out, NR);
printf(" %f", amp(buf_out, NR));
printf("\n");
}
return 0;
}

+ 1
- 0
eth_ar/eth_ar.h View File

@ -40,6 +40,7 @@ extern "C" {
#define ETH_P_ALAW 0x7365
#define ETH_P_FPRS 0x7370
#define ETH_P_ULAW 0x7385
#define ETH_AR_CALL_LEN_MAX 8
#define ETH_AR_CALL_SIZE 9


+ 4
- 1
freedv_eth.c View File

@ -251,6 +251,8 @@ int main(int argc, char **argv)
bool tx_emphasis = atoi(freedv_eth_config_value("analog_tx_emphasis", NULL, "0"));
bool rx_emphasis = atoi(freedv_eth_config_value("analog_rx_emphasis", NULL, "0"));
int dcd_threshold = atoi(freedv_eth_config_value("analog_rx_dcd_threshold", NULL, "1"));
bool tx_bb = atoi(freedv_eth_config_value("analog_tx_baseband", NULL, "0"));
bool tx_tone = atoi(freedv_eth_config_value("analog_tx_tone", NULL, "0"));
if (!strcmp(freedv_mode_str, "1600")) {
freedv_mode = FREEDV_MODE_1600;
@ -407,7 +409,8 @@ int main(int argc, char **argv)
tx_tail_msec,
tx_ctcss_f, tx_ctcss_amp,
beacon_interval, beacon_msg,
tx_emphasis);
tx_emphasis,
tx_bb, tx_tone);
}
if (nmeadev) {


+ 8
- 1
freedv_eth.conf View File

@ -51,7 +51,9 @@
## CTCSS
#analog_tx_ctcss_frequency = 0.0
#analog_tx_ctcss_amp = 0.15
# amp: 1.0 == full deviation (assuming 3kHz)
# 0.17 = about 500Hz
#analog_tx_ctcss_amp = 0.17
## Morse beacon
#analog_tx_beacon_interval = 0
#analog_tx_beacon_message = beacon
@ -60,3 +62,8 @@
#analog_rx_dcd_threshold = 1
#analog_rx_ctcss_frequency = 0.0
## Output baseband on second audio channel (without ctcss, emphasis, beacon)
#analog_tx_baseband = 0
## Output CTCSS tone on second audio channel
#analog_tx_tone = 0

+ 7
- 2
freedv_eth.h View File

@ -43,7 +43,7 @@ static inline uint16_t freedv_eth_mode2type(int mode)
break;
case FREEDV_MODE_2400A:
case FREEDV_MODE_2400B:
type = ETH_P_CODEC2_1300C;
type = ETH_P_CODEC2_1300;
break;
default:
break;
@ -77,6 +77,8 @@ static inline int freedv_eth_type2codecmode(uint16_t type)
return CODEC2_MODE_1300C;
case ETH_P_ALAW:
return 'A';
case ETH_P_ULAW:
return 'U';
default:
break;
}
@ -97,6 +99,7 @@ static inline bool freedv_eth_type_isvoice(uint16_t type)
case ETH_P_CODEC2_700C:
case ETH_P_CODEC2_1300C:
case ETH_P_ALAW:
case ETH_P_ULAW:
return true;
default:
break;
@ -154,7 +157,9 @@ int freedv_eth_txa_init(bool init_fullduplex, int hw_rate,
int tx_tail_msec,
double ctcss_f, double ctcss_amp,
int beacon_interval, char *beacon_msg,
bool emphasis);
bool emphasis,
bool init_output_bb,
bool init_output_tone);
void freedv_eth_txa_state_machine(void);
bool freedv_eth_txa_ptt(void);


+ 29
- 8
freedv_eth_txa.c View File

@ -43,6 +43,8 @@ static struct ctcss *ctcss = NULL;
static struct beacon *beacon = NULL;
static struct emphasis *emphasis_p = NULL;
static int nr_samples = FREEDV_ALAW_NR_SAMPLES;
static bool output_bb = false;
static bool output_tone = false;
static int tx_sound_out(int16_t *samples, int16_t *samples_bb, int nr)
{
@ -68,8 +70,12 @@ static void tx_silence(void)
memset(buffer_bb, 0, sizeof(int16_t)*nr_samples);
if (tx_hadvoice) {
if (ctcss)
ctcss_add(ctcss, buffer, nr_samples);
if (ctcss) {
if (output_tone)
ctcss_add(ctcss, buffer_bb, nr_samples);
else
ctcss_add(ctcss, buffer, nr_samples);
}
if (emphasis_p)
emphasis_pre(emphasis_p, buffer, nr_samples);
}
@ -90,8 +96,12 @@ static void tx_voice(void)
beacon_generate(beacon, buffer, nr_samples);
if (tx_hadvoice) {
if (ctcss)
ctcss_add(ctcss, buffer, nr_samples);
if (ctcss) {
if (output_tone)
ctcss_add(ctcss, buffer_bb, nr_samples);
else
ctcss_add(ctcss, buffer, nr_samples);
}
}
if (emphasis_p)
emphasis_pre(emphasis_p, buffer, nr_samples);
@ -104,14 +114,21 @@ static void tx_voice(void)
tx_hadvoice = true;
memcpy(buffer, packet->data, packet->len);
memcpy(buffer_bb, packet->data, packet->len);
if (output_bb)
memcpy(buffer_bb, packet->data, packet->len);
else
memset(buffer_bb, 0, packet->len);
if (beacon)
beacon_generate_add(beacon, buffer, nr);
if (ctcss)
ctcss_add(ctcss, buffer, nr);
if (emphasis_p)
emphasis_pre(emphasis_p, buffer, nr);
if (ctcss) {
if (output_tone)
ctcss_add(ctcss, buffer_bb, nr);
else
ctcss_add(ctcss, buffer, nr);
}
tx_sound_out(buffer, buffer_bb, nr);
packet = dequeue_voice();
@ -180,11 +197,15 @@ int freedv_eth_txa_init(bool init_fullduplex, int hw_rate,
int tx_tail_msec,
double ctcss_f, double ctcss_amp,
int beacon_interval, char *beacon_msg,
bool emphasis)
bool emphasis,
bool init_output_bb,
bool init_output_tone)
{
int a_rate = FREEDV_ALAW_RATE;
fullduplex = init_fullduplex;
output_bb = init_output_bb;
output_tone = init_output_tone;
tx_state = TX_STATE_OFF;
io_hl_ptt_set(false);


Loading…
Cancel
Save