diff --git a/src/lib/libdebug/Makefile.am b/src/lib/libdebug/Makefile.am deleted file mode 100644 index 210a097..0000000 --- a/src/lib/libdebug/Makefile.am +++ /dev/null @@ -1,7 +0,0 @@ -AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) - -noinst_LIBRARIES = libdebug.a - -libdebug_a_SOURCES = \ - debug.c - diff --git a/src/lib/libdebug/debug.c b/src/lib/libdebug/debug.c deleted file mode 100644 index 1045f89..0000000 --- a/src/lib/libdebug/debug.c +++ /dev/null @@ -1,327 +0,0 @@ -/* Simple debug functions for level and category filtering - * - * (C) 2016 by Andreas Eversberg - * 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 . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "debug.h" - -const char *debug_level[] = { - "debug ", - "info ", - "notice ", - "error ", - NULL, -}; - -struct debug_cat { - const char *name; - const char *color; -} debug_cat[] = { - { "options", "\033[0;33m" }, - { "sender", "\033[1;33m" }, - { "sound", "\033[0;35m" }, - { "dsp", "\033[0;31m" }, - { "anetz", "\033[1;34m" }, - { "bnetz", "\033[1;34m" }, - { "cnetz", "\033[1;34m" }, - { "nmt", "\033[1;34m" }, - { "amps", "\033[1;34m" }, - { "r2000", "\033[1;34m" }, - { "imts", "\033[1;34m" }, - { "mpt1327", "\033[1;34m" }, - { "jollycom", "\033[1;34m" }, - { "eurosignal", "\033[1;34m" }, - { "pocsag", "\033[1;34m" }, - { "5-ton-folge", "\033[1;34m" }, - { "frame", "\033[0;36m" }, - { "call", "\033[0;37m" }, - { "cc", "\033[1;32m" }, - { "database", "\033[0;33m" }, - { "transaction", "\033[0;32m" }, - { "dms", "\033[0;33m" }, - { "sms", "\033[1;37m" }, - { "sdr", "\033[1;31m" }, - { "uhd", "\033[1;35m" }, - { "soapy", "\033[1;35m" }, - { "wave", "\033[1;33m" }, - { "radio", "\033[1;34m" }, - { "am791x", "\033[0;31m" }, - { "uart", "\033[0;32m" }, - { "device", "\033[0;33m" }, - { "datenklo", "\033[1;34m" }, - { "zeit", "\033[1;34m" }, - { "sim layer 1", "\033[0;31m" }, - { "sim layer 2", "\033[0;33m" }, - { "sim ICL layer", "\033[0;36m" }, - { "sim layer 7", "\033[0;37m" }, - { "mtp layer 2", "\033[1;33m" }, - { "mtp layer 3", "\033[1;36m" }, - { "MuP", "\033[1;37m" }, - { "router", "\033[1;35m" }, - { "stderr", "\033[1;37m" }, - { "ss5", "\033[1;34m" }, - { "isdn", "\033[1;35m" }, - { "misdn", "\033[0;34m" }, - { "dss1", "\033[1;34m" }, - { "sip", "\033[1;35m" }, - { "telephone", "\033[1;34m" }, - { "UK0", "\033[0;31m" }, - { "ph", "\033[0;33m" }, - { NULL, NULL } -}; - -int debuglevel = DEBUG_INFO; -int debug_date = 0; -uint64_t debug_mask = ~0; -extern int num_kanal; - -void (*clear_console_text)(void) = NULL; -void (*print_console_text)(void) = NULL; - -int debug_limit_scroll = 0; - -static int lock_initialized = 0; -static pthread_mutex_t debug_mutex; - -void lock_debug(void) -{ - int rc; - - if (!lock_initialized) { - rc = pthread_mutex_init(&debug_mutex, NULL); - if (rc == 0) - lock_initialized = 1; - } - if (lock_initialized) - pthread_mutex_lock(&debug_mutex); -} - -void unlock_debug(void) -{ - if (lock_initialized) - pthread_mutex_unlock(&debug_mutex); -} - -void get_win_size(int *w, int *h) -{ - struct winsize win; - int rc; - - rc = ioctl(0, TIOCGWINSZ, &win); - if (rc) { - *w = 80; - *h = 25; - return; - } - - *h = win.ws_row; - *w = win.ws_col; -} - -void _printdebug(const char *file, const char __attribute__((unused)) *function, int line, int cat, int level, const char *kanal, const char *fmt, ...) -{ - char buffer[4096], *b = buffer; - int s = sizeof(buffer) - 1; - const char *p; - va_list args; - int w, h; - - if (debuglevel > level) - return; - - if (!(debug_mask & ((uint64_t)1 << cat))) - return; - - lock_debug(); - - buffer[sizeof(buffer) - 1] = '\0'; - - /* if kanal is used, prefix the channel number */ - if (num_kanal > 1 && kanal) { - sprintf(buffer, "(chan %s) ", kanal); - b = strchr(buffer, '\0'); - s -= strlen(buffer); - } - - va_start(args, fmt); - vsnprintf(b, s, fmt, args); - va_end(args); - - while ((p = strchr(file, '/'))) - file = p + 1; - if (clear_console_text) - clear_console_text(); - if (debug_limit_scroll) { - get_win_size(&w, &h); - printf("\0337\033[%d;%dr\0338", debug_limit_scroll + 1, h); - } - if (debug_date) { - struct timeval tv; - struct tm *tm; - - gettimeofday(&tv, NULL); - tm = localtime(&tv.tv_sec); - - printf("%04d-%02d-%02d %02d:%02d:%02d.%03d ", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(tv.tv_usec / 10000.0)); - } - printf("%s%s:%4d %s: %s\033[0;39m", debug_cat[cat].color, file, line, debug_level[level], buffer); - if (debug_limit_scroll) - printf("\0337\033[%d;%dr\0338", 1, h); - if (print_console_text) - print_console_text(); - fflush(stdout); - - unlock_debug(); -} - -const char *debug_amplitude(double level) -{ - static char text[42]; - - strcpy(text, " : "); - if (level > 1.0) - level = 1.0; - if (level < -1.0) - level = -1.0; - text[20 + (int)(level * 20)] = '*'; - - return text; -} - -#define level2db(level) (20 * log10(level)) - -const char *debug_db(double level_db) -{ - static char text[128]; - int l; - - strcpy(text, ": . : . : . : . : . : . : . : . | . : . : . : . : . : . : . : . :"); - if (level_db <= 0.0) - return text; - l = (int)round(level2db(level_db)); - if (l > 48) - return text; - if (l < -48) - return text; - text[l + 48] = '*'; - - return text; -} - -void debug_print_help(void) -{ - printf(" -v --verbose | ,[,[,...]] | list\n"); - printf(" Use 'list' to get a list of all levels and categories\n"); - printf(" Verbose level: digit of debug level (default = '%d')\n", debuglevel); - printf(" Verbose level+category: level digit followed by one or more categories\n"); - printf(" -> If no category is specified, all categories are selected\n"); - printf(" -v --verbose date\n"); - printf(" Show date with debug output\n"); -} - -void debug_list_cat(void) -{ - int i; - - printf("Give number of debug level:\n"); - for (i = 0; debug_level[i]; i++) - printf(" %d = %s\n", i, debug_level[i]); - printf("\n"); - - printf("Give name(s) of debug category:\n"); - for (i = 0; debug_cat[i].name; i++) - printf(" %s%s\033[0;39m\n", debug_cat[i].color, debug_cat[i].name); - printf("\n"); -} - -int parse_debug_opt(const char *optarg) -{ - int i, max_level = 0; - char *dup, *dstring, *p; - - if (!strcasecmp(optarg, "date")) { - debug_date = 1; - return 0; - } - - for (i = 0; debug_level[i]; i++) - max_level = i; - - dup = dstring = strdup(optarg); - p = strsep(&dstring, ","); - for (i = 0; i < p[i]; i++) { - if (p[i] < '0' || p[i] > '9') { - fprintf(stderr, "Only digits are allowed for debug level!\n"); - free(dup); - return -EINVAL; - } - } - debuglevel = atoi(p); - if (debuglevel > max_level) { - fprintf(stderr, "Debug level too high, use 'list' to show available levels!\n"); - free(dup); - return -EINVAL; - } - if (dstring) - debug_mask = 0; - while((p = strsep(&dstring, ","))) { - for (i = 0; debug_cat[i].name; i++) { - if (!strcasecmp(p, debug_cat[i].name)) - break; - } - if (!debug_cat[i].name) { - fprintf(stderr, "Given debug category '%s' unknown, use 'list' to show available categories!\n", p); - free(dup); - return -EINVAL; - } - debug_mask |= ((uint64_t)1 << i); - } - - free(dup); - return 0; -} - -const char *debug_hex(const uint8_t *data, int len) -{ - static char *text = NULL; - char *p; - int i; - - if (text) - free(text); - p = text = calloc(1, len * 3 + 1); - for (i = 0; i < len; i++) { - sprintf(p, "%02x ", *data++); - p += 3; - } - if (text[0]) - p[-1] = '\0'; - - return text; -} - diff --git a/src/lib/libdebug/debug.h b/src/lib/libdebug/debug.h deleted file mode 100644 index 6ef3ec0..0000000 --- a/src/lib/libdebug/debug.h +++ /dev/null @@ -1,82 +0,0 @@ - -#define DEBUG_DEBUG 0 /* debug info, not for normal use */ -#define DEBUG_INFO 1 /* all info about process */ -#define DEBUG_NOTICE 2 /* something unexpected happens */ -#define DEBUG_ERROR 3 /* there is an error with this software */ - -#define DOPTIONS 0 -#define DSENDER 1 -#define DSOUND 2 -#define DDSP 3 -#define DANETZ 4 -#define DBNETZ 5 -#define DCNETZ 6 -#define DNMT 7 -#define DAMPS 8 -#define DR2000 9 -#define DIMTS 10 -#define DMPT1327 11 -#define DJOLLY 12 -#define DEURO 13 -#define DPOCSAG 14 -#define DFUENF 15 -#define DFRAME 16 -#define DCALL 17 -#define DCC 18 -#define DDB 19 -#define DTRANS 20 -#define DDMS 21 -#define DSMS 22 -#define DSDR 23 -#define DUHD 24 -#define DSOAPY 25 -#define DWAVE 26 -#define DRADIO 27 -#define DAM791X 28 -#define DUART 29 -#define DDEVICE 30 -#define DDATENKLO 31 -#define DZEIT 32 -#define DSIM1 33 -#define DSIM2 34 -#define DSIMI 35 -#define DSIM7 36 -#define DMTP2 37 -#define DMTP3 38 -#define DMUP 39 -#define DROUTER 40 -#define DSTDERR 41 -#define DSS5 42 -#define DISDN 43 -#define DMISDN 44 -#define DDSS1 45 -#define DSIP 46 -#define DTEL 47 -#define DUK0 48 -#define DPH 49 - -void lock_debug(void); -void unlock_debug(void); - -void get_win_size(int *w, int *h); - -#define PDEBUG(cat, level, fmt, arg...) _printdebug(__FILE__, __FUNCTION__, __LINE__, cat, level, NULL, fmt, ## arg) -#define PDEBUG_CHAN(cat, level, fmt, arg...) _printdebug(__FILE__, __FUNCTION__, __LINE__, cat, level, CHAN, fmt, ## arg) -void _printdebug(const char *file, const char *function, int line, int cat, int level, const char *chan_str, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 7, 8))); - -const char *debug_amplitude(double level); -const char *debug_db(double level_db); - -void debug_print_help(void); -void debug_list_cat(void); -int parse_debug_opt(const char *opt); - -extern int debuglevel; - -extern void (*clear_console_text)(void); -extern void (*print_console_text)(void); - -extern int debug_limit_scroll; - -const char *debug_hex(const uint8_t *data, int len); - diff --git a/src/lib/libdisplay/Makefile.am b/src/lib/libdisplay/Makefile.am deleted file mode 100644 index 8f6097d..0000000 --- a/src/lib/libdisplay/Makefile.am +++ /dev/null @@ -1,19 +0,0 @@ -AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) - -noinst_LIBRARIES = libdisplay.a - -libdisplay_a_SOURCES = \ - display_status.c \ - display_wave.c \ - display_measurements.c - -if HAVE_SDR -libdisplay_a_SOURCES += \ - display_iq.c \ - display_spectrum.c -endif - -if HAVE_SDR -AM_CPPFLAGS += -DHAVE_SDR -endif - diff --git a/src/lib/libdisplay/display.h b/src/lib/libdisplay/display.h deleted file mode 100644 index 064e327..0000000 --- a/src/lib/libdisplay/display.h +++ /dev/null @@ -1,103 +0,0 @@ -#define DISPLAY_MEAS_INTERVAL 0.1 /* time (in seconds) for each measurement values interval */ -#define DISPLAY_INTERVAL 0.04 /* time (in seconds) for each other interval */ -#define DISPLAY_PARAM_HISTORIES 10 /* number of intervals (should result in one seconds) */ - -#define MAX_DISPLAY_WIDTH 1024 - -typedef struct display_wave { - const char *kanal; - int interval_pos; - int interval_max; - int offset; - sample_t buffer[MAX_DISPLAY_WIDTH]; -} dispwav_t; - -enum display_measurements_type { - DISPLAY_MEAS_LAST, /* display last value */ - DISPLAY_MEAS_PEAK, /* display peak value */ - DISPLAY_MEAS_PEAK2PEAK, /* display peak value of min..max range */ - DISPLAY_MEAS_AVG, /* display average value */ -}; - -enum display_measurements_bar { - DISPLAY_MEAS_LEFT, /* bar graph from left */ - DISPLAY_MEAS_CENTER, /* bar graph from center */ -}; - -typedef struct display_measurements_param { - struct display_measurements_param *next; - char name[32]; /* parameter name (e.g. 'Deviation') */ - char format[32]; /* unit name (e.g. "%.2f KHz") */ - enum display_measurements_type type; - enum display_measurements_bar bar; - double min; /* minimum value */ - double max; /* maximum value */ - double mark; /* mark (target) value */ - double value; /* current value (peak, sum...) */ - double value2; /* max value for min..max range */ - double last; /* last valid value (used for DISPLAY_MEAS_LAST) */ - int value_count; /* count number of values of one interval */ - double value_history[DISPLAY_PARAM_HISTORIES]; /* history of values of last second */ - double value2_history[DISPLAY_PARAM_HISTORIES]; /* stores max for min..max range */ - int value_history_pos; /* next history value to write */ -} dispmeasparam_t; - -typedef struct display_measurements { - struct display_measurements *next; - const char *kanal; - dispmeasparam_t *param; -} dispmeas_t; - -#define MAX_DISPLAY_IQ 1024 - -typedef struct display_iq { - int interval_pos; - int interval_max; - float buffer[MAX_DISPLAY_IQ * 2]; -} dispiq_t; - -#define MAX_DISPLAY_SPECTRUM 1024 - -typedef struct display_spectrum_mark { - struct display_spectrum_mark *next; - const char *kanal; - double frequency; -} dispspectrum_mark_t; - -typedef struct display_spectrum { - int interval_pos; - int interval_max; - double buffer_I[MAX_DISPLAY_SPECTRUM]; - double buffer_Q[MAX_DISPLAY_SPECTRUM]; - dispspectrum_mark_t *mark; -} dispspectrum_t; - -#define MAX_HEIGHT_STATUS 32 - -void display_wave_init(dispwav_t *disp, int samplerate, const char *kanal); -void display_wave_on(int on); -void display_wave(dispwav_t *disp, sample_t *samples, int length, double range); - -void display_status_on(int on); -void display_status_start(void); -void display_status_channel(const char *kanal, const char *type, const char *state); -void display_status_subscriber(const char *number, const char *state); -void display_status_end(void); - -void display_measurements_init(dispmeas_t *disp, int samplerate, const char *kanal); -void display_measurements_exit(dispmeas_t *disp); -void display_measurements_on(int on); -dispmeasparam_t *display_measurements_add(dispmeas_t *disp, char *name, char *format, enum display_measurements_type type, enum display_measurements_bar bar, double min, double max, double mark); -void display_measurements_update(dispmeasparam_t *param, double value, double value2); -void display_measurements(double elapsed); - -void display_iq_init(int samplerate); -void display_iq_on(int on); -void display_iq(float *samples, int length); - -void display_spectrum_init(int samplerate, double center_frequency); -void display_spectrum_add_mark(const char *kanal, double frequency); -void display_spectrum_exit(void); -void display_spectrum_on(int on); -void display_spectrum(float *samples, int length); - diff --git a/src/lib/libdisplay/display_iq.c b/src/lib/libdisplay/display_iq.c deleted file mode 100644 index 83cec6e..0000000 --- a/src/lib/libdisplay/display_iq.c +++ /dev/null @@ -1,282 +0,0 @@ -/* display IQ data form functions - * - * (C) 2016 by Andreas Eversberg - * 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 . - */ - -#include -#include -#include -#include -#include -#include -#include "../libsample/sample.h" -#include "../libdebug/debug.h" -#include "../libdisplay/display.h" - -/* must be odd value! */ -#define SIZE 23 - -static char screen[SIZE][MAX_DISPLAY_WIDTH]; -static uint8_t screen_color[SIZE][MAX_DISPLAY_WIDTH]; -static uint8_t screen_history[SIZE * 2][MAX_DISPLAY_WIDTH]; -static int iq_on = 0; -static double db = 80; - -static dispiq_t disp; - -void display_iq_init(int samplerate) -{ - memset(&disp, 0, sizeof(disp)); - memset(&screen_history, 0, sizeof(screen_history)); - disp.interval_max = (double)samplerate * DISPLAY_INTERVAL + 0.5; - /* should not happen due to low interval */ - if (disp.interval_max < MAX_DISPLAY_IQ - 1) - disp.interval_max = MAX_DISPLAY_IQ - 1; -} - -void display_iq_on(int on) -{ - int j; - int w, h; - - get_win_size(&w, &h); - if (w > MAX_DISPLAY_WIDTH - 1) - w = MAX_DISPLAY_WIDTH - 1; - - if (iq_on) { - memset(&screen, ' ', sizeof(screen)); - memset(&screen_history, 0, sizeof(screen_history)); - lock_debug(); - printf("\0337\033[H"); - for (j = 0; j < SIZE; j++) { - screen[j][w] = '\0'; - puts(screen[j]); - } - printf("\0338"); fflush(stdout); - unlock_debug(); - } - - if (on < 0) { - if (++iq_on == 3) - iq_on = 0; - } else - iq_on = on; - - if (iq_on) - debug_limit_scroll = SIZE; - else - debug_limit_scroll = 0; -} - -/* - * plot IQ data: - * - * theoretical example: SIZE = 3 allows 6 steps plotted as dots - * - * Line 0: : - * Line 1: : - * Line 2: : - * - * The level of -1.0 .. 1.0 is scaled to -3 and 3. - * - * The lowest of the upper 3 dots ranges from 0.0 .. <1.5. - * The upper most dot ranges from 2.5 .. <3.5. - * The highest of the lower 3 dots ranges from <0.0 .. >-1.5; - * The lower most dot ranges from -2.5 .. >-3.5. - * - * The center column ranges from -0.5 .. <0.5. - * The columns about the center from -1.5 .. <1.5. - */ -void display_iq(float *samples, int length) -{ - int pos, max; - float *buffer; - int i, j, k; - int color = 9; /* default color */ - int x_center, y_center; - double I, Q, L, l, s; - int x, y; - int v, r; - int width, h; - - if (!iq_on) - return; - - lock_debug(); - - get_win_size(&width, &h); - if (width > MAX_DISPLAY_WIDTH - 1) - width = MAX_DISPLAY_WIDTH - 1; - - /* at what line we draw our zero-line and what character we use */ - x_center = width >> 1; - y_center = (SIZE - 1) >> 1; - - pos = disp.interval_pos; - max = disp.interval_max; - buffer = disp.buffer; - - for (i = 0; i < length; i++) { - if (pos >= MAX_DISPLAY_IQ) { - if (++pos == max) - pos = 0; - continue; - } - buffer[pos * 2] = samples[i * 2]; - buffer[pos * 2 + 1] = samples[i * 2 + 1]; - pos++; - if (pos == MAX_DISPLAY_IQ) { - memset(&screen, ' ', sizeof(screen)); - memset(&screen_color, 7, sizeof(screen_color)); - /* render screen history to screen */ - for (y = 0; y < SIZE * 2; y++) { - for (x = 0; x < width; x++) { - v = screen_history[y][x]; - v -= 8; - if (v < 0) - v = 0; - screen_history[y][x] = v; - r = random() & 0x3f; - if (r >= v) - continue; - if (screen[y/2][x] == ':') - continue; - if (screen[y/2][x] == '.') { - if ((y & 1) == 0) - screen[y/2][x] = ':'; - continue; - } - if (screen[y/2][x] == '\'') { - if ((y & 1)) - screen[y/2][x] = ':'; - continue; - } - if ((y & 1) == 0) - screen[y/2][x] = '\''; - else - screen[y/2][x] = '.'; - screen_color[y/2][x] = 4; - } - } - /* plot current IQ date */ - for (j = 0; j < MAX_DISPLAY_IQ; j++) { - I = buffer[j * 2]; - Q = buffer[j * 2 + 1]; - L = I*I + Q*Q; - if (iq_on > 1) { - /* logarithmic scale */ - l = sqrt(L); - s = log10(l) * 20 + db; - if (s < 0) - s = 0; - I = (I / l) * (s / db); - Q = (Q / l) * (s / db); - } - x = x_center + (int)(I * (double)SIZE + (double)width + 0.5) - width; - if (x < 0) - continue; - if (x > width - 1) - continue; - if (Q >= 0) - y = SIZE - 1 - (int)(Q * (double)SIZE - 0.5); - else - y = SIZE - (int)(Q * (double)SIZE + 0.5); - if (y < 0) - continue; - if (y > SIZE * 2 - 1) - continue; - if (screen[y/2][x] == ':' && screen_color[y/2][x] >= 10) - goto cont; - if (screen[y/2][x] == '.' && screen_color[y/2][x] >= 10) { - if ((y & 1) == 0) - screen[y/2][x] = ':'; - goto cont; - } - if (screen[y/2][x] == '\'' && screen_color[y/2][x] >= 10) { - if ((y & 1)) - screen[y/2][x] = ':'; - goto cont; - } - if ((y & 1) == 0) - screen[y/2][x] = '\''; - else - screen[y/2][x] = '.'; -cont: - screen_history[y][x] = 255; - /* overdrive: - * red = close to -1..1 or above - * yellow = close to -0.5..0.5 or above - * Note: L is square of vector length, - * so we compare with square values. - */ - if (L > 0.9 * 0.9) - screen_color[y/2][x] = 11; - else if (L > 0.45 * 0.45 && screen_color[y/2][x] != 11) - screen_color[y/2][x] = 13; - else if (screen_color[y/2][x] < 10) - screen_color[y/2][x] = 12; - } - if (iq_on == 1) - sprintf(screen[0], "(IQ linear"); - else - sprintf(screen[0], "(IQ log %.0f dB", db); - *strchr(screen[0], '\0') = ')'; - printf("\0337\033[H"); - for (j = 0; j < SIZE; j++) { - for (k = 0; k < width; k++) { - if ((j == y_center || k == x_center) && screen[j][k] == ' ') { - /* cross */ - if (color != 4) { - color = 4; - printf("\033[0;34m"); - } - if (j == y_center) { - if (k == x_center) - putchar('o'); - else if (k == x_center - SIZE) - putchar('+'); - else if (k == x_center + SIZE) - putchar('+'); - else - putchar('-'); - } else { - if (j == 0 || j == SIZE - 1) - putchar('+'); - else - putchar('|'); - } - } else { - if (screen_color[j][k] != color) { - color = screen_color[j][k]; - printf("\033[%d;3%dm", color / 10, color % 10); - } - putchar(screen[j][k]); - } - } - printf("\n"); - } - /* reset color and position */ - printf("\033[0;39m\0338"); fflush(stdout); - } - } - - disp.interval_pos = pos; - - unlock_debug(); -} - - diff --git a/src/lib/libdisplay/display_measurements.c b/src/lib/libdisplay/display_measurements.c deleted file mode 100644 index e2c2f0f..0000000 --- a/src/lib/libdisplay/display_measurements.c +++ /dev/null @@ -1,360 +0,0 @@ -/* display measurements functions - * - * (C) 2017 by Andreas Eversberg - * 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 . - */ - -#include -#include -#include -#include -#include -#include -#include -#include "../libsample/sample.h" -#include "../libdebug/debug.h" -#include "../libdisplay/display.h" - -#define MAX_NAME_LEN 16 -#define MAX_UNIT_LEN 16 - -static int has_init = 0; -static int measurements_on = 0; -double time_elapsed = 0.0; -static int lines_total = 0; -static char line[MAX_DISPLAY_WIDTH]; -static char line_color[MAX_DISPLAY_WIDTH]; - -dispmeas_t *meas_head = NULL; - -void display_measurements_init(dispmeas_t *disp, int __attribute__((unused)) samplerate, const char *kanal) -{ - dispmeas_t **disp_p; - - memset(disp, 0, sizeof(*disp)); - disp->kanal = kanal; - has_init = 1; - lines_total = 0; - time_elapsed = 0.0; - - disp_p = &meas_head; - while (*disp_p) - disp_p = &((*disp_p)->next); - *disp_p = disp; -} - -void display_measurements_exit(dispmeas_t *disp) -{ - dispmeasparam_t *param = disp->param, *temp; - - while (param) { - temp = param; - param = param->next; - free(temp); - } - disp->param = NULL; - has_init = 0; -} - -static int color; - -static void display_line(int on, int w) -{ - int j; - - if (on) { - for (j = 0; j < w; j++) { - if (line_color[j] != color && line[j] != ' ') { - color = line_color[j]; - printf("\033[%d;3%dm", color / 10, color % 10); - } - putchar(line[j]); - } - } else { - for (j = 0; j < w; j++) - putchar(' '); - } - putchar('\n'); - lines_total++; -} - -static void print_measurements(int on) -{ - dispmeas_t *disp; - dispmeasparam_t *param; - int i, j; - int width, h; - char text[128]; - double value = 0.0, value2 = 0.0, hold, hold2; - int bar_width, bar_left, bar_right, bar_hold, bar_mark; - - get_win_size(&width, &h); - if (width > MAX_DISPLAY_WIDTH - 1) - width = MAX_DISPLAY_WIDTH - 1; - - /* no display, if bar graph is less than one character */ - bar_width = width - MAX_NAME_LEN - MAX_UNIT_LEN; - if (bar_width < 1) - return; - - lock_debug(); - - lines_total = 0; - color = -1; - printf("\0337\033[H"); - for (disp = meas_head; disp; disp = disp->next) { - memset(line, ' ', width); - memset(line_color, 7, width); - sprintf(line, "(chan %s", disp->kanal); - *strchr(line, '\0') = ')'; - display_line(on, width); - for (param = disp->param; param; param = param->next) { - memset(line, ' ', width); - memset(line_color, 7, width); - memset(line_color, 3, MAX_NAME_LEN); /* yellow */ - switch (param->type) { - case DISPLAY_MEAS_LAST: - value = param->value; - param->value = -NAN; - break; - case DISPLAY_MEAS_PEAK: - /* peak value */ - value = param->value; - param->value = -NAN; - param->value_count = 0; - break; - case DISPLAY_MEAS_PEAK2PEAK: - /* peak to peak value */ - value = param->value; - value2 = param->value2; - param->value = -NAN; - param->value2 = -NAN; - param->value_count = 0; - break; - case DISPLAY_MEAS_AVG: - /* average value */ - if (param->value_count) - value = param->value / (double)param->value_count; - else - value = -NAN; - param->value = 0.0; - param->value_count = 0; - break; - } - /* add current value to history */ - param->value_history[param->value_history_pos] = value; - param->value2_history[param->value_history_pos] = value2; - param->value_history_pos = param->value_history_pos % DISPLAY_PARAM_HISTORIES; - /* calculate hold values */ - hold = -NAN; - hold2 = -NAN; - switch (param->type) { - case DISPLAY_MEAS_LAST: - /* if we have valid value, we update 'last' */ - if (!isnan(value)) { - param->last = value; - hold = value; - } else - hold = param->last; - break; - case DISPLAY_MEAS_PEAK: - for (i = 0; i < DISPLAY_PARAM_HISTORIES; i++) { - if (isnan(param->value_history[i])) - continue; - if (isnan(hold) || param->value_history[i] > hold) - hold = param->value_history[i]; - } - break; - case DISPLAY_MEAS_PEAK2PEAK: - for (i = 0; i < DISPLAY_PARAM_HISTORIES; i++) { - if (isnan(param->value_history[i])) - continue; - if (isnan(hold) || param->value_history[i] < hold) - hold = param->value_history[i]; - if (isnan(hold2) || param->value2_history[i] > hold2) - hold2 = param->value2_history[i]; - } - if (!isnan(hold)) - hold = hold2 - hold; - if (!isnan(value)) - value = value2 - value; - break; - case DISPLAY_MEAS_AVG: - for (i = 0, j = 0; i < DISPLAY_PARAM_HISTORIES; i++) { - if (isnan(param->value_history[i])) - continue; - if (j == 0) - hold = 0.0; - hold += param->value_history[i]; - j++; - } - if (j) - hold /= j; - break; - } - /* "Deviation ::::::::::............ 4.5 KHz" */ - memcpy(line, param->name, (strlen(param->name) < MAX_NAME_LEN) ? strlen(param->name) : MAX_NAME_LEN); - if (isinf(value) || isnan(value)) { - bar_left = -1; - bar_right = -1; - } else if (param->bar == DISPLAY_MEAS_CENTER) { - if (value >= 0.0) { - bar_left = (-param->min) / (param->max - param->min) * ((double)bar_width - 1.0); - bar_right = (value - param->min) / (param->max - param->min) * ((double)bar_width - 1.0); - } else { - bar_left = (value - param->min) / (param->max - param->min) * ((double)bar_width - 1.0); - bar_right = (-param->min) / (param->max - param->min) * ((double)bar_width - 1.0); - } - } else { - bar_left = -1; - bar_right = (value - param->min) / (param->max - param->min) * ((double)bar_width - 1.0); - } - if (isinf(hold) || isnan(hold)) - bar_hold = -1; - else - bar_hold = (hold - param->min) / (param->max - param->min) * ((double)bar_width - 1.0); - if (isinf(param->mark)) - bar_mark = -1; - else - bar_mark = (param->mark - param->min) / (param->max - param->min) * ((double)bar_width - 1.0); - for (i = 0; i < bar_width; i++) { - line[i + MAX_NAME_LEN] = ':'; - if (i == bar_hold) - line_color[i + MAX_NAME_LEN] = 13; - else if (i == bar_mark) - line_color[i + MAX_NAME_LEN] = 14; - else if (i >= bar_left && i <= bar_right) - line_color[i + MAX_NAME_LEN] = 2; - else - line_color[i + MAX_NAME_LEN] = 4; - } - sprintf(text, param->format, hold); - if (isnan(hold)) - memset(line_color + width - MAX_UNIT_LEN, 4, MAX_UNIT_LEN); /* blue */ - else - memset(line_color + width - MAX_UNIT_LEN, 3, MAX_UNIT_LEN); /* yellow */ - strncpy(line + width - MAX_UNIT_LEN + 1, text, (strlen(text) < MAX_UNIT_LEN) ? strlen(text) : MAX_UNIT_LEN); - display_line(on, width); - } - } - /* reset color and position */ - printf("\033[0;39m\0338"); fflush(stdout); - - debug_limit_scroll = lines_total; - - unlock_debug(); -} - -void display_measurements_on(int on) -{ - if (measurements_on) - print_measurements(0); - - if (on < 0) - measurements_on = 1 - measurements_on; - else - measurements_on = on; - - debug_limit_scroll = 0; -} - -/* add new parameter on startup to the list of measurements */ -dispmeasparam_t *display_measurements_add(dispmeas_t *disp, char *name, char *format, enum display_measurements_type type, enum display_measurements_bar bar, double min, double max, double mark) -{ - dispmeasparam_t *param, **param_p = &disp->param; - int i; - - if (!has_init) { - fprintf(stderr, "Not initialized prior adding measurement, please fix!\n"); - abort(); - } - - while (*param_p) - param_p = &((*param_p)->next); - *param_p = calloc(sizeof(dispmeasparam_t), 1); - if (!*param_p) - return NULL; - param = *param_p; - strncpy(param->name, name, sizeof(param->name) - 1); - strncpy(param->format, format, sizeof(param->format) - 1); - param->type = type; - param->bar = bar; - param->min = min; - param->max = max; - param->mark = mark; - param->value = -NAN; - param->value2 = -NAN; - param->last = -NAN; - for (i = 0; i < DISPLAY_PARAM_HISTORIES; i++) - param->value_history[i] = -NAN; - param->value_count = 0; - - return param; -} - -void display_measurements_update(dispmeasparam_t *param, double value, double value2) -{ - /* special case where we do not have an instance of the parameter */ - if (!param) - return; - - if (!has_init) { - fprintf(stderr, "Not initialized prior updating measurement value, please fix!\n"); - abort(); - } - - switch (param->type) { - case DISPLAY_MEAS_LAST: - param->value = value; - break; - case DISPLAY_MEAS_PEAK: - if (isnan(param->value) || value > param->value) - param->value = value; - break; - case DISPLAY_MEAS_PEAK2PEAK: - if (param->value_count == 0 || value < param->value) - param->value = value; - if (param->value_count == 0 || value2 > param->value2) - param->value2 = value2; - param->value_count++; - break; - case DISPLAY_MEAS_AVG: - param->value += value; - param->value_count++; - break; - default: - fprintf(stderr, "Parameter '%s' has unknown type %d, please fix!\n", param->name, param->type); - abort(); - } -} - -void display_measurements(double elapsed) -{ - if (!measurements_on) - return; - - if (!has_init) - return; - - /* count and check if we need to display this time */ - time_elapsed += elapsed; - if (time_elapsed < DISPLAY_MEAS_INTERVAL) - return; - time_elapsed = fmod(time_elapsed, DISPLAY_MEAS_INTERVAL); - - print_measurements(1); -} - diff --git a/src/lib/libdisplay/display_spectrum.c b/src/lib/libdisplay/display_spectrum.c deleted file mode 100644 index b0f30f4..0000000 --- a/src/lib/libdisplay/display_spectrum.c +++ /dev/null @@ -1,414 +0,0 @@ -/* display spectrum of IQ data - * - * (C) 2016 by Andreas Eversberg - * 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 . - */ - -#include -#include -#include -#include -#include -#include "../libsample/sample.h" -#include "../libfft/fft.h" -#include "../libdebug/debug.h" -#include "../libdisplay/display.h" - -#define HEIGHT 20 - -static int has_init = 0; -static double buffer_delay[MAX_DISPLAY_SPECTRUM]; -static double buffer_hold[MAX_DISPLAY_SPECTRUM]; -static char screen[HEIGHT][MAX_DISPLAY_WIDTH]; -static uint8_t screen_color[HEIGHT][MAX_DISPLAY_WIDTH]; -static int spectrum_on = 0; -static double db = 120; -static double center_frequency, frequency_range; - -static dispspectrum_t disp; - -void display_spectrum_init(int samplerate, double _center_frequency) -{ - memset(&disp, 0, sizeof(disp)); - disp.interval_max = (double)samplerate * DISPLAY_INTERVAL + 0.5; - /* should not happen due to low interval */ - if (disp.interval_max < MAX_DISPLAY_SPECTRUM - 1) - disp.interval_max = MAX_DISPLAY_SPECTRUM - 1; - memset(buffer_delay, 0, sizeof(buffer_delay)); - - center_frequency = _center_frequency; - frequency_range = (double)samplerate; - - has_init = 1; -} - -void display_spectrum_add_mark(const char *kanal, double frequency) -{ - dispspectrum_mark_t *mark, **mark_p; - - if (!has_init) - return; - - mark = calloc(1, sizeof(*mark)); - if (!mark) { - fprintf(stderr, "no mem!"); - abort(); - } - mark->kanal = kanal; - mark->frequency = frequency; - - mark_p = &disp.mark; - while (*mark_p) - mark_p = &((*mark_p)->next); - *mark_p = mark; -} - -void display_spectrum_exit(void) -{ - dispspectrum_mark_t *mark = disp.mark, *temp; - - while (mark) { - temp = mark; - mark = mark->next; - free(temp); - } - disp.mark = NULL; - has_init = 0; -} - -void display_spectrum_on(int on) -{ - int j; - int w, h; - - get_win_size(&w, &h); - if (w > MAX_DISPLAY_WIDTH - 1) - w = MAX_DISPLAY_WIDTH - 1; - - if (spectrum_on) { - memset(&screen, ' ', sizeof(screen)); - memset(&buffer_hold, 0, sizeof(buffer_hold)); - lock_debug(); - printf("\0337\033[H"); - for (j = 0; j < HEIGHT; j++) { - screen[j][w] = '\0'; - puts(screen[j]); - } - printf("\0338"); fflush(stdout); - unlock_debug(); - } - - if (on < 0) { - if (++spectrum_on == 3) - spectrum_on = 0; - } else - spectrum_on = on; - - if (spectrum_on) - debug_limit_scroll = HEIGHT; - else - debug_limit_scroll = 0; -} - -/* - * plot spectrum data: - * - */ -void display_spectrum(float *samples, int length) -{ - dispspectrum_mark_t *mark; - char print_channel[32], print_frequency[32]; - int width, h; - int pos, max; - double *buffer_I, *buffer_Q; - int color = 9; /* default color */ - int i, j, k, o; - double I, Q, v; - int s, e, l, n; - - if (!spectrum_on) - return; - - lock_debug(); - - get_win_size(&width, &h); - if (width > MAX_DISPLAY_WIDTH - 1) - width = MAX_DISPLAY_WIDTH - 1; - - /* calculate size of FFT */ - int m, fft_size = 0, fft_taps = 0; - for (m = 0; m < 16; m++) { - if ((1 << m) > MAX_DISPLAY_SPECTRUM) - break; - if ((1 << m) <= width) { - fft_taps = m; - fft_size = 1 << m; - } - } - if (m == 16) { - fprintf(stderr, "Size of spectrum is not a power of 2, please fix!\n"); - abort(); - } - - int hold[fft_size], delay[fft_size], current[fft_size]; - - pos = disp.interval_pos; - max = disp.interval_max; - buffer_I = disp.buffer_I; - buffer_Q = disp.buffer_Q; - - for (i = 0; i < length; i++) { - if (pos >= fft_size) { - if (++pos == max) - pos = 0; - continue; - } - buffer_I[pos] = samples[i * 2]; - buffer_Q[pos] = samples[i * 2 + 1]; - pos++; - if (pos == fft_size) { - fft_process(1, fft_taps, buffer_I, buffer_Q); - k = 0; - for (j = 0; j < fft_size; j++) { - /* scale result vertically */ - I = buffer_I[(j + fft_size / 2) % fft_size]; - Q = buffer_Q[(j + fft_size / 2) % fft_size]; - v = sqrt(I*I + Q*Q); - v = log10(v) * 20 + db; - if (v < 0) - v = 0; - v /= db; - /* delayed */ - buffer_delay[j] -= DISPLAY_INTERVAL / 10.0; - if (v > buffer_delay[j]) - buffer_delay[j] = v; - delay[j] = (double)(HEIGHT * 2 - 1) * (1.0 - buffer_delay[j]); - if (delay[j] < 0) - delay[j] = 0; - if (delay[j] >= (HEIGHT * 2)) - delay[j] = (HEIGHT * 2) - 1; - /* hold */ - if (spectrum_on == 2) { - if (v > buffer_hold[j]) - buffer_hold[j] = v; - hold[j] = (double)(HEIGHT * 2 - 1) * (1.0 - buffer_hold[j]); - if (hold[j] < 0) - hold[j] = 0; - if (hold[j] >= (HEIGHT * 2)) - hold[j] = (HEIGHT * 2) - 1; - } - /* current */ - current[j] = (double)(HEIGHT * 2 - 1) * (1.0 - v); - if (current[j] < 0) - current[j] = 0; - if (current[j] >= (HEIGHT * 2)) - current[j] = (HEIGHT * 2) - 1; - } - /* plot scaled buffer */ - memset(&screen, ' ', sizeof(screen)); - memset(&screen_color, 7, sizeof(screen_color)); /* all white */ - sprintf(screen[0], "(spectrum log %.0f dB%s", db, (spectrum_on == 2) ? " HOLD" : ""); - *strchr(screen[0], '\0') = ')'; - for (j = 2; j < HEIGHT; j += 2) { - memset(screen_color[j], 4, 7); /* blue */ - sprintf(screen[j], "%4.0f dB", -(double)(j+1) * db / (double)(HEIGHT - 1)); - screen[j][7] = ' '; - } - o = (width - fft_size) / 2; /* offset from left border */ - for (j = 0; j < fft_size; j++) { - /* show current spectrum in yellow */ - s = l = n = current[j]; - /* get last and next value */ - if (j > 0) - l = (current[j - 1] + s) / 2; - if (j < fft_size - 1) - n = (current[j + 1] + s) / 2; - if (s > l && s > n) { - /* current value is a minimum */ - e = s; - s = (l < n) ? (l + 1) : (n + 1); - } else if (s < l && s < n) { - /* current value is a maximum */ - e = (l > n) ? l : n; - } else if (l < n) { - /* last value is higher, next value is lower */ - s = l + 1; - e = n; - } else if (l > n) { - /* last value is lower, next value is higher */ - s = n + 1; - e = l; - } else { - /* current, last and next values are equal */ - e = s; - } - if (s == e) { - if ((s & 1) == 0) - screen[s >> 1][j + o] = '\''; - else - screen[s >> 1][j + o] = '.'; - screen_color[s >> 1][j + o] = 13; - } else { - if ((s & 1) == 0) - screen[s >> 1][j + o] = '|'; - else - screen[s >> 1][j + o] = '.'; - screen_color[s >> 1][j + o] = 13; - if ((e & 1) == 0) - screen[e >> 1][j + o] = '\''; - else - screen[e >> 1][j + o] = '|'; - screen_color[e >> 1][j + o] = 13; - for (k = (s >> 1) + 1; k < (e >> 1); k++) { - screen[k][j + o] = '|'; - screen_color[k][j + o] = 13; - } - } - /* show delayed spectrum in blue */ - e = s; - s = delay[j]; - if ((s >> 1) < (e >> 1)) { - if ((s & 1) == 0) - screen[s >> 1][j + o] = '|'; - else - screen[s >> 1][j + o] = '.'; - screen_color[s >> 1][j + o] = 4; - for (k = (s >> 1) + 1; k < (e >> 1); k++) { - screen[k][j + o] = '|'; - screen_color[k][j + o] = 4; - } - } - if (spectrum_on == 2) { - /* show hold spectrum in white */ - s = l = n = hold[j]; - /* get last and next value */ - if (j > 0) - l = (hold[j - 1] + s) / 2; - if (j < fft_size - 1) - n = (hold[j + 1] + s) / 2; - if (s > l && s > n) { - /* hold value is a minimum */ - e = s; - s = (l < n) ? (l + 1) : (n + 1); - } else if (s < l && s < n) { - /* hold value is a maximum */ - e = (l > n) ? l : n; - } else if (l < n) { - /* last value is higher, next value is lower */ - s = l + 1; - e = n; - } else if (l > n) { - /* last value is lower, next value is higher */ - s = n + 1; - e = l; - } else { - /* hold, last and next values are equal */ - e = s; - } - if (s == e) { - if ((s & 1) == 0) - screen[s >> 1][j + o] = '\''; - else - screen[s >> 1][j + o] = '.'; - screen_color[s >> 1][j + o] = 17; - } else { - if ((s & 1) == 0) - screen[s >> 1][j + o] = '|'; - else - screen[s >> 1][j + o] = '.'; - screen_color[s >> 1][j + o] = 17; - if ((e & 1) == 0) - screen[e >> 1][j + o] = '\''; - else - screen[e >> 1][j + o] = '|'; - screen_color[e >> 1][j + o] = 17; - for (k = (s >> 1) + 1; k < (e >> 1); k++) { - screen[k][j + o] = '|'; - screen_color[k][j + o] = 17; - } - } - } - } - /* add channel positions in spectrum */ - for (mark = disp.mark; mark; mark = mark->next) { - j = (int)((mark->frequency - center_frequency) / frequency_range * (double) fft_size + width / 2 + 0.5); - if (j < 0 || j >= width) /* check out-of-range, should not happen */ - continue; - for (k = 0; k < HEIGHT; k++) { - /* skip yellow/white graph */ - if (screen_color[k][j] == 13 || screen_color[k][j] == 17) - continue; - screen[k][j] = ':'; - screen_color[k][j] = 12; - } - sprintf(print_channel, "Ch%s", mark->kanal); - for (o = 0; o < (int)strlen(print_channel); o++) { - s = j - strlen(print_channel) + o; - if (s >= 0 && s < width) { - screen[HEIGHT - 1][s] = print_channel[o]; - screen_color[HEIGHT - 1][s] = 7; - } - } - if (fmod(mark->frequency, 1000.0)) - sprintf(print_frequency, "%.4f", mark->frequency / 1e6); - else - sprintf(print_frequency, "%.3f", mark->frequency / 1e6); - for (o = 0; o < (int)strlen(print_frequency); o++) { - s = j + o + 1; - if (s >= 0 && s < width) { - screen[HEIGHT - 1][s] = print_frequency[o]; - screen_color[HEIGHT - 1][s] = 7; - } - } - } - /* add center (DC line) to spectrum */ - j = width / 2 + 0.5; - if (j < 1 || j >= width-1) /* check out-of-range, should not happen */ - continue; - for (k = 0; k < HEIGHT; k++) { - /* skip green/yellow/white graph */ - if (screen_color[k][j] == 13 || screen_color[k][j] == 17 || screen_color[k][j] == 12) - continue; - screen[k][j] = '.'; - screen_color[k][j] = 7; - } - screen[0][j-1] = 'D'; - screen[0][j+1] = 'C'; - screen_color[0][j-1] = 7; - screen_color[0][j+1] = 7; - /* display buffer */ - printf("\0337\033[H"); - for (j = 0; j < HEIGHT; j++) { - for (k = 0; k < width; k++) { - if (screen_color[j][k] != color) { - color = screen_color[j][k]; - printf("\033[%d;3%dm", color / 10, color % 10); - } - putchar(screen[j][k]); - } - printf("\n"); - } - /* reset color and position */ - printf("\033[0;39m\0338"); fflush(stdout); - } - } - - disp.interval_pos = pos; - - unlock_debug(); -} - - diff --git a/src/lib/libdisplay/display_status.c b/src/lib/libdisplay/display_status.c deleted file mode 100644 index de38c9e..0000000 --- a/src/lib/libdisplay/display_status.c +++ /dev/null @@ -1,145 +0,0 @@ -/* display status functions - * - * (C) 2017 by Andreas Eversberg - * 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 . - */ - -#include -#include -#include -#include -#include -#include "../libsample/sample.h" -#include "../libdebug/debug.h" -#include "../libdisplay/display.h" - -static int status_on = 0; -static int line_count = 0; -static int lines_total = 0; -static char screen[MAX_HEIGHT_STATUS][MAX_DISPLAY_WIDTH]; - -static void print_status(int on) -{ - int i, j; - int w, h; - - get_win_size(&w, &h); - if (w > MAX_DISPLAY_WIDTH - 1) - w = MAX_DISPLAY_WIDTH - 1; - - if (w > MAX_DISPLAY_WIDTH) - w = MAX_DISPLAY_WIDTH; - h--; - if (h > lines_total) - h = lines_total; - - lock_debug(); - printf("\0337\033[H\033[1;37m"); - for (i = 0; i < h; i++) { - j = 0; - if (on) { - for (j = 0; j < w; j++) - putchar(screen[i][j]); - } else { - for (j = 0; j < w; j++) - putchar(' '); - } - putchar('\n'); - } - printf("\0338"); fflush(stdout); - unlock_debug(); -} - -void display_status_on(int on) -{ - if (status_on) - print_status(0); - - if (on < 0) - status_on = 1 - status_on; - else - status_on = on; - - if (status_on) - print_status(1); - - if (status_on) - debug_limit_scroll = lines_total; - else - debug_limit_scroll = 0; -} - -/* start status display */ -void display_status_start(void) -{ - memset(screen, ' ', sizeof(screen)); - memset(screen[0], '-', sizeof(screen[0])); - memcpy(screen[0] + 4, "Channel Status", 14); - line_count = 1; -} - -void display_status_channel(const char *kanal, const char *type, const char *state) -{ - char line[MAX_DISPLAY_WIDTH]; - - /* add empty line after previous channel+subscriber */ - if (line_count > 1 && line_count < MAX_HEIGHT_STATUS) - line_count++; - - if (line_count == MAX_HEIGHT_STATUS) - return; - - if (type) - snprintf(line, sizeof(line), "Channel: %s Type: %s State: %s", kanal, type, state); - else - snprintf(line, sizeof(line), "Channel: %s State: %s", kanal, state); - line[sizeof(line) - 1] = '\0'; - memcpy(screen[line_count++], line, strlen(line)); -} - -void display_status_subscriber(const char *number, const char *state) -{ - char line[MAX_DISPLAY_WIDTH]; - - if (line_count == MAX_HEIGHT_STATUS) - return; - - if (state) - snprintf(line, sizeof(line), " Subscriber: %s State: %s", number, state); - else - snprintf(line, sizeof(line), " Subscriber: %s", number); - line[sizeof(line) - 1] = '\0'; - memcpy(screen[line_count++], line, strlen(line)); -} - -void display_status_end(void) -{ - if (line_count < MAX_HEIGHT_STATUS) { - memset(screen[line_count], '-', sizeof(screen[line_count])); - line_count++; - } - /* if last total lines exceed current line count, keep it, so removed lines are overwritten with spaces */ - if (line_count > lines_total) - lines_total = line_count; - if (status_on) - print_status(1); - /* set new total lines */ - lines_total = line_count; - if (status_on) - debug_limit_scroll = lines_total; -} - - diff --git a/src/lib/libdisplay/display_wave.c b/src/lib/libdisplay/display_wave.c deleted file mode 100644 index 713873f..0000000 --- a/src/lib/libdisplay/display_wave.c +++ /dev/null @@ -1,252 +0,0 @@ -/* display wave form functions - * - * (C) 2016 by Andreas Eversberg - * 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 . - */ - -#include -#include -#include -#include -#include -#include -#include "../libsample/sample.h" -#include "../libdebug/debug.h" -#include "../libdisplay/display.h" - -#define HEIGHT 11 - -static int num_sender = 0; -static char screen[HEIGHT][MAX_DISPLAY_WIDTH]; -static int wave_on = 0; - -void display_wave_init(dispwav_t *disp, int samplerate, const char *kanal) -{ - memset(disp, 0, sizeof(*disp)); - disp->offset = (num_sender++) * HEIGHT; - disp->interval_max = (double)samplerate * DISPLAY_INTERVAL + 0.5; - disp->kanal = kanal; -} - -void display_wave_on(int on) -{ - int i, j; - int w, h; - - get_win_size(&w, &h); - if (w > MAX_DISPLAY_WIDTH - 1) - w = MAX_DISPLAY_WIDTH - 1; - - if (wave_on) { - memset(&screen, ' ', sizeof(screen)); - lock_debug(); - printf("\0337\033[H"); - for (i = 0; i < num_sender; i++) { - for (j = 0; j < HEIGHT; j++) { - screen[j][w] = '\0'; - puts(screen[j]); - } - } - printf("\0338"); fflush(stdout); - unlock_debug(); - } - - if (on < 0) - wave_on = 1 - wave_on; - else - wave_on = on; - - if (wave_on) - debug_limit_scroll = HEIGHT * num_sender; - else - debug_limit_scroll = 0; -} - -/* - * draw wave form: - * - * theoretical example: HEIGHT = 3 allows 5 steps - * - * Line 0: '. - * Line 1: '. - * Line 2: ' - * - * HEIGHT is odd, so the center line's char is ''' (otherwise '.') - * (HEIGHT - 1) / 2 = 1, so the center line is drawn in line 1 - * - * y is in range of 0..4, so these are 5 steps, where 2 is the - * center line. this is calculated by (HEIGHT * 2 - 1) - */ -void display_wave(dispwav_t *disp, sample_t *samples, int length, double range) -{ - int pos, max; - sample_t *buffer; - int i, j, k, s, e; - double last, current, next; - int color = 9; /* default color */ - int center_line; - char center_char; - int width, h; - - if (!wave_on) - return; - - lock_debug(); - - get_win_size(&width, &h); - if (width > MAX_DISPLAY_WIDTH - 1) - width = MAX_DISPLAY_WIDTH - 1; - - /* at what line we draw our zero-line and what character we use */ - center_line = (HEIGHT - 1) >> 1; - center_char = (HEIGHT & 1) ? '\'' : '.'; - - pos = disp->interval_pos; - max = disp->interval_max; - buffer = disp->buffer; - - for (i = 0; i < length; i++) { - if (pos >= width + 2) { - if (++pos == max) - pos = 0; - continue; - } - buffer[pos++] = samples[i]; - if (pos == width + 2) { - memset(&screen, ' ', sizeof(screen)); - for (j = 0; j < width; j++) { - /* Input value is scaled to range -1 .. 1 and then subtracted from 1, - * so the result ranges from 0 .. 2. - * HEIGHT-1 is multiplied with the range, so a HEIGHT of 3 would allow - * 0..4 (5 steps) and a HEIGHT of 11 would allow 0..20 (21 steps). - * We always use odd number of steps, so there will be a center between - * values. - */ - last = (1.0 - buffer[j] / range) * (double)(HEIGHT - 1); - current = (1.0 - buffer[j + 1] / range) * (double)(HEIGHT - 1); - next = (1.0 - buffer[j + 2] / range) * (double)(HEIGHT - 1); - /* calculate start and end for vertical line - * if the current value is a peak (above or below last AND next point), - * round this peak point to become one end of the vertical line. - * the other end is rounded up or down, so the end of the line will - * not overlap with the ends of the surrounding lines. - */ - if (last > current) { - if (next > current) { - /* current point is a peak up */ - s = round(current); - /* use lowest neighbor point and end is half way */ - if (last > next) - e = floor((last + current) / 2.0); - else - e = floor((next + current) / 2.0); - /* end point must not be above start point */ - if (e < s) - e = s; - } else { - /* current point is a transition upwards */ - s = ceil((next + current) / 2.0); - e = floor((last + current) / 2.0); - /* end point must not be above start point */ - if (e < s) - s = e = round(current); - } - } else { - if (next <= current) { - /* current point is a peak down */ - e = round(current); - /* use heighes neighbor point and start is half way */ - if (last <= next) - s = ceil((last + current) / 2.0); - else - s = ceil((next + current) / 2.0); - /* start point must not be below end point */ - if (s > e) - s = e; - } else { - /* current point is a transition downwards */ - s = ceil((last + current) / 2.0); - e = floor((next + current) / 2.0); - /* start point must not be below end point */ - if (s > e) - s = e = round(current); - } - } - /* only draw line, if it is in range */ - if (e >= 0 && s < HEIGHT * 2 - 1) { - /* clip */ - if (s < 0) - s = 0; - if (e >= HEIGHT * 2 - 1) - e = HEIGHT * 2 - 1; - /* plot start and end point */ - if ((s & 1)) - screen[s >> 1][j] = '.'; - else if (e != s) - screen[s >> 1][j] = '|'; - if (!(e & 1)) - screen[e >> 1][j] = '\''; - else if (e != s) - screen[e >> 1][j] = '|'; - /* plot line between start and end point */ - for (k = (s >> 1) + 1; k < (e >> 1); k++) - screen[k][j] = '|'; - } - } - sprintf(screen[0], "(chan %s", disp->kanal); - *strchr(screen[0], '\0') = ')'; - printf("\0337\033[H"); - for (j = 0; j < disp->offset; j++) - puts(""); - for (j = 0; j < HEIGHT; j++) { - for (k = 0; k < width; k++) { - if (j == center_line && screen[j][k] == ' ') { - /* blue 0-line */ - if (color != 4) { - color = 4; - printf("\033[0;34m"); - } - putchar(center_char); - } else if (screen[j][k] == '\'' || screen[j][k] == '.' || screen[j][k] == '|') { - /* green scope curve */ - if (color != 2) { - color = 2; - printf("\033[1;32m"); - } - putchar(screen[j][k]); - } else if (screen[j][k] != ' ') { - /* white other characters */ - if (color != 7) { - color = 7; - printf("\033[1;37m"); - } - putchar(screen[j][k]); - } else - putchar(screen[j][k]); - } - printf("\n"); - } - /* reset color and position */ - printf("\033[0;39m\0338"); fflush(stdout); - } - } - - disp->interval_pos = pos; - - unlock_debug(); -} - - diff --git a/src/lib/libfilter/Makefile.am b/src/lib/libfilter/Makefile.am deleted file mode 100644 index 45d2ec2..0000000 --- a/src/lib/libfilter/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) - -noinst_LIBRARIES = libfilter.a - -libfilter_a_SOURCES = \ - iir_filter.c \ - fir_filter.c - diff --git a/src/lib/libfilter/fir_filter.c b/src/lib/libfilter/fir_filter.c deleted file mode 100644 index c86ac5b..0000000 --- a/src/lib/libfilter/fir_filter.c +++ /dev/null @@ -1,197 +0,0 @@ -/* FIR filter - * - * (C) 2017 by Andreas Eversberg - * 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 . - */ - -#include -#include -#include -#include -#include -#include "../libsample/sample.h" -#include "fir_filter.h" - -//#define DEBUG_TAPS - -static void kernel(double *taps, int M, double cutoff, int invert) -{ - int i; - double sum; - - for (i = 0; i <= M; i++) { - /* gen sinc */ - if (i == M / 2) - taps[i] = 2.0 * M_PI * cutoff; - else - taps[i] = sin(2.0 * M_PI * cutoff * (double)(i - M / 2)) - / (double)(i - M / 2); - /* blackman window */ - taps[i] *= 0.42 - 0.50 * cos(2 * M_PI * (double)(i / M)) - + 0.08 * cos(4 * M_PI * (double)(i / M)); - } - - /* normalize */ - sum = 0; - for (i = 0; i <= M; i++) - sum += taps[i]; - for (i = 0; i <= M; i++) - taps[i] /= sum; - - /* invert */ - if (invert) { - for (i = 0; i <= M; i++) - taps[i] = -taps[i]; - taps[M / 2] += 1.0; - } - -#ifdef DEBUG_TAPS - puts("start"); - for (i = 0; i <= M; i++) - puts(debug_amplitude(taps[i])); -#endif -} - -static fir_filter_t *fir_init(double samplerate, double transition_bandwidth) -{ - fir_filter_t *fir; - int M; - - /* alloc struct */ - fir = calloc(1, sizeof(*fir)); - if (!fir) { - fprintf(stderr, "No memory creating FIR filter!\n"); - return NULL; - } - - /* transition bandwidth */ - M = ceil(1.0 / (transition_bandwidth / samplerate)); - if ((M & 1)) - M++; - -// printf("cutoff=%.4f\n", cutoff / samplerate); -// printf("tb=%.4f\n", transition_bandwidth / samplerate); - fir->ntaps = M + 1; - fir->delay = M / 2; - - /* alloc taps */ - fir->taps = calloc(fir->ntaps, sizeof(*fir->taps)); - if (!fir->taps) { - fprintf(stderr, "No memory creating FIR filter!\n"); - fir_exit(fir); - return NULL; - } - - /* alloc ring buffer */ - fir->buffer = calloc(fir->ntaps, sizeof(*fir->buffer)); - if (!fir->buffer) { - fprintf(stderr, "No memory creating FIR filter!\n"); - fir_exit(fir); - return NULL; - } - - - return fir; -} - -fir_filter_t *fir_lowpass_init(double samplerate, double cutoff, double transition_bandwidth) -{ - /* calculate kernel */ - fir_filter_t *fir = fir_init(samplerate, transition_bandwidth); - if (!fir) - return NULL; - kernel(fir->taps, fir->ntaps - 1, cutoff / samplerate, 0); - return fir; -} - -fir_filter_t *fir_highpass_init(double samplerate, double cutoff, double transition_bandwidth) -{ - fir_filter_t *fir = fir_init(samplerate, transition_bandwidth); - if (!fir) - return NULL; - kernel(fir->taps, fir->ntaps - 1, cutoff / samplerate, 1); - return fir; -} - -fir_filter_t *fir_allpass_init(double samplerate, double transition_bandwidth) -{ - fir_filter_t *fir = fir_init(samplerate, transition_bandwidth); - if (!fir) - return NULL; - fir->taps[(fir->ntaps - 1) / 2] = 1.0; - return fir; -} - -fir_filter_t *fir_twopass_init(double samplerate, double cutoff_low, double cutoff_high, double transition_bandwidth) -{ - int i; - double sum; - fir_filter_t *fir = fir_init(samplerate, transition_bandwidth); - if (!fir) - return NULL; - double lp_taps[fir->ntaps], hp_taps[fir->ntaps]; - kernel(lp_taps, fir->ntaps - 1, cutoff_low / samplerate, 0); - kernel(hp_taps, fir->ntaps - 1, cutoff_high / samplerate, 1); - sum = 0; - printf("#warning does not work as expected\n"); - abort(); - for (i = 0; i < fir->ntaps; i++) { - fir->taps[i] = lp_taps[i] + hp_taps[i]; - sum += fir->taps[i]; - } - /* hp will die */ -// for (i = 0; i < fir->ntaps; i++) - // fir->taps[i] /= sum; - return fir; -} - -void fir_exit(fir_filter_t *fir) -{ - if (!fir) - return; - free(fir->taps); - free(fir->buffer); - free(fir); -} - -void fir_process(fir_filter_t *fir, sample_t *samples, int num) -{ - int i, j; - double y; - - for (i = 0; i < num; i++) { - /* put sample in ring buffer */ - fir->buffer[fir->buffer_pos] = samples[i]; - if (++fir->buffer_pos == fir->ntaps) - fir->buffer_pos = 0; - - /* convolve samples */ - y = 0; - for (j = 0; j < fir->ntaps; j++) { - /* convolve sample from ring buffer, starting with oldest */ - y += fir->buffer[fir->buffer_pos] * fir->taps[j]; - if (++fir->buffer_pos == fir->ntaps) - fir->buffer_pos = 0; - } - samples[i] = y; - } -} - -int fir_get_delay(fir_filter_t *fir) -{ - return fir->delay; -} - diff --git a/src/lib/libfilter/fir_filter.h b/src/lib/libfilter/fir_filter.h deleted file mode 100644 index 7d94091..0000000 --- a/src/lib/libfilter/fir_filter.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _FIR_FILTER_H -#define _FIR_FILTER_H - -typedef struct fir_filter { - int ntaps; - int delay; - double *taps; - double *buffer; - int buffer_pos; -} fir_filter_t; - -fir_filter_t *fir_lowpass_init(double samplerate, double cutoff, double transition_bandwidth); -fir_filter_t *fir_highpass_init(double samplerate, double cutoff, double transition_bandwidth); -fir_filter_t *fir_allpass_init(double samplerate, double transition_bandwidth); -fir_filter_t *fir_twopass_init(double samplerate, double cutoff_low, double cutoff_high, double transition_bandwidth); -void fir_exit(fir_filter_t *fir); -void fir_process(fir_filter_t *fir, sample_t *samples, int num); -int fir_get_delay(fir_filter_t *fir); - -#endif /* _FIR_FILTER_H */ - diff --git a/src/lib/libfilter/iir_filter.c b/src/lib/libfilter/iir_filter.c deleted file mode 100644 index 5872d61..0000000 --- a/src/lib/libfilter/iir_filter.c +++ /dev/null @@ -1,204 +0,0 @@ -/* cut-off filter (biquad) based on Nigel Redmon (www.earlevel.com) - * - * (C) 2016 by Andreas Eversberg - * 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 . - */ - -#include -#include -#include -#include -#include -#include "../libsample/sample.h" -#include "iir_filter.h" - -//#define DEBUG_NAN - -#define PI M_PI - -void iir_lowpass_init(iir_filter_t *filter, double frequency, int samplerate, int iterations) -{ - double Fc, Q, K, norm; - - if (iterations > 64) { - fprintf(stderr, "%s failed: too many iterations, please fix!\n", __func__); - abort(); - } - - memset(filter, 0, sizeof(*filter)); - filter->iter = iterations; - Q = pow(sqrt(0.5), 1.0 / (double)iterations); /* 0.7071 @ 1 iteration */ - Fc = frequency / (double)samplerate; - K = tan(PI * Fc); - norm = 1 / (1 + K / Q + K * K); - filter->a0 = K * K * norm; - filter->a1 = 2 * filter->a0; - filter->a2 = filter->a0; - filter->b1 = 2 * (K * K - 1) * norm; - filter->b2 = (1 - K / Q + K * K) * norm; -#ifdef DEBUG_NAN - printf("%p\n", filter); -#endif -} - -void iir_highpass_init(iir_filter_t *filter, double frequency, int samplerate, int iterations) -{ - double Fc, Q, K, norm; - - memset(filter, 0, sizeof(*filter)); - filter->iter = iterations; - Q = pow(sqrt(0.5), 1.0 / (double)iterations); /* 0.7071 @ 1 iteration */ - Fc = frequency / (double)samplerate; - K = tan(PI * Fc); - norm = 1 / (1 + K / Q + K * K); - filter->a0 = 1 * norm; - filter->a1 = -2 * filter->a0; - filter->a2 = filter->a0; - filter->b1 = 2 * (K * K - 1) * norm; - filter->b2 = (1 - K / Q + K * K) * norm; -} - -void iir_bandpass_init(iir_filter_t *filter, double frequency, int samplerate, int iterations) -{ - double Fc, Q, K, norm; - - memset(filter, 0, sizeof(*filter)); - filter->iter = iterations; - Q = pow(sqrt(0.5), 1.0 / (double)iterations); /* 0.7071 @ 1 iteration */ - Fc = frequency / (double)samplerate; - K = tan(PI * Fc); - norm = 1 / (1 + K / Q + K * K); - filter->a0 = K / Q * norm; - filter->a1 = 0; - filter->a2 = -filter->a0; - filter->b1 = 2 * (K * K - 1) * norm; - filter->b2 = (1 - K / Q + K * K) * norm; -} - -void iir_notch_init(iir_filter_t *filter, double frequency, int samplerate, int iterations) -{ - double Fc, Q, K, norm; - - memset(filter, 0, sizeof(*filter)); - filter->iter = iterations; - Q = pow(sqrt(0.5), 1.0 / (double)iterations); /* 0.7071 @ 1 iteration */ - Fc = frequency / (double)samplerate; - K = tan(PI * Fc); - norm = 1 / (1 + K / Q + K * K); - filter->a0 = (1 + K * K) * norm; - filter->a1 = 2 * (K * K - 1) * norm; - filter->a2 = filter->a0; - filter->b1 = filter->a1; - filter->b2 = (1 - K / Q + K * K) * norm; -} - -void iir_process(iir_filter_t *filter, sample_t *samples, int length) -{ - double a0, a1, a2, b1, b2; - double *z1, *z2; - double in, out; - int iterations = filter->iter; - int i, j; - - /* get states */ - a0 = filter->a0; - a1 = filter->a1; - a2 = filter->a2; - b1 = filter->b1; - b2 = filter->b2; - - /* these are state pointers, so no need to write back */ - z1 = filter->z1; - z2 = filter->z2; - - /* process filter */ - for (i = 0; i < length; i++) { - /* add a small value, otherwise this loop will perform really bad on my 'nuedel' machine!!! */ - in = *samples + 0.000000001; - for (j = 0; j < iterations; j++) { - out = in * a0 + z1[j]; - z1[j] = in * a1 + z2[j] - b1 * out; - z2[j] = in * a2 - b2 * out; - in = out; - } - *samples++ = in; - } -} - -#ifdef DEBUG_NAN -#pragma GCC push_options -//#pragma GCC optimize ("O0") -#endif - -void iir_process_baseband(iir_filter_t *filter, float *baseband, int length) -{ - double a0, a1, a2, b1, b2; - double *z1, *z2; - double in, out; - int iterations = filter->iter; - int i, j; - - /* get states */ - a0 = filter->a0; - a1 = filter->a1; - a2 = filter->a2; - b1 = filter->b1; - b2 = filter->b2; - - /* these are state pointers, so no need to write back */ - z1 = filter->z1; - z2 = filter->z2; - - /* process filter */ - for (i = 0; i < length; i++) { - /* add a small value, otherwise this loop will perform really bad on my 'nuedel' machine!!! */ - in = *baseband + 0.000000001; - for (j = 0; j < iterations; j++) { - out = in * a0 + z1[j]; -#ifdef DEBUG_NAN - if (!(out > -100 && out < 100)) { - printf("%p\n", filter); - printf("1. i=%d j=%d z=%.5f in=%.5f a0=%.5f out=%.5f\n", i, j, z1[j], in, a0, out); - abort(); - } -#endif - z1[j] = in * a1 + z2[j] - b1 * out; -#ifdef DEBUG_NAN - if (!(z1[j] > -100 && z1[j] < 100)) { - printf("%p\n", filter); - printf("2. i=%d j=%d z1=%.5f z2=%.5f in=%.5f a1=%.5f out=%.5f b1=%.5f\n", i, j, z1[j], z2[j], in, a1, out, b1); - abort(); - } -#endif - z2[j] = in * a2 - b2 * out; -#ifdef DEBUG_NAN - if (!(z2[j] > -100 && z2[j] < 100)) { - printf("%p\n", filter); - printf("%.5f\n", (in * a2) - (b2 * out)); - printf("3. i=%d j=%d z2=%.5f in=%.5f a2=%.5f b2=%.5f out=%.5f\n", i, j, z2[j], in, a2, b2, out); - abort(); - } -#endif - in = out; - } - *baseband = in; - baseband += 2; - } -} - -#ifdef DEBUG_NAN -#pragma GCC pop_options -#endif diff --git a/src/lib/libfilter/iir_filter.h b/src/lib/libfilter/iir_filter.h deleted file mode 100644 index a5956c8..0000000 --- a/src/lib/libfilter/iir_filter.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _FILTER_H -#define _FILTER_H - -typedef struct iir_filter { - int iter; - double a0, a1, a2, b1, b2; - double z1[64], z2[64]; -} iir_filter_t; - -void iir_lowpass_init(iir_filter_t *filter, double frequency, int samplerate, int iterations); -void iir_highpass_init(iir_filter_t *filter, double frequency, int samplerate, int iterations); -void iir_bandpass_init(iir_filter_t *filter, double frequency, int samplerate, int iterations); -void iir_notch_init(iir_filter_t *filter, double frequency, int samplerate, int iterations); -void iir_process(iir_filter_t *filter, sample_t *samples, int length); -void iir_process_baseband(iir_filter_t *filter, float *baseband, int length); - -#endif /* _FILTER_H */ diff --git a/src/lib/liboptions/Makefile.am b/src/lib/liboptions/Makefile.am deleted file mode 100644 index 0d10fa7..0000000 --- a/src/lib/liboptions/Makefile.am +++ /dev/null @@ -1,7 +0,0 @@ -AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) - -noinst_LIBRARIES = liboptions.a - -liboptions_a_SOURCES = \ - options.c - diff --git a/src/lib/liboptions/options.c b/src/lib/liboptions/options.c deleted file mode 100644 index d49e698..0000000 --- a/src/lib/liboptions/options.c +++ /dev/null @@ -1,339 +0,0 @@ -/* command line options and config file parsing - * - * (C) 2018 by Andreas Eversberg - * 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 . - */ - -#include -#include -#include -#include -#include -#include "options.h" -#include "../libdebug/debug.h" - -typedef struct option { - struct option *next; - int short_option; - const char *long_option; - int parameter_count; -} option_t; - -static option_t *option_head = NULL; -static option_t **option_tailp = &option_head; -static int first_option = 1; - -static struct options_strdup_entry { - struct options_strdup_entry *next; - char s[1]; -} *options_strdup_list = NULL; - -char *options_strdup(const char *s) -{ - struct options_strdup_entry *o; - - o = malloc(sizeof(struct options_strdup_entry) + strlen(s)); - if (!o) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "No mem!\n"); - abort(); - } - o->next = options_strdup_list; - options_strdup_list = o; - strcpy(o->s, s); - - return o->s; -} - -void option_add(int short_option, const char *long_option, int parameter_count) -{ - option_t *option; - - /* check if option already exists or is not allowed */ - for (option = option_head; option; option = option->next) { - if (!strcmp(option->long_option, "config")) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Option '%s' is not allowed to add, please fix!\n", option->long_option); - abort(); - } - if (option->short_option == short_option - || !strcmp(option->long_option, long_option)) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Option '%s' added twice, please fix!\n", option->long_option); - abort(); - } - } - - option = calloc(1, sizeof(*option)); - if (!option) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "No mem!\n"); - abort(); - } - - option->short_option = short_option; - option->long_option = long_option; - option->parameter_count = parameter_count; - *option_tailp = option; - option_tailp = &(option->next); -} - -int options_config_file(int argc, char *argv[], const char *config_file, int (*handle_options)(int short_option, int argi, char *argv[])) -{ - static const char *home; - char config[256]; - FILE *fp; - char buffer[256], opt[256], param[256], *p, *args[16]; - char params[1024]; - int line; - int rc = 1; - int i, j, quote; - option_t *option; - - /* select for alternative config file */ - if (argc > 2 && !strcmp(argv[1], "--config")) - config_file = argv[2]; - - /* add home directory */ - if (config_file[0] == '~' && config_file[1] == '/') { - home = getenv("HOME"); - if (home == NULL) - return 1; - sprintf(config, "%s/%s", home, config_file + 2); - } else - strcpy(config, config_file); - - /* open config file */ - fp = fopen(config, "r"); - if (!fp) { - PDEBUG(DOPTIONS, DEBUG_INFO, "Config file '%s' seems not to exist, using command line options only.\n", config); - return 1; - } - - /* parse config file */ - line = 0; - while((fgets(buffer, sizeof(buffer), fp))) { - line++; - /* prevent buffer overflow */ - buffer[sizeof(buffer) - 1] = '\0'; - /* cut away new-line and white spaces */ - while (buffer[0] && buffer[strlen(buffer) - 1] <= ' ') - buffer[strlen(buffer) - 1] = '\0'; - p = buffer; - /* remove white spaces in front of first keyword */ - while (*p > '\0' && *p <= ' ') - p++; - /* ignore '#' lines */ - if (*p == '#') - continue; - /* get option form line */ - i = 0; - while (*p > ' ') - opt[i++] = *p++; - opt[i] = '\0'; - if (opt[0] == '\0') - continue; - /* skip white spaces behind option */ - while (*p > '\0' && *p <= ' ') - p++; - /* get param from line */ - params[0] = '\0'; - i = 0; - while (*p) { - /* copy parameter */ - j = 0; - quote = 0; - while (*p) { - /* escape allows all following characters */ - if (*p == '\\') { - p++; - if (*p) - param[j++] = *p++; - continue; - } - /* no quote, check for them or break on white space */ - if (quote == 0) { - if (*p == '\'') { - quote = 1; - p++; - continue; - } - if (*p == '\"') { - quote = 2; - p++; - continue; - } - if (*p <= ' ') - break; - } - /* single quote, check for unquote */ - if (quote == 1 && *p == '\'') { - quote = 0; - p++; - continue; - } - /* double quote, check for unquote */ - if (quote == 2 && *p == '\"') { - quote = 0; - p++; - continue; - } - /* copy character */ - param[j++] = *p++; - } - param[j] = '\0'; - args[i] = options_strdup(param); - sprintf(strchr(params, '\0'), " '%s'", param); - /* skip white spaces behind option */ - while (*p > '\0' && *p <= ' ') - p++; - i++; - } - /* search option */ - for (option = option_head; option; option = option->next) { - if (opt[0] == option->short_option && opt[1] == '\0') { - PDEBUG(DOPTIONS, DEBUG_INFO, "Config file option '%s' ('%s'), parameter%s\n", opt, option->long_option, params); - break; - } - if (!strcmp(opt, option->long_option)) { - PDEBUG(DOPTIONS, DEBUG_INFO, "Config file option '%s', parameter%s\n", opt, params); - break; - } - } - if (!option) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given option '%s' in config file '%s' at line %d is not a valid option, use '-h' for help!\n", opt, config_file, line); - rc = -EINVAL; - goto done; - } - if (option->parameter_count != i) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given option '%s' in config file '%s' at line %d requires %d parameter(s), use '-h' for help!\n", opt, config_file, line, option->parameter_count); - return -EINVAL; - } - rc = handle_options(option->short_option, 0, args); - if (rc <= 0) - goto done; - first_option = 0; - } - -done: - /* close config file */ - fclose(fp); - - return rc; -} - -int options_command_line(int argc, char *argv[], int (*handle_options)(int short_option, int argi, char *argv[])) -{ - option_t *option; - char params[1024]; - int argi, i; - int rc; - - for (argi = 1; argi < argc; argi++) { - /* --config */ - if (!strcmp(argv[argi], "--config")) { - if (argi > 1) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given command line option '%s' must be the first option specified, use '-h' for help!\n", argv[argi]); - return -EINVAL; - } - if (argc <= 2) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given command line option '%s' requires 1 parameter, use '-h' for help!\n", argv[argi]); - return -EINVAL; - } - argi += 1; - continue; - } - if (argv[argi][0] == '-') { - if (argv[argi][1] != '-') { - if (strlen(argv[argi]) != 2) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given command line option '%s' exceeds one character, use '-h' for help!\n", argv[argi]); - return -EINVAL; - } - /* -x */ - for (option = option_head; option; option = option->next) { - if (argv[argi][1] == option->short_option) { - if (option->parameter_count && argi + option->parameter_count < argc) { - params[0] = '\0'; - for (i = 0; i < option->parameter_count; i++) - sprintf(strchr(params, '\0'), " '%s'", argv[argi + 1 + i]); - PDEBUG(DOPTIONS, DEBUG_INFO, "Command line option '%s' ('--%s'), parameter%s\n", argv[argi], option->long_option, params); - } else - PDEBUG(DOPTIONS, DEBUG_INFO, "Command line option '%s' ('--%s')\n", argv[argi], option->long_option); - break; - } - } - } else { - /* --xxxxxx */ - for (option = option_head; option; option = option->next) { - if (!strcmp(argv[argi] + 2, option->long_option)) { - if (option->parameter_count && argi + option->parameter_count < argc) { - params[0] = '\0'; - for (i = 0; i < option->parameter_count; i++) - sprintf(strchr(params, '\0'), " '%s'", argv[argi + 1 + i]); - PDEBUG(DOPTIONS, DEBUG_INFO, "Command line option '%s', parameter%s\n", argv[argi], params); - } else - PDEBUG(DOPTIONS, DEBUG_INFO, "Command line option '%s'\n", argv[argi]); - break; - } - } - } - if (!option) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given command line option '%s' is not a valid option, use '-h' for help!\n", argv[argi]); - return -EINVAL; - } - if (argi + option->parameter_count >= argc) { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given command line option '%s' requires %d parameter(s), use '-h' for help!\n", argv[argi], option->parameter_count); - return -EINVAL; - } - rc = handle_options(option->short_option, argi + 1, argv); - if (rc <= 0) - return rc; - first_option = 0; - argi += option->parameter_count; - } else - break; - } - - /* no more options, so we check if there is an option after a non-option parameter */ - for (i = argi; i < argc; i++) { - if (argv[i][0] == '-') { - PDEBUG(DOPTIONS, DEBUG_ERROR, "Given command line option '%s' behind command line parameter '%s' not allowed! Please put all command line options before command line parameter(s).\n", argv[i], argv[argi]); - return -EINVAL; - } - } - - return argi; -} - -int option_is_first(void) -{ - return first_option; -} - -void options_free(void) -{ - while (options_strdup_list) { - struct options_strdup_entry *o; - o = options_strdup_list; - options_strdup_list = o->next; - free(o); - } - - while (option_head) { - option_t *o; - o = option_head; - option_head = o->next; - free(o); - } - option_tailp = &option_head; -} - diff --git a/src/lib/liboptions/options.h b/src/lib/liboptions/options.h deleted file mode 100644 index 5f494e0..0000000 --- a/src/lib/liboptions/options.h +++ /dev/null @@ -1,8 +0,0 @@ - -char *options_strdup(const char *s); -void option_add(int short_option, const char *long_option, int parameter_count); -int options_config_file(int argc, char *argv[], const char *config_file, int (*handle_options)(int short_option, int argi, char *argv[])); -int options_command_line(int argc, char *argv[], int (*handle_options)(int short_option, int argi, char *argv[])); -int option_is_first(void); -void options_free(void); - diff --git a/src/lib/libsample/Makefile.am b/src/lib/libsample/Makefile.am deleted file mode 100644 index 5ae865c..0000000 --- a/src/lib/libsample/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) - -noinst_LIBRARIES = libsample.a - -libsample_a_SOURCES = \ - sample.c diff --git a/src/lib/libsample/sample.c b/src/lib/libsample/sample.c deleted file mode 100644 index a084b66..0000000 --- a/src/lib/libsample/sample.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Sample definition - * - * (C) 2017 by Andreas Eversberg - * 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 . - */ - -#include -#include "sample.h" - -/* - * A regular voice conversation takes place at this factor below the full range - * of 16 bits signed value: - */ -static double int_16_speech_level = SPEECH_LEVEL * 0.7079; /* 16 dBm below dBm0, which is about 3dBm below full 16 bit range */ - -/* A sample_t is a value that has virtually infinite precision but will also - * support high numbers. 'double' or 'float' types are sufficient. - * - * When using sample_t inside signal processing of each base station, the - * level of +- 1 is relative to the normal speech evenlope. - * - * When converting sample_t to int16_t, the level of +- 1 is reduced by factor. - * This way the speech may be louder before clipping happens. - * - * When using sample_t to modulate (SDR or sound card), the level is changed, - * so it represents the frequency deviation in Hz. The deviation of speech - * envelope is network dependent. - */ - -void samples_to_int16(int16_t *spl, sample_t *samples, int length) -{ - int32_t value; - - while (length--) { - value = *samples++ * int_16_speech_level * 32768.0; - if (value > 32767.0) - *spl++ = 32767; - else if (value < -32767.0) - *spl++ = -32767; - else - *spl++ = (uint16_t)value; - } -} - -void int16_to_samples(sample_t *samples, int16_t *spl, int length) -{ - while (length--) { - *samples++ = (double)(*spl++) / 32767.0 / int_16_speech_level; - } -} - diff --git a/src/lib/libsample/sample.h b/src/lib/libsample/sample.h deleted file mode 100644 index 01a17df..0000000 --- a/src/lib/libsample/sample.h +++ /dev/null @@ -1,8 +0,0 @@ - -typedef double sample_t; - -#define SPEECH_LEVEL 0.1585 - -void samples_to_int16(int16_t *spl, sample_t *samples, int length); -void int16_to_samples(sample_t *samples, int16_t *spl, int length); - diff --git a/src/lib/libsound/Makefile.am b/src/lib/libsound/Makefile.am deleted file mode 100644 index afbbb0a..0000000 --- a/src/lib/libsound/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) - -noinst_LIBRARIES = libsound.a - -libsound_a_SOURCES = \ - sound_alsa.c - -AM_CPPFLAGS += -DHAVE_ALSA diff --git a/src/lib/libsound/sound.h b/src/lib/libsound/sound.h deleted file mode 100644 index 173dfd3..0000000 --- a/src/lib/libsound/sound.h +++ /dev/null @@ -1,10 +0,0 @@ - -enum paging_signal; - -void *sound_open(const char *audiodev, double *tx_frequency, double *rx_frequency, int *am, int channels, double paging_frequency, int samplerate, int buffer_size, double interval, double max_deviation, double max_modulation, double modulation_index); -int sound_start(void *inst); -void sound_close(void *inst); -int sound_write(void *inst, sample_t **samples, uint8_t **power, int num, enum paging_signal *paging_signal, int *on, int channels); -int sound_read(void *inst, sample_t **samples, int num, int channels, double *rf_level_db); -int sound_get_tosend(void *inst, int buffer_size); - diff --git a/src/lib/libsound/sound_alsa.c b/src/lib/libsound/sound_alsa.c deleted file mode 100644 index 20a4a31..0000000 --- a/src/lib/libsound/sound_alsa.c +++ /dev/null @@ -1,535 +0,0 @@ -/* Sound device access - * - * (C) 2016 by Andreas Eversberg - * 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 . - */ - -#include -#include -#include -#include -#include "../libsample/sample.h" -#include "../libdebug/debug.h" -#ifdef HAVE_MOBILE -#include "../libmobile/sender.h" -#else -#include "sound.h" -#endif - -typedef struct sound { - snd_pcm_t *phandle, *chandle; - int pchannels, cchannels; - int channels; /* required number of channels */ - int samplerate; /* required sample rate */ - char *audiodev; /* required device */ - double spl_deviation; /* how much deviation is one sample step */ -#ifdef HAVE_MOBILE - double paging_phaseshift; /* phase to shift every sample */ - double paging_phase; /* current phase */ - double rx_frequency[2]; /* rx frequency of radio connected to channel */ - dispmeasparam_t *dmp[2]; -#endif -} sound_t; - -static int set_hw_params(snd_pcm_t *handle, int samplerate, int *channels) -{ - snd_pcm_hw_params_t *hw_params = NULL; - int rc; - unsigned int rrate; - - rc = snd_pcm_hw_params_malloc(&hw_params); - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "Failed to allocate hw_params! (%s)\n", snd_strerror(rc)); - goto error; - } - - rc = snd_pcm_hw_params_any(handle, hw_params); - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "cannot initialize hardware parameter structure (%s)\n", snd_strerror(rc)); - goto error; - } - - rc = snd_pcm_hw_params_set_rate_resample(handle, hw_params, 0); - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "cannot set real hardware rate (%s)\n", snd_strerror(rc)); - goto error; - } - - rc = snd_pcm_hw_params_set_access (handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "cannot set access to interleaved (%s)\n", snd_strerror(rc)); - goto error; - } - - rc = snd_pcm_hw_params_set_format(handle, hw_params, SND_PCM_FORMAT_S16); - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "cannot set sample format (%s)\n", snd_strerror(rc)); - goto error; - } - - rrate = samplerate; - rc = snd_pcm_hw_params_set_rate_near(handle, hw_params, &rrate, 0); - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "cannot set sample rate (%s)\n", snd_strerror(rc)); - goto error; - } - if ((int)rrate != samplerate) { - PDEBUG(DSOUND, DEBUG_ERROR, "Rate doesn't match (requested %dHz, get %dHz)\n", samplerate, rrate); - rc = -EIO; - goto error; - } - - *channels = 1; - rc = snd_pcm_hw_params_set_channels(handle, hw_params, *channels); - if (rc < 0) { - *channels = 2; - rc = snd_pcm_hw_params_set_channels(handle, hw_params, *channels); - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "cannot set channel count to 1 nor 2 (%s)\n", snd_strerror(rc)); - goto error; - } - } - - rc = snd_pcm_hw_params(handle, hw_params); - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "cannot set parameters (%s)\n", snd_strerror(rc)); - goto error; - } - - snd_pcm_hw_params_free(hw_params); - - return 0; - -error: - if (hw_params) { - snd_pcm_hw_params_free(hw_params); - } - - return rc; -} - -static int dev_open(sound_t *sound) -{ - int rc, rc_rec, rc_play; - - rc_play = snd_pcm_open(&sound->phandle, sound->audiodev, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); - rc_rec = snd_pcm_open(&sound->chandle, sound->audiodev, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK); - if (rc_play < 0 && rc_rec < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "Failed to open '%s'! (%s)\n", sound->audiodev, snd_strerror(rc_play)); - PDEBUG(DSOUND, DEBUG_ERROR, "Run 'aplay -l' to get a list of available cards and devices.\n"); - PDEBUG(DSOUND, DEBUG_ERROR, "Then use 'hw::' for audio device.\n"); - return rc_play; - } - if (rc_play < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "Failed to open '%s' for playback! (%s) Please select a device that supports both direction audio.\n", sound->audiodev, snd_strerror(rc_play)); - return rc_play; - } - if (rc_rec < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "Failed to open '%s' for capture! (%s) Please select a device that supports both direction audio.\n", sound->audiodev, snd_strerror(rc_rec)); - return rc_rec; - } - - rc = set_hw_params(sound->phandle, sound->samplerate, &sound->pchannels); - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "Failed to set playback hw params\n"); - return rc; - } - if (sound->pchannels < sound->channels) { - PDEBUG(DSOUND, DEBUG_ERROR, "Sound card only supports %d channel for playback.\n", sound->pchannels); - return rc; - } - PDEBUG(DSOUND, DEBUG_DEBUG, "Playback with %d channels.\n", sound->pchannels); - - rc = set_hw_params(sound->chandle, sound->samplerate, &sound->cchannels); - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "Failed to set capture hw params\n"); - return rc; - } - if (sound->cchannels < sound->channels) { - PDEBUG(DSOUND, DEBUG_ERROR, "Sound card only supports %d channel for capture.\n", sound->cchannels); - return -EIO; - } - PDEBUG(DSOUND, DEBUG_DEBUG, "Capture with %d channels.\n", sound->cchannels); - - rc = snd_pcm_prepare(sound->phandle); - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "cannot prepare audio interface for use (%s)\n", snd_strerror(rc)); - return rc; - } - - rc = snd_pcm_prepare(sound->chandle); - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "cannot prepare audio interface for use (%s)\n", snd_strerror(rc)); - return rc; - } - - return 0; -} - -static void dev_close(sound_t *sound) -{ - if (sound->phandle != NULL) - snd_pcm_close(sound->phandle); - if (sound->chandle != NULL) - snd_pcm_close(sound->chandle); -} - -void *sound_open(const char *audiodev, double __attribute__((unused)) *tx_frequency, double __attribute__((unused)) *rx_frequency, int __attribute__((unused)) *am, int channels, double __attribute__((unused)) paging_frequency, int samplerate, int __attribute((unused)) buffer_size, double __attribute__((unused)) interval, double max_deviation, double __attribute__((unused)) max_modulation, double __attribute__((unused)) modulation_index) -{ - 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; - } - - sound->audiodev = strdup(audiodev); // is feed when closed - sound->channels = channels; - sound->samplerate = samplerate; - sound->spl_deviation = max_deviation / 32767.0; -#ifdef HAVE_MOBILE - sound->paging_phaseshift = 1.0 / ((double)samplerate / 1000.0); -#endif - - rc = dev_open(sound); - if (rc < 0) - goto error; - -#ifdef HAVE_MOBILE - if (rx_frequency) { - sender_t *sender; - int i; - for (i = 0; i < channels; i++) { - sound->rx_frequency[i] = rx_frequency[i]; - sender = get_sender_by_empfangsfrequenz(sound->rx_frequency[i]); - if (!sender) - continue; - sound->dmp[i] = display_measurements_add(&sender->dispmeas, "RX Level", "%.1f dB", DISPLAY_MEAS_PEAK, DISPLAY_MEAS_LEFT, -96.0, 0.0, -INFINITY); - } - } -#endif - - return sound; - -error: - sound_close(sound); - return NULL; -} - -/* start streaming */ -int sound_start(void *inst) -{ - sound_t *sound = (sound_t *)inst; - int16_t buff[2]; - - /* trigger capturing */ - snd_pcm_readi(sound->chandle, buff, 1); - - return 0; -} - -void sound_close(void *inst) -{ - sound_t *sound = (sound_t *)inst; - - dev_close(sound); - free(sound->audiodev); - free(sound); -} - -#ifdef HAVE_MOBILE -static void gen_paging_tone(sound_t *sound, int16_t *samples, int length, enum paging_signal paging_signal, int on) -{ - double phaseshift, phase; - int i; - - switch (paging_signal) { - case PAGING_SIGNAL_NOTONE: - /* no tone if paging signal is on */ - on = !on; - /* FALLTHRU */ - case PAGING_SIGNAL_TONE: - /* tone if paging signal is on */ - if (on) { - phaseshift = sound->paging_phaseshift; - phase = sound->paging_phase; - for (i = 0; i < length; i++) { - if (phase < 0.5) - *samples++ = 30000; - else - *samples++ = -30000; - phase += phaseshift; - if (phase >= 1.0) - phase -= 1.0; - } - sound->paging_phase = phase; - } else - memset(samples, 0, length << 1); - break; - case PAGING_SIGNAL_NEGATIVE: - /* negative signal if paging signal is on */ - on = !on; - /* FALLTHRU */ - case PAGING_SIGNAL_POSITIVE: - /* positive signal if paging signal is on */ - if (on) - memset(samples, 127, length << 1); - else - memset(samples, 128, length << 1); - break; - case PAGING_SIGNAL_NONE: - break; - } -} -#endif - -int sound_write(void *inst, sample_t **samples, uint8_t __attribute__((unused)) **power, int num, enum paging_signal __attribute__((unused)) *paging_signal, int __attribute__((unused)) *on, int channels) -{ - sound_t *sound = (sound_t *)inst; - double spl_deviation = sound->spl_deviation; - int32_t value; - int16_t buff[num << 1]; - int rc; - int i, ii; - - if (sound->pchannels == 2) { - /* two channels */ -#ifdef HAVE_MOBILE - if (paging_signal && on && paging_signal[0] != PAGING_SIGNAL_NONE) { - int16_t paging[num << 1]; - gen_paging_tone(sound, paging, num, paging_signal[0], on[0]); - for (i = 0, ii = 0; i < num; i++) { - value = samples[0][i] / spl_deviation; - if (value > 32767) - value = 32767; - else if (value < -32767) - value = -32767; - buff[ii++] = value; - buff[ii++] = paging[i]; - } - } else -#endif - if (channels == 2) { - for (i = 0, ii = 0; i < num; i++) { - value = samples[0][i] / spl_deviation; - if (value > 32767) - value = 32767; - else if (value < -32767) - value = -32767; - buff[ii++] = value; - value = samples[1][i] / spl_deviation; - if (value > 32767) - value = 32767; - else if (value < -32767) - value = -32767; - buff[ii++] = value; - } - } else { - for (i = 0, ii = 0; i < num; i++) { - value = samples[0][i] / spl_deviation; - if (value > 32767) - value = 32767; - else if (value < -32767) - value = -32767; - buff[ii++] = value; - buff[ii++] = value; - } - } - } else { - /* one channel */ - for (i = 0, ii = 0; i < num; i++) { - value = samples[0][i] / spl_deviation; - if (value > 32767) - value = 32767; - else if (value < -32767) - value = -32767; - buff[ii++] = value; - } - } - rc = snd_pcm_writei(sound->phandle, buff, num); - - if (rc < 0) { - PDEBUG(DSOUND, DEBUG_ERROR, "failed to write audio to interface (%s)\n", snd_strerror(rc)); - if (rc == -EPIPE) { - dev_close(sound); - rc = dev_open(sound); - if (rc < 0) - return rc; - sound_start(sound); - return -EPIPE; /* indicate what happened */ - } - return rc; - } - - if (rc != num) - PDEBUG(DSOUND, DEBUG_ERROR, "short write to audio interface, written %d bytes, got %d bytes\n", num, rc); - - return rc; -} - -#define KEEP_FRAMES 8 /* minimum frames not to read, due to bug in ALSA */ - -int sound_read(void *inst, sample_t **samples, int num, int channels, double __attribute__((unused)) *rf_level_db) -{ - sound_t *sound = (sound_t *)inst; - double spl_deviation = sound->spl_deviation; - int16_t buff[num << 1]; - int32_t spl; - int32_t max[2], a; - int in, rc; - int i, ii; - - /* make valgrind happy, because snd_pcm_readi() does not seem to initially fill buffer with values */ - memset(buff, 0, sizeof(buff)); - - /* get samples in rx buffer */ - in = snd_pcm_avail(sound->chandle); - /* if not more than KEEP_FRAMES frames available, try next time */ - if (in <= KEEP_FRAMES) - return 0; - /* read some frames less than in buffer, because snd_pcm_readi() seems - * to corrupt last frames */ - in -= KEEP_FRAMES; - if (in > num) - in = num; - - rc = snd_pcm_readi(sound->chandle, buff, in); - - if (rc < 0) { - if (errno == EAGAIN) - return 0; - PDEBUG(DSOUND, DEBUG_ERROR, "failed to read audio from interface (%s)\n", snd_strerror(rc)); - /* recover read */ - if (rc == -EPIPE) { - dev_close(sound); - rc = dev_open(sound); - if (rc < 0) - return rc; - sound_start(sound); - return -EPIPE; /* indicate what happened */ - } - return rc; - } - - if (rc == 0) - return rc; - - if (sound->cchannels == 2) { - if (channels < 2) { - for (i = 0, ii = 0; i < rc; i++) { - spl = buff[ii++]; - spl += buff[ii++]; - a = (spl >= 0) ? spl : -spl; - if (i == 0 || a > max[0]) - max[0] = a; - samples[0][i] = (double)spl * spl_deviation; - } - } else { - for (i = 0, ii = 0; i < rc; i++) { - spl = buff[ii++]; - a = (spl >= 0) ? spl : -spl; - if (i == 0 || a > max[0]) - max[0] = a; - samples[0][i] = (double)spl * spl_deviation; - spl = buff[ii++]; - a = (spl >= 0) ? spl : -spl; - if (i == 0 || a > max[1]) - max[1] = a; - samples[1][i] = (double)spl * spl_deviation; - } - } - } else { - for (i = 0, ii = 0; i < rc; i++) { - spl = buff[ii++]; - a = (spl >= 0) ? spl : -spl; - if (i == 0 || a > max[0]) - max[0] = a; - samples[0][i] = (double)spl * spl_deviation; - } - } - -#ifdef HAVE_MOBILE - sender_t *sender; - for (i = 0; i < channels; i++) { - sender = get_sender_by_empfangsfrequenz(sound->rx_frequency[i]); - if (!sender) - continue; - display_measurements_update(sound->dmp[i], log10((double)max[i] / 32768.0) * 20, 0.0); - if (rf_level_db) - rf_level_db[i] = 0.0; - } -#endif - - return rc; -} - -/* - * get playback buffer space - * - * return number of samples to be sent */ -int sound_get_tosend(void *inst, int buffer_size) -{ - sound_t *sound = (sound_t *)inst; - int rc; - snd_pcm_sframes_t delay; - int tosend; - - rc = snd_pcm_delay(sound->phandle, &delay); - if (rc < 0) { - if (rc == -32) - PDEBUG(DSOUND, DEBUG_ERROR, "Buffer underrun: Please use higher buffer and enable real time scheduling\n"); - else - PDEBUG(DSOUND, DEBUG_ERROR, "failed to get delay from interface (%s)\n", snd_strerror(rc)); - if (rc == -EPIPE) { - dev_close(sound); - rc = dev_open(sound); - if (rc < 0) - return rc; - sound_start(sound); - return -EPIPE; /* indicate what happened */ - } - return rc; - } - - tosend = buffer_size - delay; - return tosend; -} - -int sound_is_stereo_capture(void *inst) -{ - sound_t *sound = (sound_t *)inst; - - if (sound->cchannels == 2) - return 1; - return 0; -} - -int sound_is_stereo_playback(void *inst) -{ - sound_t *sound = (sound_t *)inst; - - if (sound->pchannels == 2) - return 1; - return 0; -} - diff --git a/src/lib/libwave/Makefile.am b/src/lib/libwave/Makefile.am deleted file mode 100644 index c573515..0000000 --- a/src/lib/libwave/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) - -noinst_LIBRARIES = libwave.a - -libwave_a_SOURCES = \ - wave.c diff --git a/src/lib/libwave/wave.c b/src/lib/libwave/wave.c deleted file mode 100644 index 50c2c96..0000000 --- a/src/lib/libwave/wave.c +++ /dev/null @@ -1,519 +0,0 @@ -/* wave recording and playback functions - * - * (C) 2016 by Andreas Eversberg - * 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 . - */ - -#include -#include -#include -#include -#include -#include -#include -#include "../libsample/sample.h" -#include "../libdebug/debug.h" -#include "wave.h" - -/* NOTE: No locking required for writing and reading buffer pointers, since 'int' is atomic on >=32 bit machines */ - -static void *record_child(void *arg) -{ - wave_rec_t *rec = (wave_rec_t *)arg; - int to_write, to_end, len; - - while (!rec->finish || rec->buffer_writep != rec->buffer_readp) { - /* how much data is in buffer */ - to_write = (rec->buffer_size + rec->buffer_writep - rec->buffer_readp) % rec->buffer_size; - if (to_write == 0) { - usleep(10000); - continue; - } - /* only write up to the end of buffer */ - to_end = rec->buffer_size - rec->buffer_readp; - if (to_end < to_write) - to_write = to_end; - /* write */ - errno = 0; - len = fwrite(rec->buffer + rec->buffer_readp, 1, to_write, rec->fp); - /* quit on error */ - if (len < 0) { -error: - PDEBUG(DWAVE, DEBUG_ERROR, "Failed to write to recording WAVE file! (errno %d)\n", errno); - rec->finish = 1; - return NULL; - } - /* increment read pointer */ - rec->buffer_readp += len; - if (rec->buffer_readp == rec->buffer_size) - rec->buffer_readp = 0; - /* quit on end of file */ - if (len != to_write) - goto error; - } - - return NULL; -} - -static void *playback_child(void *arg) -{ - wave_play_t *play = (wave_play_t *)arg; - int to_read, to_end, len; - - while(!play->finish) { - /* how much space is in buffer */ - to_read = (play->buffer_size + play->buffer_readp - play->buffer_writep - 1) % play->buffer_size; - if (to_read == 0) { - usleep(10000); - continue; - } - /* only read up to the end of buffer */ - to_end = play->buffer_size - play->buffer_writep; - if (to_end < to_read) - to_read = to_end; - /* read */ - len = fread(play->buffer + play->buffer_writep, 1, to_read, play->fp); - /* quit on error */ - if (len < 0) { - PDEBUG(DWAVE, DEBUG_ERROR, "Failed to read from playback WAVE file! (errno %d)\n", errno); - play->finish = 1; - return NULL; - } - /* increment write pointer */ - play->buffer_writep += len; - if (play->buffer_writep == play->buffer_size) - play->buffer_writep = 0; - /* quit on end of file */ - if (len != to_read) { - play->finish = 1; - return NULL; - } - } - - return NULL; -} - -struct fmt { - uint16_t format; /* 1 = pcm, 2 = adpcm */ - uint16_t channels; /* number of channels */ - uint32_t sample_rate; /* sample rate */ - uint32_t data_rate; /* data rate */ - uint16_t bytes_sample; /* bytes per sample (all channels) */ - uint16_t bits_sample; /* bits per sample (one channel) */ -}; - -int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate, int channels, double max_deviation) -{ - /* RIFFxxxxWAVEfmt xxxx(fmt size)dataxxxx... */ - char dummyheader[4 + 4 + 4 + 4 + 4 + sizeof(struct fmt) + 4 + 4]; - int __attribute__((__unused__)) len; - int rc; - - memset(rec, 0, sizeof(*rec)); - rec->samplerate = samplerate; - rec->channels = channels; - rec->max_deviation = max_deviation; - - rec->fp = fopen(filename, "w"); - if (!rec->fp) { - PDEBUG(DWAVE, DEBUG_ERROR, "Failed to open recording file '%s'! (errno %d)\n", filename, errno); - return -errno; - } - - memset(&dummyheader, 0, sizeof(dummyheader)); - len = fwrite(dummyheader, 1, sizeof(dummyheader), rec->fp); - - rec->buffer_size = samplerate * 2 * channels; - rec->buffer = calloc(rec->buffer_size, 1); - if (!rec->buffer) { - PDEBUG(DWAVE, DEBUG_NOTICE, "No mem!\n"); - rc = ENOMEM; - goto error; - } - - rc = pthread_create(&rec->tid, NULL, record_child, rec); - if (rc < 0) { - PDEBUG(DWAVE, DEBUG_ERROR, "Failed to create thread to record WAVE file! (errno %d)\n", errno); - goto error; - } - - PDEBUG(DWAVE, DEBUG_NOTICE, "*** Writing WAVE file to %s.\n", filename); - - return 0; - -error: - if (rec->buffer) { - free(rec->buffer); - rec->buffer = NULL; - } - if (rec->fp) { - fclose(rec->fp); - rec->fp = NULL; - } - return rc; -} - -int wave_create_playback(wave_play_t *play, const char *filename, int *samplerate_p, int *channels_p, double max_deviation) -{ - uint8_t buffer[256]; - struct fmt fmt; - int32_t size, chunk, len; - int gotfmt = 0, gotdata = 0; - int rc = -EINVAL; - - memset(&fmt, 0, sizeof(fmt)); - memset(play, 0, sizeof(*play)); - play->max_deviation = max_deviation; - - play->fp = fopen(filename, "r"); - if (!play->fp) { - PDEBUG(DWAVE, DEBUG_ERROR, "Failed to open playback file '%s'! (errno %d)\n", filename, errno); - return -errno; - } - - len = fread(buffer, 1, 12, play->fp); - if (len != 12) { - PDEBUG(DWAVE, DEBUG_ERROR, "Failed to read RIFF header!\n"); - rc = -EIO; - goto error; - } - if (!!strncmp((char *)buffer, "RIFF", 4)) { - PDEBUG(DWAVE, DEBUG_ERROR, "Missing RIFF header, seems that this is no WAVE file!\n"); - rc = -EINVAL; - goto error; - } - size = buffer[4] + (buffer[5] << 8) + (buffer[6] << 16) + (buffer[7] << 24); - if (!!strncmp((char *)buffer + 8, "WAVE", 4)) { - PDEBUG(DWAVE, DEBUG_ERROR, "Missing WAVE header, seems that this is no WAVE file!\n"); - rc = -EINVAL; - goto error; - } - size -= 4; - while (size) { - if (size < 8) { - PDEBUG(DWAVE, DEBUG_ERROR, "Short read of WAVE file!\n"); - rc = -EINVAL; - goto error; - } - len = fread(buffer, 1, 8, play->fp); - if (len != 8) { - PDEBUG(DWAVE, DEBUG_ERROR, "Failed to read chunk of WAVE file!\n"); - rc = -EIO; - goto error; - } - chunk = buffer[4] + (buffer[5] << 8) + (buffer[6] << 16) + (buffer[7] << 24); - size -= 8 + chunk; - if (size < 0) { - PDEBUG(DWAVE, DEBUG_ERROR, "WAVE error: Chunk '%c%c%c%c' overflows file size!\n", buffer[4], buffer[5], buffer[6], buffer[7]); - rc = -EIO; - goto error; - } - if (!strncmp((char *)buffer, "fmt ", 4)) { - if (chunk < 16 || chunk > (int)sizeof(buffer)) { - PDEBUG(DWAVE, DEBUG_ERROR, "WAVE error: Short or corrupt 'fmt' chunk!\n"); - rc = -EINVAL; - goto error; - } - len = fread(buffer, 1, chunk, play->fp); - fmt.format = buffer[0] + (buffer[1] << 8); - fmt.channels = buffer[2] + (buffer[3] << 8); - fmt.sample_rate = buffer[4] + (buffer[5] << 8) + (buffer[6] << 16) + (buffer[7] << 24); - fmt.data_rate = buffer[8] + (buffer[9] << 8) + (buffer[10] << 16) + (buffer[11] << 24); - fmt.bytes_sample = buffer[12] + (buffer[13] << 8); - fmt.bits_sample = buffer[14] + (buffer[15] << 8); - gotfmt = 1; - } else - if (!strncmp((char *)buffer, "data", 4)) { - if (!gotfmt) { - PDEBUG(DWAVE, DEBUG_ERROR, "WAVE error: 'data' without 'fmt' chunk!\n"); - rc = -EINVAL; - goto error; - } - gotdata = 1; - break; - } else { - while(chunk > (int)sizeof(buffer)) { - len = fread(buffer, 1, sizeof(buffer), play->fp); - chunk -= sizeof(buffer); - } - if (chunk) - len = fread(buffer, 1, chunk, play->fp); - } - } - - if (!gotfmt || !gotdata) { - PDEBUG(DWAVE, DEBUG_ERROR, "WAVE error: Missing 'data' or 'fmt' chunk!\n"); - rc = -EINVAL; - goto error; - } - - if (fmt.format != 1) { - PDEBUG(DWAVE, DEBUG_ERROR, "WAVE error: We support only PCM files!\n"); - rc = -EINVAL; - goto error; - } - if (*channels_p == 0) - *channels_p = fmt.channels; - if (fmt.channels != *channels_p) { - PDEBUG(DWAVE, DEBUG_ERROR, "WAVE error: We expect %d cannel(s), but wave file only has %d channel(s)\n", *channels_p, fmt.channels); - rc = -EINVAL; - goto error; - } - if (*samplerate_p == 0) - *samplerate_p = fmt.sample_rate; - if ((int)fmt.sample_rate != *samplerate_p) { - PDEBUG(DWAVE, DEBUG_ERROR, "WAVE error: The WAVE file's sample rate (%d) does not match our sample rate (%d)!\n", fmt.sample_rate, *samplerate_p); - rc = -EINVAL; - goto error; - } - if ((int)fmt.data_rate != 2 * *channels_p * *samplerate_p) { - PDEBUG(DWAVE, DEBUG_ERROR, "WAVE error: The WAVE file's data rate is only %d bytes per second, but we expect %d bytes per second (2 bytes per sample * channels * samplerate)!\n", fmt.data_rate, 2 * *channels_p * *samplerate_p); - rc = -EINVAL; - goto error; - } - if (fmt.bytes_sample != 2 * *channels_p) { - PDEBUG(DWAVE, DEBUG_ERROR, "WAVE error: The WAVE file's bytes per sample is only %d, but we expect %d bytes sample (2 bytes per sample * channels)!\n", fmt.bytes_sample, 2 * *channels_p); - rc = -EINVAL; - goto error; - } - if (fmt.bits_sample != 16) { - PDEBUG(DWAVE, DEBUG_ERROR, "WAVE error: We support only 16 bit files!\n"); - rc = -EINVAL; - goto error; - } - - play->channels = *channels_p; - play->left = chunk / 2 / *channels_p; - - play->buffer_size = *samplerate_p * 2 * *channels_p; - play->buffer = calloc(play->buffer_size, 1); - if (!play->buffer) { - PDEBUG(DWAVE, DEBUG_ERROR, "No mem!\n"); - rc = -ENOMEM; - goto error; - } - - rc = pthread_create(&play->tid, NULL, playback_child, play); - if (rc < 0) { - PDEBUG(DWAVE, DEBUG_ERROR, "Failed to create thread to playback WAVE file! (errno %d)\n", errno); - goto error; - } - - PDEBUG(DWAVE, DEBUG_NOTICE, "*** Reading WAVE file from %s.\n", filename); - - return 0; - -error: - if (play->buffer) { - free(play->buffer); - play->buffer = NULL; - } - if (play->fp) { - fclose(play->fp); - play->fp = NULL; - } - return rc; -} - -int wave_write(wave_rec_t *rec, sample_t **samples, int length) -{ - double max_deviation = rec->max_deviation; - int32_t value; - int __attribute__((__unused__)) len; - int i, c; - int to_write; - - /* on error, don't write more */ - if (rec->finish) - return 0; - - /* how much space is in buffer */ - to_write = (rec->buffer_size + rec->buffer_readp - rec->buffer_writep - 1) % rec->buffer_size; - to_write /= 2 * rec->channels; - if (to_write < length) - PDEBUG(DWAVE, DEBUG_NOTICE, "Record WAVE buffer overflow.\n"); - else - to_write = length; - if (to_write == 0) - return 0; - - for (i = 0; i < to_write; i++) { - for (c = 0; c < rec->channels; c++) { - value = samples[c][i] / max_deviation * 32767.0; - if (value > 32767) - value = 32767; - else if (value < -32767) - value = -32767; - rec->buffer[rec->buffer_writep] = value; - rec->buffer_writep = (rec->buffer_writep + 1) % rec->buffer_size; - rec->buffer[rec->buffer_writep] = value >> 8; - rec->buffer_writep = (rec->buffer_writep + 1) % rec->buffer_size; - } - } - rec->written += to_write; - - return to_write; -} - -int wave_read(wave_play_t *play, sample_t **samples, int length) -{ - double max_deviation = play->max_deviation; - int16_t value; /* must be int16, so assembling bytes work */ - int __attribute__((__unused__)) len; - int i, c; - int to_read; - int got = 0; - - /* we have finished */ - if (play->left == 0) { - to_read = 0; -read_empty: - for (i = to_read; i < length; i++) { - for (c = 0; c < play->channels; c++) - samples[c][i] = 0; - } - return got; - } - - /* how much do we read from buffer */ - to_read = (play->buffer_size + play->buffer_writep - play->buffer_readp) % play->buffer_size; - to_read /= 2 * play->channels; - if (to_read > (int)play->left) - to_read = play->left; - if (to_read > length) - to_read = length; - - if (to_read == 0 && play->finish) { - if (play->left) { - PDEBUG(DWAVE, DEBUG_NOTICE, "*** Finished reading WAVE file. (short read)\n"); - play->left = 0; - } - goto read_empty; - } - - /* read from buffer */ - for (i = 0; i < to_read; i++) { - for (c = 0; c < play->channels; c++) { - value = play->buffer[play->buffer_readp]; - play->buffer_readp = (play->buffer_readp + 1) % play->buffer_size; - value |= play->buffer[play->buffer_readp] << 8; - play->buffer_readp = (play->buffer_readp + 1) % play->buffer_size; - samples[c][i] = (double)value / 32767.0 * max_deviation; - } - } - got += to_read; - play->left -= to_read; - - if (!play->left) - PDEBUG(DWAVE, DEBUG_NOTICE, "*** Finished reading WAVE file.\n"); - - if (to_read < length) - goto read_empty; - - return got; -} - -void wave_destroy_record(wave_rec_t *rec) -{ - uint8_t buffer[256]; - uint32_t size, wsize; - struct fmt fmt; - int __attribute__((__unused__)) len; - - if (!rec->fp) - return; - - /* on error, thread has terminated */ - if (rec->finish) { - fclose(rec->fp); - rec->fp = NULL; - return; - } - - /* finish thread */ - rec->finish = 1; - pthread_join(rec->tid, NULL); - - /* cue */ - fprintf(rec->fp, "cue %c%c%c%c%c%c%c%c", 4, 0, 0, 0, 0,0,0,0); - - /* LIST */ - fprintf(rec->fp, "LIST%c%c%c%cadtl", 4, 0, 0, 0); - - /* go to header */ - fseek(rec->fp, 0, SEEK_SET); - - size = 2 * rec->written * rec->channels; - wsize = 4 + 8 + sizeof(fmt) + 8 + size + 8 + 4 + 8 + 4; - - /* RIFF */ - fprintf(rec->fp, "RIFF%c%c%c%c", wsize & 0xff, (wsize >> 8) & 0xff, (wsize >> 16) & 0xff, wsize >> 24); - - /* WAVE */ - fprintf(rec->fp, "WAVE"); - - /* fmt */ - fprintf(rec->fp, "fmt %c%c%c%c", (uint8_t)sizeof(fmt), 0, 0, 0); - fmt.format = 1; - fmt.channels = rec->channels; - fmt.sample_rate = rec->samplerate; /* samples/sec */ - fmt.data_rate = rec->samplerate * 2 * rec->channels; /* full data rate */ - fmt.bytes_sample = 2 * rec->channels; /* all channels */ - fmt.bits_sample = 16; /* one channel */ - buffer[0] = fmt.format; - buffer[1] = fmt.format >> 8; - buffer[2] = fmt.channels; - buffer[3] = fmt.channels >> 8; - buffer[4] = fmt.sample_rate; - buffer[5] = fmt.sample_rate >> 8; - buffer[6] = fmt.sample_rate >> 16; - buffer[7] = fmt.sample_rate >> 24; - buffer[8] = fmt.data_rate; - buffer[9] = fmt.data_rate >> 8; - buffer[10] = fmt.data_rate >> 16; - buffer[11] = fmt.data_rate >> 24; - buffer[12] = fmt.bytes_sample; - buffer[13] = fmt.bytes_sample >> 8; - buffer[14] = fmt.bits_sample; - buffer[15] = fmt.bits_sample >> 8; - len = fwrite(buffer, 1, sizeof(fmt), rec->fp); - - /* data */ - fprintf(rec->fp, "data%c%c%c%c", size & 0xff, (size >> 8) & 0xff, (size >> 16) & 0xff, size >> 24); - - free(rec->buffer); - rec->buffer = NULL; - fclose(rec->fp); - rec->fp = NULL; - - PDEBUG(DWAVE, DEBUG_NOTICE, "*** WAVE file written.\n"); -} - -void wave_destroy_playback(wave_play_t *play) -{ - if (!play->fp) - return; - - /* finish thread if not already */ - play->finish = 1; - pthread_join(play->tid, NULL); - - free(play->buffer); - play->buffer = NULL; - fclose(play->fp); - play->fp = NULL; -} - diff --git a/src/lib/libwave/wave.h b/src/lib/libwave/wave.h deleted file mode 100644 index 064f914..0000000 --- a/src/lib/libwave/wave.h +++ /dev/null @@ -1,37 +0,0 @@ - -typedef struct wave_rec { - FILE *fp; - int channels; - double max_deviation; - int samplerate; - uint32_t written; /* how much samples written */ - /* thread stuff */ - pthread_t tid; /* file io thread id */ - int finish; /* indicates end of thread */ - uint8_t *buffer; /* buffer to store sample data */ - int buffer_size; /* size of buffer in bytes */ - int buffer_readp; /* read pointer to next byte in buffer */ - int buffer_writep; /* write pointer to next byte in buffer */ -} wave_rec_t; - -typedef struct wave_play { - FILE *fp; - int channels; - double max_deviation; - uint32_t left; /* how much samples left */ - /* thread stuff */ - pthread_t tid; /* file io thread id */ - int finish; /* indicates end of thread */ - uint8_t *buffer; /* buffer to store sample data */ - int buffer_size; /* size of buffer in bytes */ - int buffer_readp; /* read pointer to next byte in buffer */ - int buffer_writep; /* write pointer to next byte in buffer */ -} wave_play_t; - -int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate, int channels, double max_deviation); -int wave_create_playback(wave_play_t *play, const char *filename, int *samplerate_p, int *channels_p, double max_deviation); -int wave_read(wave_play_t *play, sample_t **samples, int length); -int wave_write(wave_rec_t *rec, sample_t **samples, int length); -void wave_destroy_record(wave_rec_t *rec); -void wave_destroy_playback(wave_play_t *play); -