Mixer: Tweak spectrum view.
This commit is contained in:
parent
1b3994a5f1
commit
45a33b8467
|
@ -679,7 +679,8 @@ Module::draw_box ( int tx, int ty, int tw, int th )
|
||||||
bool
|
bool
|
||||||
Module::show_analysis_window ( void )
|
Module::show_analysis_window ( void )
|
||||||
{
|
{
|
||||||
nframes_t nframes = 4096;
|
/* use a large window for more accuracy at low frequencies */
|
||||||
|
nframes_t nframes = sample_rate() / 2;
|
||||||
float *buf = new float[nframes];
|
float *buf = new float[nframes];
|
||||||
|
|
||||||
memset( buf, 0, sizeof(float) * nframes );
|
memset( buf, 0, sizeof(float) * nframes );
|
||||||
|
@ -698,8 +699,6 @@ Module::show_analysis_window ( void )
|
||||||
o->labelsize(10);
|
o->labelsize(10);
|
||||||
o->align(FL_ALIGN_RIGHT|FL_ALIGN_TOP);
|
o->align(FL_ALIGN_RIGHT|FL_ALIGN_TOP);
|
||||||
o->sample_rate( sample_rate() );
|
o->sample_rate( sample_rate() );
|
||||||
/* o->minimum_frequency( 10 ); */
|
|
||||||
/* o->maximum_frequency( 50000 ); */
|
|
||||||
o->data( buf, nframes );
|
o->data( buf, nframes );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -135,17 +135,20 @@ Module_Parameter_Editor::~Module_Parameter_Editor ( )
|
||||||
void
|
void
|
||||||
Module_Parameter_Editor::update_spectrum ( void )
|
Module_Parameter_Editor::update_spectrum ( void )
|
||||||
{
|
{
|
||||||
nframes_t nframes = 4096;
|
nframes_t sample_rate = _module->sample_rate();
|
||||||
|
|
||||||
|
SpectrumView *o = spectrum_view;
|
||||||
|
|
||||||
|
o->sample_rate( sample_rate );
|
||||||
|
|
||||||
|
nframes_t nframes = sample_rate / 10;
|
||||||
|
|
||||||
float *buf = new float[nframes];
|
float *buf = new float[nframes];
|
||||||
|
|
||||||
memset( buf, 0, sizeof(float) * nframes );
|
memset( buf, 0, sizeof(float) * nframes );
|
||||||
|
|
||||||
buf[0] = 1;
|
buf[0] = 1;
|
||||||
|
|
||||||
SpectrumView *o = spectrum_view;
|
|
||||||
|
|
||||||
o->sample_rate( _module->sample_rate() );
|
|
||||||
|
|
||||||
bool show = false;
|
bool show = false;
|
||||||
|
|
||||||
if ( ! _module->get_impulse_response( buf, nframes ) )
|
if ( ! _module->get_impulse_response( buf, nframes ) )
|
||||||
|
|
|
@ -26,16 +26,15 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
static std::map<int,float*> _cached_plan;
|
static std::map<std::string,float*> _cached_plan;
|
||||||
|
|
||||||
unsigned int SpectrumView::_nframes = 0;
|
|
||||||
float SpectrumView::_fmin = 10;
|
|
||||||
float SpectrumView::_fmax = 24000;
|
|
||||||
unsigned int SpectrumView::_sample_rate = 48000;
|
|
||||||
|
|
||||||
|
float SpectrumView::_fmin = 0;
|
||||||
|
float SpectrumView::_fmax = 0;
|
||||||
|
unsigned int SpectrumView::_sample_rate = 0;
|
||||||
|
|
||||||
void
|
void
|
||||||
SpectrumView::clear_bands ( void )
|
SpectrumView::clear_bands ( void )
|
||||||
|
@ -53,12 +52,10 @@ SpectrumView::data ( float *data, unsigned int nframes )
|
||||||
delete[] _data;
|
delete[] _data;
|
||||||
|
|
||||||
_data = data;
|
_data = data;
|
||||||
_data_frames = nframes;
|
_nframes = nframes;
|
||||||
|
|
||||||
clear_bands();
|
clear_bands();
|
||||||
|
|
||||||
impulse_frames( nframes );
|
|
||||||
|
|
||||||
redraw();
|
redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +64,7 @@ SpectrumView::clear_plans ( void )
|
||||||
{
|
{
|
||||||
/* invalidate all plans */
|
/* invalidate all plans */
|
||||||
|
|
||||||
for ( std::map<int,float*>::iterator i = _cached_plan.begin();
|
for ( std::map<std::string,float*>::iterator i = _cached_plan.begin();
|
||||||
i != _cached_plan.end();
|
i != _cached_plan.end();
|
||||||
i++ )
|
i++ )
|
||||||
{
|
{
|
||||||
|
@ -84,23 +81,14 @@ SpectrumView::sample_rate ( unsigned int sample_rate )
|
||||||
{
|
{
|
||||||
_sample_rate = sample_rate;
|
_sample_rate = sample_rate;
|
||||||
_fmin = 10;
|
_fmin = 10;
|
||||||
_fmax = _sample_rate * 0.5f;
|
_fmax = 20000;
|
||||||
|
if ( _fmax > _sample_rate * 0.5f )
|
||||||
|
_fmax = _sample_rate * 0.5f;
|
||||||
|
|
||||||
clear_plans();
|
clear_plans();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
SpectrumView::impulse_frames ( unsigned int nframes )
|
|
||||||
{
|
|
||||||
if ( _nframes != nframes )
|
|
||||||
{
|
|
||||||
clear_plans();
|
|
||||||
|
|
||||||
_nframes = nframes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define min(a,b) (a<b?a:b)
|
#define min(a,b) (a<b?a:b)
|
||||||
#define max(a,b) (a<b?b:a)
|
#define max(a,b) (a<b?b:a)
|
||||||
|
@ -142,6 +130,14 @@ qft_plan ( unsigned frames, unsigned samples, float Fs, float Fmin, float Fmax )
|
||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
plan_key ( unsigned int plan_size, unsigned int nframes )
|
||||||
|
{
|
||||||
|
static char s[256];
|
||||||
|
snprintf( s, sizeof(s), "%d:%d", plan_size, nframes );
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
/** Input should be an impulse response of an EQ. Output will be a
|
/** Input should be an impulse response of an EQ. Output will be a
|
||||||
* buffer of /bands/ floats of dB values for each frequency band */
|
* buffer of /bands/ floats of dB values for each frequency band */
|
||||||
void
|
void
|
||||||
|
@ -153,10 +149,12 @@ SpectrumView::analyze_data ( unsigned int _plan_size )
|
||||||
float res[_plan_size * 2];
|
float res[_plan_size * 2];
|
||||||
memset(res,0,sizeof(float) * _plan_size * 2);
|
memset(res,0,sizeof(float) * _plan_size * 2);
|
||||||
|
|
||||||
if ( _cached_plan.find( _plan_size ) == _cached_plan.end() )
|
const char *key = plan_key( _plan_size, _nframes );
|
||||||
_cached_plan[_plan_size ] = qft_plan( _nframes, _plan_size, _sample_rate, _fmin, _fmax);
|
|
||||||
|
|
||||||
const float *plan = _cached_plan[_plan_size];
|
if ( _cached_plan.find( key ) == _cached_plan.end() )
|
||||||
|
_cached_plan[ key ] = qft_plan( _nframes, _plan_size, _sample_rate, _fmin, _fmax);
|
||||||
|
|
||||||
|
const float *plan = _cached_plan[ key ];
|
||||||
|
|
||||||
//Evaluate at set frequencies
|
//Evaluate at set frequencies
|
||||||
for(unsigned i=0; i<_plan_size; ++i) {
|
for(unsigned i=0; i<_plan_size; ++i) {
|
||||||
|
@ -213,9 +211,9 @@ SpectrumView::~SpectrumView ( void )
|
||||||
SpectrumView::SpectrumView ( int X, int Y, int W, int H, const char *L )
|
SpectrumView::SpectrumView ( int X, int Y, int W, int H, const char *L )
|
||||||
: Fl_Box(X,Y,W,H,L)
|
: Fl_Box(X,Y,W,H,L)
|
||||||
{
|
{
|
||||||
|
_nframes = 0;
|
||||||
_auto_level = 0;
|
_auto_level = 0;
|
||||||
_data = 0;
|
_data = 0;
|
||||||
_data_frames = 0;
|
|
||||||
_bands = 0;
|
_bands = 0;
|
||||||
_dbmin = -70;
|
_dbmin = -70;
|
||||||
_dbmax = 30;
|
_dbmax = 30;
|
||||||
|
@ -226,61 +224,53 @@ SpectrumView::SpectrumView ( int X, int Y, int W, int H, const char *L )
|
||||||
}
|
}
|
||||||
|
|
||||||
static int padding_right = 0;
|
static int padding_right = 0;
|
||||||
static int padding_bottom = 0;
|
static int padding_bottom = 7;
|
||||||
|
|
||||||
void
|
void
|
||||||
SpectrumView::draw_semilog ( void )
|
SpectrumView::draw_semilog ( void )
|
||||||
{
|
{
|
||||||
int W = w() - padding_right;
|
int W = w() - padding_right;
|
||||||
int H = h() - padding_bottom;
|
int H = h() - padding_bottom;
|
||||||
|
char label[50];
|
||||||
|
|
||||||
/* char dash[] = {5,5 }; */
|
|
||||||
/* fl_line_style(0, 1, dash); */
|
|
||||||
fl_line_style(FL_SOLID,0);
|
fl_line_style(FL_SOLID,0);
|
||||||
|
fl_font( FL_HELVETICA_ITALIC, 7 );
|
||||||
|
|
||||||
//Db grid is easy, it is just a linear spacing
|
//Db grid is easy, it is just a linear spacing
|
||||||
for(int i=0; i<8; ++i) {
|
for(int i=0; i<8; ++i) {
|
||||||
int level = y()+H*i/8.0;
|
int level = y()+H*i/8.0;
|
||||||
fl_line(x(), level, x()+W, level);
|
fl_line(x(), level, x()+W, level);
|
||||||
|
|
||||||
|
float value = (1-i/8.0)*(_dbmax-_dbmin) + _dbmin;
|
||||||
|
sprintf(label, "%.1f dB", value);
|
||||||
|
fl_draw(label, x(), level + 3, w(), 7, FL_ALIGN_RIGHT );
|
||||||
}
|
}
|
||||||
|
|
||||||
//The frequency grid is defined with points at
|
//The frequency grid is defined with points at
|
||||||
//10,11,12,...,18,19,20,30,40,50,60,70,80,90,100,200,400,...
|
//10,11,12,...,18,19,20,30,40,50,60,70,80,90,100,200,400,...
|
||||||
//Thus we find each scale that we cover and draw the nine lines unique to
|
//Thus we find each scale that we cover and draw the nine lines unique to
|
||||||
//that scale
|
//that scale
|
||||||
const int min_base = logf(_fmin)/logf(10);
|
float lb = 1.0f / logf( 10 );
|
||||||
const int max_base = logf(_fmax)/logf(10);
|
const int min_base = logf(_fmin)*lb;
|
||||||
const float b = logf(_fmin)/logf(10);
|
const int max_base = logf(_fmax)*lb;
|
||||||
const float a = logf(_fmax)/logf(10)-b;
|
const float b = logf(_fmin)*lb;
|
||||||
|
const float a = logf(_fmax)*lb-b;
|
||||||
for(int i=min_base; i<=max_base; ++i) {
|
for(int i=min_base; i<=max_base; ++i) {
|
||||||
for(int j=1; j<10; ++j) {
|
for(int j=1; j<10; ++j) {
|
||||||
const float freq = pow(10.0, i)*j;
|
const float freq = pow(10.0, i)*j;
|
||||||
const float xloc = (logf(freq)/logf(10)-b)/a;
|
const float xloc = (logf(freq)*lb-b)/a;
|
||||||
if(xloc<1.0 && xloc > -0.001)
|
if(xloc<1.0 && xloc > -0.001)
|
||||||
|
{
|
||||||
fl_line(xloc*W+x(), y(), xloc*W+x(), y()+H);
|
fl_line(xloc*W+x(), y(), xloc*W+x(), y()+H);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fl_end_line();
|
if ( j == 1 || j == 2 || j == 5 )
|
||||||
|
{
|
||||||
fl_font( FL_HELVETICA_ITALIC, 7 );
|
sprintf(label, "%0.f %s", freq < 1000.0 ? freq : freq / 1000.0, freq < 1000.0 ? "Hz" : "KHz" );
|
||||||
//Place the text labels
|
int sx = x() + xloc*W + 1;
|
||||||
char label[256];
|
if ( sx < x() * W - 20 )
|
||||||
for(int i=0; i<8; ++i) {
|
fl_draw(label, sx, y()+h());
|
||||||
int level = (y()+H*i/8.0) + 3;
|
}
|
||||||
float value = (1-i/8.0)*(_dbmax-_dbmin) + _dbmin;
|
}
|
||||||
sprintf(label, "%.1f dB", value);
|
|
||||||
// fl_draw(label, x()+w() + 3, level);
|
|
||||||
fl_draw(label, x(), level, w(), 7, FL_ALIGN_RIGHT );
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i=min_base; i<=max_base; ++i) {
|
|
||||||
{
|
|
||||||
const float freq = pow(10.0, i)*1;
|
|
||||||
const float xloc = (logf(freq)/logf(10)-b)/a;
|
|
||||||
sprintf(label, "%0.f %s", freq < 1000.0 ? freq : freq / 1000.0, freq < 1000.0 ? "Hz" : "KHz" );
|
|
||||||
if(xloc<1.0)
|
|
||||||
fl_draw(label, xloc*W+x()+1, y()+h());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -294,11 +284,11 @@ SpectrumView::draw_curve ( void )
|
||||||
int W = w() - padding_right;
|
int W = w() - padding_right;
|
||||||
|
|
||||||
//Build lines
|
//Build lines
|
||||||
float inc = 1.0 / (float)W;
|
float inc = 1.0f / (float)W;
|
||||||
|
|
||||||
float fx = 0;
|
float fx = 0;
|
||||||
for( int i = 0; i < W; i++, fx += inc )
|
for( int i = 0; i < W; i++, fx += inc )
|
||||||
fl_vertex(fx, 1.0 - _bands[i]);
|
fl_vertex(fx, 1.0f - _bands[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -310,16 +300,6 @@ SpectrumView::draw ( void )
|
||||||
int W = w() - padding_right;
|
int W = w() - padding_right;
|
||||||
int H = h() - padding_bottom;
|
int H = h() - padding_bottom;
|
||||||
|
|
||||||
if ( _data_frames != _nframes )
|
|
||||||
{
|
|
||||||
/* invalid data */
|
|
||||||
if ( _data )
|
|
||||||
delete[] _data;
|
|
||||||
_data = 0;
|
|
||||||
|
|
||||||
clear_bands();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !_bands ) {
|
if ( !_bands ) {
|
||||||
analyze_data( W );
|
analyze_data( W );
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,10 +25,9 @@ class SpectrumView : public Fl_Box
|
||||||
static unsigned int _sample_rate;
|
static unsigned int _sample_rate;
|
||||||
static float _fmin;
|
static float _fmin;
|
||||||
static float _fmax;
|
static float _fmax;
|
||||||
static unsigned int _nframes;
|
unsigned int _nframes;
|
||||||
|
|
||||||
float * _data;
|
float * _data;
|
||||||
unsigned int _data_frames;
|
|
||||||
float * _bands;
|
float * _bands;
|
||||||
float _dbmin;
|
float _dbmin;
|
||||||
float _dbmax;
|
float _dbmax;
|
||||||
|
@ -43,9 +42,6 @@ class SpectrumView : public Fl_Box
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static void sample_rate ( unsigned int sample_rate );
|
static void sample_rate ( unsigned int sample_rate );
|
||||||
/* all subsequent calls to data() MUST contain this number of
|
|
||||||
* frames. Changing this value will invalidate all cached plans */
|
|
||||||
static void impulse_frames ( unsigned int nframes );
|
|
||||||
|
|
||||||
/* set dB range. If min == max, then auto leveling will be enabled */
|
/* set dB range. If min == max, then auto leveling will be enabled */
|
||||||
void db_range ( float min, float max )
|
void db_range ( float min, float max )
|
||||||
|
@ -55,8 +51,7 @@ public:
|
||||||
_auto_level = min == max;
|
_auto_level = min == max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** /data/ must point to allocated memory. It will be freed when new data is set or when the control is destroyed */
|
||||||
/** /data/ must point to allocated memory. It will be freed when new data is set or when the control is destroyed */
|
|
||||||
|
|
||||||
void data ( float *data, unsigned int data_frames );
|
void data ( float *data, unsigned int data_frames );
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue