From: hgn <hgodden00@gmail.com>
Date: Wed, 27 Oct 2021 04:01:26 +0000 (+0100)
Subject: fixed REALLY bad threading bugs with audio
X-Git-Url: https://harrygodden.com/git/?a=commitdiff_plain;h=026b67150e9bd238709a6aeab656f7d01f3765a8;p=fishladder.git

fixed REALLY bad threading bugs with audio
---

diff --git a/fishladder.c b/fishladder.c
index e6d2ef7..d7a1f28 100644
--- a/fishladder.c
+++ b/fishladder.c
@@ -597,6 +597,7 @@ void vg_update(void)
 		else
 			world.selected = -1;
 	}
+	else world.selected = -1;
 	
 	// Simulation stop/start
 	if( vg_get_button_down("go") )
@@ -638,9 +639,10 @@ void vg_update(void)
 	// Fish ticks
 	if( world.simulating )
 	{
-		while( world.sim_frame < (int)((vg_time-world.sim_start)*2.0f) )
+		while( world.sim_frame < (int)((vg_time-world.sim_start)*20.0f) )
 		{
 			vg_info( "frame: %u\n", world.sim_frame );
+			sfx_set_playrnd( &audio_random, &audio_system_balls_switching, 0, 5 );
 			
 			for( int i = 0; i < arrlen( world.io ); i ++ )
 			{
@@ -1100,4 +1102,5 @@ void vg_render(void)
 void vg_ui(void)
 {
 	//ui_test();
+	sfx_internal_debug_overlay();
 }
diff --git a/fishladder_resources.h b/fishladder_resources.h
index cd73f52..1f8c545 100644
--- a/fishladder_resources.h
+++ b/fishladder_resources.h
@@ -47,6 +47,19 @@ sound/rolling_01.ogg\0\
 sound/rolling_02.ogg\0"
 };
 
+sfx_set audio_random =
+{
+ .sources = "\
+sound/random_01.ogg\0\
+sound/random_02.ogg\0\
+sound/random_03.ogg\0\
+sound/random_04.ogg\0\
+sound/random_05.ogg\0\
+sound/random_06.ogg\0\
+sound/random_07.ogg\0\
+sound/random_08.ogg\0"
+};
+
 // One two or three layers of rolling noise
 sfx_system audio_system_balls_rolling =
 {
@@ -84,14 +97,17 @@ static void resource_load_main(void)
 	sfx_set_init( &audio_tile_mod, NULL );
 	sfx_set_init( &audio_splitter, NULL );
 	sfx_set_init( &audio_rolls, NULL );
+	sfx_set_init( &audio_random, NULL );
 }
 
 static void resource_free_main(void)
 {
-	vg_tex2d_free( texture_list, vg_list_size( texture_list ) );	
+	vg_tex2d_free( texture_list, vg_list_size( texture_list ) );
+	
 	sfx_set_free( &audio_tile_mod );
 	sfx_set_free( &audio_splitter );
 	sfx_set_free( &audio_rolls );
+	sfx_set_free( &audio_random );
 }
 
 // SHADERS
diff --git a/vg/vg.h b/vg/vg.h
index bd518c4..33f177c 100644
--- a/vg/vg.h
+++ b/vg/vg.h
@@ -47,6 +47,7 @@ float	vg_time_delta;
 #include "vg/vg_tex.h"
 #include "vg/vg_input.h"
 #include "vg/vg_ui.h"
+#include "vg/vg_debug.h"
 
 #include "steam/steamworks_thin.h"
 
@@ -206,8 +207,6 @@ static void vg_init( int argc, char *argv[], const char *window_name )
 		}
 	}
 	
-	vg_audio_init();
-	vg_register_exit( &vg_audio_free, "vg_audio_free" );
 	vg_lines_init();
 	vg_register_exit( &vg_lines_free, "vg_lines_free" );
 	ui_default_init();
