You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdemultimedia/noatun/modules/winskin/vis/winSkinFFT_impl.cpp

149 lines
2.8 KiB

/*
implementation for winskin fft
Copyright (C) 2000 Martin Vogt
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Library General Public License as published by
the Free Software Foundation.
For more information look at the file COPYRIGHT in this package
*/
#include "winSkinFFT_impl.h"
#include <audiosubsys.h>
#include <cstring>
#define __BANDS 75
namespace Noatun {
WinSkinFFT_impl::WinSkinFFT_impl() {
fftBands_short=256;
realFFTFilter= new RealFFTFilter(fftBands_short);
fftArray=new int[fftBands_short];
bands=0;
fragCnt=(int)(AudioSubSystem::the()->fragmentCount());
visQueue=new VISQueue(fragCnt);
writePos=0;
}
WinSkinFFT_impl::~WinSkinFFT_impl(){
delete realFFTFilter;
delete fftArray;
delete visQueue;
}
void WinSkinFFT_impl::streamInit() {
}
void WinSkinFFT_impl::streamStart() {
}
void WinSkinFFT_impl::calculateBlock(unsigned long samples) {
unsigned long i;
// monitoring only tasks can't be done with that StereoEffect
// interface nicely - copy input to output until there is
// something better
// (when?)
int n=sizeof(float)*samples;
memcpy(outleft,inleft,n);
memcpy(outright,inright,n);
if (realFFTFilter->fft16(inleft,inright,samples) == false) {
return;
}
//
// The following modifications have nothing to do
// with an fft, they only make the output look nice.
// (mostly scaling)
short* fftPtr;
int* bitReversed;
fftPtr=realFFTFilter->getPointPtr();
bitReversed=realFFTFilter->getBitReversed();
int pos=0;
int step=realFFTFilter->getPoints()/__BANDS;
int re;
int im;
int tmp;
float max=0.0;
float avg=0.0;
for (i=0;i<__BANDS;i++) {
re=(int)fftPtr[bitReversed[pos]];
im=(int)fftPtr[bitReversed[pos]+1];
tmp=re*re+im*im;
// Here I check a new idea. We remove all low values
// and all values over xyz to xyz.
fftArray[pos]=(int)(::sqrt(::sqrt(tmp)));
if (fftArray[pos]<=15) {
max+=fftArray[pos];
} else {
max+=15+fftArray[pos]/2;
}
pos=pos+step;
}
avg=0.65*max/(float)__BANDS;
pos=0;
vector<float>* visAnalyserArray=visQueue->getElement(writePos);
visAnalyserArray->clear();
visAnalyserArray->reserve(__BANDS);
for (i=0;i<__BANDS;i++) {
float val=(float)(fftArray[pos]-avg);
visAnalyserArray->push_back(val);
pos=pos+step;
}
writePos++;
if (writePos >= fragCnt) writePos=0;
}
void WinSkinFFT_impl::bandResolution(float res) {
bands=(int)res;
}
float WinSkinFFT_impl::bandResolution() {
return (float)bands;
}
vector<float>* WinSkinFFT_impl::scope() {
int delay=writePos+1;
if (delay >= fragCnt) delay=0;
vector<float>* visAnalyserArray=visQueue->getElement(delay);
return new vector<float>(*visAnalyserArray);
}
REGISTER_IMPLEMENTATION(WinSkinFFT_impl);
}