From 680ab52d9e151676b8f90d105b23d2d0d89b0471 Mon Sep 17 00:00:00 2001 From: Takamichi Horikawa Date: Sat, 15 Apr 2017 01:00:20 +0900 Subject: add fmdsp fft analyzer --- fft/fft.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 fft/fft.c (limited to 'fft/fft.c') diff --git a/fft/fft.c b/fft/fft.c new file mode 100644 index 0000000..69c0971 --- /dev/null +++ b/fft/fft.c @@ -0,0 +1,154 @@ +#include "fft.h" +#include +#include + +void fft_write(struct fmplayer_fft_data *data, const int16_t *buf, unsigned len) { + if (len > FFTLEN) { + unsigned discard = FFTLEN - len; + buf += discard*2; + len = FFTLEN; + } + unsigned towrite = FFTLEN - data->ind; + if (towrite > len) towrite = len; + for (unsigned i = 0; i < towrite; i++) { + data->buf[data->ind+i] = ((uint32_t)buf[2*i+0] + buf[2*i+1]) / 2; + } + data->ind = (data->ind + towrite) % FFTLEN; + buf += towrite*2; + len -= towrite; + + for (unsigned i = 0; i < len; i++) { + data->buf[i] = ((uint32_t)buf[2*i+0] + buf[2*i+1]) / 2; + } + data->ind = (data->ind + len) % FFTLEN; +} + +static const uint16_t fftfreqtab[FFTDISPLEN+1] = { + 0, + 18, 19, 21, 22, 23, 25, 26, 28, 29, 31, + 33, 35, 37, 39, 42, 44, 47, 50, 53, 56, + 59, 63, 66, 70, 75, 79, 84, 89, 94, 100, + 106, 112, 119, 126, 133, 141, 150, 158, 168, 178, + 189, 200, 212, 224, 238, 252, 267, 283, 300, 317, + 336, 356, 378, 400, 424, 449, 476, 504, 534, 566, + 600, 635, 673, 713, 756, 801, 848, 899, 952, 1009, +}; + +enum { + HFFTLENBIT = 12, + HFFTLEN = 1<> bit) & 1u) << (HFFTLENBIT-bit-1); + } + fftbuf[(!b)*FFTLEN+i*2+0] = fftbuf[b*FFTLEN+ii*2+0]; + fftbuf[(!b)*FFTLEN+i*2+1] = fftbuf[b*FFTLEN+ii*2+1]; + } + b = !b; + for (unsigned bit = 0; bit < HFFTLENBIT; bit++) { + for (unsigned i = 0; i < HFFTLEN; i++) { + unsigned ei = i & ~(1u<fdata.ind) % FFTLEN; + idata->work[i] = (((int32_t)idata->fdata.buf[fi]) * window[i]) >> 16; + } + for (int i = 0; i < FFTLEN; i++) { + idata->fwork[i] = ((float)idata->work[i])/32768; + } + fft_real(idata->fwork); + for (int i = 1; i < FFTLEN/2; i++) { + float re = idata->fwork[i*2]; + float im = idata->fwork[i*2+1]; + idata->fwork[i] = sqrtf((re*re) + (im*im)); + } + for (int i = 0; i < FFTLEN/2; i++) { + idata->fwork[i] = idata->fwork[i] / sqrtf(FFTLEN); + } + float dbuf[FFTDISPLEN]; + for (int i = 0; i < FFTDISPLEN; i++) { + dbuf[i] = 0.0f; + for (int j = fftfreqtab[i]; j < fftfreqtab[i+1]; j++) { + dbuf[i] += idata->fwork[j]; + } + dbuf[i] /= fftfreqtab[i+1] - fftfreqtab[i]; + } + for (int i = 0; i < FFTDISPLEN; i++) { + float res = (dbuf[i] > (1.0f / 256)) ? (4.0f*log2f(dbuf[i]) + 32.0f) : 0.0f; + if (res > 31.0f) res = 31.0f; + if (res < 0.0f) res = 0.0f; + ddata->buf[i] = res; + } +} -- cgit v1.2.3