From b190afd805ea248a4b8ebfac29f06a5937881435 Mon Sep 17 00:00:00 2001 From: casey langen Date: Mon, 17 Dec 2018 23:13:10 -0800 Subject: [PATCH] Added a stubbed Shibatch SuperEQ DSP plugin. Sources were taken/stolen from the DeaDBeeF project, which is more or less a straight port of the original, with added support for floating point samples. --- CMakeLists.txt | 5 +- src/core/audio/Stream.cpp | 2 +- src/core/sdk/IDSP.h | 2 +- src/plugins/supereqdsp/CMakeLists.txt | 9 + src/plugins/supereqdsp/SuperEqDsp.cpp | 86 + src/plugins/supereqdsp/SuperEqDsp.h | 51 + src/plugins/supereqdsp/supereq/COPYING | 33 + src/plugins/supereqdsp/supereq/Equ.cpp | 446 +++ src/plugins/supereqdsp/supereq/Equ.h | 56 + src/plugins/supereqdsp/supereq/Fftsg_fl.c | 2650 +++++++++++++++++ .../supereqdsp/supereq/dsp_superequ.txt | 30 + src/plugins/supereqdsp/supereq/paramlist.hpp | 127 + src/plugins/supereqdsp/supereqdsp_plugin.cpp | 74 + 13 files changed, 3567 insertions(+), 4 deletions(-) create mode 100644 src/plugins/supereqdsp/CMakeLists.txt create mode 100644 src/plugins/supereqdsp/SuperEqDsp.cpp create mode 100644 src/plugins/supereqdsp/SuperEqDsp.h create mode 100644 src/plugins/supereqdsp/supereq/COPYING create mode 100644 src/plugins/supereqdsp/supereq/Equ.cpp create mode 100644 src/plugins/supereqdsp/supereq/Equ.h create mode 100644 src/plugins/supereqdsp/supereq/Fftsg_fl.c create mode 100644 src/plugins/supereqdsp/supereq/dsp_superequ.txt create mode 100644 src/plugins/supereqdsp/supereq/paramlist.hpp create mode 100644 src/plugins/supereqdsp/supereqdsp_plugin.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ffe2315b..88370febc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,6 +97,7 @@ add_subdirectory(src/plugins/nullout) add_subdirectory(src/plugins/server) add_subdirectory(src/plugins/httpdatastream) add_subdirectory(src/plugins/stockencoders) +add_subdirectory(src/plugins/supereqdsp) if (${FFMPEG_DECODER} MATCHES "true") add_subdirectory(src/plugins/ffmpegdecoder) @@ -217,13 +218,13 @@ if (GENERATE_DEB MATCHES "1") endif() set(DEPENDENCIES "libboost-thread${DEB_BOOST_VERSION}, libboost-system${DEB_BOOST_VERSION}, libboost-filesystem${DEB_BOOST_VERSION}, libmicrohttpd${DEB_MICROHTTPD_VERSION}, libcurl${DEB_LIBCURL_VERSION}, libogg0, libvorbis0a, libvorbisfile3, libncursesw5, libasound2, libpulse0, pulseaudio, libmp3lame0, libev4,") - + if (${FFMPEG_DECODER} MATCHES "true") set(DEPENDENCIES "${DEPENDENCIES} libavcodec-extra, libavutil55, libavformat57, libswresample2") else() set(DEPENDENCIES "${DEPENDENCIES} libflac8, libfaad2") endif() - + set(CPACK_GENERATOR "DEB") set(CPACK_PACKAGE_DESCRIPTION "musikcube, a terminal-based music player and library") set(CPACK_PACKAGE_VERSION_MAJOR "${musikcube_VERSION_MAJOR}") diff --git a/src/core/audio/Stream.cpp b/src/core/audio/Stream.cpp index 951e82008..c0e33e4da 100644 --- a/src/core/audio/Stream.cpp +++ b/src/core/audio/Stream.cpp @@ -61,7 +61,7 @@ Stream::Stream(int samplesPerChannel, double bufferLengthSeconds, unsigned int o , capabilities(0) , rawBuffer(nullptr) { if ((this->options & NoDSP) == 0) { - streams::GetDspPlugins(); + dsps = streams::GetDspPlugins(); } this->decoderBuffer = new Buffer(); diff --git a/src/core/sdk/IDSP.h b/src/core/sdk/IDSP.h index bcde85779..cd9dfc390 100644 --- a/src/core/sdk/IDSP.h +++ b/src/core/sdk/IDSP.h @@ -41,7 +41,7 @@ namespace musik { namespace core { namespace sdk { class IDSP { public: virtual void Release() = 0; - virtual bool Process(IBuffer *buffer) = 0; + virtual bool Process(IBuffer* buffer) = 0; }; } } } diff --git a/src/plugins/supereqdsp/CMakeLists.txt b/src/plugins/supereqdsp/CMakeLists.txt new file mode 100644 index 000000000..5e8e6a4ab --- /dev/null +++ b/src/plugins/supereqdsp/CMakeLists.txt @@ -0,0 +1,9 @@ +set (nullout_SOURCES + supereq/Equ.cpp + supereq/Fftsg_fl.c + supereqdsp_plugin.cpp + SuperEqDsp.cpp +) + +add_library(supereqdsp SHARED ${nullout_SOURCES}) +target_link_libraries(supereqdsp ${musikcube_LINK_LIBS}) diff --git a/src/plugins/supereqdsp/SuperEqDsp.cpp b/src/plugins/supereqdsp/SuperEqDsp.cpp new file mode 100644 index 000000000..198e9cb6d --- /dev/null +++ b/src/plugins/supereqdsp/SuperEqDsp.cpp @@ -0,0 +1,86 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2007-2017 musikcube team +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of the author nor the names of other contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////////// + +#include "SuperEqDsp.h" + +#include +#include +#include + +using namespace musik::core::sdk; + +SuperEqDsp::SuperEqDsp() { + +} + +SuperEqDsp::~SuperEqDsp() { + if (this->supereq) { + equ_quit(this->supereq); + delete this->supereq; + } +} + +void SuperEqDsp::Release() { + delete this; +} + +bool SuperEqDsp::Process(IBuffer* buffer) { + int channels = buffer->Channels(); + + if (!this->supereq) { + this->supereq = new SuperEqState(); + equ_init(this->supereq, 10, channels); + + void *params = paramlist_alloc(); + float bands[18]; + + for (int i = 0; i < 18; i++) { + bands[i] = 1.0f; //i > 9 ? -0.0f : 1.0f; + } + + equ_makeTable( + this->supereq, + bands, + params, + buffer->SampleRate()); + + paramlist_free(params); + } + + return equ_modifySamples_float( + this->supereq, + (char*) buffer->BufferPointer(), + buffer->Samples() / channels, + channels) != 0; +} \ No newline at end of file diff --git a/src/plugins/supereqdsp/SuperEqDsp.h b/src/plugins/supereqdsp/SuperEqDsp.h new file mode 100644 index 000000000..338ba50dc --- /dev/null +++ b/src/plugins/supereqdsp/SuperEqDsp.h @@ -0,0 +1,51 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2007-2017 musikcube team +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of the author nor the names of other contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////////// +#pragma once + +#include +#include "supereq/Equ.h" + +using namespace musik::core::sdk; + +class SuperEqDsp : public IDSP { + public: + SuperEqDsp(); + ~SuperEqDsp(); + + virtual void Release() override; + virtual bool Process(IBuffer *buffer) override; + + private: + SuperEqState* supereq {nullptr}; +}; diff --git a/src/plugins/supereqdsp/supereq/COPYING b/src/plugins/supereqdsp/supereq/COPYING new file mode 100644 index 000000000..b7b70091e --- /dev/null +++ b/src/plugins/supereqdsp/supereq/COPYING @@ -0,0 +1,33 @@ +SuperEQ DSP plugin for DeaDBeeF Player +Copyright (C) 2009-2014 Alexey Yakovenko + +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 2 +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, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +The original SuperEQ code: + +Shibatch Super Equalizer ver 0.03 for winamp +written by Naoki Shibata shibatch@users.sourceforge.net +This program(except FFT part) is distributed under LGPL. See LGPL.txt for +details. + + +Ooura FFT implementation + +Copyright Takuya OOURA, 1996-2001 +http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html + +You may use, copy, modify and distribute this code for any purpose (include commercial use) and without fee. +Please refer to this package when you modify this code. diff --git a/src/plugins/supereqdsp/supereq/Equ.cpp b/src/plugins/supereqdsp/supereq/Equ.cpp new file mode 100644 index 000000000..e05359a6b --- /dev/null +++ b/src/plugins/supereqdsp/supereq/Equ.cpp @@ -0,0 +1,446 @@ +/* + SuperEQ DSP plugin for DeaDBeeF Player + Copyright (C) 2009-2014 Alexey Yakovenko + Original SuperEQ code (C) Naoki Shibata + + 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 2 + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#include +#include +#include +#include +#include "paramlist.hpp" +#include "Equ.h" + +extern "C" void rdft(int, int, REAL *, int *, REAL *); +void rfft(int n,int isign,REAL *x) +{ + static int ipsize = 0,wsize=0; + static int *ip = NULL; + static REAL *w = NULL; + int newipsize,newwsize; + if (n == 0) { + free(ip); ip = NULL; ipsize = 0; + free(w); w = NULL; wsize = 0; + return; + } + + n = 1 << n; + + + newipsize = 2+sqrt(n/2); + if (newipsize > ipsize) { + ipsize = newipsize; + ip = (int *)realloc(ip,sizeof(int)*ipsize); + ip[0] = 0; + } + + newwsize = n/2; + if (newwsize > wsize) { + wsize = newwsize; + w = (REAL *)realloc(w,sizeof(REAL)*wsize); + } + + rdft(n,isign,x,ip,w); +} + +#define PI 3.1415926535897932384626433832795 + +#define DITHERLEN 65536 + +#define M 15 +static REAL fact[M+1]; +static REAL aa = 96; +static REAL iza = 0; + +#define NBANDS 17 +static REAL bands[NBANDS] = { + 65.406392,92.498606,130.81278,184.99721,261.62557,369.99442,523.25113, + 739.9884 ,1046.5023,1479.9768,2093.0045,2959.9536,4186.0091,5919.9072, + 8372.0181,11839.814,16744.036 +}; + +static REAL alpha(REAL a) +{ + if (a <= 21) return 0; + if (a <= 50) return 0.5842*pow(a-21,0.4)+0.07886*(a-21); + return 0.1102*(a-8.7); +} + +static REAL izero(REAL x) +{ + REAL ret = 1; + int m; + + for(m=1;m<=M;m++) + { + REAL t; + t = pow(x/2,m)/fact[m]; + ret += t*t; + } + + return ret; +} + +void *equ_malloc (int size) { + return malloc (size); +} + +void equ_free (void *mem) { + free (mem); +} + +extern "C" void equ_init(SuperEqState *state, int wb, int channels) +{ + int i,j; + + if (state->lires1 != NULL) free(state->lires1); + if (state->lires2 != NULL) free(state->lires2); + if (state->irest != NULL) free(state->irest); + if (state->fsamples != NULL) free(state->fsamples); + if (state->finbuf != NULL) free(state->finbuf); + if (state->outbuf != NULL) free(state->outbuf); + if (state->ditherbuf != NULL) free(state->ditherbuf); + + + memset (state, 0, sizeof (SuperEqState)); + state->channels = channels; + state->enable = 1; + + state->winlen = (1 << (wb-1))-1; + state->winlenbit = wb; + state->tabsize = 1 << wb; + state->fft_bits = wb; + + state->lires1 = (REAL *)equ_malloc(sizeof(REAL)*state->tabsize * state->channels); + state->lires2 = (REAL *)equ_malloc(sizeof(REAL)*state->tabsize * state->channels); + state->irest = (REAL *)equ_malloc(sizeof(REAL)*state->tabsize); + state->fsamples = (REAL *)equ_malloc(sizeof(REAL)*state->tabsize); + state->finbuf = (REAL *)equ_malloc(state->winlen*state->channels*sizeof(REAL)); + state->outbuf = (REAL *)equ_malloc(state->tabsize*state->channels*sizeof(REAL)); + state->ditherbuf = (REAL *)equ_malloc(sizeof(REAL)*DITHERLEN); + + memset (state->lires1, 0, sizeof(REAL)*state->tabsize * state->channels); + memset (state->lires2, 0, sizeof(REAL)*state->tabsize * state->channels); + memset (state->irest, 0, sizeof(REAL)*state->tabsize); + memset (state->fsamples, 0, sizeof(REAL)*state->tabsize); + memset (state->finbuf, 0, state->winlen*state->channels*sizeof(REAL)); + memset (state->outbuf, 0, state->tabsize*state->channels*sizeof(REAL)); + memset (state->ditherbuf, 0, sizeof(REAL)*DITHERLEN); + + state->lires = state->lires1; + state->cur_ires = 1; + state->chg_ires = 1; + + for(i=0;iditherbuf[i] = (float(rand())/RAND_MAX-0.5); + + if (fact[0] < 1) { + for(i=0;i<=M;i++) + { + fact[i] = 1; + for(j=1;j<=i;j++) fact[i] *= j; + } + iza = izero(alpha(aa)); + } +} + +// -(N-1)/2 <= n <= (N-1)/2 +static REAL win(REAL n,int N) +{ + return izero(alpha(aa)*sqrt(1-4*n*n/((N-1)*(N-1))))/iza; +} + +static REAL sinc(REAL x) +{ + return x == 0 ? 1 : sin(x)/x; +} + +static REAL hn_lpf(int n,REAL f,REAL fs) +{ + REAL t = 1/fs; + REAL omega = 2*PI*f; + return 2*f*t*sinc(n*omega*t); +} + +static REAL hn_imp(int n) +{ + return n == 0 ? 1.0 : 0.0; +} + +static REAL hn(int n,paramlist ¶m2,REAL fs) +{ + paramlistelm *e; + REAL ret,lhn; + + lhn = hn_lpf(n,param2.elm->upper,fs); + ret = param2.elm->gain*lhn; + + for(e=param2.elm->next;e->next != NULL && e->upper < fs/2;e = e->next) + { + REAL lhn2 = hn_lpf(n,e->upper,fs); + ret += e->gain*(lhn2-lhn); + lhn = lhn2; + } + + ret += e->gain*(hn_imp(n)-lhn); + + return ret; +} + +void process_param(REAL *bc,paramlist *param,paramlist ¶m2,REAL fs,int ch) +{ + paramlistelm **pp,*p,*e,*e2; + int i; + + delete param2.elm; + param2.elm = NULL; + + for(i=0,pp=¶m2.elm;i<=NBANDS;i++,pp = &(*pp)->next) + { + (*pp) = new paramlistelm; + (*pp)->lower = i == 0 ? 0 : bands[i-1]; + (*pp)->upper = i == NBANDS ? fs : bands[i ]; + (*pp)->gain = bc[i]; + } + + for(e = param->elm;e != NULL;e = e->next) + { + if (e->lower >= e->upper) continue; + + for(p=param2.elm;p != NULL;p = p->next) + if (p->upper > e->lower) break; + + while(p != NULL && p->lower < e->upper) + { + if (e->lower <= p->lower && p->upper <= e->upper) { + p->gain *= pow(10,e->gain/20); + p = p->next; + continue; + } + if (p->lower < e->lower && e->upper < p->upper) { + e2 = new paramlistelm; + e2->lower = e->upper; + e2->upper = p->upper; + e2->gain = p->gain; + e2->next = p->next; + p->next = e2; + + e2 = new paramlistelm; + e2->lower = e->lower; + e2->upper = e->upper; + e2->gain = p->gain * pow(10,e->gain/20); + e2->next = p->next; + p->next = e2; + + p->upper = e->lower; + + p = p->next->next->next; + continue; + } + if (p->lower < e->lower) { + e2 = new paramlistelm; + e2->lower = e->lower; + e2->upper = p->upper; + e2->gain = p->gain * pow(10,e->gain/20); + e2->next = p->next; + p->next = e2; + + p->upper = e->lower; + p = p->next->next; + continue; + } + if (e->upper < p->upper) { + e2 = new paramlistelm; + e2->lower = e->upper; + e2->upper = p->upper; + e2->gain = p->gain; + e2->next = p->next; + p->next = e2; + + p->upper = e->upper; + p->gain = p->gain * pow(10,e->gain/20); + p = p->next->next; + continue; + } + abort(); + } + } +} + +extern "C" void equ_makeTable(SuperEqState *state, REAL *lbc,void *_param,REAL fs) +{ + paramlist *param = (paramlist *)_param; + int i,cires = state->cur_ires; + REAL *nires; + + if (fs <= 0) return; + + paramlist param2; + + for (int ch = 0; ch < state->channels; ch++) { + process_param(lbc,param,param2,fs,ch); + + for(i=0;iwinlen;i++) + state->irest[i] = hn(i-state->winlen/2,param2,fs)*win(i-state->winlen/2,state->winlen); + + for(;itabsize;i++) + state->irest[i] = 0; + + rfft(state->fft_bits,1,state->irest); + + nires = cires == 1 ? state->lires2 : state->lires1; + nires += ch * state->tabsize; + + for(i=0;itabsize;i++) + nires[i] = state->irest[i]; + } + state->chg_ires = cires == 1 ? 2 : 1; +} + +extern "C" void equ_quit(SuperEqState *state) +{ + equ_free(state->lires1); + equ_free(state->lires2); + equ_free(state->irest); + equ_free(state->fsamples); + equ_free(state->finbuf); + equ_free(state->outbuf); + equ_free(state->ditherbuf); + + state->lires1 = NULL; + state->lires2 = NULL; + state->irest = NULL; + state->fsamples = NULL; + state->finbuf = NULL; + state->outbuf = NULL; + + rfft(0,0,NULL); +} + +extern "C" void equ_clearbuf(SuperEqState *state) +{ + int i; + + state->nbufsamples = 0; + for(i=0;itabsize*state->channels;i++) state->outbuf[i] = 0; +} + +extern "C" int equ_modifySamples_float (SuperEqState *state, char *buf,int nsamples,int nch) +{ + int i,p,ch; + REAL *ires; + float amax = 1.0f; + float amin = -1.0f; + static float hm1 = 0, hm2 = 0; + + if (state->chg_ires) { + state->cur_ires = state->chg_ires; + state->lires = state->cur_ires == 1 ? state->lires1 : state->lires2; + state->chg_ires = 0; + } + + p = 0; + + while(state->nbufsamples+nsamples >= state->winlen) + { + for(i=0;i<(state->winlen-state->nbufsamples)*nch;i++) + { + state->finbuf[state->nbufsamples*nch+i] = ((float *)buf)[i+p*nch]; + float s = state->outbuf[state->nbufsamples*nch+i]; + //if (dither) s += ditherbuf[(ditherptr++) & (DITHERLEN-1)]; + if (s < amin) s = amin; + if (amax < s) s = amax; + ((float *)buf)[i+p*nch] = s; + } + for(i=state->winlen*nch;itabsize*nch;i++) + state->outbuf[i-state->winlen*nch] = state->outbuf[i]; + + + p += state->winlen-state->nbufsamples; + nsamples -= state->winlen-state->nbufsamples; + state->nbufsamples = 0; + + for(ch=0;chlires + ch * state->tabsize; + + for(i=0;iwinlen;i++) + state->fsamples[i] = state->finbuf[nch*i+ch]; + + for(i=state->winlen;itabsize;i++) + state->fsamples[i] = 0; + + if (state->enable) { + rfft(state->fft_bits,1,state->fsamples); + + state->fsamples[0] = ires[0]*state->fsamples[0]; + state->fsamples[1] = ires[1]*state->fsamples[1]; + + for(i=1;itabsize/2;i++) + { + REAL re,im; + + re = ires[i*2 ]*state->fsamples[i*2] - ires[i*2+1]*state->fsamples[i*2+1]; + im = ires[i*2+1]*state->fsamples[i*2] + ires[i*2 ]*state->fsamples[i*2+1]; + + state->fsamples[i*2 ] = re; + state->fsamples[i*2+1] = im; + } + + rfft(state->fft_bits,-1,state->fsamples); + } else { + for(i=state->winlen-1+state->winlen/2;i>=state->winlen/2;i--) state->fsamples[i] = state->fsamples[i-state->winlen/2]*state->tabsize/2; + for(;i>=0;i--) state->fsamples[i] = 0; + } + + for(i=0;iwinlen;i++) state->outbuf[i*nch+ch] += state->fsamples[i]/state->tabsize*2; + + for(i=state->winlen;itabsize;i++) state->outbuf[i*nch+ch] = state->fsamples[i]/state->tabsize*2; + } + } + + for(i=0;ifinbuf[state->nbufsamples*nch+i] = ((float *)buf)[i+p*nch]; + float s = state->outbuf[state->nbufsamples*nch+i]; + if (state->dither) { + float u; + s -= hm1; + u = s; +// s += ditherbuf[(ditherptr++) & (DITHERLEN-1)]; + if (s < amin) s = amin; + if (amax < s) s = amax; + hm1 = s - u; + ((float *)buf)[i+p*nch] = s; + } else { + if (s < amin) s = amin; + if (amax < s) s = amax; + ((float *)buf)[i+p*nch] = s; + } + } + + p += nsamples; + state->nbufsamples += nsamples; + + return p; +} + +extern "C" void *paramlist_alloc (void) { + return (void *)(new paramlist); +} +extern "C" void paramlist_free (void *pl) { + delete ((paramlist *)pl); +} diff --git a/src/plugins/supereqdsp/supereq/Equ.h b/src/plugins/supereqdsp/supereq/Equ.h new file mode 100644 index 000000000..2d34b7382 --- /dev/null +++ b/src/plugins/supereqdsp/supereq/Equ.h @@ -0,0 +1,56 @@ +/* + DeaDBeeF - The Ultimate Music Player + Copyright (C) 2009-2013 Alexey Yakovenko + + 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 2 + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#ifndef __EQU_H +#define __EQU_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef float REAL; +typedef struct { + REAL *lires,*lires1,*lires2; + REAL *irest; + REAL *fsamples; + REAL *ditherbuf; + int ditherptr; + volatile int chg_ires,cur_ires; + int winlen,winlenbit,tabsize,nbufsamples; + REAL *finbuf; + REAL *outbuf; + int dither; + int channels; + int enable; + int fft_bits; +} SuperEqState; + +void *paramlist_alloc (void); +void paramlist_free (void *); +void equ_makeTable(SuperEqState *state, float *lbc,void *param,float fs); +int equ_modifySamples(SuperEqState *state, char *buf,int nsamples,int nch,int bps); +int equ_modifySamples_float (SuperEqState *state, char *buf,int nsamples,int nch); +void equ_clearbuf(SuperEqState *state); +void equ_init(SuperEqState *state, int wb, int channels); +void equ_quit(SuperEqState *state); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/plugins/supereqdsp/supereq/Fftsg_fl.c b/src/plugins/supereqdsp/supereq/Fftsg_fl.c new file mode 100644 index 000000000..a873f793a --- /dev/null +++ b/src/plugins/supereqdsp/supereq/Fftsg_fl.c @@ -0,0 +1,2650 @@ +/* + Copyright Takuya OOURA, 1996-2001 + http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html + + You may use, copy, modify and distribute this code for any purpose (include commercial use) and without fee. + Please refer to this package when you modify this code. +*/ +#include + +typedef float REAL; + +/* +Fast Fourier/Cosine/Sine Transform + dimension :one + data length :power of 2 + decimation :frequency + radix :split-radix + data :inplace + table :use +functions + cdft: Complex Discrete Fourier Transform + rdft: Real Discrete Fourier Transform + ddct: Discrete Cosine Transform + ddst: Discrete Sine Transform + dfct: Cosine Transform of RDFT (Real Symmetric DFT) + dfst: Sine Transform of RDFT (Real Anti-symmetric DFT) +function prototypes + void cdft(int, int, REAL *, int *, REAL *); + void rdft(int, int, REAL *, int *, REAL *); + void ddct(int, int, REAL *, int *, REAL *); + void ddst(int, int, REAL *, int *, REAL *); + void dfct(int, REAL *, REAL *, int *, REAL *); + void dfst(int, REAL *, REAL *, int *, REAL *); + + +-------- Complex DFT (Discrete Fourier Transform) -------- + [definition] + + X[k] = sum_j=0^n-1 x[j]*exp(2*pi*i*j*k/n), 0<=k + X[k] = sum_j=0^n-1 x[j]*exp(-2*pi*i*j*k/n), 0<=k + ip[0] = 0; // first time only + cdft(2*n, 1, a, ip, w); + + ip[0] = 0; // first time only + cdft(2*n, -1, a, ip, w); + [parameters] + 2*n :data length (int) + n >= 1, n = power of 2 + a[0...2*n-1] :input/output data (REAL *) + input data + a[2*j] = Re(x[j]), + a[2*j+1] = Im(x[j]), 0<=j= 2+sqrt(n) + strictly, + length of ip >= + 2+(1<<(int)(log(n+0.5)/log(2))/2). + ip[0],ip[1] are pointers of the cos/sin table. + w[0...n/2-1] :cos/sin table (REAL *) + w[],ip[] are initialized if ip[0] == 0. + [remark] + Inverse of + cdft(2*n, -1, a, ip, w); + is + cdft(2*n, 1, a, ip, w); + for (j = 0; j <= 2 * n - 1; j++) { + a[j] *= 1.0 / n; + } + . + + +-------- Real DFT / Inverse of Real DFT -------- + [definition] + RDFT + R[k] = sum_j=0^n-1 a[j]*cos(2*pi*j*k/n), 0<=k<=n/2 + I[k] = sum_j=0^n-1 a[j]*sin(2*pi*j*k/n), 0 IRDFT (excluding scale) + a[k] = (R[0] + R[n/2]*cos(pi*k))/2 + + sum_j=1^n/2-1 R[j]*cos(2*pi*j*k/n) + + sum_j=1^n/2-1 I[j]*sin(2*pi*j*k/n), 0<=k + ip[0] = 0; // first time only + rdft(n, 1, a, ip, w); + + ip[0] = 0; // first time only + rdft(n, -1, a, ip, w); + [parameters] + n :data length (int) + n >= 2, n = power of 2 + a[0...n-1] :input/output data (REAL *) + + output data + a[2*k] = R[k], 0<=k + input data + a[2*j] = R[j], 0<=j= 2+sqrt(n/2) + strictly, + length of ip >= + 2+(1<<(int)(log(n/2+0.5)/log(2))/2). + ip[0],ip[1] are pointers of the cos/sin table. + w[0...n/2-1] :cos/sin table (REAL *) + w[],ip[] are initialized if ip[0] == 0. + [remark] + Inverse of + rdft(n, 1, a, ip, w); + is + rdft(n, -1, a, ip, w); + for (j = 0; j <= n - 1; j++) { + a[j] *= 2.0 / n; + } + . + + +-------- DCT (Discrete Cosine Transform) / Inverse of DCT -------- + [definition] + IDCT (excluding scale) + C[k] = sum_j=0^n-1 a[j]*cos(pi*j*(k+1/2)/n), 0<=k DCT + C[k] = sum_j=0^n-1 a[j]*cos(pi*(j+1/2)*k/n), 0<=k + ip[0] = 0; // first time only + ddct(n, 1, a, ip, w); + + ip[0] = 0; // first time only + ddct(n, -1, a, ip, w); + [parameters] + n :data length (int) + n >= 2, n = power of 2 + a[0...n-1] :input/output data (REAL *) + output data + a[k] = C[k], 0<=k= 2+sqrt(n/2) + strictly, + length of ip >= + 2+(1<<(int)(log(n/2+0.5)/log(2))/2). + ip[0],ip[1] are pointers of the cos/sin table. + w[0...n*5/4-1] :cos/sin table (REAL *) + w[],ip[] are initialized if ip[0] == 0. + [remark] + Inverse of + ddct(n, -1, a, ip, w); + is + a[0] *= 0.5; + ddct(n, 1, a, ip, w); + for (j = 0; j <= n - 1; j++) { + a[j] *= 2.0 / n; + } + . + + +-------- DST (Discrete Sine Transform) / Inverse of DST -------- + [definition] + IDST (excluding scale) + S[k] = sum_j=1^n A[j]*sin(pi*j*(k+1/2)/n), 0<=k DST + S[k] = sum_j=0^n-1 a[j]*sin(pi*(j+1/2)*k/n), 0 + ip[0] = 0; // first time only + ddst(n, 1, a, ip, w); + + ip[0] = 0; // first time only + ddst(n, -1, a, ip, w); + [parameters] + n :data length (int) + n >= 2, n = power of 2 + a[0...n-1] :input/output data (REAL *) + + input data + a[j] = A[j], 0 + output data + a[k] = S[k], 0= 2+sqrt(n/2) + strictly, + length of ip >= + 2+(1<<(int)(log(n/2+0.5)/log(2))/2). + ip[0],ip[1] are pointers of the cos/sin table. + w[0...n*5/4-1] :cos/sin table (REAL *) + w[],ip[] are initialized if ip[0] == 0. + [remark] + Inverse of + ddst(n, -1, a, ip, w); + is + a[0] *= 0.5; + ddst(n, 1, a, ip, w); + for (j = 0; j <= n - 1; j++) { + a[j] *= 2.0 / n; + } + . + + +-------- Cosine Transform of RDFT (Real Symmetric DFT) -------- + [definition] + C[k] = sum_j=0^n a[j]*cos(pi*j*k/n), 0<=k<=n + [usage] + ip[0] = 0; // first time only + dfct(n, a, t, ip, w); + [parameters] + n :data length - 1 (int) + n >= 2, n = power of 2 + a[0...n] :input/output data (REAL *) + output data + a[k] = C[k], 0<=k<=n + t[0...n/2] :work area (REAL *) + ip[0...*] :work area for bit reversal (int *) + length of ip >= 2+sqrt(n/4) + strictly, + length of ip >= + 2+(1<<(int)(log(n/4+0.5)/log(2))/2). + ip[0],ip[1] are pointers of the cos/sin table. + w[0...n*5/8-1] :cos/sin table (REAL *) + w[],ip[] are initialized if ip[0] == 0. + [remark] + Inverse of + a[0] *= 0.5; + a[n] *= 0.5; + dfct(n, a, t, ip, w); + is + a[0] *= 0.5; + a[n] *= 0.5; + dfct(n, a, t, ip, w); + for (j = 0; j <= n; j++) { + a[j] *= 2.0 / n; + } + . + + +-------- Sine Transform of RDFT (Real Anti-symmetric DFT) -------- + [definition] + S[k] = sum_j=1^n-1 a[j]*sin(pi*j*k/n), 0= 2, n = power of 2 + a[0...n-1] :input/output data (REAL *) + output data + a[k] = S[k], 0= 2+sqrt(n/4) + strictly, + length of ip >= + 2+(1<<(int)(log(n/4+0.5)/log(2))/2). + ip[0],ip[1] are pointers of the cos/sin table. + w[0...n*5/8-1] :cos/sin table (REAL *) + w[],ip[] are initialized if ip[0] == 0. + [remark] + Inverse of + dfst(n, a, t, ip, w); + is + dfst(n, a, t, ip, w); + for (j = 1; j <= n - 1; j++) { + a[j] *= 2.0 / n; + } + . + + +Appendix : + The cos/sin table is recalculated when the larger table required. + w[] and ip[] are compatible with all routines. +*/ + +void cdft(int n, int isgn, REAL *a, int *ip, REAL *w) +{ + void makewt(int nw, int *ip, REAL *w); + void cftfsub(int n, REAL *a, int *ip, int nw, REAL *w); + void cftbsub(int n, REAL *a, int *ip, int nw, REAL *w); + int nw; + + nw = ip[0]; + if (n > (nw << 2)) { + nw = n >> 2; + makewt(nw, ip, w); + } + if (isgn >= 0) { + cftfsub(n, a, ip + 2, nw, w); + } else { + cftbsub(n, a, ip + 2, nw, w); + } +} + + +void rdft(int n, int isgn, REAL *a, int *ip, REAL *w) +{ + void makewt(int nw, int *ip, REAL *w); + void makect(int nc, int *ip, REAL *c); + void cftfsub(int n, REAL *a, int *ip, int nw, REAL *w); + void cftbsub(int n, REAL *a, int *ip, int nw, REAL *w); + void rftfsub(int n, REAL *a, int nc, REAL *c); + void rftbsub(int n, REAL *a, int nc, REAL *c); + int nw, nc; + REAL xi; + + nw = ip[0]; + if (n > (nw << 2)) { + nw = n >> 2; + makewt(nw, ip, w); + } + nc = ip[1]; + if (n > (nc << 2)) { + nc = n >> 2; + makect(nc, ip, w + nw); + } + if (isgn >= 0) { + if (n > 4) { + cftfsub(n, a, ip + 2, nw, w); + rftfsub(n, a, nc, w + nw); + } else if (n == 4) { + cftfsub(n, a, ip + 2, nw, w); + } + xi = a[0] - a[1]; + a[0] += a[1]; + a[1] = xi; + } else { + a[1] = 0.5 * (a[0] - a[1]); + a[0] -= a[1]; + if (n > 4) { + rftbsub(n, a, nc, w + nw); + cftbsub(n, a, ip + 2, nw, w); + } else if (n == 4) { + cftbsub(n, a, ip + 2, nw, w); + } + } +} + + +void ddct(int n, int isgn, REAL *a, int *ip, REAL *w) +{ + void makewt(int nw, int *ip, REAL *w); + void makect(int nc, int *ip, REAL *c); + void cftfsub(int n, REAL *a, int *ip, int nw, REAL *w); + void cftbsub(int n, REAL *a, int *ip, int nw, REAL *w); + void rftfsub(int n, REAL *a, int nc, REAL *c); + void rftbsub(int n, REAL *a, int nc, REAL *c); + void dctsub(int n, REAL *a, int nc, REAL *c); + int j, nw, nc; + REAL xr; + + nw = ip[0]; + if (n > (nw << 2)) { + nw = n >> 2; + makewt(nw, ip, w); + } + nc = ip[1]; + if (n > nc) { + nc = n; + makect(nc, ip, w + nw); + } + if (isgn < 0) { + xr = a[n - 1]; + for (j = n - 2; j >= 2; j -= 2) { + a[j + 1] = a[j] - a[j - 1]; + a[j] += a[j - 1]; + } + a[1] = a[0] - xr; + a[0] += xr; + if (n > 4) { + rftbsub(n, a, nc, w + nw); + cftbsub(n, a, ip + 2, nw, w); + } else if (n == 4) { + cftbsub(n, a, ip + 2, nw, w); + } + } + dctsub(n, a, nc, w + nw); + if (isgn >= 0) { + if (n > 4) { + cftfsub(n, a, ip + 2, nw, w); + rftfsub(n, a, nc, w + nw); + } else if (n == 4) { + cftfsub(n, a, ip + 2, nw, w); + } + xr = a[0] - a[1]; + a[0] += a[1]; + for (j = 2; j < n; j += 2) { + a[j - 1] = a[j] - a[j + 1]; + a[j] += a[j + 1]; + } + a[n - 1] = xr; + } +} + + +void ddst(int n, int isgn, REAL *a, int *ip, REAL *w) +{ + void makewt(int nw, int *ip, REAL *w); + void makect(int nc, int *ip, REAL *c); + void cftfsub(int n, REAL *a, int *ip, int nw, REAL *w); + void cftbsub(int n, REAL *a, int *ip, int nw, REAL *w); + void rftfsub(int n, REAL *a, int nc, REAL *c); + void rftbsub(int n, REAL *a, int nc, REAL *c); + void dstsub(int n, REAL *a, int nc, REAL *c); + int j, nw, nc; + REAL xr; + + nw = ip[0]; + if (n > (nw << 2)) { + nw = n >> 2; + makewt(nw, ip, w); + } + nc = ip[1]; + if (n > nc) { + nc = n; + makect(nc, ip, w + nw); + } + if (isgn < 0) { + xr = a[n - 1]; + for (j = n - 2; j >= 2; j -= 2) { + a[j + 1] = -a[j] - a[j - 1]; + a[j] -= a[j - 1]; + } + a[1] = a[0] + xr; + a[0] -= xr; + if (n > 4) { + rftbsub(n, a, nc, w + nw); + cftbsub(n, a, ip + 2, nw, w); + } else if (n == 4) { + cftbsub(n, a, ip + 2, nw, w); + } + } + dstsub(n, a, nc, w + nw); + if (isgn >= 0) { + if (n > 4) { + cftfsub(n, a, ip + 2, nw, w); + rftfsub(n, a, nc, w + nw); + } else if (n == 4) { + cftfsub(n, a, ip + 2, nw, w); + } + xr = a[0] - a[1]; + a[0] += a[1]; + for (j = 2; j < n; j += 2) { + a[j - 1] = -a[j] - a[j + 1]; + a[j] -= a[j + 1]; + } + a[n - 1] = -xr; + } +} + + +void dfct(int n, REAL *a, REAL *t, int *ip, REAL *w) +{ + void makewt(int nw, int *ip, REAL *w); + void makect(int nc, int *ip, REAL *c); + void cftfsub(int n, REAL *a, int *ip, int nw, REAL *w); + void rftfsub(int n, REAL *a, int nc, REAL *c); + void dctsub(int n, REAL *a, int nc, REAL *c); + int j, k, l, m, mh, nw, nc; + REAL xr, xi, yr, yi; + + nw = ip[0]; + if (n > (nw << 3)) { + nw = n >> 3; + makewt(nw, ip, w); + } + nc = ip[1]; + if (n > (nc << 1)) { + nc = n >> 1; + makect(nc, ip, w + nw); + } + m = n >> 1; + yi = a[m]; + xi = a[0] + a[n]; + a[0] -= a[n]; + t[0] = xi - yi; + t[m] = xi + yi; + if (n > 2) { + mh = m >> 1; + for (j = 1; j < mh; j++) { + k = m - j; + xr = a[j] - a[n - j]; + xi = a[j] + a[n - j]; + yr = a[k] - a[n - k]; + yi = a[k] + a[n - k]; + a[j] = xr; + a[k] = yr; + t[j] = xi - yi; + t[k] = xi + yi; + } + t[mh] = a[mh] + a[n - mh]; + a[mh] -= a[n - mh]; + dctsub(m, a, nc, w + nw); + if (m > 4) { + cftfsub(m, a, ip + 2, nw, w); + rftfsub(m, a, nc, w + nw); + } else if (m == 4) { + cftfsub(m, a, ip + 2, nw, w); + } + a[n - 1] = a[0] - a[1]; + a[1] = a[0] + a[1]; + for (j = m - 2; j >= 2; j -= 2) { + a[2 * j + 1] = a[j] + a[j + 1]; + a[2 * j - 1] = a[j] - a[j + 1]; + } + l = 2; + m = mh; + while (m >= 2) { + dctsub(m, t, nc, w + nw); + if (m > 4) { + cftfsub(m, t, ip + 2, nw, w); + rftfsub(m, t, nc, w + nw); + } else if (m == 4) { + cftfsub(m, t, ip + 2, nw, w); + } + a[n - l] = t[0] - t[1]; + a[l] = t[0] + t[1]; + k = 0; + for (j = 2; j < m; j += 2) { + k += l << 2; + a[k - l] = t[j] - t[j + 1]; + a[k + l] = t[j] + t[j + 1]; + } + l <<= 1; + mh = m >> 1; + for (j = 0; j < mh; j++) { + k = m - j; + t[j] = t[m + k] - t[m + j]; + t[k] = t[m + k] + t[m + j]; + } + t[mh] = t[m + mh]; + m = mh; + } + a[l] = t[0]; + a[n] = t[2] - t[1]; + a[0] = t[2] + t[1]; + } else { + a[1] = a[0]; + a[2] = t[0]; + a[0] = t[1]; + } +} + + +void dfst(int n, REAL *a, REAL *t, int *ip, REAL *w) +{ + void makewt(int nw, int *ip, REAL *w); + void makect(int nc, int *ip, REAL *c); + void cftfsub(int n, REAL *a, int *ip, int nw, REAL *w); + void rftfsub(int n, REAL *a, int nc, REAL *c); + void dstsub(int n, REAL *a, int nc, REAL *c); + int j, k, l, m, mh, nw, nc; + REAL xr, xi, yr, yi; + + nw = ip[0]; + if (n > (nw << 3)) { + nw = n >> 3; + makewt(nw, ip, w); + } + nc = ip[1]; + if (n > (nc << 1)) { + nc = n >> 1; + makect(nc, ip, w + nw); + } + if (n > 2) { + m = n >> 1; + mh = m >> 1; + for (j = 1; j < mh; j++) { + k = m - j; + xr = a[j] + a[n - j]; + xi = a[j] - a[n - j]; + yr = a[k] + a[n - k]; + yi = a[k] - a[n - k]; + a[j] = xr; + a[k] = yr; + t[j] = xi + yi; + t[k] = xi - yi; + } + t[0] = a[mh] - a[n - mh]; + a[mh] += a[n - mh]; + a[0] = a[m]; + dstsub(m, a, nc, w + nw); + if (m > 4) { + cftfsub(m, a, ip + 2, nw, w); + rftfsub(m, a, nc, w + nw); + } else if (m == 4) { + cftfsub(m, a, ip + 2, nw, w); + } + a[n - 1] = a[1] - a[0]; + a[1] = a[0] + a[1]; + for (j = m - 2; j >= 2; j -= 2) { + a[2 * j + 1] = a[j] - a[j + 1]; + a[2 * j - 1] = -a[j] - a[j + 1]; + } + l = 2; + m = mh; + while (m >= 2) { + dstsub(m, t, nc, w + nw); + if (m > 4) { + cftfsub(m, t, ip + 2, nw, w); + rftfsub(m, t, nc, w + nw); + } else if (m == 4) { + cftfsub(m, t, ip + 2, nw, w); + } + a[n - l] = t[1] - t[0]; + a[l] = t[0] + t[1]; + k = 0; + for (j = 2; j < m; j += 2) { + k += l << 2; + a[k - l] = -t[j] - t[j + 1]; + a[k + l] = t[j] - t[j + 1]; + } + l <<= 1; + mh = m >> 1; + for (j = 1; j < mh; j++) { + k = m - j; + t[j] = t[m + k] + t[m + j]; + t[k] = t[m + k] - t[m + j]; + } + t[0] = t[m + mh]; + m = mh; + } + a[l] = t[0]; + } + a[0] = 0; +} + + +/* -------- initializing routines -------- */ + + +#include + +void makewt(int nw, int *ip, REAL *w) +{ + int j, nwh, nw0, nw1; + REAL delta, wn4r, wk1r, wk1i, wk3r, wk3i; + + ip[0] = nw; + ip[1] = 1; + if (nw > 2) { + nwh = nw >> 1; + delta = atan(1.0) / nwh; + wn4r = cos(delta * nwh); + w[0] = 1; + w[1] = wn4r; + if (nwh >= 4) { + w[2] = 0.5 / cos(delta * 2); + w[3] = 0.5 / cos(delta * 6); + } + for (j = 4; j < nwh; j += 4) { + w[j] = cos(delta * j); + w[j + 1] = sin(delta * j); + w[j + 2] = cos(3 * delta * j); + w[j + 3] = sin(3 * delta * j); + } + nw0 = 0; + while (nwh > 2) { + nw1 = nw0 + nwh; + nwh >>= 1; + w[nw1] = 1; + w[nw1 + 1] = wn4r; + if (nwh >= 4) { + wk1r = w[nw0 + 4]; + wk3r = w[nw0 + 6]; + w[nw1 + 2] = 0.5 / wk1r; + w[nw1 + 3] = 0.5 / wk3r; + } + for (j = 4; j < nwh; j += 4) { + wk1r = w[nw0 + 2 * j]; + wk1i = w[nw0 + 2 * j + 1]; + wk3r = w[nw0 + 2 * j + 2]; + wk3i = w[nw0 + 2 * j + 3]; + w[nw1 + j] = wk1r; + w[nw1 + j + 1] = wk1i; + w[nw1 + j + 2] = wk3r; + w[nw1 + j + 3] = wk3i; + } + nw0 = nw1; + } + } +} + + +void makect(int nc, int *ip, REAL *c) +{ + int j, nch; + REAL delta; + + ip[1] = nc; + if (nc > 1) { + nch = nc >> 1; + delta = atan(1.0) / nch; + c[0] = cos(delta * nch); + c[nch] = 0.5 * c[0]; + for (j = 1; j < nch; j++) { + c[j] = 0.5 * cos(delta * j); + c[nc - j] = 0.5 * sin(delta * j); + } + } +} + + +/* -------- child routines -------- */ + + +#ifndef CDFT_RECURSIVE_N /* length of the recursive FFT mode */ +#define CDFT_RECURSIVE_N 512 /* <= (L1 cache size) / 16 */ +#endif + + +void cftfsub(int n, REAL *a, int *ip, int nw, REAL *w) +{ + void bitrv2(int n, int *ip, REAL *a); + void bitrv216(REAL *a); + void bitrv208(REAL *a); + void cftf1st(int n, REAL *a, REAL *w); + void cftrec1(int n, REAL *a, int nw, REAL *w); + void cftrec2(int n, REAL *a, int nw, REAL *w); + void cftexp1(int n, REAL *a, int nw, REAL *w); + void cftfx41(int n, REAL *a, int nw, REAL *w); + void cftf161(REAL *a, REAL *w); + void cftf081(REAL *a, REAL *w); + void cftf040(REAL *a); + void cftx020(REAL *a); + int m; + + if (n > 32) { + m = n >> 2; + cftf1st(n, a, &w[nw - m]); + if (n > CDFT_RECURSIVE_N) { + cftrec1(m, a, nw, w); + cftrec2(m, &a[m], nw, w); + cftrec1(m, &a[2 * m], nw, w); + cftrec1(m, &a[3 * m], nw, w); + } else if (m > 32) { + cftexp1(n, a, nw, w); + } else { + cftfx41(n, a, nw, w); + } + bitrv2(n, ip, a); + } else if (n > 8) { + if (n == 32) { + cftf161(a, &w[nw - 8]); + bitrv216(a); + } else { + cftf081(a, w); + bitrv208(a); + } + } else if (n == 8) { + cftf040(a); + } else if (n == 4) { + cftx020(a); + } +} + + +void cftbsub(int n, REAL *a, int *ip, int nw, REAL *w) +{ + void bitrv2conj(int n, int *ip, REAL *a); + void bitrv216neg(REAL *a); + void bitrv208neg(REAL *a); + void cftb1st(int n, REAL *a, REAL *w); + void cftrec1(int n, REAL *a, int nw, REAL *w); + void cftrec2(int n, REAL *a, int nw, REAL *w); + void cftexp1(int n, REAL *a, int nw, REAL *w); + void cftfx41(int n, REAL *a, int nw, REAL *w); + void cftf161(REAL *a, REAL *w); + void cftf081(REAL *a, REAL *w); + void cftb040(REAL *a); + void cftx020(REAL *a); + int m; + + if (n > 32) { + m = n >> 2; + cftb1st(n, a, &w[nw - m]); + if (n > CDFT_RECURSIVE_N) { + cftrec1(m, a, nw, w); + cftrec2(m, &a[m], nw, w); + cftrec1(m, &a[2 * m], nw, w); + cftrec1(m, &a[3 * m], nw, w); + } else if (m > 32) { + cftexp1(n, a, nw, w); + } else { + cftfx41(n, a, nw, w); + } + bitrv2conj(n, ip, a); + } else if (n > 8) { + if (n == 32) { + cftf161(a, &w[nw - 8]); + bitrv216neg(a); + } else { + cftf081(a, w); + bitrv208neg(a); + } + } else if (n == 8) { + cftb040(a); + } else if (n == 4) { + cftx020(a); + } +} + + +void bitrv2(int n, int *ip, REAL *a) +{ + int j, j1, k, k1, l, m, m2; + REAL xr, xi, yr, yi; + + ip[0] = 0; + l = n; + m = 1; + while ((m << 3) < l) { + l >>= 1; + for (j = 0; j < m; j++) { + ip[m + j] = ip[j] + l; + } + m <<= 1; + } + m2 = 2 * m; + if ((m << 3) == l) { + for (k = 0; k < m; k++) { + for (j = 0; j < k; j++) { + j1 = 2 * j + ip[k]; + k1 = 2 * k + ip[j]; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m2; + k1 += 2 * m2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m2; + k1 -= m2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m2; + k1 += 2 * m2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + } + j1 = 2 * k + m2 + ip[k]; + k1 = j1 + m2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + } + } else { + for (k = 1; k < m; k++) { + for (j = 0; j < k; j++) { + j1 = 2 * j + ip[k]; + k1 = 2 * k + ip[j]; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m2; + k1 += m2; + xr = a[j1]; + xi = a[j1 + 1]; + yr = a[k1]; + yi = a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + } + } + } +} + + +void bitrv2conj(int n, int *ip, REAL *a) +{ + int j, j1, k, k1, l, m, m2; + REAL xr, xi, yr, yi; + + ip[0] = 0; + l = n; + m = 1; + while ((m << 3) < l) { + l >>= 1; + for (j = 0; j < m; j++) { + ip[m + j] = ip[j] + l; + } + m <<= 1; + } + m2 = 2 * m; + if ((m << 3) == l) { + for (k = 0; k < m; k++) { + for (j = 0; j < k; j++) { + j1 = 2 * j + ip[k]; + k1 = 2 * k + ip[j]; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m2; + k1 += 2 * m2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m2; + k1 -= m2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m2; + k1 += 2 * m2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + } + k1 = 2 * k + ip[k]; + a[k1 + 1] = -a[k1 + 1]; + j1 = k1 + m2; + k1 = j1 + m2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + k1 += m2; + a[k1 + 1] = -a[k1 + 1]; + } + } else { + a[1] = -a[1]; + a[m2 + 1] = -a[m2 + 1]; + for (k = 1; k < m; k++) { + for (j = 0; j < k; j++) { + j1 = 2 * j + ip[k]; + k1 = 2 * k + ip[j]; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m2; + k1 += m2; + xr = a[j1]; + xi = -a[j1 + 1]; + yr = a[k1]; + yi = -a[k1 + 1]; + a[j1] = yr; + a[j1 + 1] = yi; + a[k1] = xr; + a[k1 + 1] = xi; + } + k1 = 2 * k + ip[k]; + a[k1 + 1] = -a[k1 + 1]; + a[k1 + m2 + 1] = -a[k1 + m2 + 1]; + } + } +} + + +void bitrv216(REAL *a) +{ + REAL x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, + x5r, x5i, x7r, x7i, x8r, x8i, x10r, x10i, + x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i; + + x1r = a[2]; + x1i = a[3]; + x2r = a[4]; + x2i = a[5]; + x3r = a[6]; + x3i = a[7]; + x4r = a[8]; + x4i = a[9]; + x5r = a[10]; + x5i = a[11]; + x7r = a[14]; + x7i = a[15]; + x8r = a[16]; + x8i = a[17]; + x10r = a[20]; + x10i = a[21]; + x11r = a[22]; + x11i = a[23]; + x12r = a[24]; + x12i = a[25]; + x13r = a[26]; + x13i = a[27]; + x14r = a[28]; + x14i = a[29]; + a[2] = x8r; + a[3] = x8i; + a[4] = x4r; + a[5] = x4i; + a[6] = x12r; + a[7] = x12i; + a[8] = x2r; + a[9] = x2i; + a[10] = x10r; + a[11] = x10i; + a[14] = x14r; + a[15] = x14i; + a[16] = x1r; + a[17] = x1i; + a[20] = x5r; + a[21] = x5i; + a[22] = x13r; + a[23] = x13i; + a[24] = x3r; + a[25] = x3i; + a[26] = x11r; + a[27] = x11i; + a[28] = x7r; + a[29] = x7i; +} + + +void bitrv216neg(REAL *a) +{ + REAL x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, + x5r, x5i, x6r, x6i, x7r, x7i, x8r, x8i, + x9r, x9i, x10r, x10i, x11r, x11i, x12r, x12i, + x13r, x13i, x14r, x14i, x15r, x15i; + + x1r = a[2]; + x1i = a[3]; + x2r = a[4]; + x2i = a[5]; + x3r = a[6]; + x3i = a[7]; + x4r = a[8]; + x4i = a[9]; + x5r = a[10]; + x5i = a[11]; + x6r = a[12]; + x6i = a[13]; + x7r = a[14]; + x7i = a[15]; + x8r = a[16]; + x8i = a[17]; + x9r = a[18]; + x9i = a[19]; + x10r = a[20]; + x10i = a[21]; + x11r = a[22]; + x11i = a[23]; + x12r = a[24]; + x12i = a[25]; + x13r = a[26]; + x13i = a[27]; + x14r = a[28]; + x14i = a[29]; + x15r = a[30]; + x15i = a[31]; + a[2] = x15r; + a[3] = x15i; + a[4] = x7r; + a[5] = x7i; + a[6] = x11r; + a[7] = x11i; + a[8] = x3r; + a[9] = x3i; + a[10] = x13r; + a[11] = x13i; + a[12] = x5r; + a[13] = x5i; + a[14] = x9r; + a[15] = x9i; + a[16] = x1r; + a[17] = x1i; + a[18] = x14r; + a[19] = x14i; + a[20] = x6r; + a[21] = x6i; + a[22] = x10r; + a[23] = x10i; + a[24] = x2r; + a[25] = x2i; + a[26] = x12r; + a[27] = x12i; + a[28] = x4r; + a[29] = x4i; + a[30] = x8r; + a[31] = x8i; +} + + +void bitrv208(REAL *a) +{ + REAL x1r, x1i, x3r, x3i, x4r, x4i, x6r, x6i; + + x1r = a[2]; + x1i = a[3]; + x3r = a[6]; + x3i = a[7]; + x4r = a[8]; + x4i = a[9]; + x6r = a[12]; + x6i = a[13]; + a[2] = x4r; + a[3] = x4i; + a[6] = x6r; + a[7] = x6i; + a[8] = x1r; + a[9] = x1i; + a[12] = x3r; + a[13] = x3i; +} + + +void bitrv208neg(REAL *a) +{ + REAL x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, + x5r, x5i, x6r, x6i, x7r, x7i; + + x1r = a[2]; + x1i = a[3]; + x2r = a[4]; + x2i = a[5]; + x3r = a[6]; + x3i = a[7]; + x4r = a[8]; + x4i = a[9]; + x5r = a[10]; + x5i = a[11]; + x6r = a[12]; + x6i = a[13]; + x7r = a[14]; + x7i = a[15]; + a[2] = x7r; + a[3] = x7i; + a[4] = x3r; + a[5] = x3i; + a[6] = x5r; + a[7] = x5i; + a[8] = x1r; + a[9] = x1i; + a[10] = x6r; + a[11] = x6i; + a[12] = x2r; + a[13] = x2i; + a[14] = x4r; + a[15] = x4i; +} + + +void cftf1st(int n, REAL *a, REAL *w) +{ + int j, j0, j1, j2, j3, k, m, mh; + REAL wn4r, csc1, csc3, wk1r, wk1i, wk3r, wk3i, + wd1r, wd1i, wd3r, wd3i; + REAL x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, + y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i; + + mh = n >> 3; + m = 2 * mh; + j1 = m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[0] + a[j2]; + x0i = a[1] + a[j2 + 1]; + x1r = a[0] - a[j2]; + x1i = a[1] - a[j2 + 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + a[0] = x0r + x2r; + a[1] = x0i + x2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i - x2i; + a[j2] = x1r - x3i; + a[j2 + 1] = x1i + x3r; + a[j3] = x1r + x3i; + a[j3 + 1] = x1i - x3r; + wn4r = w[1]; + csc1 = w[2]; + csc3 = w[3]; + wd1r = 1; + wd1i = 0; + wd3r = 1; + wd3i = 0; + k = 0; + for (j = 2; j < mh - 2; j += 4) { + k += 4; + wk1r = csc1 * (wd1r + w[k]); + wk1i = csc1 * (wd1i + w[k + 1]); + wk3r = csc3 * (wd3r + w[k + 2]); + wk3i = csc3 * (wd3i - w[k + 3]); + wd1r = w[k]; + wd1i = w[k + 1]; + wd3r = w[k + 2]; + wd3i = -w[k + 3]; + j1 = j + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j] + a[j2]; + x0i = a[j + 1] + a[j2 + 1]; + x1r = a[j] - a[j2]; + x1i = a[j + 1] - a[j2 + 1]; + y0r = a[j + 2] + a[j2 + 2]; + y0i = a[j + 3] + a[j2 + 3]; + y1r = a[j + 2] - a[j2 + 2]; + y1i = a[j + 3] - a[j2 + 3]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + y2r = a[j1 + 2] + a[j3 + 2]; + y2i = a[j1 + 3] + a[j3 + 3]; + y3r = a[j1 + 2] - a[j3 + 2]; + y3i = a[j1 + 3] - a[j3 + 3]; + a[j] = x0r + x2r; + a[j + 1] = x0i + x2i; + a[j + 2] = y0r + y2r; + a[j + 3] = y0i + y2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i - x2i; + a[j1 + 2] = y0r - y2r; + a[j1 + 3] = y0i - y2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j2] = wk1r * x0r - wk1i * x0i; + a[j2 + 1] = wk1r * x0i + wk1i * x0r; + x0r = y1r - y3i; + x0i = y1i + y3r; + a[j2 + 2] = wd1r * x0r - wd1i * x0i; + a[j2 + 3] = wd1r * x0i + wd1i * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3] = wk3r * x0r + wk3i * x0i; + a[j3 + 1] = wk3r * x0i - wk3i * x0r; + x0r = y1r + y3i; + x0i = y1i - y3r; + a[j3 + 2] = wd3r * x0r + wd3i * x0i; + a[j3 + 3] = wd3r * x0i - wd3i * x0r; + j0 = m - j; + j1 = j0 + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j0] + a[j2]; + x0i = a[j0 + 1] + a[j2 + 1]; + x1r = a[j0] - a[j2]; + x1i = a[j0 + 1] - a[j2 + 1]; + y0r = a[j0 - 2] + a[j2 - 2]; + y0i = a[j0 - 1] + a[j2 - 1]; + y1r = a[j0 - 2] - a[j2 - 2]; + y1i = a[j0 - 1] - a[j2 - 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + y2r = a[j1 - 2] + a[j3 - 2]; + y2i = a[j1 - 1] + a[j3 - 1]; + y3r = a[j1 - 2] - a[j3 - 2]; + y3i = a[j1 - 1] - a[j3 - 1]; + a[j0] = x0r + x2r; + a[j0 + 1] = x0i + x2i; + a[j0 - 2] = y0r + y2r; + a[j0 - 1] = y0i + y2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i - x2i; + a[j1 - 2] = y0r - y2r; + a[j1 - 1] = y0i - y2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j2] = wk1i * x0r - wk1r * x0i; + a[j2 + 1] = wk1i * x0i + wk1r * x0r; + x0r = y1r - y3i; + x0i = y1i + y3r; + a[j2 - 2] = wd1i * x0r - wd1r * x0i; + a[j2 - 1] = wd1i * x0i + wd1r * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3] = wk3i * x0r + wk3r * x0i; + a[j3 + 1] = wk3i * x0i - wk3r * x0r; + x0r = y1r + y3i; + x0i = y1i - y3r; + a[j3 - 2] = wd3i * x0r + wd3r * x0i; + a[j3 - 1] = wd3i * x0i - wd3r * x0r; + } + wk1r = csc1 * (wd1r + wn4r); + wk1i = csc1 * (wd1i + wn4r); + wk3r = csc3 * (wd3r - wn4r); + wk3i = csc3 * (wd3i - wn4r); + j0 = mh; + j1 = j0 + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j0 - 2] + a[j2 - 2]; + x0i = a[j0 - 1] + a[j2 - 1]; + x1r = a[j0 - 2] - a[j2 - 2]; + x1i = a[j0 - 1] - a[j2 - 1]; + x2r = a[j1 - 2] + a[j3 - 2]; + x2i = a[j1 - 1] + a[j3 - 1]; + x3r = a[j1 - 2] - a[j3 - 2]; + x3i = a[j1 - 1] - a[j3 - 1]; + a[j0 - 2] = x0r + x2r; + a[j0 - 1] = x0i + x2i; + a[j1 - 2] = x0r - x2r; + a[j1 - 1] = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j2 - 2] = wk1r * x0r - wk1i * x0i; + a[j2 - 1] = wk1r * x0i + wk1i * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3 - 2] = wk3r * x0r + wk3i * x0i; + a[j3 - 1] = wk3r * x0i - wk3i * x0r; + x0r = a[j0] + a[j2]; + x0i = a[j0 + 1] + a[j2 + 1]; + x1r = a[j0] - a[j2]; + x1i = a[j0 + 1] - a[j2 + 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + a[j0] = x0r + x2r; + a[j0 + 1] = x0i + x2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j2] = wn4r * (x0r - x0i); + a[j2 + 1] = wn4r * (x0i + x0r); + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3] = -wn4r * (x0r + x0i); + a[j3 + 1] = -wn4r * (x0i - x0r); + x0r = a[j0 + 2] + a[j2 + 2]; + x0i = a[j0 + 3] + a[j2 + 3]; + x1r = a[j0 + 2] - a[j2 + 2]; + x1i = a[j0 + 3] - a[j2 + 3]; + x2r = a[j1 + 2] + a[j3 + 2]; + x2i = a[j1 + 3] + a[j3 + 3]; + x3r = a[j1 + 2] - a[j3 + 2]; + x3i = a[j1 + 3] - a[j3 + 3]; + a[j0 + 2] = x0r + x2r; + a[j0 + 3] = x0i + x2i; + a[j1 + 2] = x0r - x2r; + a[j1 + 3] = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j2 + 2] = wk1i * x0r - wk1r * x0i; + a[j2 + 3] = wk1i * x0i + wk1r * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3 + 2] = wk3i * x0r + wk3r * x0i; + a[j3 + 3] = wk3i * x0i - wk3r * x0r; +} + + +void cftb1st(int n, REAL *a, REAL *w) +{ + int j, j0, j1, j2, j3, k, m, mh; + REAL wn4r, csc1, csc3, wk1r, wk1i, wk3r, wk3i, + wd1r, wd1i, wd3r, wd3i; + REAL x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, + y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i; + + mh = n >> 3; + m = 2 * mh; + j1 = m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[0] + a[j2]; + x0i = -a[1] - a[j2 + 1]; + x1r = a[0] - a[j2]; + x1i = -a[1] + a[j2 + 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + a[0] = x0r + x2r; + a[1] = x0i - x2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i + x2i; + a[j2] = x1r + x3i; + a[j2 + 1] = x1i + x3r; + a[j3] = x1r - x3i; + a[j3 + 1] = x1i - x3r; + wn4r = w[1]; + csc1 = w[2]; + csc3 = w[3]; + wd1r = 1; + wd1i = 0; + wd3r = 1; + wd3i = 0; + k = 0; + for (j = 2; j < mh - 2; j += 4) { + k += 4; + wk1r = csc1 * (wd1r + w[k]); + wk1i = csc1 * (wd1i + w[k + 1]); + wk3r = csc3 * (wd3r + w[k + 2]); + wk3i = csc3 * (wd3i - w[k + 3]); + wd1r = w[k]; + wd1i = w[k + 1]; + wd3r = w[k + 2]; + wd3i = -w[k + 3]; + j1 = j + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j] + a[j2]; + x0i = -a[j + 1] - a[j2 + 1]; + x1r = a[j] - a[j2]; + x1i = -a[j + 1] + a[j2 + 1]; + y0r = a[j + 2] + a[j2 + 2]; + y0i = -a[j + 3] - a[j2 + 3]; + y1r = a[j + 2] - a[j2 + 2]; + y1i = -a[j + 3] + a[j2 + 3]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + y2r = a[j1 + 2] + a[j3 + 2]; + y2i = a[j1 + 3] + a[j3 + 3]; + y3r = a[j1 + 2] - a[j3 + 2]; + y3i = a[j1 + 3] - a[j3 + 3]; + a[j] = x0r + x2r; + a[j + 1] = x0i - x2i; + a[j + 2] = y0r + y2r; + a[j + 3] = y0i - y2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i + x2i; + a[j1 + 2] = y0r - y2r; + a[j1 + 3] = y0i + y2i; + x0r = x1r + x3i; + x0i = x1i + x3r; + a[j2] = wk1r * x0r - wk1i * x0i; + a[j2 + 1] = wk1r * x0i + wk1i * x0r; + x0r = y1r + y3i; + x0i = y1i + y3r; + a[j2 + 2] = wd1r * x0r - wd1i * x0i; + a[j2 + 3] = wd1r * x0i + wd1i * x0r; + x0r = x1r - x3i; + x0i = x1i - x3r; + a[j3] = wk3r * x0r + wk3i * x0i; + a[j3 + 1] = wk3r * x0i - wk3i * x0r; + x0r = y1r - y3i; + x0i = y1i - y3r; + a[j3 + 2] = wd3r * x0r + wd3i * x0i; + a[j3 + 3] = wd3r * x0i - wd3i * x0r; + j0 = m - j; + j1 = j0 + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j0] + a[j2]; + x0i = -a[j0 + 1] - a[j2 + 1]; + x1r = a[j0] - a[j2]; + x1i = -a[j0 + 1] + a[j2 + 1]; + y0r = a[j0 - 2] + a[j2 - 2]; + y0i = -a[j0 - 1] - a[j2 - 1]; + y1r = a[j0 - 2] - a[j2 - 2]; + y1i = -a[j0 - 1] + a[j2 - 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + y2r = a[j1 - 2] + a[j3 - 2]; + y2i = a[j1 - 1] + a[j3 - 1]; + y3r = a[j1 - 2] - a[j3 - 2]; + y3i = a[j1 - 1] - a[j3 - 1]; + a[j0] = x0r + x2r; + a[j0 + 1] = x0i - x2i; + a[j0 - 2] = y0r + y2r; + a[j0 - 1] = y0i - y2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i + x2i; + a[j1 - 2] = y0r - y2r; + a[j1 - 1] = y0i + y2i; + x0r = x1r + x3i; + x0i = x1i + x3r; + a[j2] = wk1i * x0r - wk1r * x0i; + a[j2 + 1] = wk1i * x0i + wk1r * x0r; + x0r = y1r + y3i; + x0i = y1i + y3r; + a[j2 - 2] = wd1i * x0r - wd1r * x0i; + a[j2 - 1] = wd1i * x0i + wd1r * x0r; + x0r = x1r - x3i; + x0i = x1i - x3r; + a[j3] = wk3i * x0r + wk3r * x0i; + a[j3 + 1] = wk3i * x0i - wk3r * x0r; + x0r = y1r - y3i; + x0i = y1i - y3r; + a[j3 - 2] = wd3i * x0r + wd3r * x0i; + a[j3 - 1] = wd3i * x0i - wd3r * x0r; + } + wk1r = csc1 * (wd1r + wn4r); + wk1i = csc1 * (wd1i + wn4r); + wk3r = csc3 * (wd3r - wn4r); + wk3i = csc3 * (wd3i - wn4r); + j0 = mh; + j1 = j0 + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j0 - 2] + a[j2 - 2]; + x0i = -a[j0 - 1] - a[j2 - 1]; + x1r = a[j0 - 2] - a[j2 - 2]; + x1i = -a[j0 - 1] + a[j2 - 1]; + x2r = a[j1 - 2] + a[j3 - 2]; + x2i = a[j1 - 1] + a[j3 - 1]; + x3r = a[j1 - 2] - a[j3 - 2]; + x3i = a[j1 - 1] - a[j3 - 1]; + a[j0 - 2] = x0r + x2r; + a[j0 - 1] = x0i - x2i; + a[j1 - 2] = x0r - x2r; + a[j1 - 1] = x0i + x2i; + x0r = x1r + x3i; + x0i = x1i + x3r; + a[j2 - 2] = wk1r * x0r - wk1i * x0i; + a[j2 - 1] = wk1r * x0i + wk1i * x0r; + x0r = x1r - x3i; + x0i = x1i - x3r; + a[j3 - 2] = wk3r * x0r + wk3i * x0i; + a[j3 - 1] = wk3r * x0i - wk3i * x0r; + x0r = a[j0] + a[j2]; + x0i = -a[j0 + 1] - a[j2 + 1]; + x1r = a[j0] - a[j2]; + x1i = -a[j0 + 1] + a[j2 + 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + a[j0] = x0r + x2r; + a[j0 + 1] = x0i - x2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i + x2i; + x0r = x1r + x3i; + x0i = x1i + x3r; + a[j2] = wn4r * (x0r - x0i); + a[j2 + 1] = wn4r * (x0i + x0r); + x0r = x1r - x3i; + x0i = x1i - x3r; + a[j3] = -wn4r * (x0r + x0i); + a[j3 + 1] = -wn4r * (x0i - x0r); + x0r = a[j0 + 2] + a[j2 + 2]; + x0i = -a[j0 + 3] - a[j2 + 3]; + x1r = a[j0 + 2] - a[j2 + 2]; + x1i = -a[j0 + 3] + a[j2 + 3]; + x2r = a[j1 + 2] + a[j3 + 2]; + x2i = a[j1 + 3] + a[j3 + 3]; + x3r = a[j1 + 2] - a[j3 + 2]; + x3i = a[j1 + 3] - a[j3 + 3]; + a[j0 + 2] = x0r + x2r; + a[j0 + 3] = x0i - x2i; + a[j1 + 2] = x0r - x2r; + a[j1 + 3] = x0i + x2i; + x0r = x1r + x3i; + x0i = x1i + x3r; + a[j2 + 2] = wk1i * x0r - wk1r * x0i; + a[j2 + 3] = wk1i * x0i + wk1r * x0r; + x0r = x1r - x3i; + x0i = x1i - x3r; + a[j3 + 2] = wk3i * x0r + wk3r * x0i; + a[j3 + 3] = wk3i * x0i - wk3r * x0r; +} + + +void cftrec1(int n, REAL *a, int nw, REAL *w) +{ + void cftrec1(int n, REAL *a, int nw, REAL *w); + void cftrec2(int n, REAL *a, int nw, REAL *w); + void cftmdl1(int n, REAL *a, REAL *w); + void cftexp1(int n, REAL *a, int nw, REAL *w); + int m; + + m = n >> 2; + cftmdl1(n, a, &w[nw - 2 * m]); + if (n > CDFT_RECURSIVE_N) { + cftrec1(m, a, nw, w); + cftrec2(m, &a[m], nw, w); + cftrec1(m, &a[2 * m], nw, w); + cftrec1(m, &a[3 * m], nw, w); + } else { + cftexp1(n, a, nw, w); + } +} + + +void cftrec2(int n, REAL *a, int nw, REAL *w) +{ + void cftrec1(int n, REAL *a, int nw, REAL *w); + void cftrec2(int n, REAL *a, int nw, REAL *w); + void cftmdl2(int n, REAL *a, REAL *w); + void cftexp2(int n, REAL *a, int nw, REAL *w); + int m; + + m = n >> 2; + cftmdl2(n, a, &w[nw - n]); + if (n > CDFT_RECURSIVE_N) { + cftrec1(m, a, nw, w); + cftrec2(m, &a[m], nw, w); + cftrec1(m, &a[2 * m], nw, w); + cftrec2(m, &a[3 * m], nw, w); + } else { + cftexp2(n, a, nw, w); + } +} + + +void cftexp1(int n, REAL *a, int nw, REAL *w) +{ + void cftmdl1(int n, REAL *a, REAL *w); + void cftmdl2(int n, REAL *a, REAL *w); + void cftfx41(int n, REAL *a, int nw, REAL *w); + void cftfx42(int n, REAL *a, int nw, REAL *w); + int j, k, l; + + l = n >> 2; + while (l > 128) { + for (k = l; k < n; k <<= 2) { + for (j = k - l; j < n; j += 4 * k) { + cftmdl1(l, &a[j], &w[nw - (l >> 1)]); + cftmdl2(l, &a[k + j], &w[nw - l]); + cftmdl1(l, &a[2 * k + j], &w[nw - (l >> 1)]); + } + } + cftmdl1(l, &a[n - l], &w[nw - (l >> 1)]); + l >>= 2; + } + for (k = l; k < n; k <<= 2) { + for (j = k - l; j < n; j += 4 * k) { + cftmdl1(l, &a[j], &w[nw - (l >> 1)]); + cftfx41(l, &a[j], nw, w); + cftmdl2(l, &a[k + j], &w[nw - l]); + cftfx42(l, &a[k + j], nw, w); + cftmdl1(l, &a[2 * k + j], &w[nw - (l >> 1)]); + cftfx41(l, &a[2 * k + j], nw, w); + } + } + cftmdl1(l, &a[n - l], &w[nw - (l >> 1)]); + cftfx41(l, &a[n - l], nw, w); +} + + +void cftexp2(int n, REAL *a, int nw, REAL *w) +{ + void cftmdl1(int n, REAL *a, REAL *w); + void cftmdl2(int n, REAL *a, REAL *w); + void cftfx41(int n, REAL *a, int nw, REAL *w); + void cftfx42(int n, REAL *a, int nw, REAL *w); + int j, k, l, m; + + m = n >> 1; + l = n >> 2; + while (l > 128) { + for (k = l; k < m; k <<= 2) { + for (j = k - l; j < m; j += 2 * k) { + cftmdl1(l, &a[j], &w[nw - (l >> 1)]); + cftmdl1(l, &a[m + j], &w[nw - (l >> 1)]); + } + for (j = 2 * k - l; j < m; j += 4 * k) { + cftmdl2(l, &a[j], &w[nw - l]); + cftmdl2(l, &a[m + j], &w[nw - l]); + } + } + l >>= 2; + } + for (k = l; k < m; k <<= 2) { + for (j = k - l; j < m; j += 2 * k) { + cftmdl1(l, &a[j], &w[nw - (l >> 1)]); + cftfx41(l, &a[j], nw, w); + cftmdl1(l, &a[m + j], &w[nw - (l >> 1)]); + cftfx41(l, &a[m + j], nw, w); + } + for (j = 2 * k - l; j < m; j += 4 * k) { + cftmdl2(l, &a[j], &w[nw - l]); + cftfx42(l, &a[j], nw, w); + cftmdl2(l, &a[m + j], &w[nw - l]); + cftfx42(l, &a[m + j], nw, w); + } + } +} + + +void cftmdl1(int n, REAL *a, REAL *w) +{ + int j, j0, j1, j2, j3, k, m, mh; + REAL wn4r, wk1r, wk1i, wk3r, wk3i; + REAL x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + mh = n >> 3; + m = 2 * mh; + j1 = m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[0] + a[j2]; + x0i = a[1] + a[j2 + 1]; + x1r = a[0] - a[j2]; + x1i = a[1] - a[j2 + 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + a[0] = x0r + x2r; + a[1] = x0i + x2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i - x2i; + a[j2] = x1r - x3i; + a[j2 + 1] = x1i + x3r; + a[j3] = x1r + x3i; + a[j3 + 1] = x1i - x3r; + wn4r = w[1]; + k = 0; + for (j = 2; j < mh; j += 2) { + k += 4; + wk1r = w[k]; + wk1i = w[k + 1]; + wk3r = w[k + 2]; + wk3i = -w[k + 3]; + j1 = j + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j] + a[j2]; + x0i = a[j + 1] + a[j2 + 1]; + x1r = a[j] - a[j2]; + x1i = a[j + 1] - a[j2 + 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + a[j] = x0r + x2r; + a[j + 1] = x0i + x2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j2] = wk1r * x0r - wk1i * x0i; + a[j2 + 1] = wk1r * x0i + wk1i * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3] = wk3r * x0r + wk3i * x0i; + a[j3 + 1] = wk3r * x0i - wk3i * x0r; + j0 = m - j; + j1 = j0 + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j0] + a[j2]; + x0i = a[j0 + 1] + a[j2 + 1]; + x1r = a[j0] - a[j2]; + x1i = a[j0 + 1] - a[j2 + 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + a[j0] = x0r + x2r; + a[j0 + 1] = x0i + x2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j2] = wk1i * x0r - wk1r * x0i; + a[j2 + 1] = wk1i * x0i + wk1r * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3] = wk3i * x0r + wk3r * x0i; + a[j3 + 1] = wk3i * x0i - wk3r * x0r; + } + j0 = mh; + j1 = j0 + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j0] + a[j2]; + x0i = a[j0 + 1] + a[j2 + 1]; + x1r = a[j0] - a[j2]; + x1i = a[j0 + 1] - a[j2 + 1]; + x2r = a[j1] + a[j3]; + x2i = a[j1 + 1] + a[j3 + 1]; + x3r = a[j1] - a[j3]; + x3i = a[j1 + 1] - a[j3 + 1]; + a[j0] = x0r + x2r; + a[j0 + 1] = x0i + x2i; + a[j1] = x0r - x2r; + a[j1 + 1] = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j2] = wn4r * (x0r - x0i); + a[j2 + 1] = wn4r * (x0i + x0r); + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3] = -wn4r * (x0r + x0i); + a[j3 + 1] = -wn4r * (x0i - x0r); +} + + +void cftmdl2(int n, REAL *a, REAL *w) +{ + int j, j0, j1, j2, j3, k, kr, m, mh; + REAL wn4r, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i; + REAL x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y2r, y2i; + + mh = n >> 3; + m = 2 * mh; + wn4r = w[1]; + j1 = m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[0] - a[j2 + 1]; + x0i = a[1] + a[j2]; + x1r = a[0] + a[j2 + 1]; + x1i = a[1] - a[j2]; + x2r = a[j1] - a[j3 + 1]; + x2i = a[j1 + 1] + a[j3]; + x3r = a[j1] + a[j3 + 1]; + x3i = a[j1 + 1] - a[j3]; + y0r = wn4r * (x2r - x2i); + y0i = wn4r * (x2i + x2r); + a[0] = x0r + y0r; + a[1] = x0i + y0i; + a[j1] = x0r - y0r; + a[j1 + 1] = x0i - y0i; + y0r = wn4r * (x3r - x3i); + y0i = wn4r * (x3i + x3r); + a[j2] = x1r - y0i; + a[j2 + 1] = x1i + y0r; + a[j3] = x1r + y0i; + a[j3 + 1] = x1i - y0r; + k = 0; + kr = 2 * m; + for (j = 2; j < mh; j += 2) { + k += 4; + wk1r = w[k]; + wk1i = w[k + 1]; + wk3r = w[k + 2]; + wk3i = -w[k + 3]; + kr -= 4; + wd1i = w[kr]; + wd1r = w[kr + 1]; + wd3i = w[kr + 2]; + wd3r = -w[kr + 3]; + j1 = j + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j] - a[j2 + 1]; + x0i = a[j + 1] + a[j2]; + x1r = a[j] + a[j2 + 1]; + x1i = a[j + 1] - a[j2]; + x2r = a[j1] - a[j3 + 1]; + x2i = a[j1 + 1] + a[j3]; + x3r = a[j1] + a[j3 + 1]; + x3i = a[j1 + 1] - a[j3]; + y0r = wk1r * x0r - wk1i * x0i; + y0i = wk1r * x0i + wk1i * x0r; + y2r = wd1r * x2r - wd1i * x2i; + y2i = wd1r * x2i + wd1i * x2r; + a[j] = y0r + y2r; + a[j + 1] = y0i + y2i; + a[j1] = y0r - y2r; + a[j1 + 1] = y0i - y2i; + y0r = wk3r * x1r + wk3i * x1i; + y0i = wk3r * x1i - wk3i * x1r; + y2r = wd3r * x3r + wd3i * x3i; + y2i = wd3r * x3i - wd3i * x3r; + a[j2] = y0r + y2r; + a[j2 + 1] = y0i + y2i; + a[j3] = y0r - y2r; + a[j3 + 1] = y0i - y2i; + j0 = m - j; + j1 = j0 + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j0] - a[j2 + 1]; + x0i = a[j0 + 1] + a[j2]; + x1r = a[j0] + a[j2 + 1]; + x1i = a[j0 + 1] - a[j2]; + x2r = a[j1] - a[j3 + 1]; + x2i = a[j1 + 1] + a[j3]; + x3r = a[j1] + a[j3 + 1]; + x3i = a[j1 + 1] - a[j3]; + y0r = wd1i * x0r - wd1r * x0i; + y0i = wd1i * x0i + wd1r * x0r; + y2r = wk1i * x2r - wk1r * x2i; + y2i = wk1i * x2i + wk1r * x2r; + a[j0] = y0r + y2r; + a[j0 + 1] = y0i + y2i; + a[j1] = y0r - y2r; + a[j1 + 1] = y0i - y2i; + y0r = wd3i * x1r + wd3r * x1i; + y0i = wd3i * x1i - wd3r * x1r; + y2r = wk3i * x3r + wk3r * x3i; + y2i = wk3i * x3i - wk3r * x3r; + a[j2] = y0r + y2r; + a[j2 + 1] = y0i + y2i; + a[j3] = y0r - y2r; + a[j3 + 1] = y0i - y2i; + } + wk1r = w[m]; + wk1i = w[m + 1]; + j0 = mh; + j1 = j0 + m; + j2 = j1 + m; + j3 = j2 + m; + x0r = a[j0] - a[j2 + 1]; + x0i = a[j0 + 1] + a[j2]; + x1r = a[j0] + a[j2 + 1]; + x1i = a[j0 + 1] - a[j2]; + x2r = a[j1] - a[j3 + 1]; + x2i = a[j1 + 1] + a[j3]; + x3r = a[j1] + a[j3 + 1]; + x3i = a[j1 + 1] - a[j3]; + y0r = wk1r * x0r - wk1i * x0i; + y0i = wk1r * x0i + wk1i * x0r; + y2r = wk1i * x2r - wk1r * x2i; + y2i = wk1i * x2i + wk1r * x2r; + a[j0] = y0r + y2r; + a[j0 + 1] = y0i + y2i; + a[j1] = y0r - y2r; + a[j1 + 1] = y0i - y2i; + y0r = wk1i * x1r - wk1r * x1i; + y0i = wk1i * x1i + wk1r * x1r; + y2r = wk1r * x3r - wk1i * x3i; + y2i = wk1r * x3i + wk1i * x3r; + a[j2] = y0r - y2r; + a[j2 + 1] = y0i - y2i; + a[j3] = y0r + y2r; + a[j3 + 1] = y0i + y2i; +} + + +void cftfx41(int n, REAL *a, int nw, REAL *w) +{ + void cftf161(REAL *a, REAL *w); + void cftf162(REAL *a, REAL *w); + void cftf081(REAL *a, REAL *w); + void cftf082(REAL *a, REAL *w); + + if (n == 128) { + cftf161(a, &w[nw - 8]); + cftf162(&a[32], &w[nw - 32]); + cftf161(&a[64], &w[nw - 8]); + cftf161(&a[96], &w[nw - 8]); + } else { + cftf081(a, &w[nw - 16]); + cftf082(&a[16], &w[nw - 16]); + cftf081(&a[32], &w[nw - 16]); + cftf081(&a[48], &w[nw - 16]); + } +} + + +void cftfx42(int n, REAL *a, int nw, REAL *w) +{ + void cftf161(REAL *a, REAL *w); + void cftf162(REAL *a, REAL *w); + void cftf081(REAL *a, REAL *w); + void cftf082(REAL *a, REAL *w); + + if (n == 128) { + cftf161(a, &w[nw - 8]); + cftf162(&a[32], &w[nw - 32]); + cftf161(&a[64], &w[nw - 8]); + cftf162(&a[96], &w[nw - 32]); + } else { + cftf081(a, &w[nw - 16]); + cftf082(&a[16], &w[nw - 16]); + cftf081(&a[32], &w[nw - 16]); + cftf082(&a[48], &w[nw - 16]); + } +} + + +void cftf161(REAL *a, REAL *w) +{ + REAL wn4r, wk1r, wk1i, + x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, + y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, + y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, + y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, + y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; + + wn4r = w[1]; + wk1i = wn4r * w[2]; + wk1r = wk1i + w[2]; + x0r = a[0] + a[16]; + x0i = a[1] + a[17]; + x1r = a[0] - a[16]; + x1i = a[1] - a[17]; + x2r = a[8] + a[24]; + x2i = a[9] + a[25]; + x3r = a[8] - a[24]; + x3i = a[9] - a[25]; + y0r = x0r + x2r; + y0i = x0i + x2i; + y4r = x0r - x2r; + y4i = x0i - x2i; + y8r = x1r - x3i; + y8i = x1i + x3r; + y12r = x1r + x3i; + y12i = x1i - x3r; + x0r = a[2] + a[18]; + x0i = a[3] + a[19]; + x1r = a[2] - a[18]; + x1i = a[3] - a[19]; + x2r = a[10] + a[26]; + x2i = a[11] + a[27]; + x3r = a[10] - a[26]; + x3i = a[11] - a[27]; + y1r = x0r + x2r; + y1i = x0i + x2i; + y5r = x0r - x2r; + y5i = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + y9r = wk1r * x0r - wk1i * x0i; + y9i = wk1r * x0i + wk1i * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + y13r = wk1i * x0r - wk1r * x0i; + y13i = wk1i * x0i + wk1r * x0r; + x0r = a[4] + a[20]; + x0i = a[5] + a[21]; + x1r = a[4] - a[20]; + x1i = a[5] - a[21]; + x2r = a[12] + a[28]; + x2i = a[13] + a[29]; + x3r = a[12] - a[28]; + x3i = a[13] - a[29]; + y2r = x0r + x2r; + y2i = x0i + x2i; + y6r = x0r - x2r; + y6i = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + y10r = wn4r * (x0r - x0i); + y10i = wn4r * (x0i + x0r); + x0r = x1r + x3i; + x0i = x1i - x3r; + y14r = wn4r * (x0r + x0i); + y14i = wn4r * (x0i - x0r); + x0r = a[6] + a[22]; + x0i = a[7] + a[23]; + x1r = a[6] - a[22]; + x1i = a[7] - a[23]; + x2r = a[14] + a[30]; + x2i = a[15] + a[31]; + x3r = a[14] - a[30]; + x3i = a[15] - a[31]; + y3r = x0r + x2r; + y3i = x0i + x2i; + y7r = x0r - x2r; + y7i = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + y11r = wk1i * x0r - wk1r * x0i; + y11i = wk1i * x0i + wk1r * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + y15r = wk1r * x0r - wk1i * x0i; + y15i = wk1r * x0i + wk1i * x0r; + x0r = y12r - y14r; + x0i = y12i - y14i; + x1r = y12r + y14r; + x1i = y12i + y14i; + x2r = y13r - y15r; + x2i = y13i - y15i; + x3r = y13r + y15r; + x3i = y13i + y15i; + a[24] = x0r + x2r; + a[25] = x0i + x2i; + a[26] = x0r - x2r; + a[27] = x0i - x2i; + a[28] = x1r - x3i; + a[29] = x1i + x3r; + a[30] = x1r + x3i; + a[31] = x1i - x3r; + x0r = y8r + y10r; + x0i = y8i + y10i; + x1r = y8r - y10r; + x1i = y8i - y10i; + x2r = y9r + y11r; + x2i = y9i + y11i; + x3r = y9r - y11r; + x3i = y9i - y11i; + a[16] = x0r + x2r; + a[17] = x0i + x2i; + a[18] = x0r - x2r; + a[19] = x0i - x2i; + a[20] = x1r - x3i; + a[21] = x1i + x3r; + a[22] = x1r + x3i; + a[23] = x1i - x3r; + x0r = y5r - y7i; + x0i = y5i + y7r; + x2r = wn4r * (x0r - x0i); + x2i = wn4r * (x0i + x0r); + x0r = y5r + y7i; + x0i = y5i - y7r; + x3r = wn4r * (x0r - x0i); + x3i = wn4r * (x0i + x0r); + x0r = y4r - y6i; + x0i = y4i + y6r; + x1r = y4r + y6i; + x1i = y4i - y6r; + a[8] = x0r + x2r; + a[9] = x0i + x2i; + a[10] = x0r - x2r; + a[11] = x0i - x2i; + a[12] = x1r - x3i; + a[13] = x1i + x3r; + a[14] = x1r + x3i; + a[15] = x1i - x3r; + x0r = y0r + y2r; + x0i = y0i + y2i; + x1r = y0r - y2r; + x1i = y0i - y2i; + x2r = y1r + y3r; + x2i = y1i + y3i; + x3r = y1r - y3r; + x3i = y1i - y3i; + a[0] = x0r + x2r; + a[1] = x0i + x2i; + a[2] = x0r - x2r; + a[3] = x0i - x2i; + a[4] = x1r - x3i; + a[5] = x1i + x3r; + a[6] = x1r + x3i; + a[7] = x1i - x3r; +} + + +void cftf162(REAL *a, REAL *w) +{ + REAL wn4r, wk1r, wk1i, wk2r, wk2i, wk3r, wk3i, + x0r, x0i, x1r, x1i, x2r, x2i, + y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, + y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, + y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, + y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; + + wn4r = w[1]; + wk1r = w[4]; + wk1i = w[5]; + wk3r = w[6]; + wk3i = w[7]; + wk2r = w[8]; + wk2i = w[9]; + x1r = a[0] - a[17]; + x1i = a[1] + a[16]; + x0r = a[8] - a[25]; + x0i = a[9] + a[24]; + x2r = wn4r * (x0r - x0i); + x2i = wn4r * (x0i + x0r); + y0r = x1r + x2r; + y0i = x1i + x2i; + y4r = x1r - x2r; + y4i = x1i - x2i; + x1r = a[0] + a[17]; + x1i = a[1] - a[16]; + x0r = a[8] + a[25]; + x0i = a[9] - a[24]; + x2r = wn4r * (x0r - x0i); + x2i = wn4r * (x0i + x0r); + y8r = x1r - x2i; + y8i = x1i + x2r; + y12r = x1r + x2i; + y12i = x1i - x2r; + x0r = a[2] - a[19]; + x0i = a[3] + a[18]; + x1r = wk1r * x0r - wk1i * x0i; + x1i = wk1r * x0i + wk1i * x0r; + x0r = a[10] - a[27]; + x0i = a[11] + a[26]; + x2r = wk3i * x0r - wk3r * x0i; + x2i = wk3i * x0i + wk3r * x0r; + y1r = x1r + x2r; + y1i = x1i + x2i; + y5r = x1r - x2r; + y5i = x1i - x2i; + x0r = a[2] + a[19]; + x0i = a[3] - a[18]; + x1r = wk3r * x0r - wk3i * x0i; + x1i = wk3r * x0i + wk3i * x0r; + x0r = a[10] + a[27]; + x0i = a[11] - a[26]; + x2r = wk1r * x0r + wk1i * x0i; + x2i = wk1r * x0i - wk1i * x0r; + y9r = x1r - x2r; + y9i = x1i - x2i; + y13r = x1r + x2r; + y13i = x1i + x2i; + x0r = a[4] - a[21]; + x0i = a[5] + a[20]; + x1r = wk2r * x0r - wk2i * x0i; + x1i = wk2r * x0i + wk2i * x0r; + x0r = a[12] - a[29]; + x0i = a[13] + a[28]; + x2r = wk2i * x0r - wk2r * x0i; + x2i = wk2i * x0i + wk2r * x0r; + y2r = x1r + x2r; + y2i = x1i + x2i; + y6r = x1r - x2r; + y6i = x1i - x2i; + x0r = a[4] + a[21]; + x0i = a[5] - a[20]; + x1r = wk2i * x0r - wk2r * x0i; + x1i = wk2i * x0i + wk2r * x0r; + x0r = a[12] + a[29]; + x0i = a[13] - a[28]; + x2r = wk2r * x0r - wk2i * x0i; + x2i = wk2r * x0i + wk2i * x0r; + y10r = x1r - x2r; + y10i = x1i - x2i; + y14r = x1r + x2r; + y14i = x1i + x2i; + x0r = a[6] - a[23]; + x0i = a[7] + a[22]; + x1r = wk3r * x0r - wk3i * x0i; + x1i = wk3r * x0i + wk3i * x0r; + x0r = a[14] - a[31]; + x0i = a[15] + a[30]; + x2r = wk1i * x0r - wk1r * x0i; + x2i = wk1i * x0i + wk1r * x0r; + y3r = x1r + x2r; + y3i = x1i + x2i; + y7r = x1r - x2r; + y7i = x1i - x2i; + x0r = a[6] + a[23]; + x0i = a[7] - a[22]; + x1r = wk1i * x0r + wk1r * x0i; + x1i = wk1i * x0i - wk1r * x0r; + x0r = a[14] + a[31]; + x0i = a[15] - a[30]; + x2r = wk3i * x0r - wk3r * x0i; + x2i = wk3i * x0i + wk3r * x0r; + y11r = x1r + x2r; + y11i = x1i + x2i; + y15r = x1r - x2r; + y15i = x1i - x2i; + x1r = y0r + y2r; + x1i = y0i + y2i; + x2r = y1r + y3r; + x2i = y1i + y3i; + a[0] = x1r + x2r; + a[1] = x1i + x2i; + a[2] = x1r - x2r; + a[3] = x1i - x2i; + x1r = y0r - y2r; + x1i = y0i - y2i; + x2r = y1r - y3r; + x2i = y1i - y3i; + a[4] = x1r - x2i; + a[5] = x1i + x2r; + a[6] = x1r + x2i; + a[7] = x1i - x2r; + x1r = y4r - y6i; + x1i = y4i + y6r; + x0r = y5r - y7i; + x0i = y5i + y7r; + x2r = wn4r * (x0r - x0i); + x2i = wn4r * (x0i + x0r); + a[8] = x1r + x2r; + a[9] = x1i + x2i; + a[10] = x1r - x2r; + a[11] = x1i - x2i; + x1r = y4r + y6i; + x1i = y4i - y6r; + x0r = y5r + y7i; + x0i = y5i - y7r; + x2r = wn4r * (x0r - x0i); + x2i = wn4r * (x0i + x0r); + a[12] = x1r - x2i; + a[13] = x1i + x2r; + a[14] = x1r + x2i; + a[15] = x1i - x2r; + x1r = y8r + y10r; + x1i = y8i + y10i; + x2r = y9r - y11r; + x2i = y9i - y11i; + a[16] = x1r + x2r; + a[17] = x1i + x2i; + a[18] = x1r - x2r; + a[19] = x1i - x2i; + x1r = y8r - y10r; + x1i = y8i - y10i; + x2r = y9r + y11r; + x2i = y9i + y11i; + a[20] = x1r - x2i; + a[21] = x1i + x2r; + a[22] = x1r + x2i; + a[23] = x1i - x2r; + x1r = y12r - y14i; + x1i = y12i + y14r; + x0r = y13r + y15i; + x0i = y13i - y15r; + x2r = wn4r * (x0r - x0i); + x2i = wn4r * (x0i + x0r); + a[24] = x1r + x2r; + a[25] = x1i + x2i; + a[26] = x1r - x2r; + a[27] = x1i - x2i; + x1r = y12r + y14i; + x1i = y12i - y14r; + x0r = y13r - y15i; + x0i = y13i + y15r; + x2r = wn4r * (x0r - x0i); + x2i = wn4r * (x0i + x0r); + a[28] = x1r - x2i; + a[29] = x1i + x2r; + a[30] = x1r + x2i; + a[31] = x1i - x2r; +} + + +void cftf081(REAL *a, REAL *w) +{ + REAL wn4r, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, + y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, + y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; + + wn4r = w[1]; + x0r = a[0] + a[8]; + x0i = a[1] + a[9]; + x1r = a[0] - a[8]; + x1i = a[1] - a[9]; + x2r = a[4] + a[12]; + x2i = a[5] + a[13]; + x3r = a[4] - a[12]; + x3i = a[5] - a[13]; + y0r = x0r + x2r; + y0i = x0i + x2i; + y2r = x0r - x2r; + y2i = x0i - x2i; + y1r = x1r - x3i; + y1i = x1i + x3r; + y3r = x1r + x3i; + y3i = x1i - x3r; + x0r = a[2] + a[10]; + x0i = a[3] + a[11]; + x1r = a[2] - a[10]; + x1i = a[3] - a[11]; + x2r = a[6] + a[14]; + x2i = a[7] + a[15]; + x3r = a[6] - a[14]; + x3i = a[7] - a[15]; + y4r = x0r + x2r; + y4i = x0i + x2i; + y6r = x0r - x2r; + y6i = x0i - x2i; + x0r = x1r - x3i; + x0i = x1i + x3r; + x2r = x1r + x3i; + x2i = x1i - x3r; + y5r = wn4r * (x0r - x0i); + y5i = wn4r * (x0r + x0i); + y7r = wn4r * (x2r - x2i); + y7i = wn4r * (x2r + x2i); + a[8] = y1r + y5r; + a[9] = y1i + y5i; + a[10] = y1r - y5r; + a[11] = y1i - y5i; + a[12] = y3r - y7i; + a[13] = y3i + y7r; + a[14] = y3r + y7i; + a[15] = y3i - y7r; + a[0] = y0r + y4r; + a[1] = y0i + y4i; + a[2] = y0r - y4r; + a[3] = y0i - y4i; + a[4] = y2r - y6i; + a[5] = y2i + y6r; + a[6] = y2r + y6i; + a[7] = y2i - y6r; +} + + +void cftf082(REAL *a, REAL *w) +{ + REAL wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, + y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, + y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; + + wn4r = w[1]; + wk1r = w[4]; + wk1i = w[5]; + y0r = a[0] - a[9]; + y0i = a[1] + a[8]; + y1r = a[0] + a[9]; + y1i = a[1] - a[8]; + x0r = a[4] - a[13]; + x0i = a[5] + a[12]; + y2r = wn4r * (x0r - x0i); + y2i = wn4r * (x0i + x0r); + x0r = a[4] + a[13]; + x0i = a[5] - a[12]; + y3r = wn4r * (x0r - x0i); + y3i = wn4r * (x0i + x0r); + x0r = a[2] - a[11]; + x0i = a[3] + a[10]; + y4r = wk1r * x0r - wk1i * x0i; + y4i = wk1r * x0i + wk1i * x0r; + x0r = a[2] + a[11]; + x0i = a[3] - a[10]; + y5r = wk1i * x0r - wk1r * x0i; + y5i = wk1i * x0i + wk1r * x0r; + x0r = a[6] - a[15]; + x0i = a[7] + a[14]; + y6r = wk1i * x0r - wk1r * x0i; + y6i = wk1i * x0i + wk1r * x0r; + x0r = a[6] + a[15]; + x0i = a[7] - a[14]; + y7r = wk1r * x0r - wk1i * x0i; + y7i = wk1r * x0i + wk1i * x0r; + x0r = y0r + y2r; + x0i = y0i + y2i; + x1r = y4r + y6r; + x1i = y4i + y6i; + a[0] = x0r + x1r; + a[1] = x0i + x1i; + a[2] = x0r - x1r; + a[3] = x0i - x1i; + x0r = y0r - y2r; + x0i = y0i - y2i; + x1r = y4r - y6r; + x1i = y4i - y6i; + a[4] = x0r - x1i; + a[5] = x0i + x1r; + a[6] = x0r + x1i; + a[7] = x0i - x1r; + x0r = y1r - y3i; + x0i = y1i + y3r; + x1r = y5r - y7r; + x1i = y5i - y7i; + a[8] = x0r + x1r; + a[9] = x0i + x1i; + a[10] = x0r - x1r; + a[11] = x0i - x1i; + x0r = y1r + y3i; + x0i = y1i - y3r; + x1r = y5r + y7r; + x1i = y5i + y7i; + a[12] = x0r - x1i; + a[13] = x0i + x1r; + a[14] = x0r + x1i; + a[15] = x0i - x1r; +} + + +void cftf040(REAL *a) +{ + REAL x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + x0r = a[0] + a[4]; + x0i = a[1] + a[5]; + x1r = a[0] - a[4]; + x1i = a[1] - a[5]; + x2r = a[2] + a[6]; + x2i = a[3] + a[7]; + x3r = a[2] - a[6]; + x3i = a[3] - a[7]; + a[0] = x0r + x2r; + a[1] = x0i + x2i; + a[4] = x0r - x2r; + a[5] = x0i - x2i; + a[2] = x1r - x3i; + a[3] = x1i + x3r; + a[6] = x1r + x3i; + a[7] = x1i - x3r; +} + + +void cftb040(REAL *a) +{ + REAL x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + x0r = a[0] + a[4]; + x0i = a[1] + a[5]; + x1r = a[0] - a[4]; + x1i = a[1] - a[5]; + x2r = a[2] + a[6]; + x2i = a[3] + a[7]; + x3r = a[2] - a[6]; + x3i = a[3] - a[7]; + a[0] = x0r + x2r; + a[1] = x0i + x2i; + a[4] = x0r - x2r; + a[5] = x0i - x2i; + a[2] = x1r + x3i; + a[3] = x1i - x3r; + a[6] = x1r - x3i; + a[7] = x1i + x3r; +} + + +void cftx020(REAL *a) +{ + REAL x0r, x0i; + + x0r = a[0] - a[2]; + x0i = a[1] - a[3]; + a[0] += a[2]; + a[1] += a[3]; + a[2] = x0r; + a[3] = x0i; +} + + +void rftfsub(int n, REAL *a, int nc, REAL *c) +{ + int j, k, kk, ks, m; + REAL wkr, wki, xr, xi, yr, yi; + + m = n >> 1; + ks = 2 * nc / m; + kk = 0; + for (j = 2; j < m; j += 2) { + k = n - j; + kk += ks; + wkr = 0.5 - c[nc - kk]; + wki = c[kk]; + xr = a[j] - a[k]; + xi = a[j + 1] + a[k + 1]; + yr = wkr * xr - wki * xi; + yi = wkr * xi + wki * xr; + a[j] -= yr; + a[j + 1] -= yi; + a[k] += yr; + a[k + 1] -= yi; + } +} + + +void rftbsub(int n, REAL *a, int nc, REAL *c) +{ + int j, k, kk, ks, m; + REAL wkr, wki, xr, xi, yr, yi; + + m = n >> 1; + ks = 2 * nc / m; + kk = 0; + for (j = 2; j < m; j += 2) { + k = n - j; + kk += ks; + wkr = 0.5 - c[nc - kk]; + wki = c[kk]; + xr = a[j] - a[k]; + xi = a[j + 1] + a[k + 1]; + yr = wkr * xr + wki * xi; + yi = wkr * xi - wki * xr; + a[j] -= yr; + a[j + 1] -= yi; + a[k] += yr; + a[k + 1] -= yi; + } +} + + +void dctsub(int n, REAL *a, int nc, REAL *c) +{ + int j, k, kk, ks, m; + REAL wkr, wki, xr; + + m = n >> 1; + ks = nc / n; + kk = 0; + for (j = 1; j < m; j++) { + k = n - j; + kk += ks; + wkr = c[kk] - c[nc - kk]; + wki = c[kk] + c[nc - kk]; + xr = wki * a[j] - wkr * a[k]; + a[j] = wkr * a[j] + wki * a[k]; + a[k] = xr; + } + a[m] *= c[0]; +} + + +void dstsub(int n, REAL *a, int nc, REAL *c) +{ + int j, k, kk, ks, m; + REAL wkr, wki, xr; + + m = n >> 1; + ks = nc / n; + kk = 0; + for (j = 1; j < m; j++) { + k = n - j; + kk += ks; + wkr = c[kk] - c[nc - kk]; + wki = c[kk] + c[nc - kk]; + xr = wki * a[k] - wkr * a[j]; + a[k] = wkr * a[k] + wki * a[j]; + a[j] = xr; + } + a[m] *= c[0]; +} diff --git a/src/plugins/supereqdsp/supereq/dsp_superequ.txt b/src/plugins/supereqdsp/supereq/dsp_superequ.txt new file mode 100644 index 000000000..5da80f9e7 --- /dev/null +++ b/src/plugins/supereqdsp/supereq/dsp_superequ.txt @@ -0,0 +1,30 @@ + +Shibatch Super Equalizer ver 0.03 for winamp +written by Naoki Shibata shibatch@users.sourceforge.net + +Shibatch Super Equalizer is a graphic and parametric equalizer plugin +for winamp. This plugin uses 16383th order FIR filter with FFT algorithm. +It's equalization is very precise. Equalization setting can be done +for each channel separately. + +Processes of internal equalizer in winamp are actually done by each +input plugin, so the results may differ for each input plugin. +With this plugin, this problem can be avoided. + +This plugin is optimized for processors which have cache equal to or +greater than 128k bytes(16383*2*sizeof(float) = 128k). This plugin +won't work efficiently with K6 series processors(buy Athlon!!!). + +Do not forget pressing "preview" button after changing setting. + +http://shibatch.sourceforge.net/ + +*** + + This program(except FFT part) is distributed under LGPL. See LGPL.txt for +details. + + FFT part is a routine made by Mr.Ooura. This routine is a freeware. Contact +Mr.Ooura for details of distributing licenses. + +http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html diff --git a/src/plugins/supereqdsp/supereq/paramlist.hpp b/src/plugins/supereqdsp/supereq/paramlist.hpp new file mode 100644 index 000000000..5a327f6bb --- /dev/null +++ b/src/plugins/supereqdsp/supereq/paramlist.hpp @@ -0,0 +1,127 @@ +/* + SuperEQ DSP plugin for DeaDBeeF Player + Copyright (C) 2009-2014 Alexey Yakovenko + Original SuperEQ code (C) Naoki Shibata + + 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 2 + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#include +#include +#include + +class paramlistelm { +public: + class paramlistelm *next; + + float lower,upper,gain,gain2; + int sortindex; + + paramlistelm(void) { + lower = upper = gain = 0; + next = NULL; + }; + + ~paramlistelm() { + delete next; + next = NULL; + }; +}; + +class paramlist { +public: + class paramlistelm *elm; + + paramlist(void) { + elm = NULL; + } + + ~paramlist() { + delete elm; + elm = NULL; + } + + void copy(paramlist &src) + { + delete elm; + elm = NULL; + + paramlistelm **p,*q; + for(p=&elm,q=src.elm;q != NULL;q = q->next,p = &(*p)->next) + { + *p = new paramlistelm; + (*p)->lower = q->lower; + (*p)->upper = q->upper; + (*p)->gain = q->gain; + } + } + + paramlistelm *newelm(void) + { + paramlistelm **e; + for(e = &elm;*e != NULL;e = &(*e)->next) ; + *e = new paramlistelm; + + return *e; + } + + int getnelm(void) + { + int i; + paramlistelm *e; + + for(e = elm,i = 0;e != NULL;e = e->next,i++) ; + + return i; + } + + void delelm(paramlistelm *p) + { + paramlistelm **e; + for(e = &elm;*e != NULL && p != *e;e = &(*e)->next) ; + if (*e == NULL) return; + *e = (*e)->next; + p->next = NULL; + delete p; + } + + void sortelm(void) + { + int i=0; + + if (elm == NULL) return; + + for(paramlistelm *r = elm;r != NULL;r = r->next) r->sortindex = i++; + + paramlistelm **p,**q; + + for(p=&elm->next;*p != NULL;) + { + for(q=&elm;*q != *p;q = &(*q)->next) + if ((*p)->lower < (*q)->lower || + ((*p)->lower == (*q)->lower && (*p)->sortindex < (*q)->sortindex)) break; + + if (p == q) {p = &(*p)->next; continue;} + + paramlistelm **pn = p; + paramlistelm *pp = *p; + *p = (*p)->next; + pp->next = *q; + *q = pp; + + p = pn; + } + } +}; + diff --git a/src/plugins/supereqdsp/supereqdsp_plugin.cpp b/src/plugins/supereqdsp/supereqdsp_plugin.cpp new file mode 100644 index 000000000..9f0938890 --- /dev/null +++ b/src/plugins/supereqdsp/supereqdsp_plugin.cpp @@ -0,0 +1,74 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2007-2017 musikcube team +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of the author nor the names of other contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "SuperEqDsp.h" + +#ifdef WIN32 +#define DLLEXPORT __declspec(dllexport) +#else +#define DLLEXPORT +#endif + +class SuperEqPlugin : public musik::core::sdk::IPlugin { + public: + virtual void Release() { delete this; } + virtual const char* Name() { return "SuperEq IDSP"; } + virtual const char* Version() { return "0.1.0"; } + virtual const char* Author() { return "Naoki Shibata, Alexey Yakovenko, clangen"; } + virtual const char* Guid() { return "6f0ed53b-0f13-4220-9b0a-ca496b6421cc"; } + virtual bool Configurable() { return false; } + virtual void Configure() { } + virtual void Reload() { } + virtual int SdkVersion() { return musik::core::sdk::SdkVersion; } +}; + +#ifdef WIN32 +BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { + return true; +} +#endif + +extern "C" DLLEXPORT musik::core::sdk::IPlugin* GetPlugin() { + return new SuperEqPlugin(); +} + +extern "C" DLLEXPORT musik::core::sdk::IDSP* GetDSP() { + return new SuperEqDsp(); +} + +extern "C" DLLEXPORT musik::core::sdk::ISchema* GetSchema(); \ No newline at end of file