attempt to improve freq responsiveness

This commit is contained in:
Matthew Bellew
2020-01-25 17:26:40 -08:00
parent 571516ba47
commit b779be76ee
4 changed files with 215 additions and 174 deletions

View File

@ -74,11 +74,15 @@ void PCM::_initPCM(int samples) {
start=0;
//Allocate FFT workspace
w= (double *)wipemalloc(maxsamples*sizeof(double));
ip= (int *)wipemalloc(maxsamples*sizeof(int));
// per rdft() documentation
// length of ip >= 2+sqrt(n) and length of w == n/2
#if FFT_LENGTH > 1024
#error update this code
#endif
w = (double *)wipemalloc(FFT_LENGTH/2*sizeof(double));
ip = (int *)wipemalloc(34 * sizeof(int));
ip[0]=0;
/** PCM data */
// this->maxsamples = 2048;
// this->numsamples = 0;
@ -134,8 +138,8 @@ void PCM::addPCMfloat(const float *PCMdata, int samples)
if (newsamples>maxsamples) newsamples=maxsamples;
numsamples = getPCMnew(pcmdataR,1,0,waveSmoothing,0,0);
getPCMnew(pcmdataL,0,0,waveSmoothing,0,1);
getPCM(vdataL,512,0,1,0,0);
getPCM(vdataR,512,1,1,0,0);
getPCM(vdataL,FFT_LENGTH,0,1,0,0);
getPCM(vdataR,FFT_LENGTH,1,1,0,0);
}
@ -158,8 +162,8 @@ void PCM::addPCMfloat_2ch(const float *PCMdata, int samples)
newsamples=maxsamples;
numsamples = getPCMnew(pcmdataR,1,0,waveSmoothing,0,0);
getPCMnew(pcmdataL,0,0,waveSmoothing,0,1);
getPCM(vdataL,512,0,1,0,0);
getPCM(vdataR,512,1,1,0,0);
getPCM(vdataL,FFT_LENGTH,0,1,0,0);
getPCM(vdataR,FFT_LENGTH,1,1,0,0);
}
@ -178,8 +182,8 @@ void PCM::addPCM16Data(const short* pcm_data, short samples) {
if (newsamples>maxsamples) newsamples=maxsamples;
numsamples = getPCMnew(pcmdataR,1,0,waveSmoothing,0,0);
getPCMnew(pcmdataL,0,0,waveSmoothing,0,1);
getPCM(vdataL,512,0,1,0,0);
getPCM(vdataR,512,1,1,0,0);
getPCM(vdataL,FFT_LENGTH,0,1,0,0);
getPCM(vdataR,FFT_LENGTH,1,1,0,0);
}
@ -210,8 +214,8 @@ void PCM::addPCM16(short PCMdata[2][512])
numsamples = getPCMnew(pcmdataR,1,0,waveSmoothing,0,0);
getPCMnew(pcmdataL,0,0,waveSmoothing,0,1);
getPCM(vdataL,512,0,1,0,0);
getPCM(vdataR,512,1,1,0,0);
getPCM(vdataL,FFT_LENGTH,0,1,0,0);
getPCM(vdataR,FFT_LENGTH,1,1,0,0);
}
@ -243,8 +247,8 @@ void PCM::addPCM8( unsigned char PCMdata[2][1024])
if (newsamples>maxsamples) newsamples=maxsamples;
numsamples = getPCMnew(pcmdataR,1,0,waveSmoothing,0,0);
getPCMnew(pcmdataL,0,0,waveSmoothing,0,1);
getPCM(vdataL,512,0,1,0,0);
getPCM(vdataR,512,1,1,0,0);
getPCM(vdataL,FFT_LENGTH,0,1,0,0);
getPCM(vdataR,FFT_LENGTH,1,1,0,0);
}
void PCM::addPCM8_512( const unsigned char PCMdata[2][512])
@ -275,8 +279,8 @@ void PCM::addPCM8_512( const unsigned char PCMdata[2][512])
if (newsamples>maxsamples) newsamples=maxsamples;
numsamples = getPCMnew(pcmdataR,1,0,waveSmoothing,0,0);
getPCMnew(pcmdataL,0,0,waveSmoothing,0,1);
getPCM(vdataL,512,0,1,0,0);
getPCM(vdataR,512,1,1,0,0);
getPCM(vdataL,FFT_LENGTH,0,1,0,0);
getPCM(vdataR,FFT_LENGTH,1,1,0,0);
}
@ -291,43 +295,57 @@ void PCM::addPCM8_512( const unsigned char PCMdata[2][512])
void PCM::getPCM(float *PCMdata, int samples, int channel, int freq, float smoothing, int derive)
{
int index;
index=start-1;
if (index<0) index=maxsamples+index;
PCMdata[0]=PCMd[channel][index];
for(int i=1;i<samples;i++)
if (smoothing == 0)
{
index=start-1-i;
if (index<0) index=maxsamples+index;
for (int i = 0; i < samples; i++)
{
int index = start - 1 - i;
if (index < 0)
index = maxsamples + index;
PCMdata[i] = PCMd[channel][index];
}
}
else
{
int index=start-1;
PCMdata[i]=(1-smoothing)*PCMd[channel][index]+smoothing*PCMdata[i-1];
if (index<0)
index=maxsamples+index;
PCMdata[0] = PCMd[channel][index];
for (int i = 1; i < samples; i++)
{
index = start - 1 - i;
if (index < 0)
index = maxsamples + index;
PCMdata[i] = (1 - smoothing) * PCMd[channel][index] + smoothing * PCMdata[i - 1];
}
}
//return derivative of PCM data
if(derive)
if (derive)
{
for(int i=0;i<samples-1;i++)
{
PCMdata[i]=PCMdata[i]-PCMdata[i+1];
}
{
PCMdata[i]=PCMdata[i]-PCMdata[i+1];
}
PCMdata[samples-1]=0;
}
//return frequency data instead of PCM (perform FFT)
if (freq)
{
// NOTE some presets set bSpectrum=1 and samples!=2^n, not sure what rdft() does with that
assert(samples <= 1024);
samples = std::min(1024,samples);
double temppcm[1024];
for (int i=0;i<samples;i++)
{temppcm[i]=(double)PCMdata[i];}
{temppcm[i]=(double)PCMdata[i];}
rdft(samples, 1, temppcm, ip, w);
for (int j=0;j<samples;j++)
{PCMdata[j]=(float)temppcm[j];}
{PCMdata[j]=(float)temppcm[j];}
}
}