@@ -220,6 +219,9 @@ static void vg_init( int argc, char *argv[], const char *window_name )
 	{
 		vg_start();
 	
+		vg_audio_init();
+		vg_register_exit( &vg_audio_free, "vg_audio_free" );
+	
 		// Main gameloop
 		while( !glfwWindowShouldClose( vg_window ) )
 		{
diff --git a/vg/vg_audio.h b/vg/vg_audio.h
index 35b36c5..249bedc 100644
--- a/vg/vg_audio.h
+++ b/vg/vg_audio.h
@@ -11,7 +11,7 @@
 #define SFX_FLAG_STEREO	 	0x2
 #define SFX_FLAG_REPEAT 	0x4
 #define SFX_FLAG_GHOST		0x8
-#define FADEOUT_LENGTH 		441
+#define FADEOUT_LENGTH 		4410
 #define FADEOUT_DIVISOR 	(1.f/(float)FADEOUT_LENGTH)
 
 typedef struct sfx_vol_control sfx_vol_control;
@@ -33,9 +33,11 @@ struct sfx_system
 	float	vol;
 	
 	// Info
-	int ch, end, cur, cur_lagged;
+	u32 ch, end, cur;
 	u32 flags;
 	
+	int is_queued;
+	
 	// Effects
 	u32 fadeout, fadeout_current;
 	
@@ -183,6 +185,7 @@ struct sfx_vorbis_a_to_inf
 #define SFX_A_FLAG_AUTOSTART 0x1
 #define SFX_A_FLAG_AUTOFREE  0x2
 
+/*
 static int sfx_save( sfx_system *sys );
 
 // Asynchronous load-to-system callback
@@ -217,16 +220,30 @@ void sfx_vorbis_a_to( sfx_system *sys, const char *strFileName, int channels, u3
 	
 	if( !sfx_vorbis_a( strFileName, channels, sfx_vorbis_a_to_c, inf ) )
 		free( inf );
-}
+}*/
 
 // 0
 // ======================================================
 
-// Mark change to be uploaded to queue system
-static int sfx_save( sfx_system *sys )
+static int sfx_begin_edit( sfx_system *sys )
 {
 	MUTEX_LOCK( sfx_mux_t01 );
+	
+	if( sys->is_queued )
+	{
+		MUTEX_UNLOCK( sfx_mux_t01 );
+		
+		vg_warn( "Sfx system locked for writing.. Spam is being created!\n" );
+		return 0;
+	}
+	
+	sys->is_queued = 1;
+	return 1;
+}
 
+// Mark change to be uploaded to queue system
+static int sfx_save( sfx_system *sys )
+{
 	if( sfx_q_len >= SFX_MAX_SYSTEMS )
 	{
 		vg_error( "Warning: No free space in sound queue\n" );
@@ -366,36 +383,43 @@ void audio_mixer_callback( ma_device *pDevice, void *pOutBuf, const void *pInput
 	while( sfx_q_len --> 0 )
 	{
 		sfx_system *src = sfx_q[sfx_q_len];
+		src->is_queued = 0;
+		
 		sfx_system *clone;
 		
 		// This is a 'new' sound if thread_clone not set.
-		if( !src->thread_clone || src->flags & SFX_FLAG_ONESHOT )
+		if( !src->thread_clone || (src->flags & SFX_FLAG_ONESHOT) )
 		{
-			src->thread_clone = sfx_alloc();
-			if( !src->thread_clone )
+			clone = sfx_alloc();
+			if( !clone )
 				break;
+				
+			src->thread_clone = clone;
 		}
 		else
 		{
-			// Modifying an active system spawns a small fadeout ghost system
-			sfx_system *ghost_system = sfx_alloc();
-			
-			if( !ghost_system )
-				break;
-			
-			ghost_system->source = src->source;
-			ghost_system->ch = src->ch;
-			ghost_system->end = src->end;
-			ghost_system->cur = src->cur_lagged;
-			ghost_system->flags = SFX_FLAG_GHOST;
-			ghost_system->fadeout = FADEOUT_LENGTH;
-			ghost_system->fadeout_current = FADEOUT_LENGTH;
-			ghost_system->vol_src = src->vol_src;
-			ghost_system->name = src->name;
-			ghost_system->thread_clone = src;
-		}
+			clone = src->thread_clone;
 		
-		clone = src->thread_clone;
+			// Modifying an active system's cursor spawns a small fadeout ghost system
+			if( clone->cur != src->cur )
+			{
+				sfx_system *ghost_system = sfx_alloc();
+				
+				if( !ghost_system )
+					break;
+				
+				ghost_system->source = clone->source;
+				ghost_system->ch = clone->ch;
+				ghost_system->end = clone->end;
+				ghost_system->cur = clone->cur;
+				ghost_system->flags = SFX_FLAG_GHOST;
+				ghost_system->fadeout = FADEOUT_LENGTH;
+				ghost_system->fadeout_current = FADEOUT_LENGTH;
+				ghost_system->vol_src = clone->vol_src;
+				ghost_system->name = clone->name;
+				ghost_system->thread_clone = src;
+			}
+		}		
 		
 		// run replacement routine if one is waiting (todo: what is this?)
 		if( src->replacement )
@@ -446,8 +470,7 @@ void audio_mixer_callback( ma_device *pDevice, void *pOutBuf, const void *pInput
 	{
 		sfx_system *sys = sfx_sys + i;
 		
-		u32 cursor = sys->cur, buffer_pos = 0;
-		
+		u32 cursor = sys->cur, buffer_pos = 0;		
 		float avgvol = 0.f;
 		float pcf[2] = { 0.f, 0.0f };
 		
@@ -456,7 +479,7 @@ void audio_mixer_callback( ma_device *pDevice, void *pOutBuf, const void *pInput
 		
 		while( frames_write )
 		{
-			u32 samples_this_run = vg_min( frames_write, sys->end - cursor );
+			u32 samples_this_run = VG_MIN( frames_write, sys->end - cursor );
 		
 			if( sys->fadeout )
 			{
@@ -468,7 +491,7 @@ void audio_mixer_callback( ma_device *pDevice, void *pOutBuf, const void *pInput
 					break;
 				}
 				
-				samples_this_run = vg_min( samples_this_run, sys->fadeout_current );
+				samples_this_run = VG_MIN( samples_this_run, sys->fadeout_current );
 			}
 			
 			for( u32 j = 0; j < samples_this_run; j ++ )
@@ -482,10 +505,15 @@ void audio_mixer_callback( ma_device *pDevice, void *pOutBuf, const void *pInput
 					vol *= (float)sys->fadeout_current * fadeout_divisor;
 					sys->fadeout_current --;
 				}
+				
+				if( buffer_pos >= frameCount )
+				{
+					break;
+				}
 
 				pOut32F[ buffer_pos*2+0 ] += pcf[0] * vol;
 				pOut32F[ buffer_pos*2+1 ] += pcf[1] * vol;
-								
+				
 				avgvol += fabs( pcf[0] * vol );
 				avgvol += fabs( pcf[1] * vol );
 				
@@ -505,7 +533,6 @@ void audio_mixer_callback( ma_device *pDevice, void *pOutBuf, const void *pInput
 			}
 
 			sys->cur = cursor;
-			sys->cur_lagged = cursor;
 			sys->signal_average = avgvol / (float)(buffer_pos*2);
 			
 			break;
@@ -514,25 +541,27 @@ void audio_mixer_callback( ma_device *pDevice, void *pOutBuf, const void *pInput
 
 	// Redistribute sound systems
 	MUTEX_LOCK( sfx_mux_t01 );
-	
-	unsigned int idx = 0, wr = 0;
+
+	u32 idx = 0, wr = 0;
 	while( idx != sfx_sys_len )
 	{
 		sfx_system *src = sfx_sys + idx;
-	
+		
 		// Keep only if cursor is before end or repeating
 		if( src->cur < src->end || (src->flags & SFX_FLAG_REPEAT) ) 
 		{
 			// Correct source pointer on persisitent originals since we shifted ID's
-			if( !(src->flags & SFX_FLAG_ONESHOT) )
+			if( !(src->flags & (SFX_FLAG_ONESHOT|SFX_FLAG_GHOST)) )
+			{
 				src->thread_clone->thread_clone = sfx_sys + wr;
+			}
 			
 			sfx_sys[ wr ++ ] = sfx_sys[ idx ];
 		}
 		else
 		{
 			// Clear link on persistent sources (done playing)
-			if( !(src->flags & SFX_FLAG_ONESHOT) )
+			if( !(src->flags & (SFX_FLAG_ONESHOT|SFX_FLAG_GHOST)) )
 				src->thread_clone->thread_clone = NULL;
 		}
 		
@@ -616,21 +645,30 @@ static void sfx_set_playrnd( sfx_set *source, sfx_system *sys, int min_id, int m
 
 	int pick = (rand() % (max_id-min_id)) + min_id;
 
-	sys->fadeout = 0;
-	sys->source = source->main;
-	sys->cur 	= source->segments[ pick*2 + 0 ];
-	sys->end 	= source->segments[ pick*2 + 1 ];
-	sys->ch 		= source->ch;
-	
-	sfx_save( sys );
+	if( sfx_begin_edit( sys ) )
+	{
+		sys->fadeout = 0;
+		sys->source = source->main;
+		sys->cur 	= source->segments[ pick*2 + 0 ];
+		sys->end 	= source->segments[ pick*2 + 1 ];
+		sys->ch 		= source->ch;
+		
+		sfx_save( sys );
+	}
 }
 
 static void sfx_system_fadeout( sfx_system *sys, u32 length_samples )
 {
-	sys->fadeout_current = length_samples;
-	sys->fadeout = length_samples;
+	if( sfx_begin_edit( sys ) )
+	{
+		sys->fadeout_current = length_samples;
+		sys->fadeout = length_samples;
+		
+		if( sys->thread_clone )
+			sys->cur = sys->thread_clone->cur;
 	
-	sfx_save( sys );
+		sfx_save( sys );
+	}
 }
 
 // Free set resources
diff --git a/vg/vg_debug.h b/vg/vg_debug.h
new file mode 100644
index 0000000..9f0ac1c
--- /dev/null
+++ b/vg/vg_debug.h
@@ -0,0 +1,73 @@
+static void sfx_internal_debug_overlay(void)
+{
+	// Grab values
+	struct sound_info
+	{
+		float signal;
+		const char *name;
+		u32 length, cursor, flags;
+	}
+	infos[ SFX_MAX_SYSTEMS ];
+	int num_systems;
+	
+	MUTEX_LOCK( sfx_mux_t01 );
+	
+	num_systems = sfx_sys_len;
+	
+	for( int i = 0; i < sfx_sys_len; i ++ )
+	{
+		sfx_system *sys = sfx_sys + i;
+		struct sound_info *snd = &infos[ i ];
+		
+		snd->signal = sys->signal_average;
+		snd->name = sys->name;
+		snd->length = sys->end;
+		snd->cursor = sys->cur;
+		snd->flags = sys->flags;		
+	}
+	
+	MUTEX_UNLOCK( sfx_mux_t01 );
+
+	// UI part
+	// ========
+
+	ui_begin( &ui_global_ctx, vg_window_x, vg_window_y );
+	
+	// TODO: Find a more elegent form for this
+	int mouse_state = 0;
+	if( vg_get_button( "primary" ) ) mouse_state = 2;
+	if( vg_get_button_down( "primary" ) ) mouse_state = 1;
+	if( vg_get_button_up( "primary" ) ) mouse_state = 3;
+		
+	ui_set_mouse( &ui_global_ctx, vg_mouse[0], vg_mouse[1], mouse_state );
+	
+	// Draw audio stack 
+	for( int i = 0; i < num_systems; i ++ )
+	{
+		ui_global_ctx.cursor[2] = 300;
+		ui_global_ctx.cursor[3] = 25;
+		
+		u32 alpha = (infos[i].flags & SFX_FLAG_GHOST)? 0x44000000: 0xff000000;
+
+		ui_new_node( &ui_global_ctx );
+		{	
+			ui_fill_rect( &ui_global_ctx, ui_global_ctx.cursor, 0x00333333 | alpha );
+			
+			ui_global_ctx.cursor[2] = (int)(((float)infos[i].cursor / (float)infos[i].length) * 300.0f);
+			ui_fill_rect( &ui_global_ctx, ui_global_ctx.cursor, 0x77ffffff );
+			
+			ui_text( &ui_global_ctx, infos[i].name, 2, 0 );
+		}
+		ui_end_down( &ui_global_ctx );
+		ui_global_ctx.cursor[1] += 1;
+	}
+	
+	ui_resolve( &ui_global_ctx );
+	
+	m3x3f view = M3X3_IDENTITY;
+	m3x3_translate( view, (v3f){ -1.0f, 1.0f, 0.0f } );
+	m3x3_scale( view, (v3f){ 1.0f/((float)vg_window_x*0.5f), -1.0f/((float)vg_window_y*0.5f), 1.0f } );
+	vg_lines_drawall( (float*)view );
+	
+	ui_draw( &ui_global_ctx );
+}
diff --git a/vg/vg_m.h b/vg/vg_m.h
index 0c4ba35..cb98db2 100644
--- a/vg/vg_m.h
+++ b/vg/vg_m.h
@@ -17,6 +17,10 @@ static inline float vg_maxf( float a, float b )
 	return a > b? a: b;
 }
 
+#define VG_MIN( A, B ) ((A)<(B)?(A):(B))
+#define VG_MAX( A, B ) ((A)>(B)?(A):(B))
+
+// Hopefully deprecate this!!
 static inline int vg_min( int a, int b )
 {
 	return a < b? a: b;
diff --git a/vg/vg_ui.h b/vg/vg_ui.h
index 45120fd..74ecc97 100644
--- a/vg/vg_ui.h
+++ b/vg/vg_ui.h
@@ -35,7 +35,7 @@ SHADER_DEFINE( shader_ui,
 )
 
 #define UI_AUTO_FILL 0
-#define UI_DEBUG
+//#define UI_DEBUG
 
 // Types
 // ===========================================================================================================