@@ -672,6 +672,41 @@ Module::draw_box ( int tx, int ty, int tw, int th ) | |||
fl_pop_clip(); | |||
} | |||
#include "SpectrumView.H" | |||
#include <FL/Fl_Double_Window.H> | |||
bool | |||
Module::show_analysis_window ( void ) | |||
{ | |||
nframes_t nframes = 4096; | |||
float *buf = new float[nframes]; | |||
if ( ! get_impulse_response( buf, nframes ) ) | |||
return false; | |||
Fl_Double_Window *w = new Fl_Double_Window( 1000, 500 ); | |||
{ | |||
SpectrumView * o = new SpectrumView( 25,25, 1000 - 50, 500 - 50, label() ); | |||
o->labelsize(10); | |||
o->align(FL_ALIGN_RIGHT|FL_ALIGN_TOP); | |||
o->sample_rate( sample_rate() ); | |||
/* o->minimum_frequency( 10 ); */ | |||
/* o->maximum_frequency( 50000 ); */ | |||
o->data( buf, nframes ); | |||
} | |||
w->end(); | |||
w->show(); | |||
while ( w->shown() ) | |||
Fl::wait(); | |||
return true; | |||
} | |||
void | |||
Module::draw_label ( int tx, int ty, int tw, int th ) | |||
{ | |||
@@ -888,6 +923,10 @@ Module::menu_cb ( const Fl_Menu_ *m ) | |||
{ | |||
paste_before(); | |||
} | |||
else if ( ! strcmp( picked, "Show Analysis" ) ) | |||
{ | |||
show_analysis_window(); | |||
} | |||
else if ( ! strcmp( picked, "Remove" ) ) | |||
command_remove(); | |||
} | |||
@@ -924,10 +963,12 @@ Module::menu ( void ) const | |||
m.add( "Insert", 0, &Module::menu_cb, (void*)this, 0); | |||
m.add( "Insert", 0, &Module::menu_cb, const_cast< Fl_Menu_Item *>( insert_menu->menu() ), FL_SUBMENU_POINTER ); | |||
m.add( "Edit Parameters", ' ', &Module::menu_cb, (void*)this, 0 ); | |||
m.add( "Show Analysis", 's', &Module::menu_cb, (void*)this, 0); | |||
m.add( "Bypass", 'b', &Module::menu_cb, (void*)this, FL_MENU_TOGGLE | ( bypass() ? FL_MENU_VALUE : 0 ) ); | |||
m.add( "Cut", FL_CTRL + 'x', &Module::menu_cb, (void*)this, is_default() ? FL_MENU_INACTIVE : 0 ); | |||
m.add( "Copy", FL_CTRL + 'c', &Module::menu_cb, (void*)this, is_default() ? FL_MENU_INACTIVE : 0 ); | |||
m.add( "Paste", FL_CTRL + 'v', &Module::menu_cb, (void*)this, _copied_module_empty ? 0 : FL_MENU_INACTIVE ); | |||
m.add( "Remove", FL_Delete, &Module::menu_cb, (void*)this ); | |||
// menu_set_callback( menu, &Module::menu_cb, (void*)this ); | |||
@@ -440,7 +440,9 @@ public: | |||
char *get_parameters ( void ) const; | |||
void set_parameters ( const char * ); | |||
bool show_analysis_window ( void ); | |||
void send_feedback ( void ); | |||
virtual bool initialize ( void ) { return true; } | |||
@@ -468,6 +470,13 @@ public: | |||
virtual void handle_port_connection_change () {} | |||
/* module should create a new context, run against this impulse, | |||
* and return true if there's anything worth reporting */ | |||
virtual bool get_impulse_response ( sample_t *buf, nframes_t nframes ) | |||
{ | |||
return false; | |||
} | |||
#define MODULE_CLONE_FUNC(class) \ | |||
virtual Module *clone_empty ( void ) const \ | |||
{ \ | |||
@@ -480,8 +489,6 @@ public: | |||
protected: | |||
nframes_t sample_rate ( void ) const { return Module::_sample_rate; } | |||
void draw_connections ( void ); | |||
void draw_label ( int X, int Y, int W, int H ); | |||
void draw_box ( int X, int Y, int W, int H ); | |||
@@ -495,6 +502,8 @@ protected: | |||
bool add_aux_port ( bool input, const char *prefix, int n ); | |||
public: | |||
nframes_t sample_rate ( void ) const { return Module::_sample_rate; } | |||
void auto_connect_outputs(); | |||
void auto_disconnect_outputs(); | |||
@@ -47,6 +47,8 @@ | |||
#include "FL/menu_popup.H" | |||
#include "SpectrumView.H" | |||
Module_Parameter_Editor::Module_Parameter_Editor ( Module *module ) : Fl_Double_Window( 900,240) | |||
{ | |||
_module = module; | |||
@@ -97,6 +99,7 @@ Module_Parameter_Editor::Module_Parameter_Editor ( Module *module ) : Fl_Double_ | |||
o->flow( true ); | |||
o->vspacing( 5 ); | |||
o->hspacing( 5 ); | |||
o->end(); | |||
} | |||
o->resizable( 0 ); | |||
@@ -117,6 +120,29 @@ Module_Parameter_Editor::~Module_Parameter_Editor ( ) | |||
void | |||
Module_Parameter_Editor::update_spectrum ( void ) | |||
{ | |||
nframes_t nframes = 4096; | |||
float *buf = new float[nframes]; | |||
SpectrumView *o = spectrum_view; | |||
o->sample_rate( _module->sample_rate() ); | |||
if ( ! _module->get_impulse_response( buf, nframes ) ) | |||
{ | |||
o->data( buf, 1 ); | |||
/* o->hide(); */ | |||
} | |||
else | |||
{ | |||
o->data( buf, nframes ); | |||
o->parent()->show(); | |||
} | |||
o->redraw(); | |||
} | |||
void | |||
Module_Parameter_Editor::make_controls ( void ) | |||
{ | |||
@@ -124,6 +150,17 @@ Module_Parameter_Editor::make_controls ( void ) | |||
control_pack->clear(); | |||
{ SpectrumView *o = spectrum_view = new SpectrumView( 25, 40, 300, 240, "Spectrum" ); | |||
o->labelsize(9); | |||
o->align(FL_ALIGN_TOP); | |||
Fl_Labelpad_Group *flg = new Fl_Labelpad_Group( (Fl_Widget*)o ); | |||
flg->hide(); | |||
control_pack->add( flg ); | |||
} | |||
controls_by_port.clear(); | |||
/* these are for detecting related parameter groups which can be | |||
@@ -156,14 +193,14 @@ Module_Parameter_Editor::make_controls ( void ) | |||
control_pack->flow(true); | |||
control_pack->flowdown(false); | |||
control_pack->type( FL_HORIZONTAL ); | |||
control_pack->size( 900, 350 ); | |||
control_pack->size( 900, 250 ); | |||
} | |||
else if ( mode_choice->value() == 0 ) | |||
{ | |||
control_pack->vspacing( 10 ); | |||
control_pack->hspacing( 10 ); | |||
control_pack->flow(true); | |||
control_pack->flowdown(false); | |||
control_pack->flowdown(true); | |||
control_pack->type( FL_HORIZONTAL ); | |||
control_pack->size( 700, 50 ); | |||
@@ -381,6 +418,8 @@ Module_Parameter_Editor::make_controls ( void ) | |||
} | |||
update_control_visibility(); | |||
update_spectrum(); | |||
control_pack->dolayout(); | |||
@@ -504,6 +543,8 @@ Module_Parameter_Editor::handle_control_changed ( Module::Port *p ) | |||
v->value( p->control_value() ); | |||
} | |||
update_spectrum(); | |||
} | |||
@@ -524,6 +565,8 @@ Module_Parameter_Editor::set_value (int i, float value ) | |||
if ( _module->control_input[i].connected() ) | |||
_module->control_input[i].connected_port()->module()->handle_control_changed( _module->control_input[i].connected_port() ); | |||
} | |||
update_spectrum(); | |||
// _module->handle_control_changed( &_module->control_input[i] ); | |||
} | |||
@@ -27,6 +27,7 @@ class Module; | |||
class Fl_Menu_Button; | |||
class Panner; | |||
class Fl_Scroll; | |||
class SpectrumView; | |||
#include <vector> | |||
#include <list> | |||
@@ -76,10 +77,12 @@ class Module_Parameter_Editor : public Fl_Double_Window | |||
void set_value (int i, float value ); | |||
void bind_control ( int i ); | |||
void make_controls ( void ); | |||
void update_spectrum ( void ); | |||
static void menu_cb ( Fl_Widget *w, void *v ); | |||
void menu_cb ( Fl_Menu_ *m ); | |||
SpectrumView *spectrum_view; | |||
Fl_Scroll *control_scroll; | |||
Fl_Flowpack *control_pack; | |||
Fl_Menu_Button *mode_choice; | |||
@@ -778,6 +778,80 @@ Plugin_Module::handle_port_connection_change ( void ) | |||
bool | |||
Plugin_Module::get_impulse_response ( sample_t *buf, nframes_t nframes ) | |||
{ | |||
memset( buf, 0, sizeof( float ) * nframes ); | |||
buf[0] = 1; | |||
apply( buf, nframes ); | |||
if ( buffer_is_digital_black( buf + 1, nframes - 1 )) | |||
/* no impulse response... */ | |||
return false; | |||
return true; | |||
} | |||
/** Instantiate a temporary version of the plugin, and run it (in place) against the provided buffer */ | |||
bool | |||
Plugin_Module::apply ( sample_t *buf, nframes_t nframes ) | |||
{ | |||
// actually osc or UI THREAD_ASSERT( UI ); | |||
LADSPA_Handle h; | |||
if ( ! (h = _idata->descriptor->instantiate( _idata->descriptor, sample_rate() ) ) ) | |||
{ | |||
WARNING( "Failed to instantiate plugin" ); | |||
return false; | |||
} | |||
int ij = 0; | |||
int oj = 0; | |||
for ( unsigned int k = 0; k < _idata->descriptor->PortCount; ++k ) | |||
{ | |||
if ( LADSPA_IS_PORT_CONTROL( _idata->descriptor->PortDescriptors[k] ) ) | |||
{ | |||
if ( LADSPA_IS_PORT_INPUT( _idata->descriptor->PortDescriptors[k] ) ) | |||
_idata->descriptor->connect_port( h, k, (LADSPA_Data*)control_input[ij++].buffer() ); | |||
else if ( LADSPA_IS_PORT_OUTPUT( _idata->descriptor->PortDescriptors[k] ) ) | |||
_idata->descriptor->connect_port( h, k, (LADSPA_Data*)control_output[oj++].buffer() ); | |||
} | |||
} | |||
if ( _idata->descriptor->activate ) | |||
_idata->descriptor->activate( h ); | |||
int tframes = 512; | |||
float tmp[tframes]; | |||
memset( tmp, 0, sizeof( float ) * tframes ); | |||
for ( unsigned int k = 0; k < _idata->descriptor->PortCount; ++k ) | |||
if ( LADSPA_IS_PORT_AUDIO( _idata->descriptor->PortDescriptors[k] ) ) | |||
_idata->descriptor->connect_port( h, k, tmp ); | |||
/* flush any parameter interpolation */ | |||
_idata->descriptor->run( h, tframes ); | |||
for ( unsigned int k = 0; k < _idata->descriptor->PortCount; ++k ) | |||
if ( LADSPA_IS_PORT_AUDIO( _idata->descriptor->PortDescriptors[k] ) ) | |||
_idata->descriptor->connect_port( h, k, buf ); | |||
/* run for real */ | |||
_idata->descriptor->run( h, nframes ); | |||
if ( _idata->descriptor->deactivate ) | |||
_idata->descriptor->deactivate( h ); | |||
if ( _idata->descriptor->cleanup ) | |||
_idata->descriptor->cleanup( h ); | |||
return true; | |||
} | |||
/**********/ | |||
/* Client */ | |||
/**********/ | |||
@@ -99,6 +99,8 @@ private: | |||
void set_control_buffer ( int n, void *buf ); | |||
void activate ( void ); | |||
void deactivate ( void ); | |||
bool apply ( sample_t *buf, nframes_t nframes ); | |||
void process ( unsigned long nframes ); | |||
bool plugin_instances ( unsigned int ); | |||
@@ -109,6 +111,8 @@ private: | |||
public: | |||
virtual bool get_impulse_response ( sample_t *buf, nframes_t nframes ); | |||
virtual nframes_t get_module_latency ( void ) const; | |||
virtual void update ( void ); | |||
@@ -0,0 +1,342 @@ | |||
/*******************************************************************************/ | |||
/* Copyright (C) 2013 Mark McCurry */ | |||
/* Copyright (C) 2013 Jonathan Moore Liles */ | |||
/* */ | |||
/* 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; see the file COPYING. If not,write to the Free Software */ | |||
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
/*******************************************************************************/ | |||
#include "SpectrumView.H" | |||
#include <FL/Fl.H> | |||
#include <FL/fl_draw.H> | |||
#include <math.h> | |||
#include <cstdlib> | |||
#include <cstring> | |||
#include <map> | |||
#include <assert.h> | |||
static std::map<int,float*> _cached_plan; | |||
float SpectrumView::_fmin = 10; | |||
float SpectrumView::_fmax = 24000; | |||
unsigned int SpectrumView::_sample_rate = 48000; | |||
void | |||
SpectrumView::clear_bands ( void ) | |||
{ | |||
if ( _bands ) | |||
delete[] _bands; | |||
_bands = NULL; | |||
} | |||
void | |||
SpectrumView::data ( float *data, unsigned int nframes ) | |||
{ | |||
if ( _data ) | |||
delete[] _data; | |||
_data = data; | |||
_nframes = nframes; | |||
clear_bands(); | |||
redraw(); | |||
} | |||
void | |||
SpectrumView::sample_rate ( unsigned int sample_rate ) | |||
{ | |||
if ( _sample_rate != sample_rate ) | |||
{ | |||
_sample_rate = sample_rate; | |||
_fmin = 10; | |||
_fmax = _sample_rate * 0.5f; | |||
/* invalidate all plans */ | |||
for ( std::map<int,float*>::iterator i = _cached_plan.begin(); | |||
i != _cached_plan.end(); | |||
i++ ) | |||
{ | |||
delete[] i->second; | |||
} | |||
_cached_plan.clear(); | |||
} | |||
} | |||
#define min(a,b) (a<b?a:b) | |||
#define max(a,b) (a<b?b:a) | |||
static float* | |||
qft_plan ( unsigned frames, unsigned samples, float Fs, float Fmin, float Fmax ) | |||
{ | |||
float *op = new float[ frames * samples * 2 ]; | |||
//Our scaling function must be some f(0) = Fmin and f(1) = Fmax | |||
// Thus, | |||
// f(x)=10^(a*x+b) -> b=log(Fmin)/log(10) | |||
// log10(Fmax)=a+b -> a=log(Fmax)/log(10)-b | |||
const float b = logf(Fmin)/logf(10); | |||
const float a = logf(Fmax)/logf(10)-b; | |||
//Evaluate at set frequencies | |||
const float one_over_samples = 1.0f / samples; | |||
const float one_over_samplerate = 1.0f / Fs; | |||
for(unsigned i=0; i<samples; ++i) | |||
{ | |||
const float F = powf(10.0,a*i*one_over_samples+b)*one_over_samplerate; | |||
const float Fp = -2*M_PI*F; | |||
float Fpj = 0; | |||
for(unsigned j = 0; j < frames; ++j, Fpj += Fp ) | |||
{ | |||
const unsigned ji = i*frames*2+2*j; | |||
op[ji+0] = sinf(Fpj); | |||
op[ji+1] = cosf(Fpj); | |||
} | |||
} | |||
return op; | |||
} | |||
/** Input should be an impulse response of an EQ. Output will be a | |||
* buffer of /bands/ floats of dB values for each frequency band */ | |||
void | |||
SpectrumView::analyze_data ( unsigned int _plan_size ) | |||
{ | |||
float res[_plan_size * 2]; | |||
memset(res,0,sizeof(float) * _plan_size * 2); | |||
if ( _cached_plan.find( _plan_size ) == _cached_plan.end() ) | |||
_cached_plan[_plan_size ] = qft_plan( _nframes, _plan_size, _sample_rate, _fmin, _fmax); | |||
const float *plan = _cached_plan[_plan_size]; | |||
//Evaluate at set frequencies | |||
for(unsigned i=0; i<_plan_size; ++i) { | |||
unsigned ti = i*2; | |||
unsigned tif = ti*_nframes; | |||
for(unsigned int j=0; j < _nframes ; ++j) { | |||
unsigned ji = tif+j*2; | |||
res[ti+0] += plan[ji+0]*_data[j]; | |||
res[ti+1] += plan[ji+1]*_data[j]; | |||
} | |||
} | |||
float *result = new float[_plan_size]; | |||
for(unsigned i=0; i<_plan_size; ++i) { | |||
const float abs_ = sqrtf(res[2*i]*res[2*i]+res[2*i+1]*res[2*i+1]); | |||
result[i] = 20*logf(abs_)/logf(10); | |||
} | |||
{ | |||
if ( _auto_level ) | |||
{ | |||
/* find range and normalize */ | |||
float _min=1000, _max=-1000; | |||
for(unsigned int i=0; i< _plan_size; ++i) | |||
{ | |||
_min = min(_min, result[i]); | |||
_max = max(_max, result[i]); | |||
} | |||
_dbmin = _min; | |||
_dbmax = _max; | |||
} | |||
double minS = 1.0 / (_dbmax-_dbmin); | |||
for( unsigned int i=0; i<_plan_size; ++i) | |||
result[i] = (result[i]-_dbmin)*minS; | |||
} | |||
clear_bands(); | |||
_bands = result; | |||
} | |||
SpectrumView::~SpectrumView ( void ) | |||
{ | |||
clear_bands(); | |||
if ( _data ) | |||
delete[] _data; | |||
} | |||
SpectrumView::SpectrumView ( int X, int Y, int W, int H, const char *L ) | |||
: Fl_Box(X,Y,W,H,L) | |||
{ | |||
_auto_level = 0; | |||
_data = 0; | |||
_nframes = 0; | |||
_bands = 0; | |||
_dbmin = -70; | |||
_dbmax = 30; | |||
box(FL_FLAT_BOX); | |||
color(fl_rgb_color(20,20,20)); | |||
selection_color( fl_rgb_color( 210, 80, 80 ) ); | |||
// end(); | |||
} | |||
static int padding_right = 0; | |||
static int padding_bottom = 0; | |||
void | |||
SpectrumView::draw_semilog ( void ) | |||
{ | |||
int W = w() - padding_right; | |||
int H = h() - padding_bottom; | |||
/* char dash[] = {5,5 }; */ | |||
/* fl_line_style(0, 1, dash); */ | |||
fl_line_style(FL_SOLID,0); | |||
//Db grid is easy, it is just a linear spacing | |||
for(int i=0; i<8; ++i) { | |||
int level = y()+H*i/8.0; | |||
fl_line(x(), level, x()+W, level); | |||
} | |||
//The frequency grid is defined with points at | |||
//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 | |||
//that scale | |||
const int min_base = logf(_fmin)/logf(10); | |||
const int max_base = logf(_fmax)/logf(10); | |||
const float b = logf(_fmin)/logf(10); | |||
const float a = logf(_fmax)/logf(10)-b; | |||
for(int i=min_base; i<=max_base; ++i) { | |||
for(int j=1; j<10; ++j) { | |||
const float freq = pow(10.0, i)*j; | |||
const float xloc = (logf(freq)/logf(10)-b)/a; | |||
if(xloc<1.0 && xloc > -0.001) | |||
fl_line(xloc*W+x(), y(), xloc*W+x(), y()+H); | |||
} | |||
} | |||
fl_end_line(); | |||
fl_font( FL_HELVETICA_ITALIC, 7 ); | |||
//Place the text labels | |||
char label[256]; | |||
for(int i=0; i<8; ++i) { | |||
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()); | |||
} | |||
} | |||
} | |||
void | |||
SpectrumView::draw_curve ( void ) | |||
{ | |||
int W = w() - padding_right; | |||
//Build lines | |||
float inc = 1.0 / (float)W; | |||
float fx = 0; | |||
for( int i = 0; i < W; i++, fx += inc ) | |||
fl_vertex(fx, 1.0 - _bands[i]); | |||
} | |||
void | |||
SpectrumView::draw ( void ) | |||
{ | |||
//Clear Widget | |||
Fl_Box::draw(); | |||
int W = w() - padding_right; | |||
int H = h() - padding_bottom; | |||
if ( !_bands ) { | |||
analyze_data( W ); | |||
} | |||
//Draw grid | |||
fl_color(fl_color_add_alpha(fl_rgb_color( 100,100,100), 50 )); | |||
draw_semilog(); | |||
fl_push_clip( x(),y(),W,H); | |||
fl_color(fl_color_add_alpha( selection_color(), 20 )); | |||
fl_push_matrix(); | |||
fl_translate( x(), y() + 2 ); | |||
fl_scale( W,H- 2 ); | |||
fl_begin_polygon(); | |||
fl_vertex(0.0,1.0); | |||
draw_curve(); | |||
fl_vertex(1.0,1.0); | |||
fl_end_polygon(); | |||
fl_color(fl_color_add_alpha( selection_color(), 100 )); | |||
fl_begin_line(); | |||
fl_line_style(FL_SOLID,2); | |||
/* fl_vertex(0.0,1.0); */ | |||
draw_curve(); | |||
/* fl_vertex(1.0,1.0); */ | |||
fl_end_line(); | |||
fl_pop_matrix(); | |||
fl_line_style(FL_SOLID,0); | |||
fl_pop_clip(); | |||
} | |||
void | |||
SpectrumView::resize ( int X, int Y, int W, int H ) | |||
{ | |||
if ( W != w() ) | |||
clear_bands(); | |||
Fl_Box::resize(X,Y,W,H); | |||
} | |||
@@ -0,0 +1,62 @@ | |||
/*******************************************************************************/ | |||
/* Copyright (C) 2013 Mark McCurry */ | |||
/* Copyright (C) 2013 Jonathan Moore Liles */ | |||
/* */ | |||
/* 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; see the file COPYING. If not,write to the Free Software */ | |||
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
/*******************************************************************************/ | |||
#include <FL/Fl_Box.H> | |||
class SpectrumView : public Fl_Box | |||
{ | |||
static unsigned int _sample_rate; | |||
static float _fmin; | |||
static float _fmax; | |||
float * _data; | |||
unsigned int _nframes; | |||
float * _bands; | |||
float _dbmin; | |||
float _dbmax; | |||
bool _auto_level; | |||
void draw_curve ( void ); | |||
void draw_semilog ( void ); | |||
void analyze_data ( unsigned int plan_size ); | |||
void clear_bands ( void ); | |||
public: | |||
static void sample_rate ( unsigned int sample_rate ); | |||
/* set dB range. If min == max, then auto leveling will be enabled */ | |||
void db_range ( float min, float max ) | |||
{ | |||
_dbmin = min; | |||
_dbmax = 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 */ | |||
void data ( float *data, unsigned int nframes ); | |||
SpectrumView ( int X, int Y, int W, int H, const char *L=0 ); | |||
virtual ~SpectrumView ( ); | |||
virtual void resize ( int X, int Y, int W, int H ); | |||
virtual void draw ( void ); | |||
}; | |||
@@ -66,6 +66,7 @@ src/Plugin_Module.C | |||
src/Project.C | |||
src/Group.C | |||
src/main.C | |||
src/SpectrumView.C | |||
src/Spatialization_Console.C | |||
''', | |||
target = 'non-mixer', | |||
@@ -181,7 +181,7 @@ buffer_fill_with_silence ( sample_t *buf, nframes_t nframes ) | |||
} | |||
bool | |||
buffer_is_digital_black ( sample_t *buf, nframes_t nframes ) | |||
buffer_is_digital_black ( const sample_t *buf, nframes_t nframes ) | |||
{ | |||
while ( nframes-- ) | |||
{ | |||