View File

@ -31,6 +31,11 @@
#include "dlldefs.h"
// 1024 is more computationally intensive, but maybe better at detecting lower bass
#define FFT_LENGTH 512
class
#ifdef WIN32
DLLEXPORT
@ -52,8 +57,8 @@ public:
float *pcmdataR; //holder for most recent pcm data
/** PCM data */
float vdataL[512]; //holders for FFT data (spectrum)
float vdataR[512];
float vdataL[FFT_LENGTH]; //holders for FFT data (spectrum)
float vdataR[FFT_LENGTH];
static int maxsamples;
PCM();

View File

@ -36,31 +36,32 @@
#include <cmath>
#include "BeatDetect.hpp"
BeatDetect::BeatDetect(PCM *_pcm) {
int x,y;
this->pcm=_pcm;
BeatDetect::BeatDetect(PCM *_pcm)
{
this->pcm=_pcm;
this->vol_instant=0;
this->vol_history=0;
this->vol_instant=0;
this->vol_history=0;
for (unsigned y=0;y<80;y++)
this->vol_buffer[y]=0;
for (y=0;y<80;y++)
{
this->vol_buffer[y]=0;
}
this->beat_buffer_pos=0;
this->beat_buffer_pos=0;
this->bass_instant = 0;
this->bass_history = 0;
for (unsigned y=0;y<80;y++)
this->bass_buffer[y]=0;
for (x=0;x<32;x++) {
this->beat_instant[x]=0;
this->beat_history[x]=0;
this->beat_val[x]=1.0;
this->beat_att[x]=1.0;
this->beat_variance[x]=0;
for (y=0;y<80;y++) {
this->beat_buffer[x][y]=0;
}
}
this->mid_instant = 0;
this->mid_history = 0;
for (unsigned y=0;y<80;y++)
this->mid_buffer[y]=0;
this->treb_instant = 0;
this->treb_history = 0;
for (unsigned y=0;y<80;y++)
this->treb_buffer[y]=0;
this->treb = 0;
this->mid = 0;
@ -72,119 +73,119 @@ BeatDetect::BeatDetect(PCM *_pcm) {
this->bass_att = 0;
this->vol_att = 0;
this->vol = 0;
}
}
BeatDetect::~BeatDetect()
BeatDetect::~BeatDetect()
{
}
void BeatDetect::reset() {
this->treb = 0;
this->mid = 0;
this->bass = 0;
this->treb_att = 0;
this->mid_att = 0;
this->bass_att = 0;
this->vol_att = 0;
}
void BeatDetect::detectFromSamples() {
vol_old = vol;
bass=0;mid=0;treb=0;
getBeatVals(pcm->pcmdataL,pcm->pcmdataR);
}
void BeatDetect::getBeatVals( float *vdataL,float *vdataR ) {
int linear=0;
int x,y;
float temp2=0;
vol_instant=0;
for ( x=0;x<16;x++)
{
beat_instant[x]=0;
for ( y=linear*2;y<(linear+8+x)*2;y++)
{
beat_instant[x]+=((vdataL[y]*vdataL[y])+(vdataR[y]*vdataR[y]))*(1.0/(8+x));
// printf( "beat_instant[%d]: %f %f %f\n", x, beat_instant[x], vdataL[y], vdataR[y] );
vol_instant+=((vdataL[y]*vdataL[y])+(vdataR[y]*vdataR[y]))*(1.0/512.0);
}
//printf("1");
linear=y/2;
beat_history[x]-=(beat_buffer[x][beat_buffer_pos])*.0125;
beat_buffer[x][beat_buffer_pos]=beat_instant[x];
beat_history[x]+=(beat_instant[x])*.0125;
beat_val[x]=(beat_instant[x])/(beat_history[x]);
beat_att[x]+=(beat_instant[x])/(beat_history[x]);
//printf("2\n");
}
//printf("b\n");
vol_history-=(vol_buffer[beat_buffer_pos])*.0125;
vol_buffer[beat_buffer_pos]=vol_instant;
vol_history+=(vol_instant)*.0125;
mid=0;
for(x=1;x<10;x++)
{
mid+=(beat_instant[x]);
temp2+=(beat_history[x]);
}
mid=mid/(1.5*temp2);
temp2=0;
treb=0;
for(x=10;x<16;x++)
{
treb+=(beat_instant[x]);
temp2+=(beat_history[x]);
}
//printf("c\n");
treb=treb/(1.5*temp2);
// *vol=vol_instant/(1.5*vol_history);
vol=vol_instant/(1.5*vol_history);
bass=(beat_instant[0])/(1.5*beat_history[0]);
if ( projectM_isnan( treb ) ) {
treb = 0.0;
}
if ( projectM_isnan( mid ) ) {
mid = 0.0;
}
if ( projectM_isnan( bass ) ) {
bass = 0.0;
}
treb_att=.6 * treb_att + .4 * treb;
mid_att=.6 * mid_att + .4 * mid;
bass_att=.6 * bass_att + .4 * bass;
vol_att=.6 * vol_att + .4 * vol;
if(bass_att>100)bass_att=100;
if(bass >100)bass=100;
if(mid_att>100)mid_att=100;
if(mid >100)mid=100;
if(treb_att>100)treb_att=100;
if(treb >100)treb=100;
if(vol_att>100)vol_att=100;
if(vol>100)vol=100;
// *vol=(beat_instant[3])/(beat_history[3]);
beat_buffer_pos++;
if( beat_buffer_pos>79)beat_buffer_pos=0;
void BeatDetect::reset()
{
this->treb = 0;
this->mid = 0;
this->bass = 0;
this->treb_att = 0;
this->mid_att = 0;
this->bass_att = 0;
this->vol_att = 0;
this->vol_old = 0;
this->vol_instant=0;
}
void BeatDetect::detectFromSamples()
{
vol_old = vol;
bass=0;
mid=0;
treb=0;
vol=0;
// TODO: get sample rate from PCM? Assume 44100
getBeatVals(44100.0f, FFT_LENGTH, pcm->pcmdataL, pcm->pcmdataR);
}
void BeatDetect::getBeatVals( float samplerate, unsigned fft_length, float *vdataL, float *vdataR )
{
assert( 512==fft_length || 1024==fft_length ); // should be power of 2, expect >= 512
// TODO: compute ranges based on samplerate
unsigned ranges512[4] = {0, 3, 23, 200};
unsigned ranges1024[4] = {0, 5, 46, 400};
unsigned *ranges = fft_length==1024 ? ranges1024 : ranges512;
bass_instant = 0;
for (unsigned i=ranges[0]+1 ; i<=ranges[1] ; i++)
{
bass_instant += (vdataL[i*2]*vdataL[i*2]) + (vdataR[i*2]*vdataR[i*2]);
}
bass_instant *= 100.0/(ranges[1]-ranges[0]);
bass_history -= bass_buffer[beat_buffer_pos] *.0125;
bass_buffer[beat_buffer_pos] = bass_instant;
bass_history += bass_instant *.0125;
mid_instant = 0;
for (unsigned i=ranges[1]+1 ; i<=ranges[2] ; i++)
{
mid_instant += (vdataL[i*2]*vdataL[i*2]) + (vdataR[i*2]*vdataR[i*2]);
}
mid_instant *= 100.0/(ranges[2]-ranges[1]);
mid_history -= mid_buffer[beat_buffer_pos] *.0125;
mid_buffer[beat_buffer_pos] = mid_instant;
mid_history += mid_instant *.0125;
treb_instant = 0;
for (unsigned i=ranges[2]+1 ; i<=ranges[3] ; i++)
{
treb_instant += (vdataL[i*2]*vdataL[i*2]) + (vdataR[i*2]*vdataR[i*2]);
}
treb_instant *= 90.0/(ranges[3]-ranges[2]);
treb_history -= treb_buffer[beat_buffer_pos] *.0125;
treb_buffer[beat_buffer_pos] = treb_instant;
treb_history += treb_instant *.0125;
vol_instant = (bass_instant + mid_instant + treb_instant) / 3.0f;
vol_history -= (vol_buffer[beat_buffer_pos])*.0125;
vol_buffer[beat_buffer_pos] = vol_instant;
vol_history += (vol_instant)*.0125;
// fprintf(stderr, "%6.3f %6.2f %6.3f\n", bass_history/vol_history, mid_history/vol_history, treb_history/vol_history);
bass = bass_instant / fmax(0.0001, bass_history + 0.5*vol_history);
mid = mid_instant / fmax(0.0001, mid_history + 0.5*vol_history);
treb = treb_instant / fmax(0.0001, treb_history + 0.5*vol_history);
vol = vol_instant / fmax(0.0001, 1.5f * vol_history);
if ( projectM_isnan( treb ) ) {
treb = 0.0;
}
if ( projectM_isnan( mid ) ) {
mid = 0.0;
}
if ( projectM_isnan( bass ) ) {
bass = 0.0;
}
treb_att = .6f * treb_att + .4f * treb;
mid_att = .6f * mid_att + .4f * mid;
bass_att = .6f * bass_att + .4f * bass;
vol_att = .6f * vol_att + .4f * vol;
if (bass_att>100) bass_att=100;
if (bass >100) bass=100;
if (mid_att>100) mid_att=100;
if (mid >100) mid=100;
if (treb_att>100) treb_att=100;
if (treb >100) treb=100;
if (vol_att>100) vol_att=100;
if (vol>100) vol=100;
beat_buffer_pos++;
if (beat_buffer_pos>79)
beat_buffer_pos=0;
}

View File

@ -59,7 +59,7 @@ class DLLEXPORT BeatDetect
void initBeatDetect();
void reset();
void detectFromSamples();
void getBeatVals ( float *vdataL, float *vdataR );
void getBeatVals( float samplerate, unsigned fft_length, float *vdataL, float *vdataR );
float getPCMScale()
{
// added to address https://github.com/projectM-visualizer/projectm/issues/161
@ -74,17 +74,34 @@ class DLLEXPORT BeatDetect
}
private:
/** Vars */
float beat_buffer[32][80],
beat_instant[32],
beat_history[32];
float beat_val[32],
beat_att[32],
beat_variance[32];
int beat_buffer_pos;
float vol_buffer[80],
vol_instant;
float vol_history;
float bass_buffer[80];
float bass_history;
float bass_instant;
float mid_buffer[80];
float mid_history;
float mid_instant;
float treb_buffer[80];
float treb_history;
float treb_instant;
float vol_buffer[80];
float vol_history;
float vol_instant;
// /** Vars */
// float beat_buffer[32][80],
// beat_instant[32],
// beat_history[32];
// float beat_val[32],
// beat_att[32],
// beat_variance[32];
// int beat_buffer_pos;
// float vol_buffer[80],
// vol_instant;
// float vol_history;
};
#endif /** !_BEAT_DETECT_H */