Refactor global variables for signal processing
These are: device, sample rate, buffer, latency Called now: dsp_device, dsp_samplerate, dsp_buffer, dsp_latency Call audio device: call_device, call_samplerate, call_buffer
This commit is contained in:
parent
eb462f6158
commit
f7d4eb961e
|
@ -71,7 +71,7 @@ typedef struct console {
|
|||
char audiodev[64]; /* headphone interface, if used */
|
||||
int samplerate; /* sample rate of headphone interface */
|
||||
void *sound; /* headphone interface */
|
||||
int latspl; /* sample latency at headphone interface */
|
||||
int buffer_size; /* sample buffer size at headphone interface */
|
||||
samplerate_t srstate; /* patterns/announcement upsampling */
|
||||
jitter_t dejitter; /* headphone audio dejittering */
|
||||
int test_audio_pos; /* position for test tone toward mobile */
|
||||
|
@ -358,7 +358,7 @@ static void _print_console_text(void)
|
|||
printf("\033[0;39m");
|
||||
}
|
||||
|
||||
int console_init(const char *station_id, const char *audiodev, int samplerate, int latency, int num_digits, int loopback, int echo_test, const char *digits)
|
||||
int console_init(const char *station_id, const char *audiodev, int samplerate, int buffer, int num_digits, int loopback, int echo_test, const char *digits)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
|
@ -372,7 +372,7 @@ int console_init(const char *station_id, const char *audiodev, int samplerate, i
|
|||
strncpy(console.station_id, station_id, sizeof(console.station_id) - 1);
|
||||
strncpy(console.audiodev, audiodev, sizeof(console.audiodev) - 1);
|
||||
console.samplerate = samplerate;
|
||||
console.latspl = latency * samplerate / 1000;
|
||||
console.buffer_size = buffer * samplerate / 1000;
|
||||
console.num_digits = num_digits;
|
||||
console.loopback = loopback;
|
||||
console.echo_test = echo_test;
|
||||
|
@ -400,7 +400,7 @@ error:
|
|||
return rc;
|
||||
}
|
||||
|
||||
int console_open_audio(int __attribute__((unused)) latspl)
|
||||
int console_open_audio(int __attribute__((unused)) buffer_size, double __attribute__((unused)) interval)
|
||||
{
|
||||
if (!console.audiodev[0])
|
||||
return 0;
|
||||
|
@ -408,7 +408,7 @@ int console_open_audio(int __attribute__((unused)) latspl)
|
|||
#ifdef HAVE_ALSA
|
||||
/* open sound device for call control */
|
||||
/* use factor 1.4 of speech level for complete range of sound card */
|
||||
console.sound = sound_open(console.audiodev, NULL, NULL, NULL, 1, 0.0, console.samplerate, latspl, 1.4, 4000.0, 2.0);
|
||||
console.sound = sound_open(console.audiodev, NULL, NULL, NULL, 1, 0.0, console.samplerate, buffer_size, interval, 1.4, 4000.0, 2.0);
|
||||
if (!console.sound) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "No sound device!\n");
|
||||
return -EIO;
|
||||
|
@ -547,12 +547,12 @@ void process_console(int c)
|
|||
|
||||
#ifdef HAVE_ALSA
|
||||
/* handle audio, if sound device is used */
|
||||
sample_t samples[console.latspl + 10], *samples_list[1];
|
||||
sample_t samples[console.buffer_size + 10], *samples_list[1];
|
||||
uint8_t *power_list[1];
|
||||
int count;
|
||||
int rc;
|
||||
|
||||
count = sound_get_tosend(console.sound, console.latspl);
|
||||
count = sound_get_tosend(console.sound, console.buffer_size);
|
||||
if (count < 0) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to get samples in buffer (rc = %d)!\n", count);
|
||||
if (count == -EPIPE)
|
||||
|
@ -572,7 +572,7 @@ void process_console(int c)
|
|||
}
|
||||
}
|
||||
samples_list[0] = samples;
|
||||
count = sound_read(console.sound, samples_list, console.latspl, 1, NULL);
|
||||
count = sound_read(console.sound, samples_list, console.buffer_size, 1, NULL);
|
||||
if (count < 0) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to read from sound device (rc = %d)!\n", count);
|
||||
if (count == -EPIPE)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
|
||||
void console_msg(osmo_cc_call_t *call, osmo_cc_msg_t *msg);
|
||||
int console_init(const char *station_id, const char *audiodev, int samplerate, int latency, int dial_digits, int loopback, int echo_test, const char *digits);
|
||||
int console_init(const char *station_id, const char *audiodev, int samplerate, int buffer, int dial_digits, int loopback, int echo_test, const char *digits);
|
||||
void console_cleanup(void);
|
||||
int console_open_audio(int latspl);
|
||||
int console_open_audio(int buffer_size, double interval);
|
||||
int console_start_audio(void);
|
||||
void console_process(int c);
|
||||
void process_console(int c);
|
||||
|
|
|
@ -50,15 +50,16 @@ static int got_init = 0;
|
|||
/* common mobile settings */
|
||||
int num_kanal = 0;
|
||||
const char *kanal[MAX_SENDER];
|
||||
int num_audiodev = 0;
|
||||
const char *audiodev[MAX_SENDER] = { "hw:0,0" };
|
||||
int num_device = 0;
|
||||
const char *dsp_device[MAX_SENDER] = { "hw:0,0" };
|
||||
int allow_sdr = 1;
|
||||
int use_sdr = 0;
|
||||
static const char *call_audiodev = "";
|
||||
int samplerate = 48000;
|
||||
int dsp_samplerate = 48000;
|
||||
double dsp_interval = 1.0;
|
||||
int dsp_buffer = 50;
|
||||
static const char *call_device = "";
|
||||
static int call_samplerate = 48000;
|
||||
int interval = 1;
|
||||
int latency = 50;
|
||||
static int call_buffer = 50;
|
||||
int uses_emphasis = 1;
|
||||
int do_pre_emphasis = 0;
|
||||
int do_de_emphasis = 0;
|
||||
|
@ -106,16 +107,17 @@ void main_mobile_print_help(const char *arg0, const char *ext_usage)
|
|||
printf(" -k --channel <channel>\n");
|
||||
printf(" Channel (German = Kanal) number of \"Sender\" (German = Transceiver)\n");
|
||||
printf(" -a --audio-device hw:<card>,<device>\n");
|
||||
printf(" Sound card and device number (default = '%s')\n", audiodev[0]);
|
||||
printf(" Sound card and device number (default = '%s')\n", dsp_device[0]);
|
||||
printf(" Don't set it for SDR!\n");
|
||||
printf(" -s --samplerate <rate>\n");
|
||||
printf(" Sample rate of sound device (default = '%d')\n", samplerate);
|
||||
printf(" -i --interval 1..25\n");
|
||||
printf(" Interval of processing loop in ms (default = '%d' ms)\n", interval);
|
||||
printf(" Use 25 to drastically reduce CPU usage. In case of buffer underrun,\n");
|
||||
printf(" increase latency accordingly.\n");
|
||||
printf(" Sample rate of sound device (default = '%d')\n", dsp_samplerate);
|
||||
printf(" -i --interval 0.1..25\n");
|
||||
printf(" Interval of processing loop in ms (default = '%.1f' ms)\n", dsp_interval);
|
||||
printf(" Use 10 to drastically reduce CPU usage. In case of buffer underrun,\n");
|
||||
printf(" increase buffer accordingly.\n");
|
||||
printf(" -b --buffer <ms>\n");
|
||||
printf(" How many milliseconds are processed in advance (default = '%d')\n", latency);
|
||||
printf(" How many milliseconds are processed in advance (default = '%d')\n", dsp_buffer);
|
||||
printf(" A buffer below 10 ms requires low interval like 0.1 ms.\n");
|
||||
if (uses_emphasis) {
|
||||
printf(" -p --pre-emphasis\n");
|
||||
printf(" Enable pre-emphasis, if you directly connect to the oscillator of the\n");
|
||||
|
@ -134,9 +136,11 @@ void main_mobile_print_help(const char *arg0, const char *ext_usage)
|
|||
printf(" Use echo test, to send back audio from mobile phone's microphone to\n");
|
||||
printf(" the speaker. (German: 'Blasprobe').\n");
|
||||
printf(" -c --call-device hw:<card>,<device>\n");
|
||||
printf(" Sound card and device number for headset (default = '%s')\n", call_audiodev);
|
||||
printf(" Sound card and device number for headset (default = '%s')\n", call_device);
|
||||
printf(" --call-samplerate <rate>\n");
|
||||
printf(" Sample rate of sound device for headset (default = '%d')\n", call_samplerate);
|
||||
printf(" --call-buffer <ms>\n");
|
||||
printf(" How many milliseconds are processed in advance (default = '%d')\n", call_buffer);
|
||||
printf(" -x --osmocc-cross\n");
|
||||
printf(" Enable built-in call forwarding between mobiles. Be sure to have\n");
|
||||
printf(" at least one control channel and two voice channels. Alternatively\n");
|
||||
|
@ -198,7 +202,8 @@ void main_mobile_print_hotkeys(void)
|
|||
#define OPT_READ_RX_WAVE 1006
|
||||
#define OPT_READ_TX_WAVE 1007
|
||||
#define OPT_CALL_SAMPLERATE 1008
|
||||
#define OPT_FAST_MATH 1009
|
||||
#define OPT_CALL_BUFFER 1009
|
||||
#define OPT_FAST_MATH 1010
|
||||
#define OPT_LIMESDR 1100
|
||||
#define OPT_LIMESDR_MINI 1101
|
||||
|
||||
|
@ -222,6 +227,7 @@ void main_mobile_add_options(void)
|
|||
option_add(OPT_OSMO_CC, "cc", 1);
|
||||
option_add('c', "call-device", 1);
|
||||
option_add(OPT_CALL_SAMPLERATE, "call-samplerate", 1);
|
||||
option_add(OPT_CALL_BUFFER, "call-buffer", 1);
|
||||
option_add('t', "tones", 1);
|
||||
option_add('l', "loopback", 1);
|
||||
option_add('r', "realtime", 1);
|
||||
|
@ -264,20 +270,20 @@ int main_mobile_handle_options(int short_option, int argi, char **argv)
|
|||
OPT_ARRAY(num_kanal, kanal, argv[argi])
|
||||
break;
|
||||
case 'a':
|
||||
OPT_ARRAY(num_audiodev, audiodev, options_strdup(argv[argi]))
|
||||
OPT_ARRAY(num_device, dsp_device, options_strdup(argv[argi]))
|
||||
break;
|
||||
case 's':
|
||||
samplerate = atoi(argv[argi]);
|
||||
dsp_samplerate = atoi(argv[argi]);
|
||||
break;
|
||||
case 'i':
|
||||
interval = atoi(argv[argi]);
|
||||
if (interval < 1)
|
||||
interval = 1;
|
||||
if (interval > 25)
|
||||
interval = 25;
|
||||
dsp_interval = atof(argv[argi]);
|
||||
if (dsp_interval < 0.1)
|
||||
dsp_interval = 0.1;
|
||||
if (dsp_interval > 10)
|
||||
dsp_interval = 10;
|
||||
break;
|
||||
case 'b':
|
||||
latency = atoi(argv[argi]);
|
||||
dsp_buffer = atoi(argv[argi]);
|
||||
break;
|
||||
case 'p':
|
||||
if (!uses_emphasis) {
|
||||
|
@ -321,11 +327,14 @@ int main_mobile_handle_options(int short_option, int argi, char **argv)
|
|||
cc_argv[cc_argc++] = options_strdup(argv[argi]);
|
||||
break;
|
||||
case 'c':
|
||||
call_audiodev = options_strdup(argv[argi]);
|
||||
call_device = options_strdup(argv[argi]);
|
||||
break;
|
||||
case OPT_CALL_SAMPLERATE:
|
||||
call_samplerate = atoi(argv[argi]);
|
||||
break;
|
||||
case OPT_CALL_BUFFER:
|
||||
call_buffer = atoi(argv[argi]);
|
||||
break;
|
||||
case 't':
|
||||
send_patterns = atoi(argv[argi]);
|
||||
break;
|
||||
|
@ -431,9 +440,9 @@ static int get_char()
|
|||
}
|
||||
|
||||
/* Loop through all transceiver instances of one network. */
|
||||
void main_mobile(const char *name, int *quit, int latency, int interval, void (*myhandler)(void), const char *station_id, int station_id_digits)
|
||||
void main_mobile(const char *name, int *quit, void (*myhandler)(void), const char *station_id, int station_id_digits)
|
||||
{
|
||||
int latspl;
|
||||
int buffer_size;
|
||||
sender_t *sender;
|
||||
double last_time_call = 0, begin_time, now, sleep;
|
||||
struct termios term, term_orig;
|
||||
|
@ -445,8 +454,8 @@ void main_mobile(const char *name, int *quit, int latency, int interval, void (*
|
|||
abort();
|
||||
}
|
||||
|
||||
/* latency of send buffer in samples */
|
||||
latspl = samplerate * latency / 1000;
|
||||
/* size of dsp buffer in samples */
|
||||
buffer_size = dsp_samplerate * dsp_buffer / 1000;
|
||||
|
||||
/* check OSMO-CC support */
|
||||
if (use_osmocc_cross && num_kanal == 1) {
|
||||
|
@ -457,15 +466,15 @@ void main_mobile(const char *name, int *quit, int latency, int interval, void (*
|
|||
fprintf(stderr, "You selected OSMO-CC socket interface and built-in call forwarding, but only one can be selected.\n");
|
||||
return;
|
||||
}
|
||||
if (echo_test && call_audiodev[0]) {
|
||||
if (echo_test && call_device[0]) {
|
||||
fprintf(stderr, "You selected call device (headset) and echo test, but only one can be selected.\n");
|
||||
return;
|
||||
}
|
||||
if (use_osmocc_sock && call_audiodev[0]) {
|
||||
if (use_osmocc_sock && call_device[0]) {
|
||||
fprintf(stderr, "You selected OSMO-CC socket interface, but it cannot be used with call device (headset).\n");
|
||||
return;
|
||||
}
|
||||
if (use_osmocc_cross && call_audiodev[0]) {
|
||||
if (use_osmocc_cross && call_device[0]) {
|
||||
fprintf(stderr, "You selected built-in call forwarding, but it cannot be used with call device (headset).\n");
|
||||
return;
|
||||
}
|
||||
|
@ -488,7 +497,7 @@ void main_mobile(const char *name, int *quit, int latency, int interval, void (*
|
|||
|
||||
/* init OSMO-CC */
|
||||
if (!use_osmocc_sock)
|
||||
console_init(station_id, call_audiodev, call_samplerate, latency, station_id_digits, loopback, echo_test, console_digits);
|
||||
console_init(station_id, call_device, call_samplerate, call_buffer, station_id_digits, loopback, echo_test, console_digits);
|
||||
|
||||
/* init call control instance */
|
||||
rc = call_init(name, (use_osmocc_sock) ? send_patterns : 0, release_on_disconnect, use_osmocc_sock, cc_argc, cc_argv);
|
||||
|
@ -498,15 +507,15 @@ void main_mobile(const char *name, int *quit, int latency, int interval, void (*
|
|||
}
|
||||
|
||||
#ifdef HAVE_SDR
|
||||
rc = sdr_configure(samplerate);
|
||||
rc = sdr_configure(dsp_samplerate);
|
||||
if (rc < 0)
|
||||
return;
|
||||
#endif
|
||||
|
||||
/* open audio */
|
||||
if (sender_open_audio(latspl))
|
||||
if (sender_open_audio(buffer_size, dsp_interval))
|
||||
return;
|
||||
if (console_open_audio(latspl))
|
||||
if (console_open_audio(buffer_size, dsp_interval))
|
||||
return;
|
||||
|
||||
if (!loopback)
|
||||
|
@ -552,7 +561,7 @@ void main_mobile(const char *name, int *quit, int latency, int interval, void (*
|
|||
/* do not process audio for an audio slave, since it is done by audio master */
|
||||
if (sender->master) /* if master is set, we are an audio slave */
|
||||
continue;
|
||||
process_sender_audio(sender, quit, latspl);
|
||||
process_sender_audio(sender, quit, buffer_size);
|
||||
}
|
||||
|
||||
/* process timers */
|
||||
|
@ -646,12 +655,12 @@ next_char:
|
|||
if (myhandler)
|
||||
myhandler();
|
||||
|
||||
display_measurements((double)interval / 1000.0);
|
||||
display_measurements(dsp_interval / 1000.0);
|
||||
|
||||
now = get_time();
|
||||
|
||||
/* sleep interval */
|
||||
sleep = ((double)interval / 1000.0) - (now - begin_time);
|
||||
sleep = (dsp_interval / 1000.0) - (now - begin_time);
|
||||
if (sleep > 0)
|
||||
usleep(sleep * 1000000.0);
|
||||
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
extern int num_kanal;
|
||||
extern const char *kanal[];
|
||||
extern int swap_links;
|
||||
extern int num_audiodev;
|
||||
extern const char *audiodev[];
|
||||
extern int num_device;
|
||||
extern int allow_sdr;
|
||||
extern int use_sdr;
|
||||
extern int samplerate;
|
||||
extern int interval;
|
||||
extern int latency;
|
||||
extern const char *dsp_device[];
|
||||
extern int dsp_samplerate;
|
||||
extern double dsp_interval;
|
||||
extern int dsp_buffer;
|
||||
extern int uses_emphasis;
|
||||
extern int do_pre_emphasis;
|
||||
extern int do_de_emphasis;
|
||||
|
@ -42,7 +42,7 @@ int main_mobile_handle_options(int short_option, int argi, char **argv);
|
|||
extern int quit;
|
||||
void sighandler(int sigset);
|
||||
|
||||
void main_mobile(const char *name, int *quit, int latency, int interval, void (*myhandler)(void), const char *station_id, int station_id_digits);
|
||||
void main_mobile(const char *name, int *quit, void (*myhandler)(void), const char *station_id, int station_id_digits);
|
||||
|
||||
void dump_info(void);
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ int cant_recover = 0;
|
|||
int check_channel = 1;
|
||||
|
||||
/* Init transceiver instance and link to list of transceivers. */
|
||||
int sender_create(sender_t *sender, const char *kanal, double sendefrequenz, double empfangsfrequenz, const char *audiodev, int use_sdr, int samplerate, double rx_gain, double tx_gain, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, const char *read_tx_wave, int loopback, enum paging_signal paging_signal)
|
||||
int sender_create(sender_t *sender, const char *kanal, double sendefrequenz, double empfangsfrequenz, const char *device, int use_sdr, int samplerate, double rx_gain, double tx_gain, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, const char *read_tx_wave, int loopback, enum paging_signal paging_signal)
|
||||
{
|
||||
sender_t *master, *slave;
|
||||
int rc = 0;
|
||||
|
@ -46,7 +46,7 @@ int sender_create(sender_t *sender, const char *kanal, double sendefrequenz, dou
|
|||
sender->kanal = kanal;
|
||||
sender->sendefrequenz = sendefrequenz;
|
||||
sender->empfangsfrequenz = (loopback) ? sendefrequenz : empfangsfrequenz;
|
||||
strncpy(sender->audiodev, audiodev, sizeof(sender->audiodev) - 1);
|
||||
strncpy(sender->device, device, sizeof(sender->device) - 1);
|
||||
sender->samplerate = samplerate;
|
||||
sender->rx_gain = rx_gain;
|
||||
sender->tx_gain = tx_gain;
|
||||
|
@ -90,7 +90,7 @@ int sender_create(sender_t *sender, const char *kanal, double sendefrequenz, dou
|
|||
PDEBUG(DSENDER, DEBUG_NOTICE, "Please use at least one channel distance to avoid that.\n");
|
||||
PDEBUG(DSENDER, DEBUG_NOTICE, "------------------------------------------------------------------------\n");
|
||||
}
|
||||
if (!strcmp(master->audiodev, audiodev))
|
||||
if (!strcmp(master->device, device))
|
||||
break;
|
||||
}
|
||||
if (master) {
|
||||
|
@ -169,7 +169,7 @@ error:
|
|||
return rc;
|
||||
}
|
||||
|
||||
int sender_open_audio(int latspl)
|
||||
int sender_open_audio(int buffer_size, double interval)
|
||||
{
|
||||
sender_t *master, *inst;
|
||||
int channels;
|
||||
|
@ -226,7 +226,7 @@ int sender_open_audio(int latspl)
|
|||
}
|
||||
|
||||
/* open device */
|
||||
master->audio = master->audio_open(master->audiodev, tx_f, rx_f, am, channels, paging_frequency, master->samplerate, latspl, (master->max_deviation) ?: 1.0, master->max_modulation, master->modulation_index);
|
||||
master->audio = master->audio_open(master->device, tx_f, rx_f, am, channels, paging_frequency, master->samplerate, buffer_size, interval, (master->max_deviation) ?: 1.0, master->max_modulation, master->modulation_index);
|
||||
if (!master->audio) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "No device for transceiver!\n");
|
||||
return -EIO;
|
||||
|
@ -321,7 +321,7 @@ static void gain_samples(sample_t *samples, int length, double gain)
|
|||
}
|
||||
|
||||
/* Handle audio streaming of one transceiver. */
|
||||
void process_sender_audio(sender_t *sender, int *quit, int latspl)
|
||||
void process_sender_audio(sender_t *sender, int *quit, int buffer_size)
|
||||
{
|
||||
sender_t *inst;
|
||||
int rc, count;
|
||||
|
@ -332,8 +332,8 @@ void process_sender_audio(sender_t *sender, int *quit, int latspl)
|
|||
|
||||
/* count instances for audio channel */
|
||||
for (num_chan = 0, inst = sender; inst; num_chan++, inst = inst->slave);
|
||||
sample_t buff[num_chan][latspl], *samples[num_chan];
|
||||
uint8_t pbuff[num_chan][latspl], *power[num_chan];
|
||||
sample_t buff[num_chan][buffer_size], *samples[num_chan];
|
||||
uint8_t pbuff[num_chan][buffer_size], *power[num_chan];
|
||||
enum paging_signal paging_signal[num_chan];
|
||||
int on[num_chan];
|
||||
double rf_level_db[num_chan];
|
||||
|
@ -345,7 +345,7 @@ void process_sender_audio(sender_t *sender, int *quit, int latspl)
|
|||
#ifdef DEBUG_TIME_CONSUMPTION
|
||||
t1 = get_time();
|
||||
#endif
|
||||
count = sender->audio_get_tosend(sender->audio, latspl);
|
||||
count = sender->audio_get_tosend(sender->audio, buffer_size);
|
||||
if (count < 0) {
|
||||
PDEBUG_CHAN(DSENDER, DEBUG_ERROR, "Failed to get number of samples in buffer (rc = %d)!\n", count);
|
||||
if (count == -EPIPE) {
|
||||
|
@ -364,8 +364,8 @@ cant_recover:
|
|||
#endif
|
||||
if (count > 0) {
|
||||
/* limit to our buffer */
|
||||
if (count > latspl)
|
||||
count = latspl;
|
||||
if (count > buffer_size)
|
||||
count = buffer_size;
|
||||
/* loop through all channels */
|
||||
for (i = 0, inst = sender; inst; i++, inst = inst->slave) {
|
||||
/* load TX data from audio loop or from sender instance */
|
||||
|
@ -414,7 +414,7 @@ cant_recover:
|
|||
t3 = get_time();
|
||||
#endif
|
||||
|
||||
count = sender->audio_read(sender->audio, samples, latspl, num_chan, rf_level_db);
|
||||
count = sender->audio_read(sender->audio, samples, buffer_size, num_chan, rf_level_db);
|
||||
if (count < 0) {
|
||||
/* special case when audio_read wants us to quit */
|
||||
if (count == -EPERM) {
|
||||
|
|
|
@ -43,8 +43,8 @@ typedef struct sender {
|
|||
|
||||
/* audio */
|
||||
void *audio;
|
||||
char audiodev[64]; /* audio device name (alsa or sdr) */
|
||||
void *(*audio_open)(const char *, double *, double *, int *, int, double, int, int, double, double, double);
|
||||
char device[64]; /* audio device name (alsa or sdr) */
|
||||
void *(*audio_open)(const char *, double *, double *, int *, int, double, int, int, double, double, double, double);
|
||||
int (*audio_start)(void *);
|
||||
void (*audio_close)(void *);
|
||||
int (*audio_write)(void *, sample_t **, uint8_t **, int, enum paging_signal *, int *, int);
|
||||
|
@ -93,13 +93,13 @@ extern sender_t *sender_head;
|
|||
extern int cant_recover;
|
||||
extern int check_channel;
|
||||
|
||||
int sender_create(sender_t *sender, const char *kanal, double sendefrequenz, double empfangsfrequenz, const char *audiodev, int use_sdr, int samplerate, double rx_gain, double tx_gain, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, const char *read_tx_wave, int loopback, enum paging_signal paging_signal);
|
||||
int sender_create(sender_t *sender, const char *kanal, double sendefrequenz, double empfangsfrequenz, const char *device, int use_sdr, int samplerate, double rx_gain, double tx_gain, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, const char *read_tx_wave, int loopback, enum paging_signal paging_signal);
|
||||
void sender_destroy(sender_t *sender);
|
||||
void sender_set_fm(sender_t *sender, double max_deviation, double max_modulation, double speech_deviation, double max_display);
|
||||
void sender_set_am(sender_t *sender, double max_modulation, double speech_deviation, double max_display, double modulation_index);
|
||||
int sender_open_audio(int latspl);
|
||||
int sender_open_audio(int buffer_size, double interval);
|
||||
int sender_start_audio(void);
|
||||
void process_sender_audio(sender_t *sender, int *quit, int latspl);
|
||||
void process_sender_audio(sender_t *sender, int *quit, int buffer_size);
|
||||
void sender_send(sender_t *sender, sample_t *samples, uint8_t *power, int count);
|
||||
void sender_receive(sender_t *sender, sample_t *samples, int count, double rf_level_db);
|
||||
void sender_paging(sender_t *sender, int on);
|
||||
|
|
44
libsdr/sdr.c
44
libsdr/sdr.c
|
@ -93,7 +93,8 @@ typedef struct sdr {
|
|||
int channels; /* number of frequencies */
|
||||
double amplitude; /* amplitude of each carrier */
|
||||
int samplerate; /* sample rate of audio data */
|
||||
int latspl; /* latency in audio samples */
|
||||
int buffer_size; /* buffer in audio samples */
|
||||
double interval; /* how often to process the loop */
|
||||
wave_rec_t wave_rx_rec;
|
||||
wave_rec_t wave_tx_rec;
|
||||
wave_play_t wave_rx_play;
|
||||
|
@ -136,7 +137,7 @@ static void show_spectrum(const char *direction, double halfbandwidth, double ce
|
|||
PDEBUG(DSDR, DEBUG_INFO, "Frequency P = %.4f MHz (Paging Frequency)\n", paging_frequency / 1e6);
|
||||
}
|
||||
|
||||
void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_frequency, double *rx_frequency, int *am, int channels, double paging_frequency, int samplerate, int latspl, double max_deviation, double max_modulation, double modulation_index)
|
||||
void *sdr_open(const char __attribute__((__unused__)) *device, double *tx_frequency, double *rx_frequency, int *am, int channels, double paging_frequency, int samplerate, int buffer_size, double interval, double max_deviation, double max_modulation, double modulation_index)
|
||||
{
|
||||
sdr_t *sdr;
|
||||
int threads = 1, oversample = 1; /* always use threads */
|
||||
|
@ -179,13 +180,14 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
|
|||
sdr->channels = channels;
|
||||
sdr->amplitude = 1.0 / (double)channels;
|
||||
sdr->samplerate = samplerate;
|
||||
sdr->latspl = latspl;
|
||||
sdr->buffer_size = buffer_size;
|
||||
sdr->interval = interval;
|
||||
sdr->threads = threads; /* always required, because write may block */
|
||||
sdr->oversample = oversample;
|
||||
|
||||
if (threads) {
|
||||
memset(&sdr->thread_read, 0, sizeof(sdr->thread_read));
|
||||
sdr->thread_read.buffer_size = sdr->latspl * 2 * sdr->oversample + 2;
|
||||
sdr->thread_read.buffer_size = sdr->buffer_size * 2 * sdr->oversample + 2;
|
||||
sdr->thread_read.buffer = calloc(sdr->thread_read.buffer_size, sizeof(*sdr->thread_read.buffer));
|
||||
if (!sdr->thread_read.buffer) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "No mem!\n");
|
||||
|
@ -202,7 +204,7 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
|
|||
iir_lowpass_init(&sdr->thread_read.lp[1], samplerate / 2.0, sdr_config->samplerate, 2);
|
||||
}
|
||||
memset(&sdr->thread_write, 0, sizeof(sdr->thread_write));
|
||||
sdr->thread_write.buffer_size = sdr->latspl * 2 + 2;
|
||||
sdr->thread_write.buffer_size = sdr->buffer_size * 2 + 2;
|
||||
sdr->thread_write.buffer = calloc(sdr->thread_write.buffer_size, sizeof(*sdr->thread_write.buffer));
|
||||
if (!sdr->thread_write.buffer) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "No mem!\n");
|
||||
|
@ -221,32 +223,32 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
|
|||
}
|
||||
|
||||
/* alloc fm modulation buffers */
|
||||
sdr->modbuff = calloc(sdr->latspl * 2, sizeof(*sdr->modbuff));
|
||||
sdr->modbuff = calloc(sdr->buffer_size * 2, sizeof(*sdr->modbuff));
|
||||
if (!sdr->modbuff) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "NO MEM!\n");
|
||||
goto error;
|
||||
}
|
||||
sdr->modbuff_I = calloc(sdr->latspl, sizeof(*sdr->modbuff_I));
|
||||
sdr->modbuff_I = calloc(sdr->buffer_size, sizeof(*sdr->modbuff_I));
|
||||
if (!sdr->modbuff_I) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "NO MEM!\n");
|
||||
goto error;
|
||||
}
|
||||
sdr->modbuff_Q = calloc(sdr->latspl, sizeof(*sdr->modbuff_Q));
|
||||
sdr->modbuff_Q = calloc(sdr->buffer_size, sizeof(*sdr->modbuff_Q));
|
||||
if (!sdr->modbuff_Q) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "NO MEM!\n");
|
||||
goto error;
|
||||
}
|
||||
sdr->modbuff_carrier = calloc(sdr->latspl, sizeof(*sdr->modbuff_carrier));
|
||||
sdr->modbuff_carrier = calloc(sdr->buffer_size, sizeof(*sdr->modbuff_carrier));
|
||||
if (!sdr->modbuff_carrier) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "NO MEM!\n");
|
||||
goto error;
|
||||
}
|
||||
sdr->wavespl0 = calloc(sdr->latspl, sizeof(*sdr->wavespl0));
|
||||
sdr->wavespl0 = calloc(sdr->buffer_size, sizeof(*sdr->wavespl0));
|
||||
if (!sdr->wavespl0) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "NO MEM!\n");
|
||||
goto error;
|
||||
}
|
||||
sdr->wavespl1 = calloc(sdr->latspl, sizeof(*sdr->wavespl1));
|
||||
sdr->wavespl1 = calloc(sdr->buffer_size, sizeof(*sdr->wavespl1));
|
||||
if (!sdr->wavespl1) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "NO MEM!\n");
|
||||
goto error;
|
||||
|
@ -567,7 +569,7 @@ static void *sdr_write_child(void *arg)
|
|||
}
|
||||
|
||||
/* delay some time */
|
||||
usleep(1000);
|
||||
usleep(sdr->interval * 1000.0);
|
||||
}
|
||||
|
||||
PDEBUG(DSDR, DEBUG_DEBUG, "Thread received exit!\n");
|
||||
|
@ -619,7 +621,7 @@ static void *sdr_read_child(void *arg)
|
|||
}
|
||||
|
||||
/* delay some time */
|
||||
usleep(1000);
|
||||
usleep(sdr->interval * 1000.0);
|
||||
}
|
||||
|
||||
PDEBUG(DSDR, DEBUG_DEBUG, "Thread received exit!\n");
|
||||
|
@ -757,8 +759,8 @@ int sdr_write(void *inst, sample_t **samples, uint8_t **power, int num, enum pag
|
|||
int c, s, ss;
|
||||
int sent = 0;
|
||||
|
||||
if (num > sdr->latspl) {
|
||||
fprintf(stderr, "exceeding maximum size given by sdr_latspl, please fix!\n");
|
||||
if (num > sdr->buffer_size) {
|
||||
fprintf(stderr, "exceeding maximum size given by sdr->buffer_size, please fix!\n");
|
||||
abort();
|
||||
}
|
||||
if (channels != sdr->channels && channels != 0) {
|
||||
|
@ -858,8 +860,8 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels, double *rf_l
|
|||
int count = 0;
|
||||
int c, s, ss;
|
||||
|
||||
if (num > sdr->latspl) {
|
||||
fprintf(stderr, "exceeding maximum size given by sdr_latspl, please fix!\n");
|
||||
if (num > sdr->buffer_size) {
|
||||
fprintf(stderr, "exceeding maximum size given by sdr->buffer_size, please fix!\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
|
@ -981,19 +983,19 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels, double *rf_l
|
|||
return count;
|
||||
}
|
||||
|
||||
/* how much do we need to send (in audio sample duration) to get the target delay (latspl) */
|
||||
int sdr_get_tosend(void *inst, int latspl)
|
||||
/* how much do we need to send (in audio sample duration) to get the target delay (buffer size) */
|
||||
int sdr_get_tosend(void *inst, int buffer_size)
|
||||
{
|
||||
sdr_t *sdr = (sdr_t *)inst;
|
||||
int count = 0;
|
||||
|
||||
#ifdef HAVE_UHD
|
||||
if (sdr_config->uhd)
|
||||
count = uhd_get_tosend(latspl * sdr->oversample);
|
||||
count = uhd_get_tosend(buffer_size * sdr->oversample);
|
||||
#endif
|
||||
#ifdef HAVE_SOAPY
|
||||
if (sdr_config->soapy)
|
||||
count = soapy_get_tosend(latspl * sdr->oversample);
|
||||
count = soapy_get_tosend(buffer_size * sdr->oversample);
|
||||
#endif
|
||||
if (count < 0)
|
||||
return count;
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
enum paging_signal;
|
||||
|
||||
int sdr_start(void *inst);
|
||||
void *sdr_open(const char *audiodev, double *tx_frequency, double *rx_frequency, int *am, int channels, double paging_frequency, int samplerate, int latspl, double max_deviation, double max_modulation, double modulation_index);
|
||||
void *sdr_open(const char *audiodev, double *tx_frequency, double *rx_frequency, int *am, int channels, double paging_frequency, int samplerate, int buffer_size, double interval, double max_deviation, double max_modulation, double modulation_index);
|
||||
void sdr_close(void *inst);
|
||||
int sdr_write(void *inst, sample_t **samples, uint8_t **power, int num, enum paging_signal *paging_signal, int *on, int channels);
|
||||
int sdr_read(void *inst, sample_t **samples, int num, int channels, double *rf_level_db);
|
||||
int sdr_get_tosend(void *inst, int latspl);
|
||||
int sdr_get_tosend(void *inst, int buffer_size);
|
||||
void calibrate_bias(void);
|
||||
|
||||
|
|
|
@ -27,9 +27,9 @@
|
|||
*
|
||||
* If a RX time stamp is valid and first chunk is to be transmitted (tosend()
|
||||
* is called), TX time stamp becomes valid and is set to RX time stamp, but
|
||||
* advanced by the duration of the latency (latspl). tosend() always returns
|
||||
* advanced by the duration of the buffer size. tosend() always returns
|
||||
* the number of samples that are needed, to make TX time stamp advance RX time
|
||||
* stamp by given latency.
|
||||
* stamp by given buffer size.
|
||||
*
|
||||
* If chunk is transmitted to SDR, the TX time stamp is advanced by the
|
||||
* duration of the transmitted chunk.
|
||||
|
@ -557,7 +557,7 @@ int soapy_receive(float *buff, int max)
|
|||
}
|
||||
|
||||
/* estimate number of samples that can be sent */
|
||||
int soapy_get_tosend(int latspl)
|
||||
int soapy_get_tosend(int buffer_size)
|
||||
{
|
||||
int tosend;
|
||||
|
||||
|
@ -567,23 +567,23 @@ int soapy_get_tosend(int latspl)
|
|||
|
||||
/* RX time stamp is valid the first time, set the TX time stamp in advance */
|
||||
if (!tx_valid) {
|
||||
tx_timeNs = rx_timeNs + latspl * Ns_per_sample;
|
||||
tx_timeNs = rx_timeNs + buffer_size * Ns_per_sample;
|
||||
tx_valid = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* we check how advance our transmitted time stamp is */
|
||||
pthread_mutex_lock(×tamp_mutex);
|
||||
tosend = latspl - (tx_timeNs - rx_timeNs) / Ns_per_sample;
|
||||
tosend = buffer_size - (tx_timeNs - rx_timeNs) / Ns_per_sample;
|
||||
pthread_mutex_unlock(×tamp_mutex);
|
||||
|
||||
/* in case of underrun */
|
||||
if (tosend > latspl) {
|
||||
if (tosend > buffer_size) {
|
||||
PDEBUG(DSOAPY, DEBUG_ERROR, "SDR TX underrun, seems we are too slow. Use lower SDR sample rate.\n");
|
||||
tosend = latspl;
|
||||
tosend = buffer_size;
|
||||
}
|
||||
|
||||
/* race condition and routing errors may cause TX time stamps to be in advance of slightly more than latspl */
|
||||
/* race condition and routing errors may cause TX time stamps to be in advance of slightly more than buffer_size */
|
||||
if (tosend < 0)
|
||||
tosend = 0;
|
||||
|
||||
|
|
|
@ -4,5 +4,5 @@ int soapy_start(void);
|
|||
void soapy_close(void);
|
||||
int soapy_send(float *buff, int num);
|
||||
int soapy_receive(float *buff, int max);
|
||||
int soapy_get_tosend(int latspl);
|
||||
int soapy_get_tosend(int buffer_size);
|
||||
|
||||
|
|
|
@ -631,7 +631,7 @@ int uhd_receive(float *buff, int max)
|
|||
}
|
||||
|
||||
/* estimate number of samples that can be sent */
|
||||
int uhd_get_tosend(int latspl)
|
||||
int uhd_get_tosend(int buffer_size)
|
||||
{
|
||||
double advance;
|
||||
int tosend;
|
||||
|
@ -645,7 +645,7 @@ int uhd_get_tosend(int latspl)
|
|||
tx_time_secs = rx_time_secs;
|
||||
tx_time_fract_sec = rx_time_fract_sec;
|
||||
if (tx_timestamps) {
|
||||
tx_time_fract_sec += (double)latspl / samplerate;
|
||||
tx_time_fract_sec += (double)buffer_size / samplerate;
|
||||
if (tx_time_fract_sec >= 1.0) {
|
||||
tx_time_fract_sec -= 1.0;
|
||||
tx_time_secs++;
|
||||
|
@ -660,7 +660,7 @@ int uhd_get_tosend(int latspl)
|
|||
PDEBUG(DSOAPY, DEBUG_ERROR, "SDR TX underrun, seems we are too slow. Use lower SDR sample rate.\n");
|
||||
advance = 0;
|
||||
}
|
||||
tosend = latspl - (int)(advance * samplerate);
|
||||
tosend = buffer_size - (int)(advance * samplerate);
|
||||
if (tosend < 0)
|
||||
tosend = 0;
|
||||
|
||||
|
|
|
@ -4,5 +4,5 @@ int uhd_start(void);
|
|||
void uhd_close(void);
|
||||
int uhd_send(float *buff, int num);
|
||||
int uhd_receive(float *buff, int max);
|
||||
int uhd_get_tosend(int latspl);
|
||||
int uhd_get_tosend(int buffer_size);
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
|
||||
enum paging_signal;
|
||||
|
||||
void *sound_open(const char *audiodev, double *tx_frequency, double *rx_frequency, int *am, int channels, double paging_frequency, int samplerate, int latspl, double max_deviation, double max_modulation, double modulation_index);
|
||||
void *sound_open(const char *audiodev, double *tx_frequency, double *rx_frequency, int *am, int channels, double paging_frequency, int samplerate, int buffer_size, double interval, double max_deviation, double max_modulation, double modulation_index);
|
||||
int sound_start(void *inst);
|
||||
void sound_close(void *inst);
|
||||
int sound_write(void *inst, sample_t **samples, uint8_t **power, int num, enum paging_signal *paging_signal, int *on, int channels);
|
||||
int sound_read(void *inst, sample_t **samples, int num, int channels, double *rf_level_db);
|
||||
int sound_get_tosend(void *inst, int latspl);
|
||||
int sound_get_tosend(void *inst, int buffer_size);
|
||||
|
||||
|
|
|
@ -187,7 +187,7 @@ static void dev_close(sound_t *sound)
|
|||
snd_pcm_close(sound->chandle);
|
||||
}
|
||||
|
||||
void *sound_open(const char *audiodev, double __attribute__((unused)) *tx_frequency, double __attribute__((unused)) *rx_frequency, int __attribute__((unused)) *am, int channels, double __attribute__((unused)) paging_frequency, int samplerate, int __attribute((unused)) latspl, double max_deviation, double __attribute__((unused)) max_modulation, double __attribute__((unused)) modulation_index)
|
||||
void *sound_open(const char *audiodev, double __attribute__((unused)) *tx_frequency, double __attribute__((unused)) *rx_frequency, int __attribute__((unused)) *am, int channels, double __attribute__((unused)) paging_frequency, int samplerate, int __attribute((unused)) buffer_size, double __attribute__((unused)) interval, double max_deviation, double __attribute__((unused)) max_modulation, double __attribute__((unused)) modulation_index)
|
||||
{
|
||||
sound_t *sound;
|
||||
int rc;
|
||||
|
@ -487,7 +487,7 @@ int sound_read(void *inst, sample_t **samples, int num, int channels, double __a
|
|||
* get playback buffer space
|
||||
*
|
||||
* return number of samples to be sent */
|
||||
int sound_get_tosend(void *inst, int latspl)
|
||||
int sound_get_tosend(void *inst, int buffer_size)
|
||||
{
|
||||
sound_t *sound = (sound_t *)inst;
|
||||
int rc;
|
||||
|
@ -497,7 +497,7 @@ int sound_get_tosend(void *inst, int latspl)
|
|||
rc = snd_pcm_delay(sound->phandle, &delay);
|
||||
if (rc < 0) {
|
||||
if (rc == -32)
|
||||
PDEBUG(DSOUND, DEBUG_ERROR, "Buffer underrun: Please use higher latency and enable real time scheduling\n");
|
||||
PDEBUG(DSOUND, DEBUG_ERROR, "Buffer underrun: Please use higher buffer and enable real time scheduling\n");
|
||||
else
|
||||
PDEBUG(DSOUND, DEBUG_ERROR, "failed to get delay from interface (%s)\n", snd_strerror(rc));
|
||||
if (rc == -EPIPE) {
|
||||
|
@ -511,7 +511,7 @@ int sound_get_tosend(void *inst, int latspl)
|
|||
return rc;
|
||||
}
|
||||
|
||||
tosend = latspl - delay;
|
||||
tosend = buffer_size - delay;
|
||||
return tosend;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue