22#include <snes9x.h>
33#include <math.h>
44
5- #define AUDIO_SAMPLE_RATE (32000 )
5+ #define AUDIO_SAMPLE_RATE (32040 )
66#define AUDIO_BUFFER_LENGTH (AUDIO_SAMPLE_RATE / 50 + 1)
77
88// #define FRAME_DOUBLE_BUFFERING
@@ -96,8 +96,6 @@ static const char *SNES_BUTTONS[] = {
9696static rg_app_t * app ;
9797static rg_surface_t * updates [2 ];
9898static rg_surface_t * currentUpdate ;
99- static rg_audio_sample_t * audioBuffers [2 ];
100- static rg_audio_sample_t * currentAudioBuffer ;
10199
102100#ifdef USE_AUDIO_TASK
103101static rg_task_t * audio_task_handle ;
@@ -138,8 +136,6 @@ static bool load_state_handler(const char *filename)
138136static bool reset_handler (bool hard )
139137{
140138 S9xReset ();
141- memset (audioBuffers [0 ], 0 , AUDIO_BUFFER_LENGTH * 4 );
142- memset (audioBuffers [1 ], 0 , AUDIO_BUFFER_LENGTH * 4 );
143139 return true;
144140}
145141
@@ -310,26 +306,30 @@ void JustifierButtons(uint32_t *justifiers)
310306 (void )justifiers ;
311307}
312308
313- static inline void mix_samples (int32_t count )
314- {
315- currentAudioBuffer = audioBuffers [currentAudioBuffer == audioBuffers [0 ]];
316- if (lowpass_filter )
317- S9xMixSamplesLowPass ((int16_t * )currentAudioBuffer , count , AUDIO_LOW_PASS_RANGE );
318- else
319- S9xMixSamples ((int16_t * )currentAudioBuffer , count );
320- }
321-
322309#ifdef USE_AUDIO_TASK
323310static void audio_task (void * arg )
324311{
312+ rg_audio_sample_t * audioBuffer = rg_alloc (AUDIO_BUFFER_LENGTH * 4 , MEM_FAST );
325313 rg_task_msg_t msg ;
314+ bool zeroed = false;
326315 while (rg_task_receive (& msg ))
327316 {
328317 if (msg .type == RG_TASK_MSG_STOP )
329318 break ;
330- if (msg .type != 0 )
331- mix_samples (AUDIO_BUFFER_LENGTH << 1 );
332- rg_audio_submit (currentAudioBuffer , AUDIO_BUFFER_LENGTH );
319+ if (msg .type != 0 ) // Sound enabled, mix
320+ {
321+ if (lowpass_filter )
322+ S9xMixSamplesLowPass ((int16_t * )audioBuffer , msg .dataInt << 1 , AUDIO_LOW_PASS_RANGE );
323+ else
324+ S9xMixSamples ((int16_t * )audioBuffer , msg .dataInt << 1 );
325+ zeroed = false;
326+ }
327+ else if (!zeroed ) // Sound disabled, zero buffer only if needed
328+ {
329+ memset (audioBuffer , 0 , AUDIO_BUFFER_LENGTH * 4 );
330+ zeroed = true;
331+ }
332+ rg_audio_submit (audioBuffer , msg .dataInt );
333333 }
334334}
335335#endif
@@ -371,22 +371,15 @@ void app_main(void)
371371#endif
372372 currentUpdate = updates [0 ];
373373
374- #ifdef AUDIO_DOUBLE_BUFFERING
375- audioBuffers [0 ] = (rg_audio_sample_t * )calloc (AUDIO_BUFFER_LENGTH , 4 );
376- audioBuffers [1 ] = (rg_audio_sample_t * )calloc (AUDIO_BUFFER_LENGTH , 4 );
377- #else
378- audioBuffers [0 ] = (rg_audio_sample_t * )calloc (AUDIO_BUFFER_LENGTH , 4 );
379- audioBuffers [1 ] = audioBuffers [0 ];
380- #endif
381- currentAudioBuffer = audioBuffers [0 ];
382-
383- if (!updates [0 ] || !updates [1 ] || !audioBuffers [0 ] || !audioBuffers [1 ])
374+ if (!updates [0 ] || !updates [1 ])
384375 RG_PANIC ("Failed to allocate buffers!" );
385376
386377#ifdef USE_AUDIO_TASK
387378 // Set up multicore audio
388379 audio_task_handle = rg_task_create ("snes_audio" , & audio_task , NULL , 2048 , RG_TASK_PRIORITY_6 , 1 );
389380 RG_ASSERT (audio_task_handle , "Failed to create audio task!" );
381+ #else
382+ rg_audio_sample_t * audioBuffer = rg_alloc (AUDIO_BUFFER_LENGTH * 4 , MEM_FAST );
390383#endif
391384
392385 Settings .CyclesPercentage = 100 ;
@@ -437,6 +430,8 @@ void app_main(void)
437430 rg_system_set_tick_rate (Memory .ROMFramesPerSecond );
438431 app -> frameskip = 3 ;
439432
433+ const float samplesPerFrame = (float )app -> sampleRate / app -> tickRate ;
434+ float samplesRemaining = 0.f ;
440435 bool menuCancelled = false;
441436 bool menuPressed = false;
442437 int skipFrames = 0 ;
@@ -463,8 +458,6 @@ void app_main(void)
463458 else if (joystick & RG_KEY_OPTION )
464459 {
465460 rg_gui_options_menu ();
466- memset (audioBuffers [0 ], 0 , AUDIO_BUFFER_LENGTH * 4 );
467- memset (audioBuffers [1 ], 0 , AUDIO_BUFFER_LENGTH * 4 );
468461 continue ;
469462 }
470463
@@ -487,17 +480,25 @@ void app_main(void)
487480 currentUpdate = updates [currentUpdate == updates [0 ]];
488481 }
489482
483+ samplesRemaining += samplesPerFrame ;
484+ int samples = (int )samplesRemaining ;
485+ samplesRemaining -= samples ;
486+
490487 #ifdef USE_AUDIO_TASK
491488 rg_system_tick (rg_system_timer () - startTime );
492- rg_task_msg_t msg = {.type = (int )sound_enabled };
489+ rg_task_msg_t msg = {.type = (int )sound_enabled , . dataInt = samples };
493490 if (sound_enabled || app -> frameTime - (rg_system_timer () - startTime ) > 2000 )
494491 rg_task_send (audio_task_handle , & msg );
495492 #else
496- if (sound_enabled )
497- mix_samples (AUDIO_BUFFER_LENGTH << 1 );
493+ if (sound_enabled && lowpass_filter )
494+ S9xMixSamplesLowPass ((int16_t * )audioBuffer , samples << 1 , AUDIO_LOW_PASS_RANGE );
495+ else if (sound_enabled )
496+ S9xMixSamples ((int16_t * )audioBuffer , samples << 1 );
497+ else
498+ memset (audioBuffer , 0 , AUDIO_BUFFER_LENGTH * sizeof (rg_audio_sample_t ));
498499 rg_system_tick (rg_system_timer () - startTime );
499500 if (sound_enabled || app -> frameTime - (rg_system_timer () - startTime ) > 2000 )
500- rg_audio_submit (currentAudioBuffer , AUDIO_BUFFER_LENGTH );
501+ rg_audio_submit (audioBuffer , samples );
501502 #endif
502503
503504 if (skipFrames == 0 )
0 commit comments