Rework on audio interface
Sound instance is now called audio instance and uses funcation pointers. This gives a clean interface to be exchanged with other technologies, linke SDR.
This commit is contained in:
parent
d54d3ac265
commit
9ff8c3bb25
|
@ -83,7 +83,7 @@ double amps_channel2freq(int channel, int uplink)
|
|||
if (uplink)
|
||||
freq -= 45.000;
|
||||
|
||||
return freq;
|
||||
return freq * 1e6;
|
||||
}
|
||||
|
||||
enum amps_chan_type amps_channel2type(int channel)
|
||||
|
@ -376,7 +376,7 @@ static amps_t *search_pc(void)
|
|||
static void amps_go_idle(amps_t *amps);
|
||||
|
||||
/* Create transceiver instance and link to a list. */
|
||||
int amps_create(int channel, enum amps_chan_type chan_type, const char *sounddev, 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, amps_si *si, uint16_t sid, uint8_t sat, int polarity, int tolerant, int loopback)
|
||||
int amps_create(int channel, enum amps_chan_type chan_type, 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, amps_si *si, uint16_t sid, uint8_t sat, int polarity, int tolerant, int loopback)
|
||||
{
|
||||
sender_t *sender;
|
||||
amps_t *amps;
|
||||
|
@ -442,7 +442,7 @@ int amps_create(int channel, enum amps_chan_type chan_type, const char *sounddev
|
|||
PDEBUG(DAMPS, DEBUG_DEBUG, "Creating 'AMPS' instance for channel = %d (sample rate %d).\n", channel, samplerate);
|
||||
|
||||
/* init general part of transceiver */
|
||||
rc = sender_create(&s->sender, channel, sounddev, samplerate, rx_gain, 0, 0, write_rx_wave, write_tx_wave, read_rx_wave, loopback, 0, PILOT_SIGNAL_NONE);
|
||||
rc = sender_create(&s->sender, channel, amps_channel2freq(channel, 0), amps_channel2freq(channel, 1), audiodev, samplerate, rx_gain, 0, 0, write_rx_wave, write_tx_wave, read_rx_wave, loopback, 0, PILOT_SIGNAL_NONE);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DAMPS, DEBUG_ERROR, "Failed to init transceiver process!\n");
|
||||
goto error;
|
||||
|
@ -919,7 +919,7 @@ void call_rx_audio(int callref, int16_t *samples, int count)
|
|||
int16_t up[(int)((double)count * amps->sender.srstate.factor + 0.5) + 10];
|
||||
compress_audio(&s->cstate, samples, count);
|
||||
count = samplerate_upsample(&s->sender.srstate, samples, count, up);
|
||||
jitter_save(&s->sender.audio, up, count);
|
||||
jitter_save(&s->sender.dejitter, up, count);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -163,7 +163,7 @@ const char *amps_min12number(uint32_t min1);
|
|||
void amps_number2min(const char *number, uint32_t *min1, uint16_t *min2);
|
||||
const char *amps_min2number(uint32_t min1, uint16_t min2);
|
||||
const char *amps_scm(uint8_t scm);
|
||||
int amps_create(int channel, enum amps_chan_type chan_type, const char *sounddev, 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, amps_si *si, uint16_t sid, uint8_t sat, int polarity, int tolerant, int loopback);
|
||||
int amps_create(int channel, enum amps_chan_type chan_type, 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, amps_si *si, uint16_t sid, uint8_t sat, int polarity, int tolerant, int loopback);
|
||||
void amps_destroy(sender_t *sender);
|
||||
void amps_rx_signaling_tone(amps_t *amps, int tone, double quality);
|
||||
void amps_rx_sat(amps_t *amps, int tone, double quality);
|
||||
|
|
|
@ -481,7 +481,7 @@ again:
|
|||
test_tone_encode(amps, samples, length);
|
||||
break;
|
||||
case DSP_MODE_AUDIO_RX_AUDIO_TX:
|
||||
jitter_load(&s->sender.audio, samples, length);
|
||||
jitter_load(&s->sender.dejitter, samples, length);
|
||||
/* pre-emphasis */
|
||||
if (amps->pre_emphasis)
|
||||
pre_emphasis(&s->estate, samples, length);
|
||||
|
|
|
@ -1701,7 +1701,7 @@ static const char *ie_chan(uint64_t value)
|
|||
|
||||
if (value == 0)
|
||||
return "No channel";
|
||||
sprintf(string, "%" PRIu64 " = %.3f MHz", value, amps_channel2freq(value, 0));
|
||||
sprintf(string, "%" PRIu64 " = %.3f MHz", value, amps_channel2freq(value, 0) / 1e6);
|
||||
return string;
|
||||
}
|
||||
|
||||
|
|
|
@ -259,9 +259,9 @@ int main(int argc, char *argv[])
|
|||
print_help(argv[-skip_args]);
|
||||
return 0;
|
||||
}
|
||||
if (num_kanal == 1 && num_sounddev == 0)
|
||||
num_sounddev = 1; /* use defualt */
|
||||
if (num_kanal != num_sounddev) {
|
||||
if (num_kanal == 1 && num_audiodev == 0)
|
||||
num_audiodev = 1; /* use defualt */
|
||||
if (num_kanal != num_audiodev) {
|
||||
fprintf(stderr, "You need to specify as many sound devices as you have channels.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
@ -291,7 +291,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
dsp_init();
|
||||
init_frame();
|
||||
rc = call_init(station_id, call_sounddev, samplerate, latency, 10, loopback);
|
||||
rc = call_init(station_id, call_audiodev, samplerate, latency, 10, loopback);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Failed to create call control instance. Quitting!\n");
|
||||
goto fail;
|
||||
|
@ -348,15 +348,15 @@ int main(int argc, char *argv[])
|
|||
amps_si si;
|
||||
|
||||
init_sysinfo(&si, ms_power, ms_power, dcc, sid >> 1, regh, regr, pureg, pdreg, locaid, regincr, bis);
|
||||
rc = amps_create(kanal[i], chan_type[i], sounddev[i], samplerate, rx_gain, do_pre_emphasis, do_de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, &si, sid, scc, polarity, tolerant, loopback);
|
||||
rc = amps_create(kanal[i], chan_type[i], audiodev[i], samplerate, rx_gain, do_pre_emphasis, do_de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, &si, sid, scc, polarity, tolerant, loopback);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Failed to create \"Sender\" instance. Quitting!\n");
|
||||
goto fail;
|
||||
}
|
||||
printf("Base station on channel %d ready (%s), please tune transmitter to %.3f MHz and receiver to %.3f MHz.\n", kanal[i], chan_type_long_name(chan_type[i]), amps_channel2freq(kanal[i], 0), amps_channel2freq(kanal[i], 1));
|
||||
printf("Base station on channel %d ready (%s), please tune transmitter to %.3f MHz and receiver to %.3f MHz.\n", kanal[i], chan_type_long_name(chan_type[i]), amps_channel2freq(kanal[i], 0) / 1e6, amps_channel2freq(kanal[i], 1) / 1e6);
|
||||
}
|
||||
|
||||
main_loop(&quit, latency, interval, NULL);
|
||||
main_common(&quit, latency, interval, NULL);
|
||||
|
||||
fail:
|
||||
/* cleanup functions */
|
||||
|
|
|
@ -82,7 +82,7 @@ double anetz_kanal2freq(int kanal, int unterband)
|
|||
if (unterband)
|
||||
freq -= 4.500;
|
||||
|
||||
return freq;
|
||||
return freq * 1e6;
|
||||
}
|
||||
|
||||
/* Convert paging frequency number to to frequency. */
|
||||
|
@ -168,7 +168,7 @@ static void anetz_timeout(struct timer *timer);
|
|||
static void anetz_go_idle(anetz_t *anetz);
|
||||
|
||||
/* Create transceiver instance and link to a list. */
|
||||
int anetz_create(int kanal, const char *sounddev, int samplerate, double rx_gain, int page_sequence, 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)
|
||||
int anetz_create(int kanal, const char *audiodev, int samplerate, double rx_gain, int page_sequence, 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)
|
||||
{
|
||||
anetz_t *anetz;
|
||||
int rc;
|
||||
|
@ -187,7 +187,7 @@ int anetz_create(int kanal, const char *sounddev, int samplerate, double rx_gain
|
|||
PDEBUG(DANETZ, DEBUG_DEBUG, "Creating 'A-Netz' instance for 'Kanal' = %d (sample rate %d).\n", kanal, samplerate);
|
||||
|
||||
/* init general part of transceiver */
|
||||
rc = sender_create(&anetz->sender, kanal, sounddev, samplerate, rx_gain, pre_emphasis, de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, loopback, loss_volume, PILOT_SIGNAL_NONE);
|
||||
rc = sender_create(&anetz->sender, kanal, anetz_kanal2freq(kanal, 0), anetz_kanal2freq(kanal, 1), audiodev, samplerate, rx_gain, pre_emphasis, de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, loopback, loss_volume, PILOT_SIGNAL_NONE);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DANETZ, DEBUG_ERROR, "Failed to init 'Sender' processing!\n");
|
||||
goto error;
|
||||
|
@ -508,7 +508,7 @@ void call_rx_audio(int callref, int16_t *samples, int count)
|
|||
if (anetz->dsp_mode == DSP_MODE_AUDIO) {
|
||||
int16_t up[(int)((double)count * anetz->sender.srstate.factor + 0.5) + 10];
|
||||
count = samplerate_upsample(&anetz->sender.srstate, samples, count, up);
|
||||
jitter_save(&anetz->sender.audio, up, count);
|
||||
jitter_save(&anetz->sender.dejitter, up, count);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ typedef struct anetz {
|
|||
|
||||
double anetz_kanal2freq(int kanal, int unterband);
|
||||
int anetz_init(void);
|
||||
int anetz_create(int kanal, const char *sounddev, int samplerate, double rx_gain, int page_sequence, 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);
|
||||
int anetz_create(int kanal, const char *audiodev, int samplerate, double rx_gain, int page_sequence, 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);
|
||||
void anetz_destroy(sender_t *sender);
|
||||
void anetz_loss_indication(anetz_t *anetz);
|
||||
void anetz_receive_tone(anetz_t *anetz, int bit);
|
||||
|
|
|
@ -371,7 +371,7 @@ void sender_send(sender_t *sender, int16_t *samples, int length)
|
|||
memset(samples, 0, length * sizeof(*samples));
|
||||
break;
|
||||
case DSP_MODE_AUDIO:
|
||||
jitter_load(&anetz->sender.audio, samples, length);
|
||||
jitter_load(&anetz->sender.dejitter, samples, length);
|
||||
break;
|
||||
case DSP_MODE_TONE:
|
||||
fsk_tone(anetz, samples, length);
|
||||
|
|
|
@ -143,9 +143,9 @@ int main(int argc, char *argv[])
|
|||
print_help(argv[-skip_args]);
|
||||
return 0;
|
||||
}
|
||||
if (num_kanal == 1 && num_sounddev == 0)
|
||||
num_sounddev = 1; /* use defualt */
|
||||
if (num_kanal != num_sounddev) {
|
||||
if (num_kanal == 1 && num_audiodev == 0)
|
||||
num_audiodev = 1; /* use defualt */
|
||||
if (num_kanal != num_audiodev) {
|
||||
fprintf(stderr, "You need to specify as many sound devices as you have channels.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
dsp_init();
|
||||
anetz_init();
|
||||
rc = call_init(station_id, call_sounddev, samplerate, latency, 5, loopback);
|
||||
rc = call_init(station_id, call_audiodev, samplerate, latency, 5, loopback);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Failed to create call control instance. Quitting!\n");
|
||||
goto fail;
|
||||
|
@ -171,15 +171,15 @@ int main(int argc, char *argv[])
|
|||
|
||||
/* create transceiver instance */
|
||||
for (i = 0; i < num_kanal; i++) {
|
||||
rc = anetz_create(kanal[i], sounddev[i], samplerate, rx_gain, page_sequence, do_pre_emphasis, do_de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, loopback, lossdetect / 100.0);
|
||||
rc = anetz_create(kanal[i], audiodev[i], samplerate, rx_gain, page_sequence, do_pre_emphasis, do_de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, loopback, lossdetect / 100.0);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Failed to create \"Sender\" instance. Quitting!\n");
|
||||
goto fail;
|
||||
}
|
||||
printf("Base station on channel %d ready, please tune transmitter to %.3f MHz and receiver to %.3f MHz.\n", kanal[i], anetz_kanal2freq(kanal[i], 0), anetz_kanal2freq(kanal[i], 1));
|
||||
printf("Base station on channel %d ready, please tune transmitter to %.3f MHz and receiver to %.3f MHz.\n", kanal[i], anetz_kanal2freq(kanal[i], 0) / 1e6, anetz_kanal2freq(kanal[i], 1) / 1e6);
|
||||
}
|
||||
|
||||
main_loop(&quit, latency, interval, NULL);
|
||||
main_common(&quit, latency, interval, NULL);
|
||||
|
||||
fail:
|
||||
/* cleanup functions */
|
||||
|
|
|
@ -106,7 +106,7 @@ double bnetz_kanal2freq(int kanal, int unterband)
|
|||
if (unterband)
|
||||
freq -= 4.600;
|
||||
|
||||
return freq;
|
||||
return freq * 1e6;
|
||||
}
|
||||
|
||||
/* switch pilot signal (tone or file) */
|
||||
|
@ -141,7 +141,7 @@ static void bnetz_timeout(struct timer *timer);
|
|||
static void bnetz_go_idle(bnetz_t *bnetz);
|
||||
|
||||
/* Create transceiver instance and link to a list. */
|
||||
int bnetz_create(int kanal, const char *sounddev, int samplerate, double rx_gain, int gfs, 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_factor, const char *pilot)
|
||||
int bnetz_create(int kanal, const char *audiodev, int samplerate, double rx_gain, int gfs, 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_factor, const char *pilot)
|
||||
{
|
||||
bnetz_t *bnetz;
|
||||
enum pilot_signal pilot_signal = PILOT_SIGNAL_NONE;
|
||||
|
@ -202,7 +202,7 @@ error_pilot:
|
|||
PDEBUG(DBNETZ, DEBUG_DEBUG, "Creating 'B-Netz' instance for 'Kanal' = %d 'Gruppenfreisignal' = %d (sample rate %d).\n", kanal, gfs, samplerate);
|
||||
|
||||
/* init general part of transceiver */
|
||||
rc = sender_create(&bnetz->sender, kanal, sounddev, samplerate, rx_gain, pre_emphasis, de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, loopback, loss_factor, pilot_signal);
|
||||
rc = sender_create(&bnetz->sender, kanal, bnetz_kanal2freq(kanal, 0), bnetz_kanal2freq(kanal, 1), audiodev, samplerate, rx_gain, pre_emphasis, de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, loopback, loss_factor, pilot_signal);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DBNETZ, DEBUG_ERROR, "Failed to init transceiver process!\n");
|
||||
goto error;
|
||||
|
@ -823,7 +823,7 @@ void call_rx_audio(int callref, int16_t *samples, int count)
|
|||
if (bnetz->dsp_mode == DSP_MODE_AUDIO) {
|
||||
int16_t up[(int)((double)count * bnetz->sender.srstate.factor + 0.5) + 10];
|
||||
count = samplerate_upsample(&bnetz->sender.srstate, samples, count, up);
|
||||
jitter_save(&bnetz->sender.audio, up, count);
|
||||
jitter_save(&bnetz->sender.dejitter, up, count);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ typedef struct bnetz {
|
|||
|
||||
double bnetz_kanal2freq(int kanal, int unterband);
|
||||
int bnetz_init(void);
|
||||
int bnetz_create(int kanal, const char *sounddev, int samplerate, double rx_gain, int gfs, 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_factor, const char *pilot);
|
||||
int bnetz_create(int kanal, const char *audiodev, int samplerate, double rx_gain, int gfs, 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_factor, const char *pilot);
|
||||
void bnetz_destroy(sender_t *sender);
|
||||
void bnetz_loss_indication(bnetz_t *bnetz);
|
||||
void bnetz_receive_tone(bnetz_t *bnetz, int bit);
|
||||
|
|
|
@ -388,7 +388,7 @@ again:
|
|||
memset(samples, 0, length * sizeof(*samples));
|
||||
break;
|
||||
case DSP_MODE_AUDIO:
|
||||
jitter_load(&bnetz->sender.audio, samples, length);
|
||||
jitter_load(&bnetz->sender.dejitter, samples, length);
|
||||
break;
|
||||
case DSP_MODE_0:
|
||||
fsk_tone(bnetz, samples, length, 0);
|
||||
|
|
|
@ -153,9 +153,9 @@ int main(int argc, char *argv[])
|
|||
print_help(argv[-skip_args]);
|
||||
return 0;
|
||||
}
|
||||
if (num_kanal == 1 && num_sounddev == 0)
|
||||
num_sounddev = 1; /* use defualt */
|
||||
if (num_kanal != num_sounddev) {
|
||||
if (num_kanal == 1 && num_audiodev == 0)
|
||||
num_audiodev = 1; /* use defualt */
|
||||
if (num_kanal != num_audiodev) {
|
||||
fprintf(stderr, "You need to specify as many sound devices as you have channels.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
@ -174,12 +174,12 @@ int main(int argc, char *argv[])
|
|||
rc = mncc_init("/tmp/bsc_mncc");
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Failed to setup MNCC socket. Quitting!\n");
|
||||
return -1;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
dsp_init();
|
||||
bnetz_init();
|
||||
rc = call_init(station_id, call_sounddev, samplerate, latency, 5, loopback);
|
||||
rc = call_init(station_id, call_audiodev, samplerate, latency, 5, loopback);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Failed to create call control instance. Quitting!\n");
|
||||
goto fail;
|
||||
|
@ -187,16 +187,16 @@ int main(int argc, char *argv[])
|
|||
|
||||
/* create transceiver instance */
|
||||
for (i = 0; i < num_kanal; i++) {
|
||||
rc = bnetz_create(kanal[i], sounddev[i], samplerate, rx_gain, gfs, do_pre_emphasis, do_de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, loopback, (double)lossdetect / 100.0, pilot[i]);
|
||||
rc = bnetz_create(kanal[i], audiodev[i], samplerate, rx_gain, gfs, do_pre_emphasis, do_de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, loopback, (double)lossdetect / 100.0, pilot[i]);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Failed to create \"Sender\" instance. Quitting!\n");
|
||||
goto fail;
|
||||
}
|
||||
printf("Base station for channel %d ready, please tune transmitter to %.3f MHz and receiver " "to %.3f MHz.\n", kanal[i], bnetz_kanal2freq(kanal[i], 0), bnetz_kanal2freq(kanal[i], 1));
|
||||
printf("To call phone, switch transmitter (using pilot signal) to %.3f MHz.\n", bnetz_kanal2freq(19, 0));
|
||||
printf("Base station for channel %d ready, please tune transmitter to %.3f MHz and receiver " "to %.3f MHz.\n", kanal[i], bnetz_kanal2freq(kanal[i], 0) / 1e6, bnetz_kanal2freq(kanal[i], 1) / 1e6);
|
||||
printf("To call phone, switch transmitter (using pilot signal) to %.3f MHz.\n", bnetz_kanal2freq(19, 0) / 1e6);
|
||||
}
|
||||
|
||||
main_loop(&quit, latency, interval, NULL);
|
||||
main_common(&quit, latency, interval, NULL);
|
||||
|
||||
fail:
|
||||
/* cleanup functions */
|
||||
|
|
|
@ -161,7 +161,7 @@ double cnetz_kanal2freq(int kanal, int unterband)
|
|||
if (unterband)
|
||||
freq -= 10.0;
|
||||
|
||||
return freq;
|
||||
return freq * 1e6;
|
||||
}
|
||||
|
||||
const char *cnetz_state_name(enum cnetz_state state)
|
||||
|
@ -215,7 +215,7 @@ int cnetz_init(void)
|
|||
static void cnetz_go_idle(cnetz_t *cnetz);
|
||||
|
||||
/* Create transceiver instance and link to a list. */
|
||||
int cnetz_create(int kanal, enum cnetz_chan_type chan_type, const char *sounddev, int samplerate, double rx_gain, int auth, int ms_power, int measure_speed, double clock_speed[2], int polarity, double noise, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, int loopback)
|
||||
int cnetz_create(int kanal, enum cnetz_chan_type chan_type, const char *audiodev, int samplerate, double rx_gain, int auth, int ms_power, int measure_speed, double clock_speed[2], int polarity, double noise, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, int loopback)
|
||||
{
|
||||
sender_t *sender;
|
||||
cnetz_t *cnetz;
|
||||
|
@ -258,7 +258,7 @@ int cnetz_create(int kanal, enum cnetz_chan_type chan_type, const char *sounddev
|
|||
|
||||
for (sender = sender_head; sender; sender = sender->next) {
|
||||
cnetz = (cnetz_t *)sender;
|
||||
if (!!strcmp(sender->sounddev, sounddev)) {
|
||||
if (!!strcmp(sender->audiodev, audiodev)) {
|
||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "To be able to sync multiple channels, all channels must be on the same sound device!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -274,7 +274,7 @@ int cnetz_create(int kanal, enum cnetz_chan_type chan_type, const char *sounddev
|
|||
|
||||
/* init general part of transceiver */
|
||||
/* do not enable emphasis, since it is done by cnetz code, not by common sender code */
|
||||
rc = sender_create(&cnetz->sender, kanal, sounddev, samplerate, rx_gain, 0, 0, write_rx_wave, write_tx_wave, read_rx_wave, loopback, 0, PILOT_SIGNAL_NONE);
|
||||
rc = sender_create(&cnetz->sender, kanal, cnetz_kanal2freq(kanal, 0), cnetz_kanal2freq(kanal, 1), audiodev, samplerate, rx_gain, 0, 0, write_rx_wave, write_tx_wave, read_rx_wave, loopback, 0, PILOT_SIGNAL_NONE);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to init transceiver process!\n");
|
||||
goto error;
|
||||
|
@ -443,7 +443,7 @@ void call_rx_audio(int callref, int16_t *samples, int count)
|
|||
|
||||
if (cnetz->dsp_mode == DSP_MODE_SPK_V) {
|
||||
/* store as is, since we convert rate when processing FSK frames */
|
||||
jitter_save(&cnetz->sender.audio, samples, count);
|
||||
jitter_save(&cnetz->sender.dejitter, samples, count);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -123,7 +123,7 @@ int cnetz_channel_by_short_name(const char *short_name);
|
|||
const char *chan_type_short_name(enum cnetz_chan_type chan_type);
|
||||
const char *chan_type_long_name(enum cnetz_chan_type chan_type);
|
||||
int cnetz_init(void);
|
||||
int cnetz_create(int kanal, enum cnetz_chan_type chan_type, const char *sounddev, int samplerate, double rx_gain, int auth, int ms_power, int measure_speed, double clock_speed[2], int polarity, double noise, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, int loopback);
|
||||
int cnetz_create(int kanal, enum cnetz_chan_type chan_type, const char *audiodev, int samplerate, double rx_gain, int auth, int ms_power, int measure_speed, double clock_speed[2], int polarity, double noise, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, int loopback);
|
||||
void cnetz_destroy(sender_t *sender);
|
||||
void cnetz_sync_frame(cnetz_t *cnetz, double sync, int ts);
|
||||
int cnetz_meldeaufruf(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest);
|
||||
|
|
|
@ -137,8 +137,8 @@ int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], do
|
|||
scrambler_setup(&cnetz->scrambler_rx, (double)cnetz->sender.samplerate / 1.1);
|
||||
|
||||
/* reinit jitter buffer for 8000 kHz */
|
||||
jitter_destroy(&cnetz->sender.audio);
|
||||
rc = jitter_create(&cnetz->sender.audio, 8000 / 5);
|
||||
jitter_destroy(&cnetz->sender.dejitter);
|
||||
rc = jitter_create(&cnetz->sender.dejitter, 8000 / 5);
|
||||
if (rc < 0)
|
||||
goto error;
|
||||
|
||||
|
@ -702,7 +702,7 @@ again:
|
|||
for (i = 0; i < copy; i++) {
|
||||
if (*spl == -32768) {
|
||||
/* marker found to insert new chunk of audio */
|
||||
jitter_load(&cnetz->sender.audio, speech_buffer, 100);
|
||||
jitter_load(&cnetz->sender.dejitter, speech_buffer, 100);
|
||||
/* 1. compress dynamics */
|
||||
compress_audio(&cnetz->cstate, speech_buffer, 100);
|
||||
/* 2. upsample */
|
||||
|
|
|
@ -217,9 +217,9 @@ int main(int argc, char *argv[])
|
|||
printf("No channel (\"Kanal\") is specified, I suggest channel %d.\n\n", CNETZ_OGK_KANAL);
|
||||
mandatory = 1;
|
||||
}
|
||||
if (num_kanal == 1 && num_sounddev == 0)
|
||||
num_sounddev = 1; /* use defualt */
|
||||
if (num_kanal != num_sounddev) {
|
||||
if (num_kanal == 1 && num_audiodev == 0)
|
||||
num_audiodev = 1; /* use defualt */
|
||||
if (num_kanal != num_audiodev) {
|
||||
fprintf(stderr, "You need to specify as many sound devices as you have channels.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
@ -248,7 +248,7 @@ int main(int argc, char *argv[])
|
|||
rc = mncc_init("/tmp/bsc_mncc");
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Failed to setup MNCC socket. Quitting!\n");
|
||||
return -1;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
scrambler_init();
|
||||
|
@ -261,7 +261,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
init_coding();
|
||||
cnetz_init();
|
||||
rc = call_init(station_id, call_sounddev, samplerate, latency, 7, loopback);
|
||||
rc = call_init(station_id, call_audiodev, samplerate, latency, 7, loopback);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Failed to create call control instance. Quitting!\n");
|
||||
goto fail;
|
||||
|
@ -302,15 +302,19 @@ int main(int argc, char *argv[])
|
|||
|
||||
/* create transceiver instance */
|
||||
for (i = 0; i < num_kanal; i++) {
|
||||
rc = cnetz_create(kanal[i], chan_type[i], sounddev[i], samplerate, rx_gain, auth, ms_power, (i == 0) ? measure_speed : 0, clock_speed, polarity, noise, do_pre_emphasis, do_de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, loopback);
|
||||
rc = cnetz_create(kanal[i], chan_type[i], audiodev[i], samplerate, rx_gain, auth, ms_power, (i == 0) ? measure_speed : 0, clock_speed, polarity, noise, do_pre_emphasis, do_de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, loopback);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Failed to create \"Sender\" instance. Quitting!\n");
|
||||
goto fail;
|
||||
}
|
||||
printf("Base station on channel %d ready, please tune transmitter to %.3f MHz and receiver to %.3f MHz.\n", kanal[i], cnetz_kanal2freq(kanal[i], 0), cnetz_kanal2freq(kanal[i], 1));
|
||||
if ((kanal[i] & 1)) {
|
||||
printf("Base station on channel %d ready, please tune transmitter to %.3f MHz and receiver to %.3f MHz.\n", kanal[i], cnetz_kanal2freq(kanal[i], 0) / 1e6, cnetz_kanal2freq(kanal[i], 1) / 1e6);
|
||||
} else {
|
||||
printf("Base station on channel %d ready, please tune transmitter to %.4f MHz and receiver to %.4f MHz.\n", kanal[i], cnetz_kanal2freq(kanal[i], 0) / 1e6, cnetz_kanal2freq(kanal[i], 1) / 1e6);
|
||||
}
|
||||
}
|
||||
|
||||
main_loop(&quit, latency, interval, NULL);
|
||||
main_common(&quit, latency, interval, NULL);
|
||||
|
||||
fail:
|
||||
/* cleanup functions */
|
||||
|
|
|
@ -170,7 +170,7 @@ typedef struct call {
|
|||
void *sound; /* headphone interface */
|
||||
int latspl; /* sample latency at sound interface */
|
||||
samplerate_t srstate; /* patterns/announcement upsampling */
|
||||
jitter_t audio; /* headphone audio dejittering */
|
||||
jitter_t dejitter; /* headphone audio dejittering */
|
||||
int audio_pos; /* position when playing patterns */
|
||||
int test_audio_pos; /* position for test tone toward mobile */
|
||||
int dial_digits; /* number of digits to be dialed */
|
||||
|
@ -454,7 +454,7 @@ static void process_timeout(struct timer *timer)
|
|||
}
|
||||
}
|
||||
|
||||
int call_init(const char *station_id, const char *sounddev, int samplerate, int latency, int dial_digits, int loopback)
|
||||
int call_init(const char *station_id, const char *audiodev, int samplerate, int latency, int dial_digits, int loopback)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
|
@ -469,11 +469,11 @@ int call_init(const char *station_id, const char *sounddev, int samplerate, int
|
|||
call.dial_digits = dial_digits;
|
||||
call.loopback = loopback;
|
||||
|
||||
if (!sounddev[0])
|
||||
if (!audiodev[0])
|
||||
return 0;
|
||||
|
||||
/* open sound device for call control */
|
||||
call.sound = sound_open(sounddev, samplerate);
|
||||
call.sound = sound_open(audiodev, NULL, NULL, 1, samplerate);
|
||||
if (!call.sound) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "No sound device!\n");
|
||||
|
||||
|
@ -487,9 +487,9 @@ int call_init(const char *station_id, const char *sounddev, int samplerate, int
|
|||
goto error;
|
||||
}
|
||||
|
||||
rc = jitter_create(&call.audio, samplerate / 5);
|
||||
rc = jitter_create(&call.dejitter, samplerate / 5);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create and init audio buffer!\n");
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create and init dejitter buffer!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -509,7 +509,7 @@ void call_cleanup(void)
|
|||
if (call.sound)
|
||||
sound_close(call.sound);
|
||||
|
||||
jitter_destroy(&call.audio);
|
||||
jitter_destroy(&call.dejitter);
|
||||
|
||||
if (process_head) {
|
||||
PDEBUG(DMNCC, DEBUG_ERROR, "Not all MNCC instances have been released!\n");
|
||||
|
@ -658,17 +658,17 @@ void process_call(int c)
|
|||
get_call_patterns(samples, count, PATTERN_RINGBACK);
|
||||
count = samplerate_upsample(&call.srstate, samples, count, up);
|
||||
/* prevent click after hangup */
|
||||
jitter_clear(&call.audio);
|
||||
jitter_clear(&call.dejitter);
|
||||
break;
|
||||
case CALL_DISCONNECTED:
|
||||
count = (int)((double)count / call.srstate.factor + 0.5);
|
||||
get_call_patterns(samples, count, cause2pattern(call.disc_cause));
|
||||
count = samplerate_upsample(&call.srstate, samples, count, up);
|
||||
/* prevent click after hangup */
|
||||
jitter_clear(&call.audio);
|
||||
jitter_clear(&call.dejitter);
|
||||
break;
|
||||
default:
|
||||
jitter_load(&call.audio, up, count);
|
||||
jitter_load(&call.dejitter, up, count);
|
||||
}
|
||||
spl_list[0] = up;
|
||||
rc = sound_write(call.sound, spl_list, count, 1);
|
||||
|
@ -691,7 +691,7 @@ void process_call(int c)
|
|||
int16_t down[count]; /* more than enough */
|
||||
|
||||
if (call.loopback == 3)
|
||||
jitter_save(&call.audio, samples, count);
|
||||
jitter_save(&call.dejitter, samples, count);
|
||||
count = samplerate_downsample(&call.srstate, samples, count, down);
|
||||
call_rx_audio(call.callref, down, count);
|
||||
}
|
||||
|
@ -922,7 +922,7 @@ void call_tx_audio(int callref, int16_t *samples, int count)
|
|||
if (call.sound) {
|
||||
int16_t up[(int)((double)count * call.srstate.factor + 0.5) + 10];
|
||||
count = samplerate_upsample(&call.srstate, samples, count, up);
|
||||
jitter_save(&call.audio, up, count);
|
||||
jitter_save(&call.dejitter, up, count);
|
||||
} else
|
||||
/* else, if no sound is used, send test tone to mobile */
|
||||
if (call.state == CALL_CONNECT) {
|
||||
|
|
|
@ -9,7 +9,7 @@ enum number_type {
|
|||
TYPE_INTERNATIONAL,
|
||||
};
|
||||
|
||||
int call_init(const char *station_id, const char *sounddev, int samplerate, int latency, int dial_digits, int loopback);
|
||||
int call_init(const char *station_id, const char *audiodev, int samplerate, int latency, int dial_digits, int loopback);
|
||||
void call_cleanup(void);
|
||||
void process_call(int c);
|
||||
void clear_console_text(void);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
|
||||
extern int num_kanal;
|
||||
extern int kanal[];
|
||||
extern int num_sounddev;
|
||||
extern const char *sounddev[];
|
||||
extern const char *call_sounddev;
|
||||
extern int num_audiodev;
|
||||
extern const char *audiodev[];
|
||||
extern const char *call_audiodev;
|
||||
extern int samplerate;
|
||||
extern int interval;
|
||||
extern int latency;
|
||||
|
@ -39,7 +39,7 @@ void opt_switch_common(int c, char *arg0, int *skip_args);
|
|||
extern int quit;
|
||||
void sighandler(int sigset);
|
||||
|
||||
void main_loop(int *quit, int latency, int interval, void (*myhandler)(void));
|
||||
void main_common(int *quit, int latency, int interval, void (*myhandler)(void));
|
||||
|
||||
void dump_info(void);
|
||||
|
||||
|
|
|
@ -36,9 +36,9 @@
|
|||
/* common settings */
|
||||
int num_kanal = 0;
|
||||
int kanal[MAX_SENDER];
|
||||
int num_sounddev = 0;
|
||||
const char *sounddev[MAX_SENDER] = { "hw:0,0" };
|
||||
const char *call_sounddev = "";
|
||||
int num_audiodev = 0;
|
||||
const char *audiodev[MAX_SENDER] = { "hw:0,0" };
|
||||
const char *call_audiodev = "";
|
||||
int samplerate = 48000;
|
||||
int interval = 1;
|
||||
int latency = 50;
|
||||
|
@ -95,7 +95,7 @@ void print_help_common(const char *arg0, const char *ext_usage)
|
|||
printf(" -m --mncc-sock\n");
|
||||
printf(" Disable built-in call contol and offer socket (to LCR)\n");
|
||||
printf(" -c --call-device hw:<card>,<device>\n");
|
||||
printf(" Sound card and device number for headset (default = '%s')\n", call_sounddev);
|
||||
printf(" Sound card and device number for headset (default = '%s')\n", call_audiodev);
|
||||
printf(" -t --tones 0 | 1\n");
|
||||
printf(" Connect call on setup/release to provide classic tones towards fixed\n");
|
||||
printf(" network (default = '%d')\n", send_patterns);
|
||||
|
@ -208,7 +208,7 @@ void opt_switch_common(int c, char *arg0, int *skip_args)
|
|||
*skip_args += 2;
|
||||
break;
|
||||
case 'a':
|
||||
OPT_ARRAY(num_sounddev, sounddev, strdup(optarg))
|
||||
OPT_ARRAY(num_audiodev, audiodev, strdup(optarg))
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case 's':
|
||||
|
@ -256,7 +256,7 @@ void opt_switch_common(int c, char *arg0, int *skip_args)
|
|||
*skip_args += 1;
|
||||
break;
|
||||
case 'c':
|
||||
call_sounddev = strdup(optarg);
|
||||
call_audiodev = strdup(optarg);
|
||||
*skip_args += 2;
|
||||
break;
|
||||
case 't':
|
||||
|
@ -322,7 +322,7 @@ static int get_char()
|
|||
}
|
||||
|
||||
/* Loop through all transceiver instances of one network. */
|
||||
void main_loop(int *quit, int latency, int interval, void (*myhandler)(void))
|
||||
void main_common(int *quit, int latency, int interval, void (*myhandler)(void))
|
||||
{
|
||||
int latspl;
|
||||
sender_t *sender;
|
||||
|
@ -330,11 +330,10 @@ void main_loop(int *quit, int latency, int interval, void (*myhandler)(void))
|
|||
struct termios term, term_orig;
|
||||
int c;
|
||||
|
||||
/* catch signals */
|
||||
signal(SIGINT, sighandler);
|
||||
signal(SIGHUP, sighandler);
|
||||
signal(SIGTERM, sighandler);
|
||||
signal(SIGPIPE, sighandler);
|
||||
|
||||
/* open audio */
|
||||
if (sender_open_audio())
|
||||
return;
|
||||
|
||||
/* real time priority */
|
||||
if (rt_prio > 0) {
|
||||
|
@ -356,6 +355,12 @@ void main_loop(int *quit, int latency, int interval, void (*myhandler)(void))
|
|||
term.c_cc[VTIME]=2;
|
||||
tcsetattr(0, TCSANOW, &term);
|
||||
|
||||
/* catch signals */
|
||||
signal(SIGINT, sighandler);
|
||||
signal(SIGHUP, sighandler);
|
||||
signal(SIGTERM, sighandler);
|
||||
signal(SIGPIPE, sighandler);
|
||||
|
||||
while(!(*quit)) {
|
||||
/* process sound of all transceivers */
|
||||
for (sender = sender_head; sender; sender = sender->next) {
|
||||
|
@ -408,6 +413,12 @@ next_char:
|
|||
usleep(interval * 1000);
|
||||
}
|
||||
|
||||
/* reset signals */
|
||||
signal(SIGINT, SIG_DFL);
|
||||
signal(SIGHUP, SIG_DFL);
|
||||
signal(SIGTERM, SIG_DFL);
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
|
||||
/* get rid of last entry */
|
||||
clear_console_text();
|
||||
|
||||
|
@ -422,11 +433,5 @@ next_char:
|
|||
schedp.sched_priority = 0;
|
||||
sched_setscheduler(0, SCHED_OTHER, &schedp);
|
||||
}
|
||||
|
||||
/* reset signals */
|
||||
signal(SIGINT, SIG_DFL);
|
||||
signal(SIGHUP, SIG_DFL);
|
||||
signal(SIGTERM, SIG_DFL);
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,13 +32,15 @@ static sender_t **sender_tailp = &sender_head;
|
|||
int cant_recover = 0;
|
||||
|
||||
/* Init transceiver instance and link to list of transceivers. */
|
||||
int sender_create(sender_t *sender, int kanal, const char *sounddev, 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 pilot_signal pilot_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 pilot_signal pilot_signal)
|
||||
{
|
||||
sender_t *master;
|
||||
sender_t *master, *slave;
|
||||
int rc = 0;
|
||||
|
||||
sender->kanal = kanal;
|
||||
strncpy(sender->sounddev, sounddev, sizeof(sender->sounddev) - 1);
|
||||
sender->sendefrequenz = sendefrequenz;
|
||||
sender->empfangsfrequenz = empfangsfrequenz;
|
||||
strncpy(sender->audiodev, audiodev, sizeof(sender->audiodev) - 1);
|
||||
sender->samplerate = samplerate;
|
||||
sender->rx_gain = rx_gain;
|
||||
sender->pre_emphasis = pre_emphasis;
|
||||
|
@ -61,43 +63,36 @@ int sender_create(sender_t *sender, int kanal, const char *sounddev, int sampler
|
|||
rc = -EIO;
|
||||
goto error;
|
||||
}
|
||||
if (!strcmp(master->sounddev, sounddev))
|
||||
if (!strcmp(master->audiodev, audiodev))
|
||||
break;
|
||||
}
|
||||
if (master) {
|
||||
// FIXME: link more than two channels
|
||||
if (master->slave) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "Sound device '%s' cannot be used for channel %d. It is already shared by channel %d and %d!\n", sounddev, kanal, master->kanal, master->slave->kanal);
|
||||
rc = -EBUSY;
|
||||
goto error;
|
||||
}
|
||||
if (!sound_is_stereo_capture(master->sound) || !sound_is_stereo_playback(master->sound)) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "Sound device '%s' cannot be used for more than one channel, because one direction is mono!\n", sounddev);
|
||||
rc = -EBUSY;
|
||||
goto error;
|
||||
}
|
||||
if (master->pilot_signal != PILOT_SIGNAL_NONE) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "Cannot share sound device with channel %d, because second channel is used for pilot signal!\n", master->kanal);
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "Cannot share audio device with channel %d, because second channel is used for pilot signal!\n", master->kanal);
|
||||
rc = -EBUSY;
|
||||
goto error;
|
||||
}
|
||||
if (pilot_signal != PILOT_SIGNAL_NONE) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "Cannot share sound device with channel %d, because we need a stereo channel for pilot signal!\n", master->kanal);
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "Cannot share audio device with channel %d, because we need a stereo channel for pilot signal!\n", master->kanal);
|
||||
rc = -EBUSY;
|
||||
goto error;
|
||||
}
|
||||
/* link us to a master/slave */
|
||||
master->slave = sender;
|
||||
// FIXME: link more than two channels, so link to last slave
|
||||
/* link us to a master */
|
||||
sender->master = master;
|
||||
/* link master (or last slave) to us */
|
||||
for (slave = master; ; slave = slave->slave) {
|
||||
if (!slave->slave)
|
||||
break;
|
||||
}
|
||||
slave->slave = sender;
|
||||
} else {
|
||||
/* open own device */
|
||||
sender->sound = sound_open(sounddev, samplerate);
|
||||
if (!sender->sound) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "No sound device!\n");
|
||||
|
||||
rc = -EIO;
|
||||
goto error;
|
||||
/* link audio device */
|
||||
{
|
||||
sender->audio_open = sound_open;
|
||||
sender->audio_close = sound_close;
|
||||
sender->audio_read = sound_read;
|
||||
sender->audio_write = sound_write;
|
||||
sender->audio_get_inbuffer = sound_get_inbuffer;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,7 +102,7 @@ int sender_create(sender_t *sender, int kanal, const char *sounddev, int sampler
|
|||
goto error;
|
||||
}
|
||||
|
||||
rc = jitter_create(&sender->audio, samplerate / 5);
|
||||
rc = jitter_create(&sender->dejitter, samplerate / 5);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create and init audio buffer!\n");
|
||||
goto error;
|
||||
|
@ -151,6 +146,42 @@ error:
|
|||
return rc;
|
||||
}
|
||||
|
||||
int sender_open_audio(void)
|
||||
{
|
||||
sender_t *master, *inst;
|
||||
int channels;
|
||||
int i;
|
||||
|
||||
for (master = sender_head; master; master = master->next) {
|
||||
/* skip audio slaves */
|
||||
if (master->master)
|
||||
continue;
|
||||
|
||||
/* get list of frequencies */
|
||||
channels = 0;
|
||||
for (inst = master; inst; inst = inst->slave) {
|
||||
channels++;
|
||||
}
|
||||
double tx_f[channels], rx_f[channels];
|
||||
for (i = 0, inst = master; inst; i++, inst = inst->slave) {
|
||||
tx_f[i] = inst->sendefrequenz;
|
||||
if (inst->loopback)
|
||||
rx_f[i] = inst->sendefrequenz;
|
||||
else
|
||||
rx_f[i] = inst->empfangsfrequenz;
|
||||
}
|
||||
|
||||
/* open device */
|
||||
master->audio = master->audio_open(master->audiodev, tx_f, rx_f, channels, master->samplerate);
|
||||
if (!master->audio) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "No audio device!\n");
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Destroy transceiver instance and unlink from list. */
|
||||
void sender_destroy(sender_t *sender)
|
||||
{
|
||||
|
@ -164,16 +195,16 @@ void sender_destroy(sender_t *sender)
|
|||
sender_tailp = &((*sender_tailp)->next);
|
||||
}
|
||||
|
||||
if (sender->sound) {
|
||||
sound_close(sender->sound);
|
||||
sender->sound = NULL;
|
||||
if (sender->audio) {
|
||||
sender->audio_close(sender->audio);
|
||||
sender->audio = NULL;
|
||||
}
|
||||
|
||||
wave_destroy_record(&sender->wave_rx_rec);
|
||||
wave_destroy_record(&sender->wave_tx_rec);
|
||||
wave_destroy_playback(&sender->wave_rx_play);
|
||||
|
||||
jitter_destroy(&sender->audio);
|
||||
jitter_destroy(&sender->dejitter);
|
||||
}
|
||||
|
||||
static void gen_pilotton(sender_t *sender, int16_t *samples, int length)
|
||||
|
@ -221,19 +252,23 @@ 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);
|
||||
if (sender->pilot_signal) {
|
||||
if (sender->pilot_signal != PILOT_SIGNAL_NONE) {
|
||||
if (num_chan != 1) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "Software error, please fix!\n");
|
||||
abort();
|
||||
}
|
||||
num_chan++;
|
||||
num_chan = 2;
|
||||
}
|
||||
int16_t buff[num_chan][latspl], *samples[num_chan];
|
||||
for (i = 0; i < num_chan; i++)
|
||||
samples[i] = buff[i];
|
||||
|
||||
count = sound_get_inbuffer(sender->sound);
|
||||
count = sender->audio_get_inbuffer(sender->audio);
|
||||
if (count < 0) {
|
||||
/* special case when the device is not yet ready to transmit packets */
|
||||
if (count == -EAGAIN) {
|
||||
goto transmit_later;
|
||||
}
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to get samples in buffer (rc = %d)!\n", count);
|
||||
if (count == -EPIPE) {
|
||||
if (cant_recover) {
|
||||
|
@ -252,7 +287,7 @@ cant_recover:
|
|||
for (i = 0, inst = sender; inst; i++, inst = inst->slave) {
|
||||
/* load TX data from audio loop or from sender instance */
|
||||
if (inst->loopback == 3)
|
||||
jitter_load(&inst->audio, samples[i], count);
|
||||
jitter_load(&inst->dejitter, samples[i], count);
|
||||
else
|
||||
sender_send(inst, samples[i], count);
|
||||
if (inst->wave_tx_rec.fp)
|
||||
|
@ -301,9 +336,9 @@ cant_recover:
|
|||
break;
|
||||
}
|
||||
|
||||
rc = sound_write(sender->sound, samples, count, num_chan);
|
||||
rc = sender->audio_write(sender->audio, samples, count, num_chan);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to write TX data to sound device (rc = %d)\n", rc);
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to write TX data to audio device (rc = %d)\n", rc);
|
||||
if (rc == -EPIPE) {
|
||||
if (cant_recover)
|
||||
goto cant_recover;
|
||||
|
@ -312,10 +347,16 @@ cant_recover:
|
|||
return;
|
||||
}
|
||||
}
|
||||
transmit_later:
|
||||
|
||||
count = sound_read(sender->sound, samples, latspl, num_chan);
|
||||
count = sender->audio_read(sender->audio, samples, latspl, num_chan);
|
||||
if (count < 0) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to read from sound device (rc = %d)!\n", count);
|
||||
/* special case when audio_read wants us to quit */
|
||||
if (count == -EPERM) {
|
||||
*quit = 1;
|
||||
return;
|
||||
}
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to read from audio device (rc = %d)!\n", count);
|
||||
if (count == -EPIPE) {
|
||||
if (cant_recover)
|
||||
goto cant_recover;
|
||||
|
@ -341,7 +382,7 @@ cant_recover:
|
|||
sender_receive(inst, samples[i], count);
|
||||
}
|
||||
if (inst->loopback == 3)
|
||||
jitter_save(&inst->audio, samples[i], count);
|
||||
jitter_save(&inst->dejitter, samples[i], count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,10 +25,17 @@ typedef struct sender {
|
|||
|
||||
/* system info */
|
||||
int kanal; /* channel number */
|
||||
double sendefrequenz; /* transmitter frequency */
|
||||
double empfangsfrequenz; /* receiver frequency */
|
||||
|
||||
/* sound */
|
||||
void *sound;
|
||||
char sounddev[64]; /* sound device name */
|
||||
/* audio */
|
||||
void *audio;
|
||||
char audiodev[64]; /* audio device name (alsa or sdr) */
|
||||
void *(*audio_open)(const char *, double *, double *, int, int);
|
||||
void (*audio_close)(void *);
|
||||
int (*audio_write)(void *, int16_t **, int, int);
|
||||
int (*audio_read)(void *, int16_t **, int, int);
|
||||
int (*audio_get_inbuffer)(void *);
|
||||
int samplerate;
|
||||
samplerate_t srstate; /* sample rate conversion state */
|
||||
double rx_gain; /* factor of level to apply on rx samples */
|
||||
|
@ -45,7 +52,7 @@ typedef struct sender {
|
|||
wave_play_t wave_rx_play; /* wave playback (as rx) */
|
||||
|
||||
/* audio buffer for audio to send to transmitter (also used as loopback buffer) */
|
||||
jitter_t audio;
|
||||
jitter_t dejitter;
|
||||
|
||||
/* audio buffer for audio to send to caller (20ms = 160 samples @ 8000Hz) */
|
||||
int16_t rxbuf[160];
|
||||
|
@ -69,8 +76,9 @@ typedef struct sender {
|
|||
extern sender_t *sender_head;
|
||||
extern int cant_recover;
|
||||
|
||||
int sender_create(sender_t *sender, int kanal, const char *sounddev, 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 pilot_signal pilot_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 pilot_signal pilot_signal);
|
||||
void sender_destroy(sender_t *sender);
|
||||
int sender_open_audio(void);
|
||||
void process_sender_audio(sender_t *sender, int *quit, int latspl);
|
||||
void sender_send(sender_t *sender, int16_t *samples, int count);
|
||||
void sender_receive(sender_t *sender, int16_t *samples, int count);
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
|
||||
void *sound_open(const char *device, int samplerate);
|
||||
void *sound_open(const char *audiodev, double *tx_frequency, double *rx_frequency, int channels, int samplerate);
|
||||
void sound_close(void *inst);
|
||||
int sound_write(void *inst, int16_t **samples, int num, int channels);
|
||||
int sound_read(void *inst, int16_t **samples, int num, int channels);
|
||||
int sound_get_inbuffer(void *inst);
|
||||
int sound_is_stereo_capture(void *inst);
|
||||
int sound_is_stereo_playback(void *inst);
|
||||
|
||||
|
|
|
@ -128,26 +128,31 @@ static int sound_prepare(sound_t *sound)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void *sound_open(const char *device, int samplerate)
|
||||
void *sound_open(const char *audiodev, double __attribute__((unused)) *tx_frequency, double __attribute__((unused)) *rx_frequency, int channels, int samplerate)
|
||||
{
|
||||
sound_t *sound;
|
||||
int rc;
|
||||
|
||||
if (channels < 1 || channels > 2) {
|
||||
PDEBUG(DSOUND, DEBUG_ERROR, "Cannot use more than two channels with the same sound card!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sound = calloc(1, sizeof(sound_t));
|
||||
if (!sound) {
|
||||
PDEBUG(DSOUND, DEBUG_ERROR, "Failed to alloc memory!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = snd_pcm_open(&sound->phandle, device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
|
||||
rc = snd_pcm_open(&sound->phandle, audiodev, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DSOUND, DEBUG_ERROR, "Failed to open '%s' for playback! (%s)\n", device, snd_strerror(rc));
|
||||
PDEBUG(DSOUND, DEBUG_ERROR, "Failed to open '%s' for playback! (%s)\n", audiodev, snd_strerror(rc));
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = snd_pcm_open(&sound->chandle, device, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
|
||||
rc = snd_pcm_open(&sound->chandle, audiodev, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DSOUND, DEBUG_ERROR, "Failed to open '%s' for capture! (%s)\n", device, snd_strerror(rc));
|
||||
PDEBUG(DSOUND, DEBUG_ERROR, "Failed to open '%s' for capture! (%s)\n", audiodev, snd_strerror(rc));
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -156,6 +161,10 @@ void *sound_open(const char *device, int samplerate)
|
|||
PDEBUG(DSOUND, DEBUG_ERROR, "Failed to set playback hw params\n");
|
||||
goto error;
|
||||
}
|
||||
if (sound->pchannels < channels) {
|
||||
PDEBUG(DSOUND, DEBUG_ERROR, "Sound card only supports %d channel for playback.\n", sound->pchannels);
|
||||
goto error;
|
||||
}
|
||||
PDEBUG(DSOUND, DEBUG_DEBUG, "Playback with %d channels.\n", sound->pchannels);
|
||||
|
||||
rc = set_hw_params(sound->chandle, samplerate, &sound->cchannels);
|
||||
|
@ -163,6 +172,10 @@ void *sound_open(const char *device, int samplerate)
|
|||
PDEBUG(DSOUND, DEBUG_ERROR, "Failed to set capture hw params\n");
|
||||
goto error;
|
||||
}
|
||||
if (sound->cchannels < channels) {
|
||||
PDEBUG(DSOUND, DEBUG_ERROR, "Sound card only supports %d channel for capture.\n", sound->cchannels);
|
||||
goto error;
|
||||
}
|
||||
PDEBUG(DSOUND, DEBUG_DEBUG, "Capture with %d channels.\n", sound->cchannels);
|
||||
|
||||
rc = sound_prepare(sound);
|
||||
|
|
|
@ -624,7 +624,7 @@ again:
|
|||
switch (nmt->dsp_mode) {
|
||||
case DSP_MODE_AUDIO:
|
||||
case DSP_MODE_DTMF:
|
||||
jitter_load(&nmt->sender.audio, samples, length);
|
||||
jitter_load(&nmt->sender.dejitter, samples, length);
|
||||
/* send after dejitter, so audio is flushed */
|
||||
if (nmt->dms.frame_valid) {
|
||||
fsk_dms_frame(nmt, samples, length);
|
||||
|
|
|
@ -281,9 +281,9 @@ int main(int argc, char *argv[])
|
|||
printf("No channel (\"Kanal\") is specified, I suggest channel 1 (-k 1).\n\n");
|
||||
mandatory = 1;
|
||||
}
|
||||
if (num_kanal == 1 && num_sounddev == 0)
|
||||
num_sounddev = 1; /* use defualt */
|
||||
if (num_kanal != num_sounddev) {
|
||||
if (num_kanal == 1 && num_audiodev == 0)
|
||||
num_audiodev = 1; /* use defualt */
|
||||
if (num_kanal != num_audiodev) {
|
||||
fprintf(stderr, "You need to specify as many sound devices as you have channels.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
@ -335,7 +335,7 @@ int main(int argc, char *argv[])
|
|||
return -1;
|
||||
}
|
||||
dsp_init();
|
||||
rc = call_init(station_id, call_sounddev, samplerate, latency, 7, loopback);
|
||||
rc = call_init(station_id, call_audiodev, samplerate, latency, 7, loopback);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Failed to create call control instance. Quitting!\n");
|
||||
goto fail;
|
||||
|
@ -343,21 +343,21 @@ int main(int argc, char *argv[])
|
|||
|
||||
/* create transceiver instance */
|
||||
for (i = 0; i < num_kanal; i++) {
|
||||
rc = nmt_create(kanal[i], (loopback) ? CHAN_TYPE_TEST : chan_type[i], sounddev[i], samplerate, rx_gain, do_pre_emphasis, do_de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, ms_power, nmt_digits2value(traffic_area, 2), area_no, compandor, supervisory, smsc_number, send_callerid, loopback);
|
||||
rc = nmt_create(kanal[i], (loopback) ? CHAN_TYPE_TEST : chan_type[i], audiodev[i], samplerate, rx_gain, do_pre_emphasis, do_de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, ms_power, nmt_digits2value(traffic_area, 2), area_no, compandor, supervisory, smsc_number, send_callerid, loopback);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Failed to create transceiver instance. Quitting!\n");
|
||||
goto fail;
|
||||
}
|
||||
if (kanal[i] > 200) {
|
||||
printf("Base station on channel %d ready, please tune transmitter to %.4f MHz and receiver to %.4f MHz.\n", kanal[i], nmt_channel2freq(kanal[i], 0), nmt_channel2freq(kanal[i], 1));
|
||||
printf("Base station on channel %d ready, please tune transmitter to %.4f MHz and receiver to %.4f MHz.\n", kanal[i], nmt_channel2freq(kanal[i], 0) / 1e6, nmt_channel2freq(kanal[i], 1) / 1e6);
|
||||
} else {
|
||||
printf("Base station on channel %d ready, please tune transmitter to %.3f MHz and receiver to %.3f MHz.\n", kanal[i], nmt_channel2freq(kanal[i], 0), nmt_channel2freq(kanal[i], 1));
|
||||
printf("Base station on channel %d ready, please tune transmitter to %.3f MHz and receiver to %.3f MHz.\n", kanal[i], nmt_channel2freq(kanal[i], 0) / 1e6, nmt_channel2freq(kanal[i], 1) / 1e6);
|
||||
}
|
||||
}
|
||||
|
||||
nmt_check_channels();
|
||||
|
||||
main_loop(&quit, latency, interval, myhandler);
|
||||
main_common(&quit, latency, interval, myhandler);
|
||||
|
||||
fail:
|
||||
/* fifo */
|
||||
|
|
|
@ -218,7 +218,7 @@ double nmt_channel2freq(int channel, int uplink)
|
|||
if (uplink)
|
||||
freq -= 10.000;
|
||||
|
||||
return freq;
|
||||
return freq * 1e6;
|
||||
}
|
||||
|
||||
/* convert 7-digits dial string to NMT number */
|
||||
|
@ -303,7 +303,7 @@ uint8_t nmt_country_by_short_name(const char *short_name)
|
|||
static void nmt_timeout(struct timer *timer);
|
||||
|
||||
/* Create transceiver instance and link to a list. */
|
||||
int nmt_create(int channel, enum nmt_chan_type chan_type, const char *sounddev, 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, uint8_t ms_power, uint8_t traffic_area, uint8_t area_no, int compandor, int supervisory, const char *smsc_number, int send_callerid, int loopback)
|
||||
int nmt_create(int channel, enum nmt_chan_type chan_type, 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, uint8_t ms_power, uint8_t traffic_area, uint8_t area_no, int compandor, int supervisory, const char *smsc_number, int send_callerid, int loopback)
|
||||
{
|
||||
nmt_t *nmt;
|
||||
int rc;
|
||||
|
@ -334,7 +334,7 @@ int nmt_create(int channel, enum nmt_chan_type chan_type, const char *sounddev,
|
|||
PDEBUG(DNMT, DEBUG_DEBUG, "Creating 'NMT' instance for channel = %d (sample rate %d).\n", channel, samplerate);
|
||||
|
||||
/* init general part of transceiver */
|
||||
rc = sender_create(&nmt->sender, channel, sounddev, samplerate, rx_gain, pre_emphasis, de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, loopback, 0, PILOT_SIGNAL_NONE);
|
||||
rc = sender_create(&nmt->sender, channel, nmt_channel2freq(channel, 0), nmt_channel2freq(channel, 1), audiodev, samplerate, rx_gain, pre_emphasis, de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, loopback, 0, PILOT_SIGNAL_NONE);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DNMT, DEBUG_ERROR, "Failed to init transceiver process!\n");
|
||||
goto error;
|
||||
|
@ -1816,7 +1816,7 @@ void call_rx_audio(int callref, int16_t *samples, int count)
|
|||
if (nmt->compandor)
|
||||
compress_audio(&nmt->cstate, samples, count);
|
||||
count = samplerate_upsample(&nmt->sender.srstate, samples, count, up);
|
||||
jitter_save(&nmt->sender.audio, up, count);
|
||||
jitter_save(&nmt->sender.dejitter, up, count);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ const char *chan_type_long_name(enum nmt_chan_type chan_type);
|
|||
double nmt_channel2freq(int channel, int uplink);
|
||||
void nmt_country_list(void);
|
||||
uint8_t nmt_country_by_short_name(const char *short_name);
|
||||
int nmt_create(int channel, enum nmt_chan_type chan_type, const char *sounddev, 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, uint8_t ms_power, uint8_t traffic_area, uint8_t area_no, int compandor, int supervisory, const char *smsc_number, int send_callerid, int loopback);
|
||||
int nmt_create(int channel, enum nmt_chan_type chan_type, 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, uint8_t ms_power, uint8_t traffic_area, uint8_t area_no, int compandor, int supervisory, const char *smsc_number, int send_callerid, int loopback);
|
||||
void nmt_check_channels(void);
|
||||
void nmt_destroy(sender_t *sender);
|
||||
void nmt_go_idle(nmt_t *nmt);
|
||||
|
|
Loading…
Reference in New Issue