kopia lustrzana https://github.com/rs1729/RS
iq_svcl: test -> master (FFT csv)
rodzic
22ef6e1370
commit
2ce01d8b9a
|
@ -23,16 +23,23 @@ receive IF stream from baseband IQ via TCP, default `PORT=1280 (iq_svcl.h)`<br /
|
||||||
`-0.5 < fq < 0.5`: (relative) frequency, `fq=frequency/sr` <br />
|
`-0.5 < fq < 0.5`: (relative) frequency, `fq=frequency/sr` <br />
|
||||||
`<if_sr>`: IF sample rate <br />
|
`<if_sr>`: IF sample rate <br />
|
||||||
`<bo>=8,16,32`: output/IF bits per (real) sample (u8, s16 or f32) <br />
|
`<bo>=8,16,32`: output/IF bits per (real) sample (u8, s16 or f32) <br />
|
||||||
down-converts up to `MAX_FQ=(4+1) (iq_base.h)` channels/signals. More signals than number of CPUs/cores is not recommended.<br />
|
down-converts up to `MAX_FQ=(4+1) (iq_base.h)` channels/signals. (On older CPUs, more signals than number of CPU cores is not recommended.)<br />
|
||||||
(Note: If the baseband sample rate has no appropriate factors (e.g. if prime), the IF sample rate might be high and IF-processing slow.)<br />
|
(Note: If the baseband sample rate has no appropriate factors (e.g. if prime), the IF sample rate might be high and IF-processing slow.)<br />
|
||||||
One channel can be used for scanning, `--fft <fft.txt>` makes FFT (2 seconds average).
|
One channel can be used for scanning, e.g. `./iq_server --fft_avg <m> <fft_avg.csv>` makes *m* rows of avg-FFT (FFT_AVG=2 seconds average), and
|
||||||
The FFT is saved in `<fft.txt>` as `<fq>;<dB>`, approx. 200 Hz per bin.<br />
|
this channel will be reused for client FFT requests. Only one channel/thread can be used for FFT/scanning. A client can request a new FFT,
|
||||||
|
if the last FFT has finished.<br />
|
||||||
|
There are two kinds of FFTs, `fft_all` and `fft_avg`. `fft_avg` integrates over FFT_AVG=2 seconds and can be used for signal peak scanning.
|
||||||
|
For waterfall display, `--fft_all <m> <fft_all.csv>` produces *m*\*FFT_AVG\*FFT_FPS/2 rows of FFT (FFT_AVG seconds, FFT_FPS/2 per sec).
|
||||||
|
The FFT is saved in `<fft.csv>` as<br />
|
||||||
|
`sec.ms,freq_min,freq_max,Hz/bin,N_bins, db_1,...,db_N`<br />
|
||||||
|
approx. 200 Hz per bin.
|
||||||
|
Choose `filename="-"` for `stdout`.<br />
|
||||||
If no output bps is chosen (`--bo [8,16,32]`), the IF bps is equal to the baseband bps. It is recommended to use
|
If no output bps is chosen (`--bo [8,16,32]`), the IF bps is equal to the baseband bps. It is recommended to use
|
||||||
`--bo 32` (i.e. float32) output, then no quantization noise is introduced when converting from internal float32 samples.<br />
|
`--bo 32` (i.e. float32) output, then no quantization noise is introduced when converting from internal float32 samples.<br />
|
||||||
|
|
||||||
- Ex.2<br />
|
- Ex.2<br />
|
||||||
[terminal 1]<br />
|
[terminal 1]<br />
|
||||||
`T1$ rtl_sdr -f 403.0M -s 1920000 - | ./iq_server --fft fft_server.txt --bo 32 - 1920000 8`<br />
|
`T1$ rtl_sdr -f 403.0M -s 1920000 - | ./iq_server --fft_avg 1 fft_server.csv --bo 32 - 1920000 8`<br />
|
||||||
[terminal 2]<br />
|
[terminal 2]<br />
|
||||||
`T2$ ./iq_client --freq -0.3125 | ./m10mod -c -vv --IQ 0.0 - 48000 32`<br />
|
`T2$ ./iq_client --freq -0.3125 | ./m10mod -c -vv --IQ 0.0 - 48000 32`<br />
|
||||||
[terminal 3]<br />
|
[terminal 3]<br />
|
||||||
|
@ -41,7 +48,17 @@ receive IF stream from baseband IQ via TCP, default `PORT=1280 (iq_svcl.h)`<br /
|
||||||
`T4$ ./iq_client -1` (*close channel 1*)<br />
|
`T4$ ./iq_client -1` (*close channel 1*)<br />
|
||||||
`T4$ ./iq_client --stop` (*close all clients and stop server*)<br />
|
`T4$ ./iq_client --stop` (*close all clients and stop server*)<br />
|
||||||
|
|
||||||
The `iq_server` `--fft` option immediately starts reading the IQ stream (so buffering is reduced).<br />
|
- The `iq_server` FFT options immediately start reading the IQ stream (so buffering is reduced).<br />
|
||||||
`./iq_client --fft <fft_cl.txt>` can also request FFT.<br />
|
`./iq_client <fft_opt> <m> <fft_cl.txt>`, where `<fft_opt>=--fft_avg_cl` or `--fft_all_cl`, requests FFT from the server.<br />
|
||||||
The IF sample rate `if_sr` is at least 48000 such that the baseband sample rate `sr` is a multiple of `if_sr`.
|
(`<fft_opt>=--fft_avg_sv/--fft_all_sv` would save the FFT at the server, but only if `./iq_server --enable_clsv_out`.)<br />
|
||||||
|
The IF sample rate `if_sr` is at least 48000 and such that the baseband sample rate `sr` is a multiple of `if_sr`.
|
||||||
|
|
||||||
|
- Ex.3<br />
|
||||||
|
[terminal 1]<br />
|
||||||
|
`T1$ rtl_sdr -f 404550k -s 2048000 - | ./iq_server --fft_avg 1 fft_avg.csv --bo 32 - 2048000 8`<br />
|
||||||
|
(scan FFT: `./scan_fft fft_avg.csv`)<br />
|
||||||
|
[terminal 3]<br />
|
||||||
|
`T3$ ./iq_client --fft_all_cl -1 - | python plot_fft_ani.py 3 -`<br />
|
||||||
|
![FFT image](fft3-1.png "FFT")
|
||||||
|
|
||||||
|
|
||||||
|
|
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 212 KiB |
|
@ -34,7 +34,10 @@ typedef struct {
|
||||||
double xlt_fq;
|
double xlt_fq;
|
||||||
float complex *blk;
|
float complex *blk;
|
||||||
int used;
|
int used;
|
||||||
|
//
|
||||||
int fft;
|
int fft;
|
||||||
|
int stop_fft;
|
||||||
|
int fft_num;
|
||||||
} thd_t;
|
} thd_t;
|
||||||
|
|
||||||
|
|
||||||
|
@ -97,6 +100,7 @@ typedef struct {
|
||||||
thd_t thd;
|
thd_t thd;
|
||||||
int fd;
|
int fd;
|
||||||
char *fname;
|
char *fname;
|
||||||
|
FILE *fpo;
|
||||||
} thargs_t;
|
} thargs_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,27 @@
|
||||||
*
|
*
|
||||||
* gcc -O2 iq_client.c -o iq_client
|
* gcc -O2 iq_client.c -o iq_client
|
||||||
*
|
*
|
||||||
|
* usage:
|
||||||
|
* (request IF IQ samples)
|
||||||
|
* ./iq_client [--ip <ip_adr>] [--port <pn>] --freq <fq> # -0.5 < fq < 0.5
|
||||||
|
*
|
||||||
|
* (request FFT)
|
||||||
|
* ./iq_client <fft_opt> <m> <filename> # FFT csv output
|
||||||
|
* <fft_opt>:
|
||||||
|
* --fft_avg_cl # client out
|
||||||
|
* --fft_all_cl # client out
|
||||||
|
* --fft_avg_sv # server out (if iq_server --enable_clsv_out)
|
||||||
|
* --fft_avg_sv # server out (if iq_server --enable_clsv_out)
|
||||||
|
* <m>:
|
||||||
|
* _avg_: m avg-FFTs
|
||||||
|
* _all_: m*FFT_FPS/2 FFTs
|
||||||
|
* m = -1 : continuous FFT output
|
||||||
|
* <filename>:
|
||||||
|
* csv filename ("-": stdout)
|
||||||
|
*
|
||||||
|
* ./iq_client -<n> # close client <n>
|
||||||
|
* ./iq_client --stop # close all clients, stop server
|
||||||
|
*
|
||||||
* author: zilog80
|
* author: zilog80
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -49,17 +70,24 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
else serv_port = port;
|
else serv_port = port;
|
||||||
}
|
}
|
||||||
else if (strcmp(*argv, "--fft0") == 0) {
|
else if (strncmp(*argv, "--fft", 5) == 0) {
|
||||||
sprintf(sendln, "%s", "--fft0");
|
char *arg_fft = *argv;
|
||||||
}
|
int fft_num = 0;
|
||||||
else if (strcmp(*argv, "--fft") == 0) {
|
int opt_fft_cl = 0;
|
||||||
sprintf(sendln, "%s", "--fft");
|
if (strncmp(arg_fft+5, "_avg", 4) == 0) opt_fft_cl = OPT_FFT_AVG;
|
||||||
++argv;
|
else if (strncmp(arg_fft+5, "_all", 4) != 0) return -1;
|
||||||
if (*argv) {
|
if (strncmp(arg_fft+5+4, "_cl", 3) == 0) {
|
||||||
fname_fft = *argv;
|
opt_fft_cl |= OPT_FFT_CLNT;
|
||||||
|
re = 2;
|
||||||
}
|
}
|
||||||
|
else if (strncmp(arg_fft+5+4, "_sv", 3) == 0) opt_fft_cl |= OPT_FFT_SERV;
|
||||||
else return -1;
|
else return -1;
|
||||||
re = 2;
|
++argv;
|
||||||
|
if (*argv) fft_num = atoi(*argv); else return -1;
|
||||||
|
++argv;
|
||||||
|
if (*argv) fname_fft = *argv; else return -1;
|
||||||
|
//sprintf(sendln, "%s_%s_%s", "--fft", (opt_fft_cl & OPT_FFT_AVG) ? "avg" : "all", (opt_fft_cl & OPT_FFT_CLNT) ? "cl" : "sv");
|
||||||
|
sprintf(sendln, "%s %d %s", arg_fft, fft_num, fname_fft);
|
||||||
}
|
}
|
||||||
else if (strcmp(*argv, "--freq") == 0) {
|
else if (strcmp(*argv, "--freq") == 0) {
|
||||||
++argv;
|
++argv;
|
||||||
|
@ -155,7 +183,9 @@ int main(int argc, char *argv[]) {
|
||||||
else if ( re == 2 )
|
else if ( re == 2 )
|
||||||
{
|
{
|
||||||
// fft data
|
// fft data
|
||||||
FILE *fpo = fopen(fname_fft, "wb");
|
FILE *fpo = NULL;
|
||||||
|
if (fname_fft[0] == '-') fpo = stdout;
|
||||||
|
else fpo = fopen(fname_fft, "wb");
|
||||||
if (fpo != NULL) {
|
if (fpo != NULL) {
|
||||||
|
|
||||||
memset(recvln, 0, LINELEN+1);
|
memset(recvln, 0, LINELEN+1);
|
||||||
|
|
|
@ -7,6 +7,24 @@
|
||||||
*
|
*
|
||||||
* (gcc -O2 iq_client.c -o iq_client)
|
* (gcc -O2 iq_client.c -o iq_client)
|
||||||
*
|
*
|
||||||
|
* usage:
|
||||||
|
* ./iq_server [--enable_clsv_out] [--port <pn>] [iq_baseband.wav]
|
||||||
|
* no wav-file: stdin
|
||||||
|
*
|
||||||
|
* ./iq_server [--bo <b>] - <sr> <bs> [iq_baseband.raw]
|
||||||
|
* <b>=8,16,32 bit client/IF output
|
||||||
|
*
|
||||||
|
* ./iq_server <fft_opt> <m> <filename> [iq_baseband.wav] # FFT csv output
|
||||||
|
* <fft_opt>:
|
||||||
|
* --fft_avg
|
||||||
|
* --fft_all
|
||||||
|
* <m>:
|
||||||
|
* _avg: m avg-FFTs
|
||||||
|
* _all: m*FFT_FPS/2 FFTs
|
||||||
|
* m = -1 : continuous FFT output
|
||||||
|
* <filename>:
|
||||||
|
* csv filename ("-": stdout)
|
||||||
|
*
|
||||||
* author: zilog80
|
* author: zilog80
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -27,13 +45,13 @@
|
||||||
#include "iq_svcl.h"
|
#include "iq_svcl.h"
|
||||||
#include "iq_base.h"
|
#include "iq_base.h"
|
||||||
|
|
||||||
|
#define FFT_AVG 2 // fft_avg: integrate FFT_AVG seconds, 2*FFT_FPS FFTs
|
||||||
|
#define FFT_FPS 16 // fft_all: output (ca.) FFT_FPS/2 per sec
|
||||||
|
|
||||||
#define FPOUT stderr
|
#define FPOUT stderr
|
||||||
|
|
||||||
#define OPT_FFT_SERV 1 // server
|
|
||||||
#define OPT_FFT_CLSV 2 // server (client request)
|
|
||||||
#define OPT_FFT_CLNT 3 // server -> client
|
|
||||||
|
|
||||||
static int option_dbg = 0;
|
static int option_dbg = 0;
|
||||||
|
static int option_clsv_out = 0;
|
||||||
|
|
||||||
static int tcp_eof = 0;
|
static int tcp_eof = 0;
|
||||||
|
|
||||||
|
@ -275,21 +293,82 @@ static void *thd_IF(void *targs) { // pcm_t *pcm, double xlt_fq
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FFT_SEC 2
|
|
||||||
#define FFT_FPS 20
|
static int fft_txt_prn(FILE *fpo, dft_t *dft, float *db) {
|
||||||
|
int j;
|
||||||
|
|
||||||
|
fprintf(fpo, "# <freq/sr>;<dB> ## sr:%d , N:%d\n", dft->sr, dft->N);
|
||||||
|
for (j = dft->N/2; j < dft->N/2 + dft->N; j++) {
|
||||||
|
fprintf(fpo, "%+11.8f;%7.2f\n", bin2fq(dft, j % dft->N), db[j % dft->N]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fft_txt_tcp(int fd, dft_t *dft, float *db) {
|
||||||
|
char sendln[LINELEN+1];
|
||||||
|
int sendln_len;
|
||||||
|
int j, l;
|
||||||
|
|
||||||
|
snprintf(sendln, LINELEN, "# <freq/sr>;<dB> ## sr:%d , N:%d\n", dft->sr, dft->N);
|
||||||
|
sendln_len = strlen(sendln);
|
||||||
|
l = write(fd, sendln, sendln_len);
|
||||||
|
for (j = dft->N/2; j < dft->N/2 + dft->N; j++) {
|
||||||
|
memset(sendln, 0, LINELEN+1);
|
||||||
|
snprintf(sendln, LINELEN, "%+11.8f;%7.2f\n", bin2fq(dft, j % dft->N), db[j % dft->N]);
|
||||||
|
sendln_len = strlen(sendln);
|
||||||
|
l = write(fd, sendln, sendln_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int fft_csv_prn(FILE *fpo, dft_t *dft, float *db, double t_sec) {
|
||||||
|
int j;
|
||||||
|
|
||||||
|
fprintf(fpo, "%7.3f, ", t_sec);
|
||||||
|
fprintf(fpo, "%d, %d, ", (int)bin2freq(dft, dft->N/2), (int)bin2freq(dft, dft->N/2 - 1));
|
||||||
|
fprintf(fpo, "%.2f, ", dft->sr/(double)dft->N);
|
||||||
|
fprintf(fpo, "%d, ", dft->N);
|
||||||
|
for (j = dft->N/2; j < dft->N/2 + dft->N; j++) {
|
||||||
|
fprintf(fpo, "%7.2f%c", db[j % dft->N], j < dft->N/2 + dft->N-1 ? ',' : '\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fft_csv_tcp(int fd, dft_t *dft, float *db, double t_sec) {
|
||||||
|
char sendln[LINELEN+1];
|
||||||
|
int sendln_len;
|
||||||
|
int j, l;
|
||||||
|
|
||||||
|
snprintf(sendln, LINELEN, "%7.3f, %d, %d, %.2f, %d, ",
|
||||||
|
t_sec, (int)bin2freq(dft, dft->N/2), (int)bin2freq(dft, dft->N/2 - 1), dft->sr/(double)dft->N, dft->N);
|
||||||
|
sendln_len = strlen(sendln);
|
||||||
|
l = write(fd, sendln, sendln_len);
|
||||||
|
for (j = dft->N/2; j < dft->N/2 + dft->N; j++) {
|
||||||
|
memset(sendln, 0, LINELEN+1);
|
||||||
|
snprintf(sendln, LINELEN, "%7.2f%c", db[j % dft->N], j < dft->N/2 + dft->N-1 ? ',' : '\n');
|
||||||
|
sendln_len = strlen(sendln);
|
||||||
|
l = write(fd, sendln, sendln_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *thd_FFT(void *targs) {
|
static void *thd_FFT(void *targs) {
|
||||||
|
|
||||||
thargs_t *tharg = targs;
|
thargs_t *tharg = targs;
|
||||||
pcm_t *pcm = &(tharg->pcm);
|
pcm_t *pcm = &(tharg->pcm);
|
||||||
|
|
||||||
FILE *fpo = NULL;
|
|
||||||
char *fname_fft = "db_fft.txt";
|
|
||||||
|
|
||||||
int k;
|
int k;
|
||||||
int bitQ = 0;
|
int bitQ = 0;
|
||||||
|
|
||||||
float complex *z = NULL;
|
float complex *z = NULL;
|
||||||
|
float *db = NULL;
|
||||||
|
float *all_rZ = NULL;
|
||||||
float *avg_rZ = NULL;
|
float *avg_rZ = NULL;
|
||||||
float *avg_db = NULL;
|
float *avg_db = NULL;
|
||||||
|
|
||||||
|
@ -312,7 +391,6 @@ static void *thd_FFT(void *targs) {
|
||||||
dsp.bps_out = pcm->bps_out;
|
dsp.bps_out = pcm->bps_out;
|
||||||
|
|
||||||
|
|
||||||
//(dsp.thd)->fft = 1;
|
|
||||||
if (option_dbg) {
|
if (option_dbg) {
|
||||||
fprintf(stderr, "init FFT buffers\n");
|
fprintf(stderr, "init FFT buffers\n");
|
||||||
}
|
}
|
||||||
|
@ -326,6 +404,8 @@ static void *thd_FFT(void *targs) {
|
||||||
|
|
||||||
z = calloc(dsp.decM+1, sizeof(float complex)); if (z == NULL) goto exit_thread;
|
z = calloc(dsp.decM+1, sizeof(float complex)); if (z == NULL) goto exit_thread;
|
||||||
|
|
||||||
|
db = calloc(dsp.DFT.N+1, sizeof(float)); if (db == NULL) goto exit_thread;
|
||||||
|
all_rZ = calloc(dsp.DFT.N+1, sizeof(float)); if (all_rZ == NULL) goto exit_thread;
|
||||||
avg_rZ = calloc(dsp.DFT.N+1, sizeof(float)); if (avg_rZ == NULL) goto exit_thread;
|
avg_rZ = calloc(dsp.DFT.N+1, sizeof(float)); if (avg_rZ == NULL) goto exit_thread;
|
||||||
avg_db = calloc(dsp.DFT.N+1, sizeof(float)); if (avg_db == NULL) goto exit_thread;
|
avg_db = calloc(dsp.DFT.N+1, sizeof(float)); if (avg_db == NULL) goto exit_thread;
|
||||||
|
|
||||||
|
@ -334,12 +414,16 @@ static void *thd_FFT(void *targs) {
|
||||||
int len = dsp.DFT.N / dsp.decM;
|
int len = dsp.DFT.N / dsp.decM;
|
||||||
int mlen = len*dsp.decM;
|
int mlen = len*dsp.decM;
|
||||||
int sum_n = 0;
|
int sum_n = 0;
|
||||||
int sec = FFT_SEC;
|
int sum_fft = 0;
|
||||||
int fft_step = dsp.sr_base/(dsp.DFT.N*FFT_FPS);
|
int avg_sec = FFT_AVG;
|
||||||
|
int fft_step = (int)(dsp.sr_base/(double)(dsp.DFT.N*FFT_FPS) + 0.5);
|
||||||
int n_fft = 0;
|
int n_fft = 0;
|
||||||
int th_used = 0;
|
int th_used = 0;
|
||||||
int readSamples = 1;
|
int readSamples = 1;
|
||||||
|
|
||||||
|
int n_out = 0;
|
||||||
|
|
||||||
|
|
||||||
bitQ = 0;
|
bitQ = 0;
|
||||||
while ( bitQ != EOF )
|
while ( bitQ != EOF )
|
||||||
{
|
{
|
||||||
|
@ -367,65 +451,95 @@ static void *thd_FFT(void *targs) {
|
||||||
n++;
|
n++;
|
||||||
if (n == len) { // mlen = len * decM <= DFT.N
|
if (n == len) { // mlen = len * decM <= DFT.N
|
||||||
|
|
||||||
n_fft += 1;
|
if ( (dsp.thd)->fft )
|
||||||
|
|
||||||
if ((dsp.thd)->fft && sum_n*n_fft*mlen < sec*dsp.sr_base && n_fft >= fft_step)
|
|
||||||
{
|
{
|
||||||
for (j = 0; j < mlen; j++) {
|
if ((dsp.thd)->fft_num == 0)
|
||||||
dsp.DFT.Z[j] *= dsp.DFT.win[j];
|
{
|
||||||
|
if ( tharg->fpo ) { fclose(tharg->fpo); tharg->fpo = NULL; }
|
||||||
|
else if ( tharg->fd > STDIN_FILENO ) { close(tharg->fd); tharg->fd = -1; }
|
||||||
|
|
||||||
|
(dsp.thd)->fft = 0;
|
||||||
}
|
}
|
||||||
while (j < dsp.DFT.N) dsp.DFT.Z[j++] = 0.0; // dft(Z[...]) != 0
|
|
||||||
|
|
||||||
raw_dft(&(dsp.DFT), dsp.DFT.Z);
|
n_fft += 1;
|
||||||
|
|
||||||
for (j = 0; j < dsp.DFT.N; j++) avg_rZ[j] += cabs(dsp.DFT.Z[j]);
|
if (sum_n*n_fft*mlen < avg_sec*dsp.sr_base && n_fft >= fft_step) {
|
||||||
|
n_fft = fft_step;
|
||||||
|
|
||||||
sum_n++;
|
if (sum_fft == 0) {
|
||||||
n_fft = 0;
|
pthread_mutex_lock( (dsp.thd)->mutex );
|
||||||
}
|
fprintf(FPOUT, "<%d: FFT_START>\n", (dsp.thd)->tn);
|
||||||
if (sum_n*fft_step*mlen >= sec*dsp.sr_base) {
|
pthread_mutex_unlock( (dsp.thd)->mutex );
|
||||||
|
|
||||||
for (j = 0; j < dsp.DFT.N; j++) avg_rZ[j] /= dsp.DFT.N*(float)sum_n;
|
|
||||||
for (j = 0; j < dsp.DFT.N; j++) avg_db[j] = 20.0*log10(avg_rZ[j]+1e-20);
|
|
||||||
|
|
||||||
|
|
||||||
pthread_mutex_lock( (dsp.thd)->mutex );
|
|
||||||
fprintf(FPOUT, "<%d: FFT>\n", (dsp.thd)->tn);
|
|
||||||
pthread_mutex_unlock( (dsp.thd)->mutex );
|
|
||||||
|
|
||||||
if ( (dsp.thd)->fft == OPT_FFT_CLNT ) { // send FFT data to client
|
|
||||||
char sendln[LINELEN+1];
|
|
||||||
int sendln_len;
|
|
||||||
int l;
|
|
||||||
snprintf(sendln, LINELEN, "# <freq/sr>;<dB> ## sr:%d , N:%d\n", dsp.DFT.sr, dsp.DFT.N);
|
|
||||||
sendln_len = strlen(sendln);
|
|
||||||
l = write(tharg->fd, sendln, sendln_len);
|
|
||||||
for (j = dsp.DFT.N/2; j < dsp.DFT.N/2 + dsp.DFT.N; j++) {
|
|
||||||
memset(sendln, 0, LINELEN+1);
|
|
||||||
snprintf(sendln, LINELEN, "%+11.8f;%7.2f\n", bin2fq(&(dsp.DFT), j % dsp.DFT.N), avg_db[j % dsp.DFT.N]);
|
|
||||||
sendln_len = strlen(sendln);
|
|
||||||
l = write(tharg->fd, sendln, sendln_len);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else { // save FFT at server
|
for (j = 0; j < mlen; j++) {
|
||||||
if ( (dsp.thd)->fft == OPT_FFT_SERV ) fname_fft = tharg->fname;
|
dsp.DFT.Z[j] *= dsp.DFT.win[j];
|
||||||
else /* OPT_FFT_CLSV */ fname_fft = "db_fft_cl.txt";
|
}
|
||||||
fpo = fopen(fname_fft, "wb");
|
while (j < dsp.DFT.N) dsp.DFT.Z[j++] = 0.0; // dft(Z[...]) != 0
|
||||||
if (fpo != NULL) {
|
|
||||||
fprintf(fpo, "# <freq/sr>;<dB> ## sr:%d , N:%d\n", dsp.DFT.sr, dsp.DFT.N);
|
raw_dft(&(dsp.DFT), dsp.DFT.Z);
|
||||||
for (j = dsp.DFT.N/2; j < dsp.DFT.N/2 + dsp.DFT.N; j++) {
|
|
||||||
fprintf(fpo, "%+11.8f;%7.2f\n", bin2fq(&(dsp.DFT), j % dsp.DFT.N), avg_db[j % dsp.DFT.N]);
|
for (j = 0; j < dsp.DFT.N; j++) {
|
||||||
|
float rZ = cabs(dsp.DFT.Z[j]);
|
||||||
|
avg_rZ[j] += rZ;
|
||||||
|
all_rZ[j] += rZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (sum_fft&1)==1 && ((dsp.thd)->fft & OPT_FFT_AVG) == 0 ) {
|
||||||
|
double t_sec = sum_fft*n_fft*mlen / (double)dsp.sr_base;
|
||||||
|
for (j = 0; j < dsp.DFT.N; j++) { // if sum_fft odd,
|
||||||
|
db[j] = 20.0*log10(0.5*all_rZ[j]/dsp.DFT.N+1e-20); // 0.5: rZ_0+rZ_1
|
||||||
|
all_rZ[j] = 0.0f;
|
||||||
|
}
|
||||||
|
// sec.ms, freq_min, freq_max, Hz/bin, N_bins, db_1, ..., db_N
|
||||||
|
if ( tharg->fpo ) { // save FFT at server
|
||||||
|
fft_csv_prn(tharg->fpo, &(dsp.DFT), db, t_sec);
|
||||||
|
}
|
||||||
|
else if ( tharg->fd > STDIN_FILENO ) {
|
||||||
|
fft_csv_tcp(tharg->fd, &(dsp.DFT), db, t_sec);
|
||||||
}
|
}
|
||||||
fclose(fpo);
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
fprintf(stderr, "error: open %s\n", fname_fft);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( (dsp.thd)->fft != OPT_FFT_SERV ) close(tharg->fd);
|
|
||||||
|
|
||||||
(dsp.thd)->fft = 0;
|
sum_n++;
|
||||||
sum_n = 0;
|
sum_fft++;
|
||||||
|
n_fft = 0;
|
||||||
|
}
|
||||||
|
if (sum_n*fft_step*mlen >= avg_sec*dsp.sr_base) {
|
||||||
|
float nN = 1.0/(dsp.DFT.N*(float)sum_n);
|
||||||
|
for (j = 0; j < dsp.DFT.N; j++) {
|
||||||
|
avg_db[j] = 20.0*log10(nN*avg_rZ[j]+1e-20);
|
||||||
|
avg_rZ[j] = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (dsp.thd)->fft & OPT_FFT_AVG ) {
|
||||||
|
double t_sec = sum_fft*fft_step*mlen / (double)dsp.sr_base;
|
||||||
|
if ( tharg->fpo ) { // send FFT data to client
|
||||||
|
fft_csv_prn(tharg->fpo, &(dsp.DFT), avg_db, t_sec);
|
||||||
|
}
|
||||||
|
else if ( tharg->fd > STDIN_FILENO ) {
|
||||||
|
fft_csv_tcp(tharg->fd, &(dsp.DFT), avg_db, t_sec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
n_out++;
|
||||||
|
|
||||||
|
if ((dsp.thd)->fft_num > 0 && n_out >= (dsp.thd)->fft_num)
|
||||||
|
{
|
||||||
|
if ( tharg->fpo ) { fclose(tharg->fpo); tharg->fpo = NULL; }
|
||||||
|
else if ( tharg->fd > STDIN_FILENO ) { close(tharg->fd); tharg->fd = -1; }
|
||||||
|
|
||||||
|
(dsp.thd)->fft = 0;
|
||||||
|
sum_fft = 0;
|
||||||
|
n_out = 0;
|
||||||
|
|
||||||
|
pthread_mutex_lock( (dsp.thd)->mutex );
|
||||||
|
fprintf(FPOUT, "<%d: FFT_STOP>\n", (dsp.thd)->tn);
|
||||||
|
pthread_mutex_unlock( (dsp.thd)->mutex );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
sum_n = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FFT_READ_SINK_MIN
|
#ifdef FFT_READ_SINK_MIN
|
||||||
|
@ -445,12 +559,39 @@ static void *thd_FFT(void *targs) {
|
||||||
|
|
||||||
if ( (dsp.thd)->used == 0 )
|
if ( (dsp.thd)->used == 0 )
|
||||||
{
|
{
|
||||||
|
(dsp.thd)->fft = 0;
|
||||||
pthread_mutex_lock( (dsp.thd)->mutex );
|
pthread_mutex_lock( (dsp.thd)->mutex );
|
||||||
fprintf(FPOUT, "<%d: CLOSE>\n", (dsp.thd)->tn);
|
fprintf(FPOUT, "<%d: CLOSE>\n", (dsp.thd)->tn);
|
||||||
pthread_mutex_unlock( (dsp.thd)->mutex );
|
pthread_mutex_unlock( (dsp.thd)->mutex );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( (dsp.thd)->stop_fft > 0 )
|
||||||
|
{
|
||||||
|
if ( tharg->fpo ) { fclose(tharg->fpo); tharg->fpo = NULL; }
|
||||||
|
else if ( tharg->fd > STDIN_FILENO ) { close(tharg->fd); tharg->fd = -1; }
|
||||||
|
|
||||||
|
(dsp.thd)->fft = 0;
|
||||||
|
(dsp.thd)->stop_fft = 0;
|
||||||
|
sum_fft = 0;
|
||||||
|
sum_n = 0;
|
||||||
|
n_out = 0;
|
||||||
|
|
||||||
|
pthread_mutex_lock( (dsp.thd)->mutex );
|
||||||
|
fprintf(FPOUT, "<%d: STOP_FFT>\n", (dsp.thd)->tn);
|
||||||
|
pthread_mutex_unlock( (dsp.thd)->mutex );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((dsp.thd)->fft_num < 0)
|
||||||
|
{
|
||||||
|
if ( tharg->fpo ) { fclose(tharg->fpo); tharg->fpo = NULL; }
|
||||||
|
else if ( tharg->fd > STDIN_FILENO ) { close(tharg->fd); tharg->fd = -1; }
|
||||||
|
(dsp.thd)->fft = 0;
|
||||||
|
|
||||||
|
pthread_mutex_lock( (dsp.thd)->mutex );
|
||||||
|
fprintf(FPOUT, "<%d: FFT_STOP>\n", (dsp.thd)->tn);
|
||||||
|
pthread_mutex_unlock( (dsp.thd)->mutex );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bitQ == EOF) {
|
if (bitQ == EOF) {
|
||||||
|
@ -465,6 +606,8 @@ static void *thd_FFT(void *targs) {
|
||||||
exit_thread:
|
exit_thread:
|
||||||
|
|
||||||
if (z) { free(z); z = NULL; }
|
if (z) { free(z); z = NULL; }
|
||||||
|
if (db) { free(db); db = NULL; }
|
||||||
|
if (all_rZ) { free(all_rZ); all_rZ = NULL; }
|
||||||
if (avg_rZ) { free(avg_rZ); avg_rZ = NULL; }
|
if (avg_rZ) { free(avg_rZ); avg_rZ = NULL; }
|
||||||
if (avg_db) { free(avg_db); avg_db = NULL; }
|
if (avg_db) { free(avg_db); avg_db = NULL; }
|
||||||
|
|
||||||
|
@ -496,6 +639,8 @@ int main(int argc, char **argv) {
|
||||||
char tcp_buf[TCPBUF_LEN];
|
char tcp_buf[TCPBUF_LEN];
|
||||||
int th_used = 0;
|
int th_used = 0;
|
||||||
int tn_fft = -1;
|
int tn_fft = -1;
|
||||||
|
int opt_fft = 0;
|
||||||
|
int fft_num = 0;
|
||||||
|
|
||||||
pcm_t pcm = {0};
|
pcm_t pcm = {0};
|
||||||
|
|
||||||
|
@ -510,11 +655,15 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
for (k = 0; k < MAX_FQ; k++) base_fqs[k] = 0.0;
|
for (k = 0; k < MAX_FQ; k++) base_fqs[k] = 0.0;
|
||||||
|
|
||||||
|
// server options
|
||||||
++argv;
|
++argv;
|
||||||
while ((*argv) && (!wavloaded)) {
|
while ((*argv) && (!wavloaded)) {
|
||||||
if (strcmp(*argv, "--dbg") == 0) {
|
if (strcmp(*argv, "--dbg") == 0) {
|
||||||
option_dbg = 1;
|
option_dbg = 1;
|
||||||
}
|
}
|
||||||
|
else if (strcmp(*argv, "--enable_clsv_out") == 0) {
|
||||||
|
option_clsv_out = 1;
|
||||||
|
}
|
||||||
else if (strcmp(*argv, "--port") == 0) {
|
else if (strcmp(*argv, "--port") == 0) {
|
||||||
int port = 0;
|
int port = 0;
|
||||||
++argv;
|
++argv;
|
||||||
|
@ -524,7 +673,11 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
else serv_port = port;
|
else serv_port = port;
|
||||||
}
|
}
|
||||||
else if (strcmp(*argv, "--fft") == 0) {
|
else if (strncmp(*argv, "--fft", 5) == 0) {
|
||||||
|
char *arg_fft = *argv;
|
||||||
|
if (strncmp(arg_fft+5, "_avg", 4) == 0) opt_fft = OPT_FFT_SERV | OPT_FFT_AVG;
|
||||||
|
else if (strncmp(arg_fft+5, "_all", 4) == 0) opt_fft = OPT_FFT_SERV;
|
||||||
|
else return -1;
|
||||||
if (xlt_cnt < MAX_FQ) {
|
if (xlt_cnt < MAX_FQ) {
|
||||||
base_fqs[xlt_cnt] = 0.0;
|
base_fqs[xlt_cnt] = 0.0;
|
||||||
rstype[xlt_cnt] = thd_FFT;
|
rstype[xlt_cnt] = thd_FFT;
|
||||||
|
@ -532,6 +685,8 @@ int main(int argc, char **argv) {
|
||||||
xlt_cnt++;
|
xlt_cnt++;
|
||||||
}
|
}
|
||||||
++argv;
|
++argv;
|
||||||
|
if (*argv) fft_num = atoi(*argv); else return -1;
|
||||||
|
++argv;
|
||||||
if (*argv) fname_fft = *argv; else return -1;
|
if (*argv) fname_fft = *argv; else return -1;
|
||||||
}
|
}
|
||||||
else if (strcmp(*argv, "-") == 0) {
|
else if (strcmp(*argv, "-") == 0) {
|
||||||
|
@ -597,8 +752,21 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
for (k = 0; k < xlt_cnt; k++) {
|
for (k = 0; k < xlt_cnt; k++) {
|
||||||
if (k == tn_fft) {
|
if (k == tn_fft) {
|
||||||
tharg[k].thd.fft = OPT_FFT_SERV;
|
tharg[k].thd.fft = opt_fft;
|
||||||
tharg[k].fname = fname_fft;
|
tharg[k].fname = fname_fft;
|
||||||
|
tharg[k].thd.fft_num = fft_num;
|
||||||
|
tharg[k].thd.stop_fft = 0;
|
||||||
|
|
||||||
|
if ( (tharg[k].thd.fft & 0xF) == OPT_FFT_SERV ) { // save FFT at server
|
||||||
|
if (fname_fft) {
|
||||||
|
if (fname_fft[0] == '-') tharg[k].fpo = stdout;
|
||||||
|
else tharg[k].fpo = fopen(fname_fft, "wb");
|
||||||
|
}
|
||||||
|
else return -1;
|
||||||
|
if (tharg[k].fpo == NULL) {
|
||||||
|
fprintf(stderr, "error: open %s\n", fname_fft);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tharg[k].thd.tn = k;
|
tharg[k].thd.tn = k;
|
||||||
tharg[k].thd.tn_bit = (1<<k);
|
tharg[k].thd.tn_bit = (1<<k);
|
||||||
|
@ -686,6 +854,7 @@ int main(int argc, char **argv) {
|
||||||
//if (th_used == 0) break;
|
//if (th_used == 0) break;
|
||||||
|
|
||||||
|
|
||||||
|
// client commands
|
||||||
if ( l > 1 ) {
|
if ( l > 1 ) {
|
||||||
char *freq = tcp_buf;
|
char *freq = tcp_buf;
|
||||||
while (l > 1 && tcp_buf[l-1] < 0x20) l--;
|
while (l > 1 && tcp_buf[l-1] < 0x20) l--;
|
||||||
|
@ -701,23 +870,76 @@ int main(int argc, char **argv) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if ( strncmp(tcp_buf, "--fft", 5) == 0 ) {
|
else if ( strncmp(tcp_buf, "--fft", 5) == 0 ) {
|
||||||
|
opt_fft = 0;
|
||||||
|
if (strncmp(tcp_buf+5, "_avg", 4) == 0) opt_fft = OPT_FFT_AVG;
|
||||||
|
else if (strncmp(tcp_buf+5, "_all", 4) != 0) return -1;
|
||||||
|
if (strncmp(tcp_buf+5+4, "_cl", 3) == 0) opt_fft |= OPT_FFT_CLNT;
|
||||||
|
else if (strncmp(tcp_buf+5+4, "_sv", 3) == 0) {
|
||||||
|
if (option_clsv_out) opt_fft |= OPT_FFT_SERV;
|
||||||
|
else {
|
||||||
|
pthread_mutex_lock( &mutex );
|
||||||
|
fprintf(FPOUT, "<NO CLSV OUT>\n");
|
||||||
|
pthread_mutex_unlock( &mutex );
|
||||||
|
close(conn_fd);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else return -1;
|
||||||
|
if (tcp_buf+5+4+4) fft_num = atoi(tcp_buf+5+4+4); else fft_num = 0;
|
||||||
char *fname_fft_cl = "db_fft_cl.txt";
|
char *fname_fft_cl = "db_fft_cl.txt";
|
||||||
int opt_fft = strcmp(tcp_buf, "--fft0") == 0 ? OPT_FFT_CLSV : OPT_FFT_CLNT;
|
char *pbuf = tcp_buf;
|
||||||
//close(conn_fd);
|
for (pbuf = tcp_buf+5+4+4; *pbuf; pbuf++) {
|
||||||
|
if (*pbuf == ' ') break;
|
||||||
|
}
|
||||||
|
if (*pbuf == ' ') {
|
||||||
|
fname_fft_cl = pbuf+1;
|
||||||
|
}
|
||||||
if ( !tcp_eof )
|
if ( !tcp_eof )
|
||||||
{
|
{
|
||||||
if (tn_fft >= 0) {
|
if (tn_fft >= 0) {
|
||||||
tharg[tn_fft].thd.fft = opt_fft;
|
if (tharg[tn_fft].thd.fft == 0) {
|
||||||
tharg[tn_fft].fname = fname_fft_cl;
|
tharg[tn_fft].thd.fft_num = fft_num;
|
||||||
tharg[tn_fft].fd = conn_fd;
|
tharg[tn_fft].thd.stop_fft = 0;
|
||||||
|
tharg[tn_fft].fname = fname_fft_cl;
|
||||||
|
tharg[tn_fft].fd = conn_fd;
|
||||||
|
|
||||||
|
if ( (opt_fft & 0xF) == OPT_FFT_SERV ) { // save FFT at server
|
||||||
|
if (fname_fft_cl) {
|
||||||
|
if (fname_fft_cl[0] == '-') tharg[tn_fft].fpo = stdout;
|
||||||
|
else tharg[tn_fft].fpo = fopen(fname_fft_cl, "wb");
|
||||||
|
}
|
||||||
|
else return -1;
|
||||||
|
if (tharg[tn_fft].fpo == NULL) {
|
||||||
|
fprintf(stderr, "error: open %s\n", fname_fft_cl);
|
||||||
|
}
|
||||||
|
close(tharg[tn_fft].fd); tharg[tn_fft].fd = -1; // tharg[tn_fft].fd == conn_fd
|
||||||
|
}
|
||||||
|
else { // (opt_fft & 0xF) == OPT_FFT_CLNT : send FFT to client
|
||||||
|
tharg[tn_fft].fpo = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
tharg[tn_fft].thd.fft = opt_fft;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pthread_mutex_lock( &mutex );
|
||||||
|
fprintf(FPOUT, "<%d: FFT running>\n", tn_fft);
|
||||||
|
pthread_mutex_unlock( &mutex );
|
||||||
|
|
||||||
|
close(conn_fd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (k = 0; k < MAX_FQ; k++) {
|
for (k = 0; k < MAX_FQ; k++) {
|
||||||
if (tharg[k].thd.used == 0) break;
|
if (tharg[k].thd.used == 0) {
|
||||||
|
if (k != tn_fft) break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (k < MAX_FQ) {
|
if (k < MAX_FQ) {
|
||||||
tharg[k].thd.fft = opt_fft;
|
tharg[k].thd.fft_num = fft_num;
|
||||||
|
tharg[k].thd.stop_fft = 0;
|
||||||
tharg[k].fname = fname_fft_cl;
|
tharg[k].fname = fname_fft_cl;
|
||||||
|
tharg[k].fd = conn_fd;
|
||||||
|
|
||||||
tn_fft = k;
|
tn_fft = k;
|
||||||
tharg[k].thd.tn = k;
|
tharg[k].thd.tn = k;
|
||||||
tharg[k].thd.tn_bit = (1<<k);
|
tharg[k].thd.tn_bit = (1<<k);
|
||||||
|
@ -726,12 +948,26 @@ int main(int argc, char **argv) {
|
||||||
//tharg[k].thd.lock = &lock;
|
//tharg[k].thd.lock = &lock;
|
||||||
tharg[k].thd.blk = block_decMB;
|
tharg[k].thd.blk = block_decMB;
|
||||||
tharg[k].thd.xlt_fq = 0.0;
|
tharg[k].thd.xlt_fq = 0.0;
|
||||||
|
|
||||||
tharg[k].pcm = pcm;
|
tharg[k].pcm = pcm;
|
||||||
tharg[k].fd = conn_fd;
|
|
||||||
|
if ( (opt_fft & 0xF) == OPT_FFT_SERV ) { // save FFT at server
|
||||||
|
if (fname_fft_cl) {
|
||||||
|
if (fname_fft_cl[0] == '-') tharg[k].fpo = stdout;
|
||||||
|
else tharg[k].fpo = fopen(fname_fft_cl, "wb");
|
||||||
|
}
|
||||||
|
else return -1;
|
||||||
|
if (tharg[k].fpo == NULL) {
|
||||||
|
fprintf(stderr, "error: open %s\n", fname_fft_cl);
|
||||||
|
}
|
||||||
|
close(tharg[k].fd); tharg[k].fd = -1; // tharg[k].fd == conn_fd
|
||||||
|
}
|
||||||
|
else { // (opt_fft & 0xF) == OPT_FFT_CLNT : send FFT to client
|
||||||
|
tharg[k].fpo = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
rbf1 |= tharg[k].thd.tn_bit;
|
rbf1 |= tharg[k].thd.tn_bit;
|
||||||
tharg[k].thd.used = 1;
|
tharg[k].thd.used = 1;
|
||||||
|
tharg[k].thd.fft = opt_fft;
|
||||||
|
|
||||||
pthread_create(&tharg[k].thd.tid, NULL, thd_FFT, &tharg[k]);
|
pthread_create(&tharg[k].thd.tid, NULL, thd_FFT, &tharg[k]);
|
||||||
|
|
||||||
|
@ -753,9 +989,14 @@ int main(int argc, char **argv) {
|
||||||
else if (tcp_buf[0] == '-') { // -<n> : close <n>
|
else if (tcp_buf[0] == '-') { // -<n> : close <n>
|
||||||
int num = atoi(tcp_buf+1);
|
int num = atoi(tcp_buf+1);
|
||||||
if (num >= 0 && num < MAX_FQ) {
|
if (num >= 0 && num < MAX_FQ) {
|
||||||
if (num != tn_fft) {
|
if (num != tn_fft)
|
||||||
|
{
|
||||||
tharg[num].thd.used = 0;
|
tharg[num].thd.used = 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tharg[num].thd.stop_fft = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
close(conn_fd);
|
close(conn_fd);
|
||||||
}
|
}
|
||||||
|
@ -789,6 +1030,7 @@ int main(int argc, char **argv) {
|
||||||
rbf1 |= tharg[k].thd.tn_bit;
|
rbf1 |= tharg[k].thd.tn_bit;
|
||||||
tharg[k].thd.used = 1;
|
tharg[k].thd.used = 1;
|
||||||
tharg[k].thd.fft = 0;
|
tharg[k].thd.fft = 0;
|
||||||
|
tharg[k].thd.stop_fft = 0;
|
||||||
|
|
||||||
pthread_create(&tharg[k].thd.tid, NULL, thd_IF, &tharg[k]);
|
pthread_create(&tharg[k].thd.tid, NULL, thd_IF, &tharg[k]);
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define OPT_FFT_SERV 1 // server
|
||||||
|
#define OPT_FFT_CLNT 2 // server -> client
|
||||||
|
#define OPT_FFT_AVG 0x100
|
||||||
|
|
||||||
#define TCPBUF_LEN 1024
|
#define TCPBUF_LEN 1024
|
||||||
#define SERV_BACKLOG 6
|
#define SERV_BACKLOG 6
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import matplotlib.ticker as ticker
|
||||||
|
|
||||||
if len(sys.argv) < 2:
|
if len(sys.argv) < 2:
|
||||||
print("usage:")
|
print("usage:")
|
||||||
print("\tpython %s <fft_file>" % sys.argv[0])
|
print("\tpython %s <fft_file.csv>" % sys.argv[0])
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
fft_file = sys.argv[1]
|
fft_file = sys.argv[1]
|
||||||
|
@ -18,10 +18,17 @@ if not os.path.isfile(fft_file):
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
|
||||||
data = np.genfromtxt( fft_file, delimiter=';', names=['fq','db'] , skip_header=1 )
|
raw_data = np.genfromtxt( fft_file, delimiter=',', max_rows=1)
|
||||||
|
data1 = raw_data[:] # max_rows=2: raw_data[0,:]
|
||||||
|
print(data1)
|
||||||
|
|
||||||
fq = data['fq']
|
db = data1[5:]
|
||||||
db = data['db']
|
|
||||||
|
sr = -2.0*data1[1]
|
||||||
|
|
||||||
|
freq_min = data1[1] / sr
|
||||||
|
freq_max = data1[2] / sr
|
||||||
|
fq = np.arange(freq_min, freq_max, 1.0/(data1[4]+1))
|
||||||
|
|
||||||
N = len(db)
|
N = len(db)
|
||||||
m = np.mean(db)
|
m = np.mean(db)
|
||||||
|
|
|
@ -0,0 +1,186 @@
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import numpy as np
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import matplotlib.ticker as ticker
|
||||||
|
import matplotlib.animation as animation
|
||||||
|
|
||||||
|
|
||||||
|
if len(sys.argv) < 3:
|
||||||
|
print("usage:")
|
||||||
|
print("\tpython <1/2/3> %s <fft_all.csv>" % sys.argv[0])
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
OPT_FFT_L = 1
|
||||||
|
OPT_FFT_W = 2
|
||||||
|
OPT_FFT_B = 3
|
||||||
|
|
||||||
|
OPT_FFT = OPT_FFT_B
|
||||||
|
if (sys.argv[1] == '1'):
|
||||||
|
OPT_FFT = OPT_FFT_L
|
||||||
|
elif (sys.argv[1] == '2'):
|
||||||
|
OPT_FFT = OPT_FFT_W
|
||||||
|
|
||||||
|
fft_file = sys.argv[2]
|
||||||
|
|
||||||
|
|
||||||
|
if (fft_file == "-"):
|
||||||
|
f = sys.stdin
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
f = open(fft_file)
|
||||||
|
except IOError:
|
||||||
|
print("error: open %s" % fft_file)
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
|
||||||
|
FFT_FPS = 16/2
|
||||||
|
WIN_SEC = 10
|
||||||
|
win = WIN_SEC*FFT_FPS
|
||||||
|
|
||||||
|
line = f.readline()
|
||||||
|
#line = f.readline()
|
||||||
|
|
||||||
|
row = np.fromstring(line, dtype=float, sep=',')
|
||||||
|
data = row[5:]
|
||||||
|
|
||||||
|
l = len(data)
|
||||||
|
m = np.mean(data)
|
||||||
|
|
||||||
|
data5 = np.full([win,l], m)
|
||||||
|
for x in range(2, l-2):
|
||||||
|
data5[0,x] = (data[x-2]+data[x-1]+data[x]+data[x+1]+data[x+2])/5.0
|
||||||
|
|
||||||
|
min_db = np.min(data5)
|
||||||
|
max_db = np.max(data5)
|
||||||
|
|
||||||
|
sr = -2.0*row[1]
|
||||||
|
|
||||||
|
freq_min = row[1]
|
||||||
|
freq_max = row[2]
|
||||||
|
N = row[4]
|
||||||
|
|
||||||
|
limits = [freq_min/1e3, freq_max/1e3, WIN_SEC, 0.0]
|
||||||
|
|
||||||
|
fq = np.arange(freq_min/sr, freq_max/sr, 1.0/(row[4]+1))
|
||||||
|
|
||||||
|
|
||||||
|
################################################################################################
|
||||||
|
|
||||||
|
if (OPT_FFT == OPT_FFT_L):
|
||||||
|
fig = plt.figure(figsize=(12, 5))
|
||||||
|
ax1 = fig.add_subplot(111)
|
||||||
|
ax1.set_xlim([fq[0], fq[-1]])
|
||||||
|
ax1.set_ylim([-110.0, -30.0])
|
||||||
|
|
||||||
|
lp, = ax1.plot( fq, data5[0,:], color='g', linewidth=0.4)
|
||||||
|
|
||||||
|
count = 0
|
||||||
|
|
||||||
|
def animate_lp(i):
|
||||||
|
line = f.readline()
|
||||||
|
if line:
|
||||||
|
row = np.fromstring(line, dtype=float, sep=',')
|
||||||
|
data = row[5:]
|
||||||
|
|
||||||
|
global count
|
||||||
|
count += 1
|
||||||
|
global data5
|
||||||
|
#data5 = np.roll(data5, 1, axis=0)
|
||||||
|
for x in range(2, l-2):
|
||||||
|
data5[0,x] = (data[x-2]+data[x-1]+data[x]+data[x+1]+data[x+2])/5.0
|
||||||
|
|
||||||
|
lp.set_data(fq, data5[0,:])
|
||||||
|
|
||||||
|
return [lp]
|
||||||
|
|
||||||
|
ani = animation.FuncAnimation(fig, animate_lp, interval=10, blit=True)
|
||||||
|
|
||||||
|
################################################################################################
|
||||||
|
|
||||||
|
elif (OPT_FFT == OPT_FFT_W):
|
||||||
|
fig = plt.figure(figsize=(12, 5))
|
||||||
|
ax2 = fig.add_subplot(111)
|
||||||
|
ax2.set_xlabel('Frequency (kHz)')
|
||||||
|
ax2.set_ylabel('Time (s)')
|
||||||
|
|
||||||
|
im = ax2.imshow(data5, vmin=-110.0, vmax=-50.0, extent=limits, animated=True)
|
||||||
|
ax2.set_aspect('auto')
|
||||||
|
fig.colorbar(im, orientation='vertical')
|
||||||
|
|
||||||
|
count = 0
|
||||||
|
|
||||||
|
def animate_im(i):
|
||||||
|
line = f.readline()
|
||||||
|
if line:
|
||||||
|
row = np.fromstring(line, dtype=float, sep=',')
|
||||||
|
data = row[5:]
|
||||||
|
|
||||||
|
global count
|
||||||
|
count += 1
|
||||||
|
global data5
|
||||||
|
data5 = np.roll(data5, 1, axis=0)
|
||||||
|
for x in range(2, l-2):
|
||||||
|
data5[0,x] = (data[x-2]+data[x-1]+data[x]+data[x+1]+data[x+2])/5.0
|
||||||
|
|
||||||
|
im.set_data(data5)
|
||||||
|
|
||||||
|
# update vmin/vmax
|
||||||
|
if (count % win == 0):
|
||||||
|
min_db = np.min(data5)
|
||||||
|
max_db = np.max(data5)
|
||||||
|
im.set_clim(vmin=min_db, vmax=max_db)
|
||||||
|
return [im]
|
||||||
|
|
||||||
|
ani = animation.FuncAnimation(fig, animate_im, interval=10, blit=True)
|
||||||
|
|
||||||
|
################################################################################################
|
||||||
|
|
||||||
|
else:
|
||||||
|
fig = plt.figure(figsize=(12, 8))
|
||||||
|
ax1 = fig.add_subplot(211)
|
||||||
|
ax1.set_xlim([fq[0], fq[-1]])
|
||||||
|
ax1.set_ylim([-110.0, -30.0])
|
||||||
|
ax2 = fig.add_subplot(212)
|
||||||
|
ax2.set_xlabel('Frequency (kHz)')
|
||||||
|
ax2.set_ylabel('Time (s)')
|
||||||
|
|
||||||
|
lp, = ax1.plot( fq, data5[0,:], color='g', linewidth=0.4)
|
||||||
|
im = ax2.imshow(data5, vmin=-110.0, vmax=-50.0, extent=limits, animated=True)
|
||||||
|
|
||||||
|
ax2.set_aspect('auto')
|
||||||
|
|
||||||
|
count = 0
|
||||||
|
|
||||||
|
def animate(i):
|
||||||
|
line = f.readline()
|
||||||
|
if line:
|
||||||
|
row = np.fromstring(line, dtype=float, sep=',')
|
||||||
|
data = row[5:]
|
||||||
|
|
||||||
|
global count
|
||||||
|
count += 1
|
||||||
|
global data5
|
||||||
|
data5 = np.roll(data5, 1, axis=0)
|
||||||
|
for x in range(2, l-2):
|
||||||
|
data5[0,x] = (data[x-2]+data[x-1]+data[x]+data[x+1]+data[x+2])/5.0
|
||||||
|
|
||||||
|
im.set_data(data5)
|
||||||
|
lp.set_data(fq, data5[0,:])
|
||||||
|
|
||||||
|
# update vmin/vmax
|
||||||
|
if (count % win == 0):
|
||||||
|
min_db = np.min(data5)
|
||||||
|
max_db = np.max(data5)
|
||||||
|
im.set_clim(vmin=min_db, vmax=max_db)
|
||||||
|
return [lp,im]
|
||||||
|
|
||||||
|
ani = animation.FuncAnimation(fig, animate, interval=10, blit=True)
|
||||||
|
|
||||||
|
################################################################################################
|
||||||
|
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import numpy as np
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import matplotlib.ticker as ticker
|
||||||
|
|
||||||
|
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("usage:")
|
||||||
|
print("\tpython %s <wfft_file>" % sys.argv[0])
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
fft_file = sys.argv[1]
|
||||||
|
|
||||||
|
if not os.path.isfile(fft_file):
|
||||||
|
print("error: %s not found" % fft_file)
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
|
||||||
|
raw_data = np.genfromtxt( fft_file, delimiter=',')
|
||||||
|
data = raw_data[:,5:]
|
||||||
|
|
||||||
|
dim = np.shape(data)
|
||||||
|
m = np.mean(data)
|
||||||
|
data5 = np.full(dim, m)
|
||||||
|
for y in range(dim[0]):
|
||||||
|
for x in range(2, dim[1]-2):
|
||||||
|
data5[y,x] = (data[y,x-2]+data[y,x-1]+data[y,x]+data[y,x+1]+data[y,x+2])/5.0
|
||||||
|
|
||||||
|
freq_min = raw_data[0,1] / 1e3
|
||||||
|
freq_max = raw_data[0,2] / 1e3
|
||||||
|
N = raw_data[0,4]
|
||||||
|
tmin = raw_data[dim[0]-1,0]
|
||||||
|
tmax = raw_data[0,0]
|
||||||
|
limits = [freq_min, freq_max, tmin, tmax]
|
||||||
|
|
||||||
|
|
||||||
|
fig = plt.figure(figsize=(15, 5))
|
||||||
|
ax = fig.add_subplot(111)
|
||||||
|
ax.set_title('Waterfall')
|
||||||
|
ax.set_xlabel('Frequency (kHz)')
|
||||||
|
ax.set_ylabel('Time (s)')
|
||||||
|
|
||||||
|
plt.imshow(data5, extent=limits)
|
||||||
|
|
||||||
|
ax.set_aspect('auto')
|
||||||
|
plt.colorbar(orientation='vertical')
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
if (argv[1] == NULL) {
|
if (argv[1] == NULL) {
|
||||||
fprintf(stderr, "usage:\n");
|
fprintf(stderr, "usage:\n");
|
||||||
fprintf(stderr, "\t%s <fft_file>\n", argv[0]);
|
fprintf(stderr, "\t%s <fft_avg.csv>\n", argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
fp = fopen(argv[1], "rb");
|
fp = fopen(argv[1], "rb");
|
||||||
|
@ -61,9 +61,34 @@ int main(int argc, char **argv) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
memset(line, 0, LINELEN+1);
|
||||||
|
|
||||||
N = 0;
|
N = 0;
|
||||||
|
j = 0;
|
||||||
|
n = 0;
|
||||||
|
// sec.ms,freq_min,freq_max,Hz/bin,N_bins, ...
|
||||||
while ( (c = fgetc(fp)) != EOF) {
|
while ( (c = fgetc(fp)) != EOF) {
|
||||||
if (c == '\n') N++;
|
if (c == '\n') break;
|
||||||
|
if (c == ' ') continue;
|
||||||
|
if (c == ',') {
|
||||||
|
if (n == 1) {
|
||||||
|
int freq_min = atoi(line);
|
||||||
|
sr = -2*freq_min;
|
||||||
|
}
|
||||||
|
if (n == 4) {
|
||||||
|
N = atoi(line);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
n++;
|
||||||
|
memset(line, 0, LINELEN+1);
|
||||||
|
j = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
line[j] = c;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
db = calloc(N+1, sizeof(float)); if (db == NULL) return 2;
|
db = calloc(N+1, sizeof(float)); if (db == NULL) return 2;
|
||||||
|
@ -73,20 +98,30 @@ int main(int argc, char **argv) {
|
||||||
intdb = calloc(N+1, sizeof(float)); if (intdb == NULL) return 2;
|
intdb = calloc(N+1, sizeof(float)); if (intdb == NULL) return 2;
|
||||||
peak = calloc(N+1, sizeof(float)); if (peak == NULL) return 2;
|
peak = calloc(N+1, sizeof(float)); if (peak == NULL) return 2;
|
||||||
|
|
||||||
fseek(fp, 0, SEEK_SET);
|
|
||||||
|
|
||||||
pbuf = fgets(line, LINELEN, fp);
|
// ..., db_1,...,db_N:
|
||||||
p1 = strstr(line, "sr:");
|
memset(line, 0, LINELEN+1);
|
||||||
if (p1) sr = atoi(p1+3);
|
j = 0;
|
||||||
for (n = 0; n < N; n++) {
|
n = 0;
|
||||||
memset(line, 0, LINELEN+1);
|
while ( (c = fgetc(fp)) != EOF) {
|
||||||
pbuf = fgets(line, LINELEN, fp);
|
if (c == '\n') break;
|
||||||
p1 = strstr(line, ";"); //p2 = strstr(p1+1, ";");
|
if (c == ' ') continue;
|
||||||
if (p1) {
|
if (c == ',') {
|
||||||
fq[n] = atof(line); //freq[n] = atof(p1+1);
|
if (n < N) {
|
||||||
db[n] = atof(p1+1); //atof(p2+1);
|
db[n] = atof(line);
|
||||||
|
fq[n] = -0.5 + n/(float)N;
|
||||||
|
}
|
||||||
|
|
||||||
|
n++;
|
||||||
|
memset(line, 0, LINELEN+1);
|
||||||
|
j = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
line[j] = c;
|
||||||
|
j++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f0 = N/2;
|
f0 = N/2;
|
||||||
|
|
||||||
globmin = 0.0;
|
globmin = 0.0;
|
||||||
|
@ -94,14 +129,12 @@ int main(int argc, char **argv) {
|
||||||
float db_spike3 = 10.0;
|
float db_spike3 = 10.0;
|
||||||
int spike_wl3 = 3; //freq2bin(&DFT, 200); // 3 // 200 Hz
|
int spike_wl3 = 3; //freq2bin(&DFT, 200); // 3 // 200 Hz
|
||||||
int spike_wl5 = 5; //freq2bin(&DFT, 200); // 3 // 200 Hz
|
int spike_wl5 = 5; //freq2bin(&DFT, 200); // 3 // 200 Hz
|
||||||
//float db_spike1 = 15.0;
|
|
||||||
//int spike_wl1 = 1; //freq2bin(&DFT, 200); // 3 // 200 Hz
|
|
||||||
|
|
||||||
dx = 200.0;
|
dx = 200.0;
|
||||||
if (sr) dx = sr*(fq[f0+1]-fq[f0]); //freq[f0+1]-freq[f0];
|
if (sr) dx = sr*(fq[f0+1]-fq[f0]); //freq[f0+1]-freq[f0];
|
||||||
dn = 2*(int)(2400.0/dx)+1; // (odd/symmetric) integration width: 4800+dx Hz
|
dn = 2*(int)(2400.0/dx)+1; // (odd/symmetric) integration width: 4800+dx Hz
|
||||||
if (option_verbose > 1) fprintf(stderr, "dn = %d\n", dn);
|
if (option_verbose > 1) fprintf(stderr, "dn = %d\n", dn);
|
||||||
//for (j = 0; j < N; j++) db[j] /= (float)n;
|
|
||||||
|
|
||||||
// dc-spike (N-1,)N,0,1(,2): subtract mean/avg
|
// dc-spike (N-1,)N,0,1(,2): subtract mean/avg
|
||||||
// spikes in general:
|
// spikes in general:
|
||||||
|
|
Ładowanie…
Reference in New Issue