Skip to content

Commit ad22c23

Browse files
authored
Merge pull request #1 from RetroPorts/throttle-fix
Fix to frame delay management induced by audio
2 parents 5b4a196 + a26c452 commit ad22c23

File tree

4 files changed

+51
-63
lines changed

4 files changed

+51
-63
lines changed

src/drivers/dingux-sdl/dingoo-sound.cpp

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
/// \brief Handles sound emulation using the SDL.
2323

2424
#include <stdio.h>
25-
#include <string.h>
25+
#include <string.h>
2626
#include <stdlib.h>
2727

2828
#include "dingoo.h"
@@ -67,14 +67,14 @@ static void fillaudio(void *udata, uint8 *stream, int len) // len == spec.sample
6767

6868
*tmps = sample;
6969
tmps++;
70-
len--;
70+
len--;
7171
}
7272
}
7373

7474
/**
7575
* Initialize the audio subsystem.
7676
*/
77-
int InitSound()
77+
int InitSound()
7878
{
7979
int sound, soundrate, soundbufsize, soundvolume, soundtrianglevolume,
8080
soundsquare1volume, soundsquare2volume, soundnoisevolume,
@@ -94,7 +94,7 @@ int InitSound()
9494
}
9595
char driverName[8];
9696
SDL_AudioDriverName(driverName, 8);
97-
97+
9898
fprintf(stderr, "Loading SDL sound with %s driver...\n", driverName);
9999

100100
// load configuration variables
@@ -179,7 +179,7 @@ uint32 GetBufferedSound(void) {
179179
/**
180180
* Send a sound clip to the audio subsystem.
181181
*/
182-
void WriteSound(int32 *buf, int Count)
182+
void WriteSound(int32 *buf, int Count)
183183
{
184184
//extern int EmulationPaused;
185185
// if(ispressed(DINGOO_L)) {
@@ -196,19 +196,14 @@ void WriteSound(int32 *buf, int Count)
196196
s_Buffer[s_BufferWrite] = *buf;
197197
Count--;
198198
s_BufferWrite = (s_BufferWrite + 1) % s_BufferSize;
199-
199+
200200
s_BufferIn++;
201-
201+
202202
buf++;
203203
}
204204
}
205205
_exit:
206206
SDL_UnlockAudio();
207-
208-
// If we have too much audio, wait a bit before accepting more.
209-
// This keeps the lag in check.
210-
while (GetBufferedSound() > 3 * GetBufferSize())
211-
usleep(1000);
212207
}
213208

