Browse Source

Strip analog_trx from all trx stuff (dtmf, beacon, ctcss, hamlib).

Also add rate conversion to rx paths in freedv_eth
Simplify sound code.
master
Jeroen Vreeken 4 years ago
parent
commit
0eae0041ca
9 changed files with 130 additions and 350 deletions
  1. +1
    -1
      Makefile.am
  2. +43
    -255
      analog_trx.c
  3. +14
    -6
      freedv_eth.c
  4. +2
    -1
      freedv_eth.h
  5. +27
    -4
      freedv_eth_rx.c
  6. +2
    -2
      freedv_eth_rx.h
  7. +17
    -5
      freedv_eth_rxa.c
  8. +22
    -75
      sound.c
  9. +2
    -1
      sound.h

+ 1
- 1
Makefile.am View File

@ -14,7 +14,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
analog_trx_SOURCES = sound.c alaw.c dsp.c io.c interface.c beacon.c analog_trx.c ctcss.c emphasis.c freedv_eth_rx.c
analog_trx_SOURCES = sound.c alaw.c io.c interface.c analog_trx.c
analog_trx_LDADD = libeth_ar.la
analog_trx_LDFLAGS = -lcodec2 -lsamplerate -lasound -lhamlib


+ 43
- 255
analog_trx.c View File

