Calculate number of audio samples to read per frame deterministically
This commit is contained in:
		
							parent
							
								
									f8359a74d3
								
							
						
					
					
						commit
						20bd7c111b
					
				
					 3 changed files with 55 additions and 69 deletions
				
			
		|  | @ -54,13 +54,9 @@ static int translation_caches_inited = 0; | |||
| // Usually 59.72750057 Hz, unless GBC_RATE is overclocked (for 60FPS)
 | ||||
| #define GBA_FPS ((float) GBC_BASE_RATE) / (308 * 228 * 4) | ||||
| 
 | ||||
| /* An alpha factor of 1/180 is *somewhat* equivalent
 | ||||
|  * to calculating the average for the last 180 | ||||
|  * frames, or 3 seconds of runtime... */ | ||||
| #define SAMPLES_PER_FRAME_MOVING_AVG_ALPHA (1.0f / 180.0f) | ||||
| static s16 *audio_sample_buffer          = NULL; | ||||
| static u32 audio_sample_buffer_size      = 0; | ||||
| static float audio_samples_per_frame_avg = 0.0f; | ||||
| static s16 *audio_sample_buffer        = NULL; | ||||
| static float audio_samples_per_frame   = 0.0f; | ||||
| static float audio_samples_accumulator = 0.0f; | ||||
| 
 | ||||
| /* Workaround for a RetroArch audio driver
 | ||||
|  * limitation: a maximum of 1024 frames | ||||
|  | @ -383,51 +379,40 @@ void set_fastforward_override(bool fastforward) | |||
| 
 | ||||
| static void audio_run(void) | ||||
| { | ||||
|    u32 samples_available = sound_samples_available(); | ||||
|    s16 *audio_buffer_ptr; | ||||
|    u32 samples_to_read; | ||||
|    u32 samples_produced; | ||||
| 
 | ||||
|    if (samples_available > 0) | ||||
|    /* audio_samples_per_frame is decimal;
 | ||||
|     * get integer component */ | ||||
|    samples_to_read = (u32)audio_samples_per_frame; | ||||
| 
 | ||||
|    /* Account for fractional component */ | ||||
|    audio_samples_accumulator += audio_samples_per_frame - | ||||
|          (float)samples_to_read; | ||||
| 
 | ||||
|    if (audio_samples_accumulator >= 1.0f) | ||||
|    { | ||||
|       s16 *audio_buffer_ptr; | ||||
|       u32 samples_to_read; | ||||
|       u32 samples_produced; | ||||
|       samples_to_read++; | ||||
|       audio_samples_accumulator -= 1.0f; | ||||
|    } | ||||
| 
 | ||||
|       /* Update 'running average' of number of
 | ||||
|       * samples per frame. | ||||
|       * Note that this is not a true running | ||||
|       * average, but just a leaky-integrator/ | ||||
|       * exponential moving average, used because | ||||
|       * it is simple and fast (i.e. requires no | ||||
|       * window of samples). */ | ||||
|       audio_samples_per_frame_avg = (SAMPLES_PER_FRAME_MOVING_AVG_ALPHA * (float)samples_available) + | ||||
|             ((1.0f - SAMPLES_PER_FRAME_MOVING_AVG_ALPHA) * audio_samples_per_frame_avg); | ||||
|    samples_produced = sound_read_samples(audio_sample_buffer, samples_to_read); | ||||
| 
 | ||||
|       samples_to_read = (u32)(audio_samples_per_frame_avg + 0.5f); | ||||
|    /* Workaround for a RetroArch audio driver
 | ||||
|     * limitation: a maximum of 1024 frames | ||||
|     * can be written per call of audio_batch_cb(), | ||||
|     * so we have to send samples in chunks */ | ||||
|    audio_buffer_ptr = audio_sample_buffer; | ||||
|    while (samples_produced > 0) | ||||
|    { | ||||
|       u32 samples_to_write = (samples_produced > AUDIO_BATCH_FRAMES_MAX) ? | ||||
|             AUDIO_BATCH_FRAMES_MAX : samples_produced; | ||||
| 
 | ||||
|       /* Resize audio output buffer, if required */ | ||||
|       if (audio_sample_buffer_size < (samples_to_read * 2)) | ||||
|       { | ||||
|          audio_sample_buffer_size = (samples_to_read * 2); | ||||
|          audio_sample_buffer      = (s16*)realloc(audio_sample_buffer, | ||||
|                audio_sample_buffer_size * sizeof(s16)); | ||||
|       } | ||||
|       audio_batch_cb(audio_buffer_ptr, samples_to_write); | ||||
| 
 | ||||
|       samples_produced = sound_read_samples(audio_sample_buffer, samples_to_read); | ||||
| 
 | ||||
|       /* Workaround for a RetroArch audio driver
 | ||||
|        * limitation: a maximum of 1024 frames | ||||
|        * can be written per call of audio_batch_cb(), | ||||
|        * so we have to send samples in chunks */ | ||||
|       audio_buffer_ptr = audio_sample_buffer; | ||||
|       while (samples_produced > 0) | ||||
|       { | ||||
|          u32 samples_to_write = (samples_produced > AUDIO_BATCH_FRAMES_MAX) ? | ||||
|                AUDIO_BATCH_FRAMES_MAX : samples_produced; | ||||
| 
 | ||||
|          audio_batch_cb(audio_buffer_ptr, samples_to_write); | ||||
| 
 | ||||
|          samples_produced -= samples_to_write; | ||||
|          audio_buffer_ptr += samples_to_write << 1; | ||||
|       } | ||||
|       samples_produced -= samples_to_write; | ||||
|       audio_buffer_ptr += samples_to_write << 1; | ||||
|    } | ||||
| } | ||||
| 
 | ||||
