aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2016-06-17 07:28:45 +0200
committerAndreas Eversberg <jolly@eversberg.eu>2016-06-17 17:03:28 +0200
commit7d5d3da8d35ee5e34eb9b3b4fbd821b9f4b28fb5 (patch)
tree4ec63334aec05cf73d24546d153c0a385d8fbee8 /src
parent4e0e13cb2d98479b62da5b8ca449e3a9d1286e3f (diff)
Add function to display wave form from input/loop
Use 'w' to toggle display. Move terminal input processing and main loop to main_common.c
Diffstat (limited to 'src')
-rw-r--r--src/common/Makefile.am1
-rw-r--r--src/common/call.c64
-rw-r--r--src/common/call.h2
-rw-r--r--src/common/display_wave.c99
-rw-r--r--src/common/display_wave.h12
-rw-r--r--src/common/main.h3
-rw-r--r--src/common/main_common.c86
-rw-r--r--src/common/sender.c51
-rw-r--r--src/common/sender.h6
9 files changed, 223 insertions, 101 deletions
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 7c11451..f15a9ad 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -21,5 +21,6 @@ libcommon_a_SOURCES = \
../common/emphasis.c \
../common/compander.c \
../common/sender.c \
+ ../common/display_wave.c \
../common/main_common.c
diff --git a/src/common/call.c b/src/common/call.c
index 4735404..d49ff1f 100644
--- a/src/common/call.c
+++ b/src/common/call.c
@@ -24,7 +24,6 @@
#include <stdlib.h>
#include <errno.h>
#include <sys/time.h>
-#include <termios.h>
#include "../common/debug.h"
#include "../common/sender.h"
#include "cause.h"
@@ -331,25 +330,13 @@ static void get_process_patterns(process_t *process, int16_t *samples, int lengt
process->audio_pos = pos;
}
-static struct termios term_orig;
-
int call_init(const char *station_id, const char *sounddev, int samplerate, int latency, int dial_digits, int loopback)
{
- struct termios term;
int rc = 0;
if (use_mncc_sock)
return 0;
- if (!loopback) {
- tcgetattr(0, &term_orig);
- term = term_orig;
- term.c_lflag &= ~(ISIG|ICANON|ECHO);
- term.c_cc[VMIN]=1;
- term.c_cc[VTIME]=2;
- tcsetattr(0, TCSANOW, &term);
- }
-
memset(&call, 0, sizeof(call));
strncpy(call.station_id, station_id, sizeof(call.station_id) - 1);
call.latspl = latency * samplerate / 1000;
@@ -391,8 +378,6 @@ void call_cleanup(void)
{
if (use_mncc_sock)
return;
- if (!call.loopback)
- tcsetattr(0, TCSANOW, &term_orig);
/* close sound devoice */
if (call.sound)
@@ -405,33 +390,8 @@ void call_cleanup(void)
}
}
-static int get_char()
-{
- struct timeval tv = {0, 0};
- fd_set fds;
- char c = 0;
- int __attribute__((__unused__)) rc;
-
- FD_ZERO(&fds);
- FD_SET(0, &fds);
- select(0+1, &fds, NULL, NULL, &tv);
- if (FD_ISSET(0, &fds)) {
- rc = read(0, &c, 1);
- return c;
- } else
- return -1;
-}
-
-static int process_ui(void)
+static void process_ui(int c)
{
- int c;
-
- c = get_char();
-
- /* break */
- if (c == 3)
- return 1;
-
switch (call.state) {
case CALL_IDLE:
if (c > 0) {
@@ -493,26 +453,22 @@ dial_after_hangup:
break;
}
fflush(stdout);
-
- return 0;
}
/* get keys from keyboad to control call via console
* returns 1 on exit (ctrl+c) */
-int process_call(void)
+void process_call(int c)
{
if (use_mncc_sock) {
mncc_handle();
- return 0;
+ return;
}
- if (!call.loopback) {
- if (process_ui())
- return 1;
- }
+ if (!call.loopback)
+ process_ui(c);
if (!call.sound)
- return 0;
+ return;
/* handle audio, if sound device is used */
int16_t samples[call.latspl];
@@ -524,7 +480,7 @@ int process_call(void)
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to get samples in buffer (rc = %d)!\n", count);
if (count == -EPIPE)
PDEBUG(DSENDER, DEBUG_ERROR, "Trying to recover.\n");
- return 0;
+ return;
}
if (count < call.latspl) {
int16_t up[count + 10];
@@ -552,7 +508,7 @@ int process_call(void)
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to write TX data to sound device (rc = %d)\n", rc);
if (rc == -EPIPE)
PDEBUG(DSENDER, DEBUG_ERROR, "Trying to recover.\n");
- return 0;
+ return;
}
}
count = sound_read(call.sound, samples, samples, call.latspl);
@@ -560,7 +516,7 @@ int process_call(void)
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to read from sound device (rc = %d)!\n", count);
if (count == -EPIPE)
PDEBUG(DSENDER, DEBUG_ERROR, "Trying to recover.\n");
- return 0;
+ return;
}
if (count) {
int16_t down[count]; /* more than enough */
@@ -570,8 +526,6 @@ int process_call(void)
count = samplerate_downsample(&call.srstate, samples, count, down);
call_rx_audio(call.callref, down, count);
}
-
- return 0;
}
/* Setup is received from transceiver. */
diff --git a/src/common/call.h b/src/common/call.h
index 4df116d..aa38c97 100644
--- a/src/common/call.h
+++ b/src/common/call.h
@@ -1,7 +1,7 @@
int call_init(const char *station_id, const char *sounddev, int samplerate, int latency, int dial_digits, int loopback);
void call_cleanup(void);
-int process_call(void);
+void process_call(int c);
/* received messages */
int call_in_setup(int callref, const char *callerid, const char *dialing);
diff --git a/src/common/display_wave.c b/src/common/display_wave.c
new file mode 100644
index 0000000..a10debe
--- /dev/null
+++ b/src/common/display_wave.c
@@ -0,0 +1,99 @@
+/* display wave form functions
+ *
+ * (C) 2016 by Andreas Eversberg <jolly@eversberg.eu>
+ * All Rights Reserved
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include "sender.h"
+
+#define DISPLAY_INTERVAL 0.04
+
+#define WIDTH 80
+#define HEIGHT 10
+
+static char screen[HEIGHT][WIDTH+1];
+static int wave_on = 0;
+
+void display_wave_init(sender_t *sender, int samplerate)
+{
+ dispwav_t *disp = &sender->dispwav;
+
+ memset(disp, 0, sizeof(*disp));
+ disp->interval_max = (double)samplerate * DISPLAY_INTERVAL + 0.5;
+}
+
+void display_wave_on(int on)
+{
+ int j;
+
+ if (on < 0)
+ wave_on = 1 - wave_on;
+ else
+ wave_on = on;
+
+ memset(&screen, ' ', sizeof(screen));
+ printf("\0337\033[H");
+ for (j = 0; j < HEIGHT; j++) {
+ screen[j][WIDTH] = '\0';
+ puts(screen[j]);
+ }
+ printf("\0338"); fflush(stdout);
+}
+
+void display_wave(sender_t *sender, int16_t *samples, int length)
+{
+ dispwav_t *disp = &sender->dispwav;
+ int pos, max;
+ int16_t *buffer;
+ int i, j, y;
+
+ if (!wave_on)
+ return;
+
+ pos = disp->interval_pos;
+ max = disp->interval_max;
+ buffer = disp->buffer;
+
+ for (i = 0; i < length; i++) {
+ if (pos >= WIDTH) {
+ if (++pos == max)
+ pos = 0;
+ continue;
+ }
+ buffer[pos++] = samples[i];
+ if (pos == WIDTH) {
+ memset(&screen, ' ', sizeof(screen));
+ for (j = 0; j < WIDTH; j++) {
+ /* must divide by 65536, because we may never reach HEIGHT*2! */
+ y = (32767 - (int)buffer[j]) * HEIGHT * 2 / 65536;
+ screen[y >> 1][j] = (y & 1) ? '_' : '-';
+ }
+ printf("\0337\033[H");
+ for (j = 0; j < HEIGHT; j++) {
+ screen[j][WIDTH] = '\0';
+ puts(screen[j]);
+ }
+ printf("\0338"); fflush(stdout);
+ }
+ }
+
+ disp->interval_pos = pos;
+}
+
+
diff --git a/src/common/display_wave.h b/src/common/display_wave.h
new file mode 100644
index 0000000..7ff72c0
--- /dev/null
+++ b/src/common/display_wave.h
@@ -0,0 +1,12 @@
+typedef struct sender sender_t;
+
+typedef struct display_wave {
+ int interval_pos;
+ int interval_max;
+ int16_t buffer[256];
+} dispwav_t;
+
+void display_wave_init(sender_t *sender, int samplerate);
+void display_wave_on(int on);
+void display_wave(sender_t *sender, int16_t *samples, int length);
+
diff --git a/src/common/main.h b/src/common/main.h
index 0df6539..cc50013 100644
--- a/src/common/main.h
+++ b/src/common/main.h
@@ -35,3 +35,6 @@ 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);
+
diff --git a/src/common/main_common.c b/src/common/main_common.c
index 4f4d2ea..9820c1a 100644
--- a/src/common/main_common.c
+++ b/src/common/main_common.c
@@ -23,10 +23,14 @@
#include <stdlib.h>
#include <string.h>
#include <signal.h>
+#include <unistd.h>
#include <math.h>
+#include <termios.h>
#include "main.h"
#include "debug.h"
-#include "../common/sender.h"
+#include "sender.h"
+#include "timer.h"
+#include "call.h"
/* common settings */
int num_kanal = 0;
@@ -241,3 +245,83 @@ void sighandler(int sigset)
quit = 1;
}
+static int get_char()
+{
+ struct timeval tv = {0, 0};
+ fd_set fds;
+ char c = 0;
+ int __attribute__((__unused__)) rc;
+
+ FD_ZERO(&fds);
+ FD_SET(0, &fds);
+ select(0+1, &fds, NULL, NULL, &tv);
+ if (FD_ISSET(0, &fds)) {
+ rc = read(0, &c, 1);
+ return c;
+ } else
+ return -1;
+}
+
+/* Loop through all transceiver instances of one network. */
+void main_loop(int *quit, int latency)
+{
+ int latspl;
+ sender_t *sender;
+ double last_time = 0, now;
+ struct termios term, term_orig;
+ int c;
+
+ /* prepare terminal */
+ tcgetattr(0, &term_orig);
+ term = term_orig;
+ term.c_lflag &= ~(ISIG|ICANON|ECHO);
+ term.c_cc[VMIN]=1;
+ term.c_cc[VTIME]=2;
+ tcsetattr(0, TCSANOW, &term);
+
+ while(!(*quit)) {
+ /* process sound of all transceivers */
+ for (sender = sender_head; sender; sender = sender->next) {
+ /* do not process audio for an audio slave, since it is done by audio master */
+ if (sender->master) /* if master is set, we are an audio slave */
+ continue;
+ latspl = sender->samplerate * latency / 1000;
+ process_sender_audio(sender, quit, latspl);
+ }
+
+ /* process timers */
+ process_timer();
+
+ /* process audio for mncc call instances */
+ now = get_time();
+ if (now - last_time >= 0.1)
+ last_time = now;
+ if (now - last_time >= 0.020) {
+ last_time += 0.020;
+ /* call clock every 20ms */
+ call_mncc_clock();
+ }
+
+ c = get_char();
+ switch (c) {
+ case 3:
+ /* quit */
+ *quit = 1;
+ break;
+ case 'w':
+ /* toggle display */
+ display_wave_on(-1);
+ break;
+ default:
+ /* process audio of built-in call control */
+ process_call(c);
+ }
+
+ /* sleep a while */
+ usleep(1000);
+ }
+
+ /* reset terminal */
+ tcsetattr(0, TCSANOW, &term_orig);
+}
+
diff --git a/src/common/sender.c b/src/common/sender.c
index f25df9e..16c7ac4 100644
--- a/src/common/sender.c
+++ b/src/common/sender.c
@@ -23,13 +23,10 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
-#include <unistd.h>
#include <errno.h>
#include <string.h>
#include "debug.h"
#include "sender.h"
-#include "timer.h"
-#include "call.h"
sender_t *sender_head = NULL;
static sender_t **sender_tailp = &sender_head;
@@ -138,6 +135,9 @@ int sender_create(sender_t *sender, int kanal, const char *sounddev, int sampler
*sender_tailp = sender;
sender_tailp = &sender->next;
+ if (sender == sender_head)
+ display_wave_init(sender, samplerate);
+
return 0;
error:
sender_destroy(sender);
@@ -209,7 +209,7 @@ static void gain_samples(int16_t *samples, int length, double gain)
}
/* Handle audio streaming of one transceiver. */
-static void process_sender_audio(sender_t *sender, int *quit, int latspl)
+void process_sender_audio(sender_t *sender, int *quit, int latspl)
{
sender_t *slave = sender->slave;
int16_t samples[latspl], pilot[latspl], slave_samples[latspl];
@@ -245,6 +245,8 @@ cant_recover:
#ifndef WAVE_WRITE_TX
if (sender->wave_rec.fp)
wave_write(&sender->wave_rec, samples, count);
+ if (sender == sender_head)
+ display_wave(sender, samples, count);
sender_receive(sender, samples, count);
#endif
}
@@ -362,6 +364,8 @@ cant_recover:
if (sender->wave_rec.fp)
wave_write(&sender->wave_rec, samples, count);
#endif
+ if (sender == sender_head)
+ display_wave(sender, samples, count);
sender_receive(sender, samples, count);
}
if (sender->loopback == 3)
@@ -387,42 +391,3 @@ cant_recover:
}
}
-/* Loop through all transceiver instances of one network. */
-void main_loop(int *quit, int latency)
-{
- int latspl;
- sender_t *sender;
- double last_time = 0, now;
-
- while(!(*quit)) {
- /* process sound of all transceivers */
- for (sender = sender_head; sender; sender = sender->next) {
- /* do not process audio for an audio slave, since it is done by audio master */
- if (sender->master) /* if master is set, we are an audio slave */
- continue;
- latspl = sender->samplerate * latency / 1000;
- process_sender_audio(sender, quit, latspl);
- }
-
- /* process timers */
- process_timer();
-
- /* process audio for mncc call instances */
- now = get_time();
- if (now - last_time >= 0.1)
- last_time = now;
- if (now - last_time >= 0.020) {
- last_time += 0.020;
- /* call clock every 20ms */
- call_mncc_clock();
- }
-
- /* process audio of built-in call control */
- if (process_call())
- break;
-
- /* sleep a while */
- usleep(1000);
- }
-}
-
diff --git a/src/common/sender.h b/src/common/sender.h
index e1a8176..8a26537 100644
--- a/src/common/sender.h
+++ b/src/common/sender.h
@@ -4,6 +4,7 @@
#include "jitter.h"
#include "loss.h"
#include "emphasis.h"
+#include "display_wave.h"
#define MAX_SENDER 16
@@ -53,6 +54,9 @@ typedef struct sender {
int pilot_on; /* 1 or 0 for on or off */
double pilotton_phaseshift; /* phase to shift every sample */
double pilotton_phase; /* current phase */
+
+ /* display wave */
+ dispwav_t dispwav; /* display wave form */
} sender_t;
/* list of all senders */
@@ -61,7 +65,7 @@ extern int cant_recover;
int sender_create(sender_t *sender, int kanal, const char *sounddev, int samplerate, int cross_channels, double rx_gain, int pre_emphasis, int de_emphasis, const char *write_wave, const char *read_wave, int loopback, double loss_volume, int use_pilot_signal);
void sender_destroy(sender_t *sender);
+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);
-void main_loop(int *quit, int latency);