diff options
author | Andreas Eversberg <jolly@eversberg.eu> | 2017-01-04 14:14:02 +0100 |
---|---|---|
committer | Andreas Eversberg <jolly@eversberg.eu> | 2017-02-18 21:00:45 +0100 |
commit | 9ff8c3bb25422e100801f90c17b9c21118920cfd (patch) | |
tree | 5715f3cc08893ed86dfc2514c93797d12e24d461 | |
parent | d54d3ac2654844c7b8e4ee67752941c9037d5f42 (diff) |
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.
-rw-r--r-- | src/amps/amps.c | 8 | ||||
-rw-r--r-- | src/amps/amps.h | 2 | ||||
-rw-r--r-- | src/amps/dsp.c | 2 | ||||
-rw-r--r-- | src/amps/frame.c | 2 | ||||
-rw-r--r-- | src/amps/main.c | 14 | ||||
-rw-r--r-- | src/anetz/anetz.c | 8 | ||||
-rw-r--r-- | src/anetz/anetz.h | 2 | ||||
-rw-r--r-- | src/anetz/dsp.c | 2 | ||||
-rw-r--r-- | src/anetz/main.c | 14 | ||||
-rw-r--r-- | src/bnetz/bnetz.c | 8 | ||||
-rw-r--r-- | src/bnetz/bnetz.h | 2 | ||||
-rw-r--r-- | src/bnetz/dsp.c | 2 | ||||
-rw-r--r-- | src/bnetz/main.c | 18 | ||||
-rw-r--r-- | src/cnetz/cnetz.c | 10 | ||||
-rw-r--r-- | src/cnetz/cnetz.h | 2 | ||||
-rw-r--r-- | src/cnetz/dsp.c | 6 | ||||
-rw-r--r-- | src/cnetz/main.c | 20 | ||||
-rw-r--r-- | src/common/call.c | 24 | ||||
-rw-r--r-- | src/common/call.h | 2 | ||||
-rw-r--r-- | src/common/main.h | 8 | ||||
-rw-r--r-- | src/common/main_common.c | 41 | ||||
-rw-r--r-- | src/common/sender.c | 123 | ||||
-rw-r--r-- | src/common/sender.h | 18 | ||||
-rw-r--r-- | src/common/sound.h | 4 | ||||
-rw-r--r-- | src/common/sound_alsa.c | 23 | ||||
-rw-r--r-- | src/nmt/dsp.c | 2 | ||||
-rw-r--r-- | src/nmt/main.c | 16 | ||||
-rw-r--r-- | src/nmt/nmt.c | 8 | ||||
-rw-r--r-- | src/nmt/nmt.h | 2 |
29 files changed, 231 insertions, 162 deletions
diff --git a/src/amps/amps.c b/src/amps/amps.c index cfe5155..8f9b1ad 100644 --- a/src/amps/amps.c +++ b/src/amps/amps.c @@ -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); } } diff --git a/src/amps/amps.h b/src/amps/amps.h index b9f4ad2..4ff910b 100644 --- a/src/amps/amps.h +++ b/src/amps/amps.h @@ -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); diff --git a/src/amps/dsp.c b/src/amps/dsp.c index ae8b27b..776ec3b 100644 --- a/src/amps/dsp.c +++ b/src/amps/dsp.c @@ -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); diff --git a/src/amps/frame.c b/src/amps/frame.c index 6cf00bb..478739b 100644 --- a/src/amps/frame.c +++ b/src/amps/frame.c @@ -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; } diff --git a/src/amps/main.c b/src/amps/main.c index d50b423..e97c5d4 100644 --- a/src/amps/main.c +++ b/src/amps/main.c @@ -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 */ diff --git a/src/anetz/anetz.c b/src/anetz/anetz.c index f8c13fd..23ec592 100644 --- a/src/anetz/anetz.c +++ b/src/anetz/anetz.c @@ -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); } } diff --git a/src/anetz/anetz.h b/src/anetz/anetz.h index eacc616..ed5c4d5 100644 --- a/src/anetz/anetz.h +++ b/src/anetz/anetz.h @@ -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); diff --git a/src/anetz/dsp.c b/src/anetz/dsp.c index b79b572..41888cd 100644 --- a/src/anetz/dsp.c +++ b/src/anetz/dsp.c @@ -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); diff --git a/src/anetz/main.c b/src/anetz/main.c index 9b06859..d13d5be 100644 --- a/src/anetz/main.c +++ b/src/anetz/main.c @@ -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 */ diff --git a/src/bnetz/bnetz.c b/src/bnetz/bnetz.c index 9bb4b8b..6b8a6d9 100644 --- a/src/bnetz/bnetz.c +++ b/src/bnetz/bnetz.c @@ -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); } } diff --git a/src/bnetz/bnetz.h b/src/bnetz/bnetz.h index 444a5a2..10f5a6d 100644 --- a/src/bnetz/bnetz.h +++ b/src/bnetz/bnetz.h @@ -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); diff --git a/src/bnetz/dsp.c b/src/bnetz/dsp.c index d91780f..2e2a7f1 100644 --- a/src/bnetz/dsp.c +++ b/src/bnetz/dsp.c @@ -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); diff --git a/src/bnetz/main.c b/src/bnetz/main.c index 6f5a73b..7322ca3 100644 --- a/src/bnetz/main.c +++ b/src/bnetz/main.c @@ -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 */ diff --git a/src/cnetz/cnetz.c b/src/cnetz/cnetz.c index ca0e941..f0a4ec5 100644 --- a/src/cnetz/cnetz.c +++ b/src/cnetz/cnetz.c @@ -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); } } diff --git a/src/cnetz/cnetz.h b/src/cnetz/cnetz.h index 8691ac4..5897735 100644 --- a/src/cnetz/cnetz.h +++ b/src/cnetz/cnetz.h @@ -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); diff --git a/src/cnetz/dsp.c b/src/cnetz/dsp.c index 0b78b92..a35e8c8 100644 --- a/src/cnetz/dsp.c +++ b/src/cnetz/dsp.c @@ -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 */ diff --git a/src/cnetz/main.c b/src/cnetz/main.c index efe3148..ddb8216 100644 --- a/src/cnetz/main.c +++ b/src/cnetz/main.c @@ -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 */ diff --git a/src/common/call.c b/src/common/call.c index 62bfa89..7f8fae6 100644 --- a/src/common/call.c +++ b/src/common/call.c @@ -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) { diff --git a/src/common/call.h b/src/common/call.h index 1f96fe7..996224f 100644 --- a/src/common/call.h +++ b/src/common/call.h @@ -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); diff --git a/src/common/main.h b/src/common/main.h index c8d1180..3b680e4 100644 --- a/src/common/main.h +++ b/src/common/main.h @@ -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); diff --git a/src/common/main_common.c b/src/common/main_common.c index 4c731f6..11fa358 100644 --- a/src/common/main_common.c +++ b/src/common/main_common.c @@ -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); } diff --git a/src/common/sender.c b/src/common/sender.c index 3a5dc43..45760e1 100644 --- a/src/common/sender.c +++ b/src/common/sender.c @@ -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); } } } diff --git a/src/common/sender.h b/src/common/sender.h index 2f3fc75..c89b405 100644 --- a/src/common/sender.h +++ b/src/common/sender.h @@ -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); diff --git a/src/common/sound.h b/src/common/sound.h index b516fdf..45eb2c0 100644 --- a/src/common/sound.h +++ b/src/common/sound.h @@ -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); diff --git a/src/common/sound_alsa.c b/src/common/sound_alsa.c index 219971f..15fe1a9 100644 --- a/src/common/sound_alsa.c +++ b/src/common/sound_alsa.c @@ -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); diff --git a/src/nmt/dsp.c b/src/nmt/dsp.c index f0069e8..49f7fb4 100644 --- a/src/nmt/dsp.c +++ b/src/nmt/dsp.c @@ -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); diff --git a/src/nmt/main.c b/src/nmt/main.c index c34e1e6..085330a 100644 --- a/src/nmt/main.c +++ b/src/nmt/main.c @@ -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 */ diff --git a/src/nmt/nmt.c b/src/nmt/nmt.c index 46c9775..db764ec 100644 --- a/src/nmt/nmt.c +++ b/src/nmt/nmt.c @@ -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); } } diff --git a/src/nmt/nmt.h b/src/nmt/nmt.h index 6cb8c73..f09d33d 100644 --- a/src/nmt/nmt.h +++ b/src/nmt/nmt.h @@ -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); |