@ -1,5 +1,5 @@
/*
Copyright Jeroen Vreeken (jeroen@vreeken.net), 2016
Copyright Jeroen Vreeken (jeroen@vreeken.net), 2016, 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
@ -28,28 +28,14 @@
#include <sys/mman.h>
#include <codec2/codec2.h>
#include <codec2/freedv_api.h>
#include "interface.h"
#include <eth_ar/eth_ar.h>
#include "sound.h"
#include "dtmf.h"
#include "alaw.h"
#include "io.h"
#include "beacon.h"
#include "ctcss.h"
#include "emphasis.h"
#include "freedv_eth_rx.h"
static bool verbose = false;
static bool cdc = false;
static bool fullduplex = false;
static ptt_type_t ptt_type = RIG_PTT_NONE;
static dcd_type_t dcd_type = RIG_DCD_NONE;
static int dcd_threshold = 1;
static struct beacon *beacon;
static struct CODEC2 *rx_codec;
static uint16_t rx_type;
@ -61,19 +47,8 @@ static int nr_rx;
static uint8_t mac[6];
static uint8_t bcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
static struct ctcss *ctcss = NULL;
static struct emphasis *emphasis_p = NULL;
static struct emphasis *emphasis_d = NULL;
struct freedv *freedv;
enum tx_state {
TX_STATE_OFF,
TX_STATE_ON,
TX_STATE_TAIL,
};
static enum tx_state tx_state = TX_STATE_OFF;
static struct sound_resample *sr_out = NULL;
static struct sound_resample *sr_in = NULL;
struct tx_packet {
int16_t *samples;
@ -89,14 +64,7 @@ static struct tx_packet *queue_voice = NULL;
static bool squelch(void)
{
bool dcd;
if (dcd_type == RIG_DCD_NONE)
return io_state_rx_get();
dcd = io_hl_dcd_get();
return dcd;
return io_state_rx_get();
}
@ -104,43 +72,37 @@ static void cb_control(char *ctrl)
{
uint8_t *msg = (uint8_t *)ctrl;
printf("DTMF: %s\n", ctrl);
printf("Control: %s\n", ctrl);
interface_rx(bcast, mac, ETH_P_AR_CONTROL, msg, strlen(ctrl));
}
static void cb_sound_in(int16_t *samples_l, int16_t *samples_r, int nr_l, int nr_r)
static void cb_sound_in(int16_t *hw_samples, int16_t *samples_r, int hw_nr, int nr_r)
{
bool rx_state = squelch();
if (freedv)
freedv_eth_rx(freedv, samples_r, nr_r);
int nr;
int16_t *samples;
if (!rx_state) {
cdc = false;
return;
if (sr_in) {
nr = sound_resample_nr_out(sr_in, hw_nr);
samples = alloca(sizeof(int16_t) * nr);
sound_resample_perform(sr_in, samples, hw_samples, nr, hw_nr);
} else {
if (fullduplex || tx_state == TX_STATE_OFF) {
cdc = true;
} else {
return;
}
nr = hw_nr;
samples = hw_samples;
}
if (emphasis_d)
emphasis_de(emphasis_d, samples_l, nr_l);
dtmf_rx(samples_l, nr_l, cb_control);
if (rx_codec) {
while (nr_l) {
while (nr) {
int copy = nr_samples - nr_rx;
if (copy > nr_l)
copy = nr_l;
if (copy > nr)
copy = nr;
memcpy(samples_rx + nr_rx, samples_l, copy * 2);
samples_l += copy;
nr_l -= copy;
memcpy(samples_rx + nr_rx, samples, copy * 2);
samples += copy;
nr -= copy;
nr_rx += copy;
if (nr_rx == nr_samples) {
@ -156,11 +118,11 @@ static void cb_sound_in(int16_t *samples_l, int16_t *samples_r, int nr_l, int nr
}
}
} else {
uint8_t alaw[nr_l];
uint8_t alaw[nr];
alaw_encode(alaw, samples_l, nr_l);
alaw_encode(alaw, samples, nr);
interface_rx(bcast, mac, ETH_P_ALAW, alaw, nr_l);
interface_rx(bcast, mac, ETH_P_ALAW, alaw, nr);
}
}
@ -199,9 +161,6 @@ static int cb_int_tx(uint8_t to[6], uint8_t from[6], uint16_t eth_type, uint8_t
int newmode = 0;
bool is_c2 = true;
if (tx_state == TX_STATE_OFF && (cdc && !fullduplex))
return 0;
switch (eth_type) {
case ETH_P_CODEC2_3200:
newmode = CODEC2_MODE_3200;
@ -302,112 +261,37 @@ static void dequeue_voice(void)
{
struct tx_packet *p = queue_voice;
if (!p) {
if (!beacon) {
sound_silence();
} else {
int16_t buffer[nr_samples];
beacon_generate(beacon, buffer, nr_samples);
if (emphasis_p)
emphasis_pre(emphasis_p, p->samples, p->nr_samples);
sound_out(buffer, nr_samples, true, true);
}
sound_silence();
} else {
queue_voice = p->next;
if (beacon)
beacon_generate_add(beacon, p->samples, p->nr_samples);
if (ctcss)
ctcss_add(ctcss, p->samples, p->nr_samples);
if (emphasis_p)
emphasis_pre(emphasis_p, p->samples, p->nr_samples);
sound_out(p->samples, p->nr_samples, true, true);
if (!sr_out) {
sound_out(p->samples, p->nr_samples, true, true);
} else {
int nr_out = sound_resample_nr_out(sr_out, p->nr_samples);
int16_t hw_mod_out[nr_out];
sound_resample_perform(sr_out, hw_mod_out, p->samples, nr_out, p->nr_samples);
sound_out(hw_mod_out, nr_out, true, true);
}
free(p->samples);
free(p);
}
}
static int tx_tail = 100;
static int tx_state_cnt;
static void tx_state_machine(void)
{
tx_state_cnt++;
bool bcn;
if (beacon) {
bcn = beacon_state_check(beacon);
bcn = bcn && (!cdc || fullduplex);
} else {
bcn = false;
}
switch (tx_state) {
case TX_STATE_OFF:
if (queue_voice || bcn) {
tx_state = TX_STATE_ON;
io_hl_ptt_set(true);
tx_state_cnt = 0;
if (ctcss)
ctcss_reset(ctcss);
} else {
sound_silence();
break;
}
case TX_STATE_ON:
if (!queue_voice && !bcn) {
tx_state = TX_STATE_TAIL;
tx_state_cnt = 0;
} else {
dequeue_voice();
break;
}
case TX_STATE_TAIL:
if (tx_state_cnt >= tx_tail) {
tx_state = TX_STATE_OFF;
tx_state_cnt = 0;
io_hl_ptt_set(false);
sound_silence();
} else {
if (queue_voice || bcn) {
tx_state = TX_STATE_ON;
tx_state_cnt = 0;
dequeue_voice();
} else {
sound_silence();
}
}
}
}
static void usage(void)
{
printf("Options:\n");
printf("-a\tUse A-Law encoding\n");
printf("-B [sec]\tMorse beacon interval\n");
printf("-b [msg]\tMorse beacon message\n");
printf("-c [call]\town callsign\n");
printf("-D [type]\tHAMlib DCD type\n");
printf("-d [thrh]\tDCD threshold (default: %d)\n", dcd_threshold);
printf("-e\tAdd pre-emphasis\n");
printf("-f\tfull-duplex\n");
printf("-F\tEnable FreeDV mode 2400B reception\n");
printf("-I\tUse input device as toggle instead of keypress\n");
printf("-i [dev]\tUse input device instead of DCD\n");
printf("-M [mode]\tCodec2 mode\n");
printf("-m [model]\tHAMlib rig model\n");
printf("-n [dev]\tNetwork device name (default: \"analog\")\n");
printf("-o\tAdd de-emphasis\n");
printf("-P [type]\tHAMlib PTT type\n");
printf("-p [dev]\tHAMlib PTT device file\n");
printf("-r [rate]\tSound rate\n");
printf("-S\tUse socket on existing network device\n");
printf("-s [dev]\tSound device (default: \"default\")\n");
printf("-T [freq]\tAdd CTCSS tone\n");
printf("-t [msec]\tTX tail\n");
printf("-v\tverbose\n");
}
@ -430,60 +314,17 @@ int main(int argc, char **argv)
int mode = CODEC2_MODE_3200;
bool is_c2 = true;
bool tap = true;
int rate = 8000;
int beacon_interval = 0;
char *beacon_msg = NULL;
int freedv_mode = FREEDV_MODE_2400B;
rig_model_t rig_model;
char *ptt_file = NULL;
bool freedv_enabled = false;
rig_model = 1; // set to dummy.
while ((opt = getopt(argc, argv, "aB:b:c:d:D:efFIi:M:m:n:oP:p:r:Ss:t:T:v")) != -1) {
int a_rate = 8000;
int rate = a_rate;
while ((opt = getopt(argc, argv, "ac:Ii:M:n:r:Ss:v")) != -1) {
switch(opt) {
case 'a':
is_c2 = false;
break;
case 'B':
beacon_interval = atoi(optarg);
break;
case 'b':
beacon_msg = optarg;
break;
case 'c':
call = optarg;
break;
case 'D':
if (!strcmp(optarg, "RIG"))
dcd_type = RIG_DCD_RIG;
else if (!strcmp(optarg, "DSR"))
dcd_type = RIG_DCD_SERIAL_DSR;
else if (!strcmp(optarg, "CTS"))
dcd_type = RIG_DCD_SERIAL_CTS;
else if (!strcmp(optarg, "CD"))
dcd_type = RIG_DCD_SERIAL_CAR;
else if (!strcmp(optarg, "PARALLEL"))
dcd_type = RIG_DCD_PARALLEL;
else if (!strcmp(optarg, "CM108"))
dcd_type = RIG_DCD_CM108;
else if (!strcmp(optarg, "NONE"))
dcd_type = RIG_DCD_NONE;
else
dcd_type = atoi(optarg);
break;
case 'd':
dcd_threshold = atoi(optarg);
break;
case 'e':
emphasis_p = emphasis_init();
break;
case 'f':
fullduplex = true;
break;
case 'F':
freedv_enabled = true;
break;
case 'I':
inputtoggle = true;
break;
@ -509,38 +350,9 @@ int main(int argc, char **argv)
mode = CODEC2_MODE_700B;
}
break;
case 'm':
rig_model = atoi(optarg);
break;
case 'n':
netname = optarg;
break;
case 'o':
emphasis_d = emphasis_init();
break;
case 'P':
if (!strcmp(optarg, "RIG"))
ptt_type = RIG_PTT_RIG;
else if (!strcmp(optarg, "DTR"))
ptt_type = RIG_PTT_SERIAL_DTR;
else if (!strcmp(optarg, "RTS"))
ptt_type = RIG_PTT_SERIAL_RTS;
else if (!strcmp(optarg, "PARALLEL"))
ptt_type = RIG_PTT_PARALLEL;
else if (!strcmp(optarg, "CM108"))
ptt_type = RIG_PTT_CM108;
else if (!strcmp(optarg, "GPIO"))
ptt_type = RIG_PTT_GPIO;
else if (!strcmp(optarg, "GPION"))
ptt_type = RIG_PTT_GPION;
else if (!strcmp(optarg, "NONE"))
ptt_type = RIG_PTT_NONE;
else
ptt_type = atoi(optarg);
break;
case 'p':
ptt_file = optarg;
break;
case 'r':
rate = atoi(optarg);
break;
@ -550,15 +362,6 @@ int main(int argc, char **argv)
case 's':
sounddev = optarg;
break;
case 'T': {
double f = atof(optarg);
double amp = 0.15;
ctcss = ctcss_init(rate, f, amp);
break;
}
case 't':
tx_tail = atoi(optarg);
break;
case 'v':
verbose = true;
break;
@ -609,29 +412,18 @@ int main(int argc, char **argv)
samples_rx = calloc(nr_samples, sizeof(samples_rx[0]));
tx_data = calloc(16, sizeof(uint8_t));
int freedv_rate = 0;
if (freedv_enabled) {
freedv = freedv_open(freedv_mode);
freedv_rate = freedv_get_modem_sample_rate(freedv);
freedv_eth_rx_init(freedv, mac);
freedv_set_callback_txt(freedv, freedv_eth_rx_vc_callback, NULL, NULL);
freedv_set_callback_data(freedv, freedv_eth_rx_cb_datarx, NULL, NULL);
}
fd_int = interface_init(netname, mac, tap, 0);
if (sound_init(sounddev, cb_sound_in,
8000,
8000, freedv_rate,
rate)) {
if ((rate = sound_init(sounddev, cb_sound_in, rate)) < 0) {
printf("Could not open sound device\n");
return -1;
}
sound_set_nr(nr_samples);
tx_tail /= 1000 / (8000 / nr_samples);
if (a_rate != rate) {
sr_out = sound_resample_create(rate, a_rate);
sr_in = sound_resample_create(a_rate, rate);
}
io_hl_init(rig_model, dcd_threshold, ptt_type, ptt_file, dcd_type);
dtmf_init();
if (inputdev)
io_init_input(inputdev, inputtoggle);
io_init_tty();
@ -643,10 +435,6 @@ int main(int argc, char **argv)
return -1;
}
if (beacon_interval) {
beacon = beacon_init(rate, nr_samples, beacon_interval, beacon_msg);
}
sound_fdc_tx = sound_poll_count_tx();
sound_fdc_rx = sound_poll_count_rx();
nfds = sound_fdc_tx + sound_fdc_rx + 1;
@ -666,7 +454,7 @@ int main(int argc, char **argv)
do {
poll(fds, nfds, -1);
if (sound_poll_out_tx(fds, sound_fdc_tx)) {
tx_state_machine();
dequeue_voice();
}
if (sound_poll_in_rx(fds + sound_fdc_tx, sound_fdc_rx)) {
sound_rx();


+ 14
- 6
freedv_eth.c View File

@ -87,9 +87,17 @@ static void cb_sound_in(int16_t *samples_l, int16_t *samples_r, int nr_l, int nr
if (rx_mode == RX_MODE_FREEDV ||
rx_mode == RX_MODE_MIXED) {
if (freedv_rx_channel == 0) {
freedv_eth_rx(freedv, samples_l, nr_l);
freedv_eth_rx(samples_l, nr_l);
} else {
freedv_eth_rx(freedv, samples_r, nr_r);
freedv_eth_rx(samples_r, nr_r);
}
}
if (rx_mode == RX_MODE_ANALOG ||
rx_mode == RX_MODE_MIXED) {
if (analog_rx_channel == 0) {
freedv_eth_rxa(samples_l, nr_l);
} else {
freedv_eth_rxa(samples_r, nr_r);
}
}
}
@ -362,11 +370,11 @@ int main(int argc, char **argv)
tx_codecmode = 'S';
}
fd_int = interface_init(netname, mac, true, 0);
int freedv_rate = freedv_get_modem_sample_rate(freedv);
printf("freedv sample rate: %d\n", freedv_rate);
sound_init(sounddev, cb_sound_in, freedv_rate, freedv_rate, freedv_rate, sound_rate);
sound_rate = sound_init(sounddev, cb_sound_in, sound_rate);
if (tx_mode == TX_MODE_FREEDV) {
int freedv_rate = freedv_get_modem_sample_rate(freedv);
printf("freedv sample rate: %d\n", freedv_rate);
nr_samples = freedv_get_n_nom_modem_samples(freedv) * sound_rate / freedv_rate;
} else {
nr_samples = FREEDV_ALAW_NR_SAMPLES * sound_rate / FREEDV_ALAW_RATE;
@ -375,7 +383,7 @@ int main(int argc, char **argv)
sound_set_nr(nr_samples);
freedv_eth_rx_init(freedv, mac);
freedv_eth_rx_init(freedv, mac, sound_rate);
freedv_eth_rxa_init(sound_rate, mac, rx_emphasis);


+ 2
- 1
freedv_eth.h View File

@ -151,6 +151,7 @@ void freedv_eth_txa_state_machine(void);
bool freedv_eth_txa_ptt(void);
bool freedv_eth_rxa_cdc(void);
int freedv_eth_rxa_init(int rate, uint8_t mac_init[6], bool emphasis);
int freedv_eth_rxa_init(int hw_rate, uint8_t mac_init[6], bool emphasis);
void freedv_eth_rxa(int16_t *samples, int nr);
#endif /* _INCLUDE_FREEDV_ETH_H_ */

