The contents of src/lib will be replaced with a submodule in a following commmitpull/2/head
parent
9ed1f48b5d
commit
5c474118b1
@ -1,7 +0,0 @@ |
||||
AM_CPPFLAGS = -Wall -Wextra -g $(all_includes)
|
||||
|
||||
noinst_LIBRARIES = libaaimage.a
|
||||
|
||||
libaaimage_a_SOURCES = \
|
||||
aaimage.c
|
||||
|
@ -1,74 +0,0 @@ |
||||
|
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
#include <stdlib.h> |
||||
#include "aaimage.h" |
||||
|
||||
extern const char *aaimage[]; |
||||
|
||||
void print_aaimage(void) |
||||
{ |
||||
int i, j; |
||||
|
||||
for (i = 0; aaimage[i]; i++) { |
||||
for (j = 0; j < (int)strlen(aaimage[i]); j++) { |
||||
if (aaimage[i][j] == '@') { |
||||
j++; |
||||
switch(aaimage[i][j]) { |
||||
case 'k': /* black */ |
||||
printf("\033[0;30m"); |
||||
break; |
||||
case 'r': /* red */ |
||||
printf("\033[0;31m"); |
||||
break; |
||||
case 'g': /* green */ |
||||
printf("\033[0;32m"); |
||||
break; |
||||
case 'y': /* yellow */ |
||||
printf("\033[0;33m"); |
||||
break; |
||||
case 'b': /* blue */ |
||||
printf("\033[0;34m"); |
||||
break; |
||||
case 'm': /* magenta */ |
||||
printf("\033[0;35m"); |
||||
break; |
||||
case 'c': /* cyan */ |
||||
printf("\033[0;36m"); |
||||
break; |
||||
case 'w': /* white */ |
||||
printf("\033[0;37m"); |
||||
break; |
||||
case 'K': /* bright black */ |
||||
printf("This will not work on some terminals, please use 'w'\n"); |
||||
abort(); |
||||
case 'R': /* bright red */ |
||||
printf("\033[1;31m"); |
||||
break; |
||||
case 'G': /* bright green */ |
||||
printf("\033[1;32m"); |
||||
break; |
||||
case 'Y': /* bright yellow */ |
||||
printf("\033[1;33m"); |
||||
break; |
||||
case 'B': /* bright blue */ |
||||
printf("\033[1;34m"); |
||||
break; |
||||
case 'M': /* bright magenta */ |
||||
printf("\033[1;35m"); |
||||
break; |
||||
case 'C': /* bright cyan */ |
||||
printf("\033[1;36m"); |
||||
break; |
||||
case 'W': /* bright white */ |
||||
printf("\033[1;37m"); |
||||
break; |
||||
} |
||||
} else |
||||
printf("%c", aaimage[i][j]); |
||||
} |
||||
printf("\n"); |
||||
} |
||||
printf("\033[0;39m"); |
||||
} |
||||
|
@ -1,3 +0,0 @@ |
||||
|
||||
void print_aaimage(void); |
||||
|
@ -1,6 +0,0 @@ |
||||
AM_CPPFLAGS = -Wall -Wextra -g $(all_includes)
|
||||
|
||||
noinst_LIBRARIES = libam.a
|
||||
|
||||
libam_a_SOURCES = \
|
||||
am.c
|
@ -1,204 +0,0 @@ |
||||
/* AM modulation and de-modulation
|
||||
* |
||||
* (C) 2018 by Andreas Eversberg <jolly@eversberg.eu> |
||||
* All Rights Reserved |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation, either version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
|
||||
#include <stdio.h> |
||||
#include <stdint.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include <errno.h> |
||||
#include <math.h> |
||||
#include "../libsample/sample.h" |
||||
#include "am.h" |
||||
|
||||
static int has_init = 0; |
||||
static int fast_math = 0; |
||||
static float *sin_tab = NULL, *cos_tab = NULL; |
||||
|
||||
/* global init */ |
||||
int am_init(int _fast_math) |
||||
{ |
||||
fast_math = _fast_math; |
||||
|
||||
if (fast_math) { |
||||
int i; |
||||
|
||||
sin_tab = calloc(65536+16384, sizeof(*sin_tab)); |
||||
if (!sin_tab) { |
||||
fprintf(stderr, "No mem!\n"); |
||||
return -ENOMEM; |
||||
} |
||||
cos_tab = sin_tab + 16384; |
||||
|
||||
/* generate sine and cosine */ |
||||
for (i = 0; i < 65536+16384; i++) |
||||
sin_tab[i] = sin(2.0 * M_PI * (double)i / 65536.0); |
||||
} |
||||
|
||||
has_init = 1; |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/* global exit */ |
||||
void am_exit(void) |
||||
{ |
||||
if (sin_tab) { |
||||
free(sin_tab); |
||||
sin_tab = cos_tab = NULL; |
||||
} |
||||
|
||||
has_init = 0; |
||||
} |
||||
|
||||
#define CARRIER_FILTER 30.0 |
||||
|
||||
/* Amplitude modulation in SDR:
|
||||
* Just use the base band (audio signal) as real value, and 0.0 as imaginary |
||||
* value. The you have two side bands. Be sure to have a DC level, so you |
||||
* have a carrier. |
||||
*/ |
||||
|
||||
int am_mod_init(am_mod_t *mod, double samplerate, double offset, double gain, double bias) |
||||
{ |
||||
memset(mod, 0, sizeof(*mod)); |
||||
mod->gain = gain; |
||||
mod->bias = bias; |
||||
if (fast_math) |
||||
mod->rot = 65536.0 * offset / samplerate; |
||||
else |
||||
mod->rot = 2.0 * M_PI * offset / samplerate; |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
void am_mod_exit(am_mod_t __attribute__((unused)) *mod) |
||||
{ |
||||
} |
||||
|
||||
void am_modulate_complex(am_mod_t *mod, sample_t *amplitude, uint8_t *power, int num, float *baseband) |
||||
{ |
||||
int s; |
||||
double vector; |
||||
double rot = mod->rot; |
||||
double phase = mod->phase; |
||||
double gain = mod->gain; |
||||
double bias = mod->bias; |
||||
|
||||
for (s = 0; s < num; s++) { |
||||
if (*power++) |
||||
vector = *amplitude++ * gain + bias; |
||||
else |
||||
vector = 0.0; |
||||
if (fast_math) { |
||||
*baseband++ += cos_tab[(uint16_t)phase] * vector; |
||||
*baseband++ += sin_tab[(uint16_t)phase] * vector; |
||||
phase += rot; |
||||
if (phase < 0.0) |
||||
phase += 65536.0; |
||||
else if (phase >= 65536.0) |
||||
phase -= 65536.0; |
||||
} else { |
||||
*baseband++ += cos(phase) * vector; |
||||
*baseband++ += sin(phase) * vector; |
||||
phase += rot; |
||||
if (phase < 0.0) |
||||
phase += 2.0 * M_PI; |
||||
else if (phase >= 2.0 * M_PI) |
||||
phase -= 2.0 * M_PI; |
||||
} |
||||
} |
||||
|
||||
mod->phase = phase; |
||||
} |
||||
|
||||
/* init AM demodulator */ |
||||
int am_demod_init(am_demod_t *demod, double samplerate, double offset, double bandwidth, double gain) |
||||
{ |
||||
memset(demod, 0, sizeof(*demod)); |
||||
demod->gain = gain; |
||||
if (fast_math) |
||||
demod->rot = 65536.0 * -offset / samplerate; |
||||
else |
||||
demod->rot = 2 * M_PI * -offset / samplerate; |
||||
|
||||
/* use fourth order (2 iter) filter, since it is as fast as second order (1 iter) filter */ |
||||
iir_lowpass_init(&demod->lp[0], bandwidth, samplerate, 2); |
||||
iir_lowpass_init(&demod->lp[1], bandwidth, samplerate, 2); |
||||
|
||||
/* filter carrier */ |
||||
iir_lowpass_init(&demod->lp[2], CARRIER_FILTER, samplerate, 1); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
void am_demod_exit(am_demod_t __attribute__((unused)) *demod) |
||||
{ |
||||
} |
||||
|
||||
/* do amplitude demodulation of baseband and write them to samples */ |
||||
void am_demodulate_complex(am_demod_t *demod, sample_t *amplitude, int length, float *baseband, sample_t *I, sample_t *Q, sample_t *carrier) |
||||
{ |
||||
int s, ss; |
||||
double rot = demod->rot; |
||||
double phase = demod->phase; |
||||
double gain = demod->gain; |
||||
double i, q; |
||||
double _sin, _cos; |
||||
|
||||
/* rotate spectrum */ |
||||
for (s = 0, ss = 0; s < length; s++) { |
||||
i = baseband[ss++]; |
||||
q = baseband[ss++]; |
||||
phase += rot; |
||||
if (fast_math) { |
||||
if (phase < 0.0) |
||||
phase += 65536.0; |
||||
else if (phase >= 65536.0) |
||||
phase -= 65536.0; |
||||
_sin = sin_tab[(uint16_t)phase]; |
||||
_cos = cos_tab[(uint16_t)phase]; |
||||
} else { |
||||
if (phase < 0.0) |
||||
phase += 2.0 * M_PI; |
||||
else if (phase >= 2.0 * M_PI) |
||||
phase -= 2.0 * M_PI; |
||||
_sin = sin(phase); |
||||
_cos = cos(phase); |
||||
} |
||||
I[s] = i * _cos - q * _sin; |
||||
Q[s] = i * _sin + q * _cos; |
||||
} |
||||
demod->phase = phase; |
||||
|
||||
/* filter bandwidth */ |
||||
iir_process(&demod->lp[0], I, length); |
||||
iir_process(&demod->lp[1], Q, length); |
||||
|
||||
/* demod */ |
||||
for (s = 0; s < length; s++) |
||||
amplitude[s] = carrier[s] = sqrt(I[s] * I[s] + Q[s] * Q[s]); |
||||
|
||||
/* filter carrier */ |
||||
iir_process(&demod->lp[2], carrier, length); |
||||
|
||||
/* normalize */ |
||||
for (s = 0; s < length; s++) |
||||
amplitude[s] = (amplitude[s] - carrier[s]) / carrier[s] * gain; |
||||
} |
||||
|
@ -1,28 +0,0 @@ |
||||
#include "../libfilter/iir_filter.h" |
||||
|
||||
int am_init(int fast_math); |
||||
void am_exit(void); |
||||
|
||||
typedef struct am_mod { |
||||
double rot; /* angle to rotate vector per sample */ |
||||
double phase; /* current phase */ |
||||
double gain; /* gain to be multiplied to amplitude */ |
||||
double bias; /* DC offset to add (carrier amplitude) */ |
||||
} am_mod_t; |
||||
|
||||
int am_mod_init(am_mod_t *mod, double samplerate, double offset, double gain, double bias); |
||||
void am_mod_exit(am_mod_t *mod); |
||||
void am_modulate_complex(am_mod_t *mod, sample_t *amplitude, uint8_t *power, int num, float *baseband); |
||||
|
||||
typedef struct am_demod { |
||||
double rot; /* angle to rotate vector per sample */ |
||||
double phase; /* current rotation phase (used to shift) */ |
||||
iir_filter_t lp[3]; /* filters received IQ signal/carrier */ |
||||
double gain; /* gain to be expected from amplitude */ |
||||
double bias; /* DC offset to be expected (carrier amplitude) */ |
||||
} am_demod_t; |
||||
|
||||
int am_demod_init(am_demod_t *demod, double samplerate, double offset, double gain, double bias); |
||||
void am_demod_exit(am_demod_t *demod); |
||||
void am_demodulate_complex(am_demod_t *demod, sample_t *amplitude, int length, float *baseband, sample_t *I, sample_t *Q, sample_t *carrier); |
||||
|
@ -1,6 +0,0 @@ |
||||
AM_CPPFLAGS = -Wall -Wextra -g $(all_includes)
|
||||
|
||||
noinst_LIBRARIES = libclipper.a
|
||||
|
||||
libclipper_a_SOURCES = \
|
||||
clipper.c
|
@ -1,81 +0,0 @@ |
||||
/* Clipper implementation, based on code by Jonathan Olds
|
||||
* |
||||
* (C) 2017 by Andreas Eversberg <jolly@eversberg.eu> |
||||
* All Rights Reserved |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation, either version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
|
||||
#include <stdio.h> |
||||
#include <math.h> |
||||
#include <stdint.h> |
||||
#include <stdlib.h> |
||||
#include "../libsample/sample.h" |
||||
#include "clipper.h" |
||||
|
||||
static double clipper_lut[6000]; |
||||
|
||||
static double clipper_point = NAN; |
||||
|
||||
void clipper_init(double point) |
||||
{ |
||||
double a; |
||||
int i; |
||||
|
||||
if (point > 0.99) |
||||
point = 0.99; |
||||
if (point < 0.01) |
||||
point = 0.01; |
||||
clipper_point = point; |
||||
|
||||
a = M_PI / (2.0 * (1.0 - clipper_point)); |
||||
|
||||
for (i = 0; i < 6000; i++) |
||||
clipper_lut[i] = clipper_point + atan(a * i / 1000.0) / a; |
||||
} |
||||
|
||||
void clipper_process(sample_t *samples, int length) |
||||
{ |
||||
int i; |
||||
double val, inv, shiftmultval; |
||||
int n, q; |
||||
|
||||
if (isnan(clipper_point)) { |
||||
fprintf(stderr, "Clipper not initialized, aborting!\n"); |
||||
abort(); |
||||
} |
||||
|
||||
for (i = 0; i < length; i++) { |
||||
val = samples[i]; |
||||
if (val < 0) { |
||||
inv = -1.0; |
||||
val = -val; |
||||
} else |
||||
inv = 1.0; |
||||
shiftmultval = (val - clipper_point) * 1000.0; |
||||
/* no clipping up to clipping point */ |
||||
if (shiftmultval <= 0.0) |
||||
continue; |
||||
n = (int)shiftmultval; |
||||
q = n + 1; |
||||
if (q >= 6000) { |
||||
samples[i] = inv; |
||||
continue; |
||||
} |
||||
/* get clipped value from lut, interpolate between table entries */ |
||||
val = clipper_lut[n] + (shiftmultval - (double)n) * (clipper_lut[q] - clipper_lut[n]); |
||||
samples[i] = val * inv; |
||||
} |
||||
} |
||||
|
@ -1,4 +0,0 @@ |
||||
|
||||
void clipper_init(double point); |
||||
void clipper_process(sample_t *samples, int length); |
||||
|
@ -1,6 +0,0 @@ |
||||
AM_CPPFLAGS = -Wall -Wextra -g $(all_includes)
|
||||
|
||||
noinst_LIBRARIES = libcompandor.a
|
||||
|
||||
libcompandor_a_SOURCES = \
|
||||
compandor.c
|
@ -1,141 +0,0 @@ |
||||
/* Compandor to use various networks like C-Netz / NMT / AMPS / TACS
|
||||
* |
||||
* (C) 2016 by Andreas Eversberg <jolly@eversberg.eu> |
||||
* All Rights Reserved |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation, either version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
|
||||
#include <stdio.h> |
||||
#include <stdint.h> |
||||
#include <string.h> |
||||
#include <math.h> |
||||
#include "../libsample/sample.h" |
||||
#include "compandor.h" |
||||
|
||||
//#define db2level(db) pow(10, (double)db / 20.0)
|
||||
|
||||
/* factor is the gain (raise and fall) after given attack/recovery time */ |
||||
#define COMPRESS_ATTACK_FACTOR 1.83 /* about 1.5 after 12 dB step up */ |
||||
#define COMPRESS_RECOVERY_FACTOR 0.44 /* about 0.75 after 12 dB step down */ |
||||
#define EXPAND_ATTACK_FACTOR 1.145 /* about 0.57 after 6 dB step up */ |
||||
#define EXPAND_RECOVERY_FACTOR 0.753 /* about 1.51 after 6 dB step down */ |
||||
|
||||
/* Minimum level value to keep state (-60 dB) */ |
||||
#define ENVELOPE_MIN 0.001 |
||||
|
||||
/* Maximum level, to prevent sqrt_tab to overflow */ |
||||
#define ENVELOPE_MAX 9.990 |
||||
|
||||
static double sqrt_tab[10000]; |
||||
|
||||
/*
|
||||
* Init compandor according to ITU-T G.162 specification |
||||
* |
||||
* Hopefully this is correct |
||||
* |
||||
*/ |
||||
void init_compandor(compandor_t *state, double samplerate, double attack_ms, double recovery_ms) |
||||
{ |
||||
int i; |
||||
|
||||
memset(state, 0, sizeof(*state)); |
||||
|
||||
state->c.peak = 1.0; |
||||
state->c.envelope = 1.0; |
||||
state->e.peak = 1.0; |
||||
state->e.envelope = 1.0; |
||||
state->c.step_up = pow(COMPRESS_ATTACK_FACTOR, 1000.0 / attack_ms / samplerate); |
||||
state->c.step_down = pow(COMPRESS_RECOVERY_FACTOR, 1000.0 / recovery_ms / samplerate); |
||||
state->e.step_up = pow(EXPAND_ATTACK_FACTOR, 1000.0 / attack_ms / samplerate); |
||||
state->e.step_down = pow(EXPAND_RECOVERY_FACTOR, 1000.0 / recovery_ms / samplerate); |
||||
|
||||
// FIXME: make global, not at instance
|
||||
for (i = 0; i < 10000; i++) |
||||
sqrt_tab[i] = sqrt(i * 0.001); |
||||
} |
||||
|
||||
void compress_audio(compandor_t *state, sample_t *samples, int num) |
||||
{ |
||||
double value, peak, envelope, step_up, step_down; |
||||
int i; |
||||
|
||||
step_up = state->c.step_up; |
||||
step_down = state->c.step_down; |
||||
peak = state->c.peak; |
||||
envelope = state->c.envelope; |
||||
|
||||
// printf("envelope=%.4f\n", envelope);
|
||||
for (i = 0; i < num; i++) { |
||||
value = *samples; |
||||
|
||||
/* 'peak' is the level that raises directly with the signal
|
||||
* level, but falls with specified recovery rate. */ |
||||
if (fabs(value) > peak) |
||||
peak = fabs(value); |
||||
else |
||||
peak *= step_down; |
||||
/* 'evelope' is the level that raises with the specified attack
|
||||
* rate to 'peak', but falls with specified recovery rate. */ |
||||
if (peak > envelope) |
||||
envelope *= step_up; |
||||
else |
||||
envelope = peak; |
||||
if (envelope < ENVELOPE_MIN) |
||||
envelope = ENVELOPE_MIN; |
||||
if (envelope > ENVELOPE_MAX) |
||||
envelope = ENVELOPE_MAX; |
||||
|
||||
*samples++ = value / sqrt_tab[(int)(envelope / 0.001)]; |
||||
//if (i > 47000.0 && i < 48144)
|
||||
//printf("time=%.4f envelope=%.4fdb, value=%.4f\n", (double)i/48000.0, 20*log10(envelope), value);
|
||||
} |
||||
//exit(0);
|
||||
|
||||
state->c.envelope = envelope; |
||||
state->c.peak = peak; |
||||
} |
||||
|
||||
void expand_audio(compandor_t *state, sample_t *samples, int num) |
||||
{ |
||||
double value, peak, envelope, step_up, step_down; |
||||
int i; |
||||
|
||||
step_up = state->e.step_up; |
||||
step_down = state->e.step_down; |
||||
peak = state->e.peak; |
||||
envelope = state->e.envelope; |
||||
|
||||
for (i = 0; i < num; i++) { |
||||
value = *samples; |
||||
|
||||
/* for comments: see compress_audio() */ |
||||
if (fabs(value) > peak) |
||||
peak = fabs(value); |
||||
else |
||||
peak *= step_down; |
||||
if (peak > envelope) |
||||
envelope *= step_up; |
||||
else |
||||
envelope = peak; |
||||
if (envelope < ENVELOPE_MIN) |
||||
envelope = ENVELOPE_MIN; |
||||
|
||||
*samples++ = value * envelope; |
||||
} |
||||
|
||||
state->e.envelope = envelope; |
||||
state->e.peak = peak; |
||||
} |
||||
|
@ -1,20 +0,0 @@ |
||||
|
||||
typedef struct compandor { |
||||
struct { |
||||
double step_up; |
||||
double step_down; |
||||
double peak; |
||||
double envelope; |
||||
} c; |
||||
struct { |
||||
double step_up; |
||||
double step_down; |
||||
double peak; |
||||
double envelope; |
||||
} e; |
||||
} compandor_t; |
||||
|
||||
void init_compandor(compandor_t *state, double samplerate, double attack_ms, double recovery_ms); |
||||
void compress_audio(compandor_t *state, sample_t *samples, int num); |
||||
void expand_audio(compandor_t *state, sample_t *samples, int num); |
||||
|
@ -1,7 +0,0 @@ |
||||
AM_CPPFLAGS = -Wall -Wextra -g $(all_includes)
|
||||
|
||||
noinst_LIBRARIES = libdebug.a
|
||||
|
||||
libdebug_a_SOURCES = \
|
||||
debug.c
|
||||
|
@ -1,325 +0,0 @@ |
||||
/* Simple debug functions for level and category filtering
|
||||
* |
||||
* (C) 2016 by Andreas Eversberg <jolly@eversberg.eu> |
||||
* All Rights Reserved |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation, either version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
|
||||
#include <stdarg.h> |
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
#include <stdlib.h> |
||||
#include <stdint.h> |
||||
#include <errno.h> |
||||
#include <math.h> |
||||
#include <time.h> |
||||
#include <pthread.h> |
||||
#include <sys/ioctl.h> |
||||
#include <sys/time.h> |
||||
#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" }, |
||||
{ 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 <level> | <level>,<category>[,<category>[,...]] | 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; |
||||
} |
||||
|
@ -1,80 +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 |
||||
|
||||
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); |
||||
|
@ -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 |
||||
|
@ -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); |
||||
|
@ -1,282 +0,0 @@ |
||||
/* display IQ data form functions
|
||||
* |
||||
* (C) 2016 by Andreas Eversberg <jolly@eversberg.eu> |
||||
* All Rights Reserved |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation, either version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
|
||||
#include <stdio.h> |
||||
#include <stdint.h> |
||||
#include <string.h> |
||||
#include <math.h> |
||||
#include <pthread.h> |
||||
#include <stdlib.h> |
||||
#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 |