Mixer: Try to better cope with parameter feedback feedback cycles.

pull/119/merge
Jonathan Moore Liles 2020-11-19 18:48:41 -08:00
parent 1f0f01c0ad
commit 82f9610ca8
6 changed files with 82 additions and 23 deletions

View File

@ -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;
} }

View File

@ -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,7 +169,8 @@ 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 );
align( FL_ALIGN_CENTER | FL_ALIGN_INSIDE ); align( FL_ALIGN_CENTER | FL_ALIGN_INSIDE );
@ -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 ); if ( fabsf( _feedback_value - f ) > (1.0f / 128.0f) )
{
/* send feedback for by number signal */ /* only send feedback if value has changed significantly since the last time we sent it. */
mixer->osc_endpoint->send_feedback( osc_number_path(), f ); /* 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 */

View File

@ -48,7 +48,8 @@ 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;
static Module *_copied_module_empty; static Module *_copied_module_empty;
@ -103,6 +104,7 @@ public:
connected_port()->_buf = _buf; connected_port()->_buf = _buf;
} }
public: public:
enum Direction { INPUT, OUTPUT }; enum Direction { INPUT, OUTPUT };
@ -120,7 +122,7 @@ public:
float default_value; float default_value;
int dimensions; int dimensions;
bool visible; bool visible;
Hints ( ) Hints ( )
{ {
type = LINEAR; type = LINEAR;
@ -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 );
}; };

View File

@ -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 );
} }

View File

@ -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;

View File

@ -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"