+ 27
- 4
freedv_eth_rx.c View File

@ -19,6 +19,7 @@
#include "freedv_eth_rx.h"
#include "freedv_eth.h"
#include "interface.h"
#include "sound.h"
#include <string.h>
#include <stdio.h>
@ -35,6 +36,8 @@ static int bytes_per_codec_frame;
static int bytes_per_eth_frame;
static uint16_t eth_type_rx;
static void *silence_packet = NULL;
static struct sound_resample *sr = NULL;
struct freedv *freedv;
static uint8_t rx_add[6], mac[6];
@ -49,8 +52,20 @@ bool freedv_eth_rx_cdc(void)
}
void freedv_eth_rx(struct freedv *freedv, int16_t *samples, int nr)
void freedv_eth_rx(int16_t *hw_samples, int hw_nr)
{
int nr;
int16_t *samples;
if (sr) {
nr = sound_resample_nr_out(sr, hw_nr);
samples = alloca(sizeof(int16_t) * nr);
sound_resample_perform(sr, samples, hw_samples, nr, hw_nr);
} else {
nr = hw_nr;
samples = hw_samples;
}
while (nr) {
int nin = freedv_nin(freedv);
int copy = nin - nr_rx;
@ -71,8 +86,7 @@ void freedv_eth_rx(struct freedv *freedv, int16_t *samples, int nr)
int ret = freedv_codecrx(freedv, packed_codec_bits, samples_rx);
/* Don't 'detect' a voice signal to soon.
Might be nice to have some SNR number from the
2400B mode so we can take it into account */
*/
int sync;
float snr_est;
freedv_get_modem_stats(freedv, &sync, &snr_est);
@ -184,12 +198,21 @@ static void create_silence_packet(struct CODEC2 *c2)
}
int freedv_eth_rx_init(struct freedv *freedv, uint8_t init_mac[6])
int freedv_eth_rx_init(struct freedv *init_freedv, uint8_t init_mac[6], int hw_rate)
{
int nr_samples;
int f_rate = freedv_get_modem_sample_rate(freedv);
freedv = init_freedv;
cdc = false;
sound_resample_destroy(sr);
if (f_rate != hw_rate) {
sr = sound_resample_create(f_rate, hw_rate);
} else {
sr = NULL;
}
bytes_per_eth_frame = codec2_bits_per_frame(freedv_get_codec2(freedv));
bytes_per_eth_frame += 7;
bytes_per_eth_frame /= 8;


+ 2
- 2
freedv_eth_rx.h View File

@ -25,8 +25,8 @@
#include <codec2/freedv_api.h>
#include <eth_ar/eth_ar.h>
int freedv_eth_rx_init(struct freedv *freedv, uint8_t mac[6]);
void freedv_eth_rx(struct freedv *freedv, int16_t *samples, int nr);
int freedv_eth_rx_init(struct freedv *freedv, uint8_t mac[6], int hw_rate);
void freedv_eth_rx(int16_t *samples, int nr);
bool freedv_eth_rx_cdc(void);
void freedv_eth_rx_vc_callback(void *arg, char c);


+ 17
- 5
freedv_eth_rxa.c View File

@ -22,6 +22,7 @@
#include "emphasis.h"
#include "interface.h"
#include "alaw.h"
#include "sound.h"
#include <string.h>
@ -30,6 +31,7 @@ static uint8_t mac[6];
static uint8_t bcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
static bool dtmf_initialized = false;
static bool cdc;
static struct sound_resample *sr = NULL;
bool freedv_eth_rxa_cdc(void)
{
@ -48,25 +50,35 @@ static void cb_control(char *ctrl)
void freedv_eth_rxa(int16_t *samples, int nr)
{
int nr_a = sound_resample_nr_out(sr, nr);
int16_t mod_a[nr_a];
sound_resample_perform(sr, mod_a, samples, nr_a, nr);
cdc = io_hl_dcd_get();
if (emphasis_d)
emphasis_de(emphasis_d, samples, nr);
dtmf_rx(samples, nr, cb_control);
emphasis_de(emphasis_d, mod_a, nr_a);
dtmf_rx(mod_a, nr_a, cb_control);
uint8_t alaw[nr];
uint8_t alaw[nr_a];
alaw_encode(alaw, samples, nr);
alaw_encode(alaw, mod_a, nr_a);
interface_rx(bcast, mac, ETH_P_ALAW, alaw, nr);
}
int freedv_eth_rxa_init(int rate, uint8_t mac_init[6], bool emphasis)
int freedv_eth_rxa_init(int hw_rate, uint8_t mac_init[6], bool emphasis)
{
int a_rate = FREEDV_ALAW_RATE;
memcpy(mac, mac_init, 6);
cdc = false;
sound_resample_destroy(sr);
sr = sound_resample_create(a_rate, hw_rate);
if (!dtmf_initialized) {
dtmf_init();
dtmf_initialized = true;


+ 22
- 75
sound.c View File

@ -27,9 +27,6 @@ static snd_pcm_t *pcm_handle_tx = NULL;
static snd_pcm_t *pcm_handle_rx = NULL;
static void (*sound_in_cb)(int16_t *samples_l, int16_t *samples_r, int nr_l, int nr_r);
static SRC_STATE *src_out = NULL;
static SRC_STATE *src_in = NULL;
static double ratio_out = 1.0;
static double ratio_in = 1.0;
@ -111,27 +108,6 @@ int sound_out(int16_t *samples, int nr, bool left, bool right)
int16_t play_samples[play_nr * channels_out];
int i;
if (src_out) {
float data_in[nr], data_out[play_nr];
SRC_DATA data;
data.data_in = data_in;
data.data_out = data_out;
data.input_frames = nr;
data.output_frames = play_nr;
data.end_of_input = 0;
data.src_ratio = ratio_out;
src_short_to_float_array(samples, data_in, nr);
src_process(src_out, &data);
src_float_to_short_array(data_out, play_samples, play_nr);
samples = play_samples;
nr = play_nr;
}
/* Output is always multiple channels */
for (i = play_nr; i >= 0; i--) {
if (left)
@ -249,33 +225,12 @@ int sound_rx(void)
samples_r = rec_samples;
}
if (src_in) {
int r_in = r * ratio_in;
float data_in[r], data_out[r_in];
SRC_DATA data;
data.data_in = data_in;
data.data_out = data_out;
data.input_frames = r;
data.output_frames = r_in;
data.end_of_input = 0;
data.src_ratio = ratio_in;
int16_t samples[r_in];
src_short_to_float_array(samples_l, data_in, r);
src_process(src_in, &data);
src_float_to_short_array(data_out, samples, r_in);
sound_in_cb(samples, samples_r, r_in, r);
} else {
sound_in_cb(samples_l, samples_r, r, r);
}
sound_in_cb(samples_l, samples_r, r, r);
return 0;
}
int sound_param(snd_pcm_t *pcm_handle, bool is_tx, int sw_rate, int hw_rate, int force_channels)
int sound_param(snd_pcm_t *pcm_handle, bool is_tx, int hw_rate, int force_channels)
{
int channels = !force_channels ? 1 : force_channels;
snd_pcm_hw_params_t *hw_params;
@ -291,17 +246,12 @@ int sound_param(snd_pcm_t *pcm_handle, bool is_tx, int sw_rate, int hw_rate, int
else
snd_pcm_hw_params_set_format (pcm_handle, hw_params, SND_PCM_FORMAT_S16_BE);
unsigned int rate = sw_rate;
unsigned int rrate = hw_rate;
if (snd_pcm_hw_params_set_rate_near (pcm_handle, hw_params, &rrate, NULL)) {
printf("Could not set rate %d\n", rrate);
}
printf("rate: %d got rate: %d\n", rate, rrate);
if (!is_tx && rrate != hw_rate) {
printf("is_tx: %d, rrate: %d, hw_rate: %d\n", is_tx, rrate, hw_rate);
return -1;
}
printf("requested rate: %d got rate: %d\n", hw_rate, rrate);
if (is_tx || channels == 1 || snd_pcm_hw_params_set_channels (pcm_handle, hw_params, 1)) {
if (!is_tx && channels == 1)
@ -313,27 +263,14 @@ int sound_param(snd_pcm_t *pcm_handle, bool is_tx, int sw_rate, int hw_rate, int
}
}
printf("Channels: %d\n", channels);
if (rate != rrate) {
int err;
SRC_STATE *src = src_new(SRC_LINEAR, 1, &err);
double ratio = (double)rate / (double)rrate;
if (is_tx) {
src_out = src;
ratio_out = 1.0/ratio;
} else {
src_in = src;
ratio_in = ratio;
}
}
if (is_tx) {
channels_out = channels;
} else {
channels_in = channels;
}
snd_pcm_uframes_t buffer_size = hw_rate;
snd_pcm_uframes_t period_size = hw_rate / 100;
snd_pcm_uframes_t buffer_size = rrate;
snd_pcm_uframes_t period_size = rrate / 100;
snd_pcm_hw_params_set_buffer_size_near (pcm_handle, hw_params, &buffer_size);
snd_pcm_hw_params_set_period_size_near (pcm_handle, hw_params, &period_size, NULL);
@ -346,7 +283,7 @@ int sound_param(snd_pcm_t *pcm_handle, bool is_tx, int sw_rate, int hw_rate, int
snd_pcm_hw_params_free (hw_params);
return 0;
return rrate;
}
@ -374,9 +311,10 @@ int sound_buffer(snd_pcm_t *pcm_handle, int buffer_nr, bool is_tx)
int sound_init(char *device,
void (*in_cb)(int16_t *samples_l, int16_t *samples_r, int nr_l, int nr_r),
int rate_out, int rate_in_l, int rate_in_r, int hw_rate)
int hw_rate)
{
int err;
int rrate_tx, rrate_rx;
/* The device name */
const char *device_name;
@ -389,20 +327,29 @@ int sound_init(char *device,
/* Open the device */
err = snd_pcm_open (&pcm_handle_tx, device_name, SND_PCM_STREAM_PLAYBACK, 0);
if (err < 0)
if (err < 0) {
printf("snd_pcm_open() err %d: %s\n", err, snd_strerror(err));
return -1;
}
if (sound_param(pcm_handle_tx, true, rate_out, hw_rate, 0))
if ((rrate_tx = sound_param(pcm_handle_tx, true, hw_rate, 0)) < 0)
return -1;
err = snd_pcm_open (&pcm_handle_rx, device_name, SND_PCM_STREAM_CAPTURE, 0);
if (err < 0)
if (err < 0) {
printf("snd_pcm_open() err %d: %s\n", err, snd_strerror(err));
return -1;
}
if (sound_param(pcm_handle_rx, false, rate_in_l, rate_in_r ? rate_in_r : hw_rate, rate_in_r ? 2 :0))
if ((rrate_rx = sound_param(pcm_handle_rx, false, hw_rate, 2)) < 0)
return -1;
return 0;
if (rrate_rx != rrate_tx) {
printf("TX and RX sample rate do not match\n");
return -1;
}
return hw_rate;
}
int sound_set_nr(int nr_set)


+ 2
- 1
sound.h View File

@ -24,9 +24,10 @@
int sound_out(int16_t *samples, int nr, bool left, bool right);
int sound_silence(void);
/* Returns hw_rate or negative error*/
int sound_init(char *device,
void (*in_cb)(int16_t *samples_l, int16_t *samples_r, int nr_l, int nr_r),
int rate_out, int rate_in_l, int rate_in_r, int hw_rate);
int hw_rate);
int sound_set_nr(int nr_set);
int sound_poll_count_tx(void);
int sound_poll_fill_tx(struct pollfd *fds, int count);


Loading…
Cancel
Save