summaryrefslogtreecommitdiff
path: root/gfft.c
diff options
context:
space:
mode:
Diffstat (limited to 'gfft.c')
-rw-r--r--gfft.c100
1 files changed, 100 insertions, 0 deletions
diff --git a/gfft.c b/gfft.c
new file mode 100644
index 0000000..fa21a11
--- /dev/null
+++ b/gfft.c
@@ -0,0 +1,100 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <ctype.h>
+
+#include "gfft.h"
+
+void window_hard(sample *in, double *out, size_t size, int ch, int nch)
+{
+ for (size_t i = 0; i < size; i++) {
+ sample val = in[i * nch + ch];
+ out[i] = (1./32768.) * val;
+ }
+}
+
+void window_hann(sample *in, double *out, size_t size, int ch, int nch)
+{
+ double cfac = 2. * M_PI / ((double) size - 1);
+ for (size_t i = 0; i < size; i++) {
+ sample val = in[i * nch + ch];
+ out[i] = (1./32768.) * val
+ * 0.5 * (1. - cos (cfac * (double)i));
+ }
+}
+
+static gpointer fftrun_threadf(gpointer param)
+{
+ struct fft_runner *fftr = param;
+ fftw_plan p;
+ double *in;
+ fftw_complex *out;
+ struct qe *qe;
+ struct fe *fe;
+ int stopped = 0;
+ sample *hist;
+ size_t span = fftr->span;
+ size_t pktsize = fftr->dev->pktsize;
+
+ hist = malloc(sizeof(sample) * pktsize * span * fftr->dev->chan);
+ in = fftw_malloc(sizeof(double) * pktsize * span);
+ out = fftw_malloc(sizeof(fftw_complex) * pktsize * span);
+ p = fftw_plan_dft_r2c_1d(pktsize * span, in, out,
+ FFTW_MEASURE | FFTW_DESTROY_INPUT);
+ free(out);
+
+ while (!stopped) {
+ qe = g_async_queue_pop(fftr->dev->queue);
+ fe = calloc(sizeof(struct fe), 1);
+
+ switch (qe->message) {
+ case QE_STOPPED:
+ fe->message = FE_STOPPED;
+ stopped = 1;
+ break;
+
+ case QE_ERROR:
+ fe->message = FE_DEV_ERROR;
+ fe->errcode = qe->errcode;
+ fe->errp = qe->errp;
+ break;
+
+ case QE_DATA:
+ memmove(hist, hist + pktsize,
+ pktsize * (span - 1) * fftr->dev->chan * sizeof(*hist));
+ memmove(hist + pktsize * (span - 1), qe->samples,
+ pktsize * fftr->dev->chan * sizeof(*hist));
+
+ fe->message = FE_DATA;
+ fe->data = fftw_malloc(sizeof(fftw_complex)
+ * pktsize * span);
+ fe->size = pktsize * span;
+ fftr->winf(hist, in, pktsize * span, 0, fftr->dev->chan);
+ fftw_execute_dft_r2c(p, in, fe->data);
+ break;
+ }
+ free(qe);
+
+ g_async_queue_push(fftr->queue, fe);
+ }
+
+ free(in);
+ fftw_destroy_plan(p);
+ return NULL;
+}
+
+struct fft_runner *fftrun_attach(struct device *device,
+ window_func *winf, size_t span)
+{
+ GError *error = NULL;
+ struct fft_runner *fftr;
+
+ fftr = malloc(sizeof(*fftr));
+ fftr->dev = device;
+ fftr->queue = g_async_queue_new();
+ fftr->thread = g_thread_create(fftrun_threadf, fftr, 0, &error);
+ fftr->winf = winf;
+ fftr->span = span;
+ return fftr;
+}
+