Mixer: Try to better cope with parameter feedback feedback cycles.
This commit is contained in:
parent
1f0f01c0ad
commit
82f9610ca8
|
@ -49,7 +49,8 @@
|
||||||
|
|
||||||
#include "Controller_Module.H"
|
#include "Controller_Module.H"
|
||||||
|
|
||||||
const double FEEDBACK_UPDATE_FREQ = 1.0f;
|
/* const double FEEDBACK_UPDATE_FREQ = 1.0f; */
|
||||||
|
const double FEEDBACK_UPDATE_FREQ = 1.0f / 30.0f;
|
||||||
|
|
||||||
extern char *user_config_dir;
|
extern char *user_config_dir;
|
||||||
extern char *instance_name;
|
extern char *instance_name;
|
||||||
|
@ -593,7 +594,6 @@ Mixer::Mixer ( int X, int Y, int W, int H, const char *L ) :
|
||||||
|
|
||||||
update_frequency( 24 );
|
update_frequency( 24 );
|
||||||
|
|
||||||
Fl::add_timeout( FEEDBACK_UPDATE_FREQ, send_feedback_cb, this );
|
|
||||||
|
|
||||||
update_menu();
|
update_menu();
|
||||||
|
|
||||||
|
@ -1078,6 +1078,7 @@ Mixer::send_feedback_cb ( void *v )
|
||||||
|
|
||||||
m->send_feedback();
|
m->send_feedback();
|
||||||
|
|
||||||
|
/* just to it once at the start... */
|
||||||
Fl::repeat_timeout( FEEDBACK_UPDATE_FREQ, send_feedback_cb, v );
|
Fl::repeat_timeout( FEEDBACK_UPDATE_FREQ, send_feedback_cb, v );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1297,6 +1298,9 @@ Mixer::command_load ( const char *path, const char *display_name )
|
||||||
|
|
||||||
mixer->activate();
|
mixer->activate();
|
||||||
|
|
||||||
|
/* Fl::remove_timeout( send_feedback_cb, this ); */
|
||||||
|
Fl::add_timeout( FEEDBACK_UPDATE_FREQ, send_feedback_cb, this );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,9 @@
|
||||||
|
|
||||||
#include "string_util.h"
|
#include "string_util.h"
|
||||||
|
|
||||||
|
#include "time.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
nframes_t Module::_sample_rate = 0;
|
nframes_t Module::_sample_rate = 0;
|
||||||
|
@ -166,6 +169,7 @@ Module::init ( void )
|
||||||
_chain = 0;
|
_chain = 0;
|
||||||
_instances = 1;
|
_instances = 1;
|
||||||
_bypass = 0;
|
_bypass = 0;
|
||||||
|
_pending_feedback = false;
|
||||||
|
|
||||||
box( FL_UP_BOX );
|
box( FL_UP_BOX );
|
||||||
labeltype( FL_NO_LABEL );
|
labeltype( FL_NO_LABEL );
|
||||||
|
@ -331,8 +335,11 @@ Module::Port::osc_number_path ( void )
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Module::Port::send_feedback ( void )
|
Module::Port::send_feedback ( bool force )
|
||||||
{
|
{
|
||||||
|
if ( !_pending_feedback )
|
||||||
|
return;
|
||||||
|
|
||||||
float f = control_value();
|
float f = control_value();
|
||||||
|
|
||||||
if ( hints.ranged )
|
if ( hints.ranged )
|
||||||
|
@ -345,18 +352,39 @@ Module::Port::send_feedback ( void )
|
||||||
f = ( f - offset ) / scale;
|
f = ( f - offset ) / scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( f > 1.0 )
|
if ( f > 1.0f )
|
||||||
f = 1.0;
|
f = 1.0f;
|
||||||
else if ( f < 0.0 )
|
else if ( f < 0.0f )
|
||||||
f = 0.0;
|
f = 0.0f;
|
||||||
|
|
||||||
|
/* struct timespec t; */
|
||||||
|
/* clock_gettime( CLOCK_MONOTONIC, &t ); */
|
||||||
|
|
||||||
|
/* /\* don't send feedback more at more than 30Hz rate. *\/ */
|
||||||
|
/* unsigned long long ms = (t.tv_sec * 1000 + ( t.tv_nsec / 1000000 )); */
|
||||||
|
/* if ( ms - _feedback_milliseconds < 1000 / 30 ) */
|
||||||
|
/* return; */
|
||||||
|
|
||||||
|
/* _feedback_milliseconds = ms; */
|
||||||
|
|
||||||
if ( _scaled_signal )
|
if ( _scaled_signal )
|
||||||
{
|
{
|
||||||
/* send feedback for by_name signal */
|
|
||||||
mixer->osc_endpoint->send_feedback( _scaled_signal->path(), f );
|
|
||||||
|
|
||||||
/* send feedback for by number signal */
|
if ( fabsf( _feedback_value - f ) > (1.0f / 128.0f) )
|
||||||
mixer->osc_endpoint->send_feedback( osc_number_path(), f );
|
{
|
||||||
|
/* only send feedback if value has changed significantly since the last time we sent it. */
|
||||||
|
/* DMESSAGE( "signal value: %f, controL_value: %f", _scaled_signal->value(), f ); */
|
||||||
|
/* send feedback for by_name signal */
|
||||||
|
mixer->osc_endpoint->send_feedback( _scaled_signal->path(), f );
|
||||||
|
|
||||||
|
/* send feedback for by number signal */
|
||||||
|
mixer->osc_endpoint->send_feedback( osc_number_path(), f );
|
||||||
|
|
||||||
|
_feedback_value = f;
|
||||||
|
|
||||||
|
_pending_feedback = false;
|
||||||
|
/* _scaled_signal->value( f ); */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,7 +392,7 @@ void
|
||||||
Module::send_feedback ( void )
|
Module::send_feedback ( void )
|
||||||
{
|
{
|
||||||
for ( int i = 0; i < ncontrol_inputs(); i++ )
|
for ( int i = 0; i < ncontrol_inputs(); i++ )
|
||||||
control_input[i].send_feedback();
|
control_input[i].send_feedback(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -373,7 +401,11 @@ Module::handle_control_changed ( Port *p )
|
||||||
if ( _editor )
|
if ( _editor )
|
||||||
_editor->handle_control_changed ( p );
|
_editor->handle_control_changed ( p );
|
||||||
|
|
||||||
p->send_feedback();
|
|
||||||
|
p->schedule_feedback();
|
||||||
|
|
||||||
|
/* DMESSAGE("Control changed"); */
|
||||||
|
/* p->send_feedback(false); */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* bool */
|
/* bool */
|
||||||
|
|
|
@ -48,6 +48,7 @@ class Module : public Fl_Group, public Loggable {
|
||||||
int _instances;
|
int _instances;
|
||||||
Chain *_chain;
|
Chain *_chain;
|
||||||
bool _is_default;
|
bool _is_default;
|
||||||
|
bool _pending_feedback;
|
||||||
|
|
||||||
nframes_t _nframes;
|
nframes_t _nframes;
|
||||||
static nframes_t _sample_rate;
|
static nframes_t _sample_rate;
|
||||||
|
@ -103,6 +104,7 @@ public:
|
||||||
connected_port()->_buf = _buf;
|
connected_port()->_buf = _buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum Direction { INPUT, OUTPUT };
|
enum Direction { INPUT, OUTPUT };
|
||||||
|
@ -153,6 +155,9 @@ public:
|
||||||
_by_number_path = 0;
|
_by_number_path = 0;
|
||||||
_by_number_number = -1;
|
_by_number_number = -1;
|
||||||
_jack_port = 0;
|
_jack_port = 0;
|
||||||
|
_feedback_value = -2;
|
||||||
|
_pending_feedback = false;
|
||||||
|
_feedback_milliseconds = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Port ( const Port& p )
|
Port ( const Port& p )
|
||||||
|
@ -169,6 +174,7 @@ public:
|
||||||
_by_number_path = 0;
|
_by_number_path = 0;
|
||||||
_by_number_number = -1;
|
_by_number_number = -1;
|
||||||
_jack_port = p._jack_port;
|
_jack_port = p._jack_port;
|
||||||
|
_feedback_value = p._feedback_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Port ( )
|
virtual ~Port ( )
|
||||||
|
@ -299,7 +305,7 @@ public:
|
||||||
_buf = buf;
|
_buf = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_feedback ( void );
|
void send_feedback ( bool force );
|
||||||
|
|
||||||
bool connected_to ( Port *p )
|
bool connected_to ( Port *p )
|
||||||
{
|
{
|
||||||
|
@ -332,6 +338,8 @@ public:
|
||||||
void jack_port ( JACK::Port *v ) { _jack_port = v; }
|
void jack_port ( JACK::Port *v ) { _jack_port = v; }
|
||||||
JACK::Port *jack_port ( void ) const { return _jack_port; }
|
JACK::Port *jack_port ( void ) const { return _jack_port; }
|
||||||
|
|
||||||
|
void schedule_feedback ( void ) { _pending_feedback = true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
char *generate_osc_path ( void );
|
char *generate_osc_path ( void );
|
||||||
|
@ -350,6 +358,10 @@ public:
|
||||||
OSC::Signal *_scaled_signal;
|
OSC::Signal *_scaled_signal;
|
||||||
OSC::Signal *_unscaled_signal;
|
OSC::Signal *_unscaled_signal;
|
||||||
|
|
||||||
|
float _feedback_value;
|
||||||
|
bool _pending_feedback;
|
||||||
|
unsigned long long _feedback_milliseconds;
|
||||||
|
|
||||||
static void handle_signal_connection_state_changed ( OSC::Signal *, void *o );
|
static void handle_signal_connection_state_changed ( OSC::Signal *, void *o );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -394,8 +394,14 @@ int signal_handler ( float value, void *user_data )
|
||||||
{
|
{
|
||||||
signal_mapping *m = (signal_mapping*)user_data;
|
signal_mapping *m = (signal_mapping*)user_data;
|
||||||
|
|
||||||
|
/* DMESSAGE( "Received value: %f", value ); */
|
||||||
|
|
||||||
m->last_feedback_tick = buffers;
|
m->last_feedback_tick = buffers;
|
||||||
|
|
||||||
|
/* magic number to give a release time to prevent thrashing. */
|
||||||
|
/* if ( ! ( m->last_feedback_tick > m->last_midi_tick + 4 )) */
|
||||||
|
/* return 0; */
|
||||||
|
|
||||||
if ( m->is_nrpn )
|
if ( m->is_nrpn )
|
||||||
{
|
{
|
||||||
jack_midi_event_t jev[4];
|
jack_midi_event_t jev[4];
|
||||||
|
@ -916,7 +922,7 @@ void emit_signal_for_event ( const char *midi_event, midievent &e, struct nrpn_s
|
||||||
else if ( e.opcode() == MIDI::midievent::PITCH_WHEEL )
|
else if ( e.opcode() == MIDI::midievent::PITCH_WHEEL )
|
||||||
val = e.pitch() / (float)MAX_14BIT;
|
val = e.pitch() / (float)MAX_14BIT;
|
||||||
|
|
||||||
/* DMESSAGE( "Val: %f", val ); */
|
/* DMESSAGE( "Val: %f, sigval %f", val, m->signal->value() ); */
|
||||||
|
|
||||||
/* wait for values to sync for continuous controls (faders and knobs) before emitting signal. For toggles, just send it immediately. */
|
/* wait for values to sync for continuous controls (faders and knobs) before emitting signal. For toggles, just send it immediately. */
|
||||||
if (
|
if (
|
||||||
|
@ -925,7 +931,7 @@ void emit_signal_for_event ( const char *midi_event, midievent &e, struct nrpn_s
|
||||||
&&
|
&&
|
||||||
!m->is_toggle )
|
!m->is_toggle )
|
||||||
{
|
{
|
||||||
float percent_off = fabs( (val - m->signal->value()) * 100 );
|
float percent_off = fabs( val - m->signal->value() ) * 100.0f;
|
||||||
|
|
||||||
if ( percent_off > 5 )
|
if ( percent_off > 5 )
|
||||||
{
|
{
|
||||||
|
@ -941,6 +947,9 @@ void emit_signal_for_event ( const char *midi_event, midievent &e, struct nrpn_s
|
||||||
}
|
}
|
||||||
|
|
||||||
m->last_midi_tick = buffers;
|
m->last_midi_tick = buffers;
|
||||||
|
|
||||||
|
/* DMESSAGE( "Sent value: %f", val ); */
|
||||||
|
|
||||||
m->signal->value( val );
|
m->signal->value( val );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -714,7 +714,9 @@ namespace OSC
|
||||||
i->second.current_value = argv[0]->f;
|
i->second.current_value = argv[0]->f;
|
||||||
}
|
}
|
||||||
|
|
||||||
i->second.suppress_feedback = true;
|
/* FIXME: this was intended to break feedback cycles, but it actually
|
||||||
|
results in some feedback values not being sent at all */
|
||||||
|
/* i->second.suppress_feedback = true; */
|
||||||
|
|
||||||
lo_send_message(ep->_addr, dpath, msg );
|
lo_send_message(ep->_addr, dpath, msg );
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -74,7 +74,7 @@ PROJECT="$1"
|
||||||
|
|
||||||
cd "$PROJECT" || fatal "No such project"
|
cd "$PROJECT" || fatal "No such project"
|
||||||
|
|
||||||
[ -f history ] && [ -f info ] || fatal "Not a Non-DAW project?"
|
[ -f history ] && [ -f info ] || fatal "Not a Non-Timeline project?"
|
||||||
|
|
||||||
[ -f .lock ] && fatal "Project appears to be in use"
|
[ -f .lock ] && fatal "Project appears to be in use"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue