@@ -592,6 +592,12 @@ typedef struct MIDI_CC_T {
592592 port_t * port ;
593593} midi_cc_t ;
594594
595+ typedef struct MIDI_CC_TEMPO_TAP_T {
596+ int8_t channel ;
597+ uint8_t controller ;
598+ jack_nframes_t last_frame_time ;
599+ } midi_cc_tempo_tap_t ;
600+
595601typedef struct ASSIGNMENT_T {
596602 int effect_id ;
597603 port_t * port ;
@@ -755,6 +761,8 @@ typedef struct CACHED_EFFECT_FLUSH_T {
755761static effect_t g_effects [MAX_INSTANCES ];
756762static midi_cc_t g_midi_cc_list [MAX_MIDI_CC_ASSIGN ], * g_midi_learning ;
757763
764+ static midi_cc_tempo_tap_t g_midi_cc_tempo_tap ;
765+
758766#ifdef HAVE_CONTROLCHAIN
759767/* Control Chain */
760768static cc_client_t * g_cc_client = NULL ;
@@ -2943,6 +2951,26 @@ static int ProcessGlobalClient(jack_nframes_t nframes, void *arg)
29432951 handled = false;
29442952 channel = (event .buffer [0 ] & 0x0F );
29452953
2954+ const float max_tap_delay = 10.0f ;
2955+ const float min_tap_delay = 0.1f ;
2956+ if (g_midi_cc_tempo_tap .channel != -1 )
2957+ {
2958+ if (channel == g_midi_cc_tempo_tap .channel && controller == g_midi_cc_tempo_tap .controller && mvalue > 63 )
2959+ {
2960+ jack_nframes_t current = event .time + g_monotonic_frame_count ;
2961+ const float delta_t = (current - g_midi_cc_tempo_tap .last_frame_time ) / (float )g_sample_rate ;
2962+ if (delta_t < max_tap_delay && delta_t > min_tap_delay )
2963+ {
2964+ const float bpm = 60.0f / delta_t ;
2965+ effects_set_beats_per_minute (bpm );
2966+ // printf("bpm: %f delta_t: %f current: %d last: %d\n", bpm, delta_t, current, g_midi_cc_tempo_tap.last_frame_time);
2967+ }
2968+
2969+ g_midi_cc_tempo_tap .last_frame_time = current ;
2970+ continue ;
2971+ }
2972+ }
2973+
29462974 for (int j = 0 ; j < MAX_MIDI_CC_ASSIGN ; j ++ )
29472975 {
29482976 if (g_midi_cc_list [j ].effect_id == ASSIGNMENT_NULL )
@@ -4313,6 +4341,8 @@ static void ExternalControllerWriteFunction(LV2UI_Controller controller,
43134341
43144342int effects_init (void * client )
43154343{
4344+ g_midi_cc_tempo_tap .channel = -1 ;
4345+
43164346 /* This global client is for connections / disconnections and midi-learn */
43174347 if (client != NULL )
43184348 {
@@ -7898,6 +7928,22 @@ int effects_midi_unmap(int effect_id, const char *control_symbol)
78987928 return ERR_LV2_INVALID_PARAM_SYMBOL ;
78997929}
79007930
7931+ int effects_midi_map_tempo_tap (int channel , int controller )
7932+ {
7933+ g_midi_cc_tempo_tap .channel = channel ;
7934+ g_midi_cc_tempo_tap .controller = controller ;
7935+ g_midi_cc_tempo_tap .last_frame_time = g_monotonic_frame_count ;
7936+ return SUCCESS ;
7937+ }
7938+
7939+ int effects_midi_unmap_tempo_tap ()
7940+ {
7941+ g_midi_cc_tempo_tap .channel = -1 ;
7942+ g_midi_cc_tempo_tap .controller = 0 ;
7943+ return SUCCESS ;
7944+ }
7945+
7946+
79017947int effects_licensee (int effect_id , char * * licensee_ptr )
79027948{
79037949 if (!InstanceExist (effect_id ))
0 commit comments