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 
@@ -48,6 +49,8 @@ uniform float elapsed_time_enable;\n\
4849uniform int loops;\n\ 
4950uniform float loop_second;\n\ 
5051uniform float local_time;\n\ 
52+ uniform float audio_peak;\n\ 
53+ uniform float audio_magnitude;\n\ 
5154\n\ 
5255sampler_state textureSampler{\n\ 
5356	Filter = Linear;\n\ 
@@ -225,6 +228,8 @@ struct shader_filter_data {
225228	gs_eparam_t  * param_transition_time ;
226229	gs_eparam_t  * param_convert_linear ;
227230	gs_eparam_t  * param_previous_output ;
231+ 	gs_eparam_t  * param_audio_peak ;
232+ 	gs_eparam_t  * param_audio_magnitude ;
228233
229234	int  expand_left ;
230235	int  expand_right ;
@@ -247,6 +252,14 @@ struct shader_filter_data {
247252	float  rand_f ;
248253	float  rand_instance_f ;
249254	float  rand_activation_f ;
255+ 	float  audio_peak ;
256+ 	float  audio_magnitude ;
257+ 	
258+ 	obs_source_t  * audio_source ;
259+ 	char  * audio_source_name ;
260+ 	obs_volmeter_t  * volmeter ;
261+ 	float  current_audio_peak ;
262+ 	float  current_audio_magnitude ;
250263
251264	DARRAY (struct  effect_param_data ) stored_param_list ;
252265};
@@ -351,6 +364,8 @@ static void shader_filter_clear_params(struct shader_filter_data *filter)
351364	filter -> param_loops  =  NULL ;
352365	filter -> param_loop_second  =  NULL ;
353366	filter -> param_local_time  =  NULL ;
367+ 	filter -> param_audio_peak  =  NULL ;
368+ 	filter -> param_audio_magnitude  =  NULL ;
354369	filter -> param_image  =  NULL ;
355370	filter -> param_previous_image  =  NULL ;
356371	filter -> param_image_a  =  NULL ;
@@ -612,6 +627,10 @@ static void shader_filter_reload_effect(struct shader_filter_data *filter)
612627			filter -> param_loop_second  =  param ;
613628		} else  if  (strcmp (info .name , "local_time" ) ==  0 ) {
614629			filter -> param_local_time  =  param ;
630+ 		} else  if  (strcmp (info .name , "audio_peak" ) ==  0 ) {
631+ 			filter -> param_audio_peak  =  param ;
632+ 		} else  if  (strcmp (info .name , "audio_magnitude" ) ==  0 ) {
633+ 			filter -> param_audio_magnitude  =  param ;
615634		} else  if  (strcmp (info .name , "ViewProj" ) ==  0 ) {
616635			// Nothing. 
617636		} else  if  (strcmp (info .name , "image" ) ==  0 ) {
@@ -710,6 +729,14 @@ static void *shader_filter_create(obs_data_t *settings, obs_source_t *source)
710729	filter -> rand_instance_f  =  (float )((double )rand_interval (0 , 10000 ) / (double )10000 );
711730	filter -> rand_activation_f  =  (float )((double )rand_interval (0 , 10000 ) / (double )10000 );
712731
732+ 	filter -> audio_peak  =  0.0f ;
733+ 	filter -> audio_magnitude  =  0.0f ;
734+ 	filter -> audio_source  =  NULL ;
735+ 	filter -> audio_source_name  =  NULL ;
736+ 	filter -> volmeter  =  NULL ;
737+ 	filter -> current_audio_peak  =  0.0f ;
738+ 	filter -> current_audio_magnitude  =  0.0f ;
739+ 
713740	da_init (filter -> stored_param_list );
714741	load_output_effect (filter );
715742	obs_source_update (source , settings );
@@ -741,6 +768,13 @@ static void shader_filter_destroy(void *data)
741768
742769	dstr_free (& filter -> last_path );
743770	da_free (filter -> stored_param_list );
771+ 	
772+   if  (filter -> volmeter )
773+     obs_volmeter_destroy (filter -> volmeter );
774+   if  (filter -> audio_source )
775+     obs_source_release (filter -> audio_source );
776+   if  (filter -> audio_source_name )
777+     bfree (filter -> audio_source_name );
744778
745779	bfree (filter );
746780}
@@ -2097,6 +2131,52 @@ static bool shader_filter_convert(obs_properties_t *props, obs_property_t *prope
20972131
20982132static  const  char  * shader_filter_texture_file_filter  =  "Textures (*.bmp *.tga *.png *.jpeg *.jpg *.gif);;" ;
20992133
2134+ #define  MIN_AUDIO_THRESHOLD  -60.0f
2135+ 
2136+ static  float  convert_db_to_linear (float  db_value ) {
2137+   if  (db_value  <= MIN_AUDIO_THRESHOLD  ||  db_value  >  0.0f )
2138+     return  0.0f ;
2139+ 
2140+ 	return  fmaxf (0.0f , fminf (1.0f , (db_value  -  MIN_AUDIO_THRESHOLD ) / (- MIN_AUDIO_THRESHOLD )));
2141+ }
2142+ 
2143+ static  void  shader_filter_audio_callback (void  * data , const  float  magnitude [MAX_AUDIO_CHANNELS ], 
2144+ 	const  float  peak [MAX_AUDIO_CHANNELS ], const  float  input_peak [MAX_AUDIO_CHANNELS ])
2145+ {
2146+ 	UNUSED_PARAMETER (input_peak );
2147+ 	struct  shader_filter_data  * filter  =  (struct  shader_filter_data  * )data ;
2148+ 	
2149+ 	float  max_peak  =  MIN_AUDIO_THRESHOLD ;
2150+ 	for  (int  i  =  0 ; i  <  MAX_AUDIO_CHANNELS ; i ++ ) {
2151+ 		if  (peak [i ] >  max_peak  &&  peak [i ] !=  0.0f ) {
2152+ 			max_peak  =  peak [i ];
2153+ 		}
2154+ 	}
2155+ 	
2156+ 	float  max_magnitude  =  MIN_AUDIO_THRESHOLD ;
2157+ 	for  (int  i  =  0 ; i  <  MAX_AUDIO_CHANNELS ; i ++ ) {
2158+ 		if  (magnitude [i ] >  max_magnitude  &&  magnitude [i ] !=  0.0f ) {
2159+ 			max_magnitude  =  magnitude [i ];
2160+ 		}
2161+ 	}
2162+ 	
2163+ 	filter -> current_audio_peak  =  convert_db_to_linear (max_peak );
2164+ 	filter -> current_audio_magnitude  =  convert_db_to_linear (max_magnitude );
2165+ }
2166+ 
2167+ static  bool  shader_filter_enum_audio_sources (void  * data , obs_source_t  * source )
2168+ {
2169+ 	obs_property_t  * prop  =  (obs_property_t  * )data ;
2170+ 	uint32_t  flags  =  obs_source_get_output_flags (source );
2171+ 	
2172+ 	if  ((flags  &  OBS_SOURCE_AUDIO ) !=  0 ) {
2173+ 		const  char  * name  =  obs_source_get_name (source );
2174+ 		obs_property_list_add_string (prop , name , name );
2175+ 	}
2176+ 	
2177+ 	return  true;
2178+ }
2179+ 
21002180static  obs_properties_t  * shader_filter_properties (void  * data )
21012181{
21022182	struct  shader_filter_data  * filter  =  data ;
@@ -2114,6 +2194,12 @@ static obs_properties_t *shader_filter_properties(void *data)
21142194		obs_properties_add_int (props , "expand_right" , obs_module_text ("ShaderFilter.ExpandRight" ), 0 , 9999 , 1 );
21152195		obs_properties_add_int (props , "expand_top" , obs_module_text ("ShaderFilter.ExpandTop" ), 0 , 9999 , 1 );
21162196		obs_properties_add_int (props , "expand_bottom" , obs_module_text ("ShaderFilter.ExpandBottom" ), 0 , 9999 , 1 );
2197+ 		
2198+ 		obs_property_t  * audio_source  =  obs_properties_add_list (props , "audio_source" , "Audio source" , 
2199+ 			OBS_COMBO_TYPE_LIST , OBS_COMBO_FORMAT_STRING );
2200+ 		obs_property_list_add_string (audio_source , "None" , "" );
2201+ 		
2202+ 		obs_enum_sources (shader_filter_enum_audio_sources , audio_source );
21172203	}
21182204
21192205	obs_properties_add_bool (props , "override_entire_effect" , obs_module_text ("ShaderFilter.OverrideEntireEffect" ));
@@ -2386,6 +2472,48 @@ static void shader_filter_update(void *data, obs_data_t *settings)
23862472	filter -> expand_top  =  (int )obs_data_get_int (settings , "expand_top" );
23872473	filter -> expand_bottom  =  (int )obs_data_get_int (settings , "expand_bottom" );
23882474	filter -> rand_activation_f  =  (float )((double )rand_interval (0 , 10000 ) / (double )10000 );
2475+ 	
2476+ 	const  char  * audio_source_name  =  obs_data_get_string (settings , "audio_source" );
2477+ 
2478+ 	if  (audio_source_name  &&  strlen (audio_source_name ) >  0 ) {
2479+ 		if  (filter -> audio_source ) {
2480+ 			obs_source_release (filter -> audio_source );
2481+ 			filter -> audio_source  =  NULL ;
2482+ 		}
2483+ 
2484+     if  (filter -> audio_source_name )
2485+       bfree (filter -> audio_source_name );
2486+ 
2487+ 		filter -> audio_source_name  =  bstrdup (audio_source_name );
2488+ 		filter -> audio_source  =  obs_get_source_by_name (audio_source_name );
2489+ 	} else  {
2490+ 		if  (filter -> audio_source ) {
2491+ 			obs_source_release (filter -> audio_source );
2492+ 			filter -> audio_source  =  NULL ;
2493+ 		}
2494+ 
2495+ 		if  (filter -> audio_source_name ) {
2496+ 			bfree (filter -> audio_source_name );
2497+ 			filter -> audio_source_name  =  NULL ;
2498+ 		}
2499+ 	}
2500+ 	
2501+ 	if  (filter -> volmeter ) {
2502+ 		obs_volmeter_destroy (filter -> volmeter );
2503+ 		filter -> volmeter  =  NULL ;
2504+ 	}
2505+ 	
2506+ 	if  (filter -> audio_source ) {
2507+ 		filter -> current_audio_peak  =  0.0f ;
2508+     filter -> current_audio_magnitude  =  0.0f ;
2509+ 		filter -> volmeter  =  obs_volmeter_create (OBS_FADER_LOG );
2510+ 
2511+ 		obs_volmeter_attach_source (filter -> volmeter , filter -> audio_source );
2512+ 		obs_volmeter_add_callback (filter -> volmeter , shader_filter_audio_callback , filter );
2513+ 	} else  {
2514+ 		filter -> current_audio_peak  =  0.0f ;
2515+     filter -> current_audio_magnitude  =  0.0f ;
2516+ 	}
23892517
23902518	if  (filter -> reload_effect ) {
23912519		filter -> reload_effect  =  false;
@@ -2664,6 +2792,14 @@ static void shader_filter_tick(void *data, float seconds)
26642792	// undecided between this and "rand_float(1);" 
26652793	filter -> rand_f  =  (float )((double )rand_interval (0 , 10000 ) / (double )10000 );
26662794
2795+ 	if  (filter -> audio_source  &&  filter -> volmeter ) {
2796+ 		filter -> audio_peak  =  filter -> current_audio_peak ;
2797+ 		filter -> audio_magnitude  =  filter -> current_audio_magnitude ;
2798+ 	} else  {
2799+ 		filter -> audio_peak  =  0.0f ;
2800+ 		filter -> audio_magnitude  =  0.0f ;
2801+ 	}
2802+ 
26672803	filter -> output_rendered  =  false;
26682804	filter -> input_rendered  =  false;
26692805}
@@ -2832,6 +2968,12 @@ void shader_filter_set_effect_params(struct shader_filter_data *filter)
28322968	if  (filter -> param_local_time  !=  NULL ) {
28332969		gs_effect_set_float (filter -> param_local_time , filter -> local_time );
28342970	}
2971+ 	if  (filter -> param_audio_peak  !=  NULL ) {
2972+ 		gs_effect_set_float (filter -> param_audio_peak , filter -> audio_peak );
2973+ 	}
2974+ 	if  (filter -> param_audio_magnitude  !=  NULL ) {
2975+ 		gs_effect_set_float (filter -> param_audio_magnitude , filter -> audio_magnitude );
2976+ 	}
28352977	if  (filter -> param_loops  !=  NULL ) {
28362978		gs_effect_set_int (filter -> param_loops , filter -> loops );
28372979	}
0 commit comments