|  | @ -521,10 +506,11 @@ void retro_get_system_av_info(struct retro_system_av_info* info) | |||
| 
 | ||||
| void retro_init(void) | ||||
| { | ||||
|    u32 audio_samples_per_frame = (u32)((float)(GBA_SOUND_FREQUENCY) / (float)(GBA_FPS)); | ||||
|    audio_sample_buffer_size    = audio_samples_per_frame * 2; | ||||
|    audio_sample_buffer         = (s16*)malloc(audio_sample_buffer_size * sizeof(s16)); | ||||
|    audio_samples_per_frame_avg = (float)audio_samples_per_frame; | ||||
|    u32 audio_sample_buffer_size; | ||||
|    audio_samples_per_frame   = (float)(GBA_SOUND_FREQUENCY) / (float)(GBA_FPS); | ||||
|    audio_samples_accumulator = 0.0f; | ||||
|    audio_sample_buffer_size  = ((u32)audio_samples_per_frame + 1) * 2; | ||||
|    audio_sample_buffer       = (s16*)malloc(audio_sample_buffer_size * sizeof(s16)); | ||||
| 
 | ||||
| #if defined(HAVE_DYNAREC) | ||||
|   #if defined(MMAP_JIT_CACHE) | ||||
|  | @ -666,9 +652,9 @@ void retro_deinit(void) | |||
|    if (audio_sample_buffer) | ||||
|       free(audio_sample_buffer); | ||||
| 
 | ||||
|    audio_sample_buffer         = NULL; | ||||
|    audio_sample_buffer_size    = 0; | ||||
|    audio_samples_per_frame_avg = 0.0f; | ||||
|    audio_sample_buffer       = NULL; | ||||
|    audio_samples_per_frame   = 0.0f; | ||||
|    audio_samples_accumulator = 0.0f; | ||||
| } | ||||
| 
 | ||||
| static retro_time_t retro_perf_dummy_get_time_usec() { return 0; } | ||||
|  |  | |||
							
								
								
									
										29
									
								
								sound.c
									
										
									
									
									
								
							
							
						
						
									
										29
									
								
								sound.c
									
										
									
									
									
								
							|  | @ -749,22 +749,22 @@ unsigned sound_write_savestate(u8 *dst) | |||
|   return (unsigned int)(dst - startp); | ||||
| } | ||||
| 
 | ||||
| u32 sound_samples_available(void) | ||||
| u32 sound_read_samples(s16 *out, u32 frames) | ||||
| { | ||||
|    u32 num_samples = (gbc_sound_buffer_index - sound_buffer_base) & BUFFER_SIZE_MASK; | ||||
|    num_samples = (num_samples > 512) ? (num_samples - 512) : 0; | ||||
|    return (num_samples >> 1); | ||||
| } | ||||
| 
 | ||||
| u32 sound_read_samples(s16 *out, u32 count) | ||||
| { | ||||
|    u32 samples_available = sound_samples_available(); | ||||
|    u32 i; | ||||
|    u32 samples_to_read   = frames << 1; | ||||
|    /* Get total number of samples in the buffer */ | ||||
|    u32 samples_available = (gbc_sound_buffer_index - sound_buffer_base) & BUFFER_SIZE_MASK; | ||||
|    /* The last 512 samples are 'in use', and cannot
 | ||||
|     * be read out yet */ | ||||
|    samples_available     = (samples_available > 512) ? (samples_available - 512) : 0; | ||||
|    /* Available sample count must be an even number */ | ||||
|    samples_available     = (samples_available >> 1) << 1; | ||||
| 
 | ||||
|    if (count > samples_available) | ||||
|       count = samples_available; | ||||
|    if (samples_to_read > samples_available) | ||||
|       samples_to_read = samples_available; | ||||
| 
 | ||||
|    for(i = 0; i < (count << 1); i++) | ||||
|    for(i = 0; i < samples_to_read; i++) | ||||
|    { | ||||
|       u32 source_index   = (sound_buffer_base + i) & BUFFER_SIZE_MASK; | ||||
|       s32 current_sample = sound_buffer[source_index]; | ||||
|  | @ -779,8 +779,9 @@ u32 sound_read_samples(s16 *out, u32 count) | |||
|       out[i] = current_sample * 16; | ||||
|    } | ||||
| 
 | ||||
|    sound_buffer_base += (count << 1); | ||||
|    sound_buffer_base += samples_to_read; | ||||
|    sound_buffer_base &= BUFFER_SIZE_MASK; | ||||
| 
 | ||||
|    return count; | ||||
|    /* Function returns number of frames read */ | ||||
|    return (samples_to_read >> 1); | ||||
| } | ||||
|  |  | |||
							
								
								
									
										3
									
								
								sound.h
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								sound.h
									
										
									
									
									
								
							|  | @ -108,8 +108,7 @@ void init_sound(int need_reset); | |||
| unsigned sound_write_savestate(u8 *dst); | ||||
| bool sound_read_savestate(const u8 *src); | ||||
| 
 | ||||
| u32 sound_samples_available(void); | ||||
| u32 sound_read_samples(s16 *out, u32 count); | ||||
| u32 sound_read_samples(s16 *out, u32 frames); | ||||
| 
 | ||||
| void reset_sound(void); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue