#include "fft.h" #include #include void fft_write(struct fmplayer_fft_data *data, const int16_t *buf, unsigned len) { if (len > FFTLEN) { unsigned discard = len - FFTLEN; 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; } }