214209
/**
@@ -218,7 +213,7 @@ void SilenceSound(int n)
218213
{
219214
// Not needed, the callback will write silence to buffer anyway
220215
// otherwise it causes noticable lag
221-
SDL_PauseAudio(n);
216+
SDL_PauseAudio(n);
222217
}
223218

224219
/**

src/drivers/dingux-sdl/dingoo-throttle.cpp

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,11 @@ void delay_us(uint64 us_count)
5858
void RefreshThrottleFPS()
5959
{
6060
uint64 fps = FCEUI_GetDesiredFPS(); // Do >> 24 to get in Hz
61-
desired_frametime = 16777216.0l / (fps * g_fpsScale);
61+
//desired_frametime = 16777216.0l / (fps * g_fpsScale);
62+
desired_frametime = 20132659.0l / (fps * g_fpsScale);
6263
desired_frametime_us = (uint64)(desired_frametime * 1000000.0l);
6364

64-
Lasttime=0;
65+
Lasttime=0;
6566
Nexttime=0;
6667
InFrame=0;
6768
printf("desired_frametime: %i\n", desired_frametime_us);
@@ -80,30 +81,30 @@ int SpeedThrottle()
8081
}
8182
uint64 time_left;
8283
uint64 cur_time;
83-
84+
8485
if(!Lasttime) Lasttime = get_ticks_us();
85-
86+
8687
if(!InFrame) {
8788
InFrame = 1;
8889
Nexttime = Lasttime + desired_frametime_us;
8990
}
90-
91+
9192
cur_time = get_ticks_us();
9293

9394
if(cur_time >= Nexttime)
9495
time_left = 0;
9596
else
9697
time_left = Nexttime - cur_time;
97-
98+
9899
if(time_left > 50000) {
99100
time_left = 50000;
100101
/* In order to keep input responsive, don't wait too long at once */
101102
/* 50 ms wait gives us a 20 Hz responsetime which is nice. */
102103
} else InFrame = 0;
103-
104+
104105
//printf("attempting to sleep %Ld ms, frame complete=%i\n", time_left, InFrame);
105106
delay_us(time_left);
106-
107+
107108
if(!InFrame)
108109
{
109110
Lasttime = get_ticks_us();
@@ -119,11 +120,11 @@ void IncreaseEmulationSpeed(void)
119120
{
120121
puts("IncreaseEmulationSpeed");
121122
g_fpsScale *= LOGMUL;
122-
123+
123124
if(g_fpsScale > Fastest) g_fpsScale = Fastest;
124125

125126
RefreshThrottleFPS();
126-
127+
127128
FCEU_DispMessage("emulation speed %.1f%%", g_fpsScale*100.0);
128129
}
129130

@@ -150,7 +151,7 @@ FCEUD_SetEmulationSpeed(int cmd)
150151
{
151152
puts("SetEmulationSpeed");
152153
MaxSpeed = false;
153-
154+
154155
switch(cmd) {
155156
case EMUSPEED_SLOWEST:
156157
g_fpsScale = Slowest;

src/drivers/dingux-sdl/dingoo-video.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -317,9 +317,9 @@ void flip_NNOptimized_AllowOutOfScreen(SDL_Surface *src_surface, SDL_Surface *ds
317317
continue;
318318
}
319319

320-
uint16_t *t = (uint16_t *) (dst_surface->pixels + ((i + y_padding) * ((w2 > RES_HW_SCREEN_HORIZONTAL) ? RES_HW_SCREEN_HORIZONTAL : w2)) * sizeof (uint16_t));
320+
uint16_t *t = static_cast<uint16_t*>(dst_surface->pixels) + ((i + y_padding) * ((w2 > RES_HW_SCREEN_HORIZONTAL) ? RES_HW_SCREEN_HORIZONTAL : w2));
321321
y2 = (i * y_ratio) >> 16;
322-
uint16_t *p = (uint16_t *) (src_surface->pixels + (y2 * w1 + x_padding_ratio) * sizeof (uint16_t));
322+
uint16_t *p = static_cast<uint16_t*>(src_surface->pixels) + (y2 * w1 + x_padding_ratio);
323323
int rat = 0;
324324
for (int j = 0; j < w2; j++) {
325325
if (j >= RES_HW_SCREEN_HORIZONTAL) {
@@ -357,7 +357,7 @@ void flip_NNOptimized_AllowOutOfScreen_NES(uint8_t *nes_px, SDL_Surface *dst_sur
357357
continue;
358358
}
359359

360-
uint16_t *t = (uint16_t *) (dst_surface->pixels + ((i + y_padding) * ((w2 > RES_HW_SCREEN_HORIZONTAL) ? RES_HW_SCREEN_HORIZONTAL : w2)) * sizeof (uint16_t));
360+
uint16_t *t = static_cast<uint16_t*>(dst_surface->pixels) + ((i + y_padding) * ((w2 > RES_HW_SCREEN_HORIZONTAL) ? RES_HW_SCREEN_HORIZONTAL : w2));
361361
y2 = (i * y_ratio) >> 16;
362362
uint8_t *p = (uint8_t *) (nes_px + (y2 * w1 + x_padding_ratio) * sizeof (uint8_t));
363363
int rat = 0;
@@ -408,7 +408,7 @@ void flip_Downscale_LeftRightGaussianFilter_NES(uint8_t *nes_px, SDL_Surface *ds
408408
continue;
409409
}
410410

411-
uint16_t *t = (uint16_t *) (dst_surface->pixels + ((i + y_padding) * ((w2 > RES_HW_SCREEN_HORIZONTAL) ? RES_HW_SCREEN_HORIZONTAL : w2)) * sizeof (uint16_t));
411+
uint16_t *t = static_cast<uint16_t*>(dst_surface->pixels) + ((i + y_padding) * ((w2 > RES_HW_SCREEN_HORIZONTAL) ? RES_HW_SCREEN_HORIZONTAL : w2));
412412
y1 = (i * y_ratio) >> 16;
413413
uint8_t *p = (uint8_t *) (nes_px + (y1 * w1 + x_padding_ratio) * sizeof (uint8_t));
414414
int rat = 0;

src/drivers/dingux-sdl/dingoo.cpp

Lines changed: 27 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@
4949
#include <windows.h>
5050
#endif
5151

52+
#include <chrono>
53+
#include <thread>
54+
5255
extern double g_fpsScale;
5356

5457
extern bool MaxSpeed;
@@ -328,44 +331,33 @@ void quick_save_and_poweroff()
328331
}
329332

330333
static void DoFun(int fskip) {
331-
uint8 *gfx;
332-
int32 *sound;
333-
int32 ssize;
334-
extern uint8 PAL;
335-
int done = 0, timer = 0, ticks = 0, tick = 0, fps = 0;
336-
unsigned int frame_limit = 60, frametime = 16667;
337-
338-
while (GameInfo) {
339-
/* Frameskip decision based on the audio buffer */
340-
if (!fpsthrottle) {
341-
// Fill up the audio buffer with up to 6 frames dropped.
342-
int FramesSkipped = 0;
343-
while (GameInfo
344-
&& GetBufferedSound() < GetBufferSize() * 3 / 2
345-
&& ++FramesSkipped < 6) {
346-
FCEUI_Emulate(&gfx, &sound, &ssize, 1);
347-
FCEUD_Update(NULL, sound, ssize);
348-
}
334+
uint8 *gfx;
335+
int32 *sound;
336+
int32 ssize;
337+
extern uint8 PAL;
338+
int done = 0, timer = 0, ticks = 0, tick = 0, fps = 0;
339+
unsigned int frame_limit = 60;
349340

350-
// Force at least one frame to be displayed.
351-
if (GameInfo) {
352-
FCEUI_Emulate(&gfx, &sound, &ssize, 0);
353-
FCEUD_Update(gfx, sound, ssize);
354-
}
341+
namespace sc = std::chrono;
342+
using time_stamp = sc::time_point<sc::steady_clock, sc::microseconds>;
355343

356-
// Then render all frames while audio is sufficient.
357-
while (GameInfo
358-
&& GetBufferedSound() > GetBufferSize() * 3 / 2) {
359-
FCEUI_Emulate(&gfx, &sound, &ssize, 0);
360-
FCEUD_Update(gfx, sound, ssize);
361-
}
362-
}
363-
else {
364-
FCEUI_Emulate(&gfx, &sound, &ssize, 0);
365-
FCEUD_Update(gfx, sound, ssize);
366-
}
367-
}
344+
static constexpr auto frametime = sc::microseconds((uint64_t)(1000000 / 60.0f));
345+
346+
while (GameInfo) {
347+
time_stamp s = sc::time_point_cast<sc::microseconds>(sc::steady_clock::now());
348+
349+
FCEUI_Emulate(&gfx, &sound, &ssize, 0);
350+
FCEUD_Update(gfx, sound, ssize);
351+
352+
time_stamp e = sc::time_point_cast<sc::microseconds>(sc::steady_clock::now());
353+
354+
auto delta = e - s;
355+
356+
//printf("%d %d %d\n", delta.count(), (frametime - delta).count(), frametime.count());
368357

358+
if (delta < frametime)
359+
std::this_thread::sleep_for(frametime - delta);
360+
}
369361
}
370362

371363
/**

0 commit comments

Comments
 (0)