1515#include <stdio.h>
1616#include <time.h>
1717#include <string.h>
18+ #include <math.h>
1819
1920#include <util/threading.h>
2021#ifdef _WIN32
@@ -225,6 +226,8 @@ struct shader_filter_data {
225226 gs_eparam_t * param_transition_time ;
226227 gs_eparam_t * param_convert_linear ;
227228 gs_eparam_t * param_previous_output ;
229+ gs_eparam_t * param_audio_peak ;
230+ gs_eparam_t * param_audio_magnitude ;
228231
229232 int expand_left ;
230233 int expand_right ;
@@ -247,6 +250,13 @@ struct shader_filter_data {
247250 float rand_f ;
248251 float rand_instance_f ;
249252 float rand_activation_f ;
253+ float audio_peak ;
254+ float audio_magnitude ;
255+
256+ char * audio_source_name ;
257+ obs_volmeter_t * volmeter ;
258+ float current_audio_peak ;
259+ float current_audio_magnitude ;
250260
251261 DARRAY (struct effect_param_data ) stored_param_list ;
252262};
@@ -351,6 +361,8 @@ static void shader_filter_clear_params(struct shader_filter_data *filter)
351361 filter -> param_loops = NULL ;
352362 filter -> param_loop_second = NULL ;
353363 filter -> param_local_time = NULL ;
364+ filter -> param_audio_peak = NULL ;
365+ filter -> param_audio_magnitude = NULL ;
354366 filter -> param_image = NULL ;
355367 filter -> param_previous_image = NULL ;
356368 filter -> param_image_a = NULL ;
@@ -612,6 +624,10 @@ static void shader_filter_reload_effect(struct shader_filter_data *filter)
612624 filter -> param_loop_second = param ;
613625 } else if (strcmp (info .name , "local_time" ) == 0 ) {
614626 filter -> param_local_time = param ;
627+ } else if (strcmp (info .name , "audio_peak" ) == 0 ) {
628+ filter -> param_audio_peak = param ;
629+ } else if (strcmp (info .name , "audio_magnitude" ) == 0 ) {
630+ filter -> param_audio_magnitude = param ;
615631 } else if (strcmp (info .name , "ViewProj" ) == 0 ) {
616632 // Nothing.
617633 } else if (strcmp (info .name , "image" ) == 0 ) {
@@ -742,6 +758,11 @@ static void shader_filter_destroy(void *data)
742758 dstr_free (& filter -> last_path );
743759 da_free (filter -> stored_param_list );
744760
761+ if (filter -> volmeter )
762+ obs_volmeter_destroy (filter -> volmeter );
763+ if (filter -> audio_source_name )
764+ bfree (filter -> audio_source_name );
765+
745766 bfree (filter );
746767}
747768
@@ -2097,6 +2118,53 @@ static bool shader_filter_convert(obs_properties_t *props, obs_property_t *prope
20972118
20982119static const char * shader_filter_texture_file_filter = "Textures (*.bmp *.tga *.png *.jpeg *.jpg *.gif);;" ;
20992120
2121+ #define MIN_AUDIO_THRESHOLD -60.0f
2122+
2123+ static float convert_db_to_linear (float db_value )
2124+ {
2125+ if (db_value <= MIN_AUDIO_THRESHOLD || db_value > 0.0f )
2126+ return 0.0f ;
2127+
2128+ return fmaxf (0.0f , fminf (1.0f , (db_value - MIN_AUDIO_THRESHOLD ) / (- MIN_AUDIO_THRESHOLD )));
2129+ }
2130+
2131+ static void shader_filter_audio_callback (void * data , const float magnitude [MAX_AUDIO_CHANNELS ],
2132+ const float peak [MAX_AUDIO_CHANNELS ], const float input_peak [MAX_AUDIO_CHANNELS ])
2133+ {
2134+ UNUSED_PARAMETER (input_peak );
2135+ struct shader_filter_data * filter = (struct shader_filter_data * )data ;
2136+
2137+ float max_peak = MIN_AUDIO_THRESHOLD ;
2138+ for (int i = 0 ; i < MAX_AUDIO_CHANNELS ; i ++ ) {
2139+ if (peak [i ] > max_peak && peak [i ] != 0.0f ) {
2140+ max_peak = peak [i ];
2141+ }
2142+ }
2143+
2144+ float max_magnitude = MIN_AUDIO_THRESHOLD ;
2145+ for (int i = 0 ; i < MAX_AUDIO_CHANNELS ; i ++ ) {
2146+ if (magnitude [i ] > max_magnitude && magnitude [i ] != 0.0f ) {
2147+ max_magnitude = magnitude [i ];
2148+ }
2149+ }
2150+
2151+ filter -> current_audio_peak = convert_db_to_linear (max_peak );
2152+ filter -> current_audio_magnitude = convert_db_to_linear (max_magnitude );
2153+ }
2154+
2155+ static bool shader_filter_enum_audio_sources (void * data , obs_source_t * source )
2156+ {
2157+ obs_property_t * prop = (obs_property_t * )data ;
2158+ uint32_t flags = obs_source_get_output_flags (source );
2159+
2160+ if ((flags & OBS_SOURCE_AUDIO ) != 0 ) {
2161+ const char * name = obs_source_get_name (source );
2162+ obs_property_list_add_string (prop , name , name );
2163+ }
2164+
2165+ return true;
2166+ }
2167+
21002168static obs_properties_t * shader_filter_properties (void * data )
21012169{
21022170 struct shader_filter_data * filter = data ;
@@ -2150,6 +2218,14 @@ static obs_properties_t *shader_filter_properties(void *data)
21502218 obs_properties_add_button (props , "reload_effect" , obs_module_text ("ShaderFilter.ReloadEffect" ),
21512219 shader_filter_reload_effect_clicked );
21522220
2221+ if (filter && (filter -> param_audio_magnitude || filter -> param_audio_peak )) {
2222+ obs_property_t * audio_source = obs_properties_add_list (props , "audio_source" , "Audio source" , OBS_COMBO_TYPE_LIST ,
2223+ OBS_COMBO_FORMAT_STRING );
2224+ obs_property_list_add_string (audio_source , "None" , "" );
2225+
2226+ obs_enum_sources (shader_filter_enum_audio_sources , audio_source );
2227+ }
2228+
21532229 DARRAY (obs_property_t * ) groups ;
21542230 da_init (groups );
21552231
@@ -2393,6 +2469,56 @@ static void shader_filter_update(void *data, obs_data_t *settings)
23932469 obs_source_update_properties (filter -> context );
23942470 }
23952471
2472+ if (filter -> param_audio_magnitude || filter -> param_audio_peak ) {
2473+ const char * audio_source_name = obs_data_get_string (settings , "audio_source" );
2474+ if (!filter -> audio_source_name || strcmp (filter -> audio_source_name , audio_source_name ) != 0 ) {
2475+ obs_source_t * audio_source = strlen (audio_source_name ) > 0 ? obs_get_source_by_name (audio_source_name ) : NULL ;
2476+ if (audio_source && ((obs_source_get_output_flags (audio_source ) & OBS_SOURCE_AUDIO ) == 0 )) {
2477+ obs_source_release (audio_source );
2478+ audio_source = NULL ;
2479+ }
2480+ if (audio_source ) {
2481+ if (filter -> audio_source_name )
2482+ bfree (filter -> audio_source_name );
2483+ filter -> audio_source_name = bstrdup (audio_source_name );
2484+ }
2485+
2486+ if (!audio_source ) {
2487+ audio_source = obs_source_get_ref (obs_filter_get_parent (filter -> context ));
2488+ if (audio_source && ((obs_source_get_output_flags (audio_source ) & OBS_SOURCE_AUDIO ) == 0 )) {
2489+ obs_source_release (audio_source );
2490+ audio_source = NULL ;
2491+ }
2492+ }
2493+ if (audio_source ) {
2494+ if (!filter -> volmeter ) {
2495+ filter -> volmeter = obs_volmeter_create (OBS_FADER_LOG );
2496+ obs_volmeter_add_callback (filter -> volmeter , shader_filter_audio_callback , filter );
2497+ }
2498+ obs_volmeter_attach_source (filter -> volmeter , audio_source );
2499+ obs_source_release (audio_source );
2500+ } else {
2501+ if (filter -> volmeter ) {
2502+ obs_volmeter_destroy (filter -> volmeter );
2503+ filter -> volmeter = NULL ;
2504+ }
2505+ if (filter -> audio_source_name ) {
2506+ bfree (filter -> audio_source_name );
2507+ filter -> audio_source_name = NULL ;
2508+ }
2509+ }
2510+ }
2511+ } else {
2512+ if (filter -> volmeter ) {
2513+ obs_volmeter_destroy (filter -> volmeter );
2514+ filter -> volmeter = NULL ;
2515+ }
2516+ if (filter -> audio_source_name ) {
2517+ bfree (filter -> audio_source_name );
2518+ filter -> audio_source_name = NULL ;
2519+ }
2520+ }
2521+
23962522 size_t param_count = filter -> stored_param_list .num ;
23972523 for (size_t param_index = 0 ; param_index < param_count ; param_index ++ ) {
23982524 struct effect_param_data * param = (filter -> stored_param_list .array + param_index );
@@ -2664,6 +2790,14 @@ static void shader_filter_tick(void *data, float seconds)
26642790 // undecided between this and "rand_float(1);"
26652791 filter -> rand_f = (float )((double )rand_interval (0 , 10000 ) / (double )10000 );
26662792
2793+ if (filter -> volmeter ) {
2794+ filter -> audio_peak = filter -> current_audio_peak ;
2795+ filter -> audio_magnitude = filter -> current_audio_magnitude ;
2796+ } else {
2797+ filter -> audio_peak = 0.0f ;
2798+ filter -> audio_magnitude = 0.0f ;
2799+ }
2800+
26672801 filter -> output_rendered = false;
26682802 filter -> input_rendered = false;
26692803}
@@ -2832,6 +2966,12 @@ void shader_filter_set_effect_params(struct shader_filter_data *filter)
28322966 if (filter -> param_local_time != NULL ) {
28332967 gs_effect_set_float (filter -> param_local_time , filter -> local_time );
28342968 }
2969+ if (filter -> param_audio_peak != NULL ) {
2970+ gs_effect_set_float (filter -> param_audio_peak , filter -> audio_peak );
2971+ }
2972+ if (filter -> param_audio_magnitude != NULL ) {
2973+ gs_effect_set_float (filter -> param_audio_magnitude , filter -> audio_magnitude );
2974+ }
28352975 if (filter -> param_loops != NULL ) {
28362976 gs_effect_set_int (filter -> param_loops , filter -> loops );
28372977 }
0 commit comments