summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNebuleon <nebuleon@alakazam>2013-10-20 03:57:54 +0000
committerNebuleon <nebuleon@alakazam>2013-10-20 03:57:54 +0000
commitc8a6cefc73f2e65e2a100785749b9578355e3c8c (patch)
treeaa87814e6c5af52a792d4f8d1e31d91521074dc2
parent7b55a50eea79105f508ada053d0470f8c97b6f60 (diff)
downloadReGBA-c8a6cefc73f2e65e2a100785749b9578355e3c8c.zip
ReGBA-c8a6cefc73f2e65e2a100785749b9578355e3c8c.tar.gz
ReGBA-c8a6cefc73f2e65e2a100785749b9578355e3c8c.tar.bz2
OpenDingux: Improve fast-forwarding. Better detection of the need to increase frame skipping when there is insufficient buffered audio, and to raise the frame rate again once a fair amount of time has passed without audio underruns. This may help the Dingoo A320.
-rw-r--r--source/opendingux/draw.c55
-rw-r--r--source/opendingux/draw.h4
-rw-r--r--source/opendingux/od-input.c8
-rw-r--r--source/opendingux/od-input.h33
-rw-r--r--source/opendingux/od-sound.c13
-rw-r--r--source/opendingux/od-sound.h5
-rw-r--r--source/opendingux/port.c18
7 files changed, 83 insertions, 53 deletions
diff --git a/source/opendingux/draw.c b/source/opendingux/draw.c
index 8427295..bc47a29 100644
--- a/source/opendingux/draw.c
+++ b/source/opendingux/draw.c
@@ -22,9 +22,10 @@
uint16_t* GBAScreen;
uint32_t GBAScreenPitch = GBA_SCREEN_WIDTH;
-volatile uint_fast8_t VideoFastForwarded;
+volatile unsigned int VideoFastForwarded;
uint_fast8_t AudioFrameskip = 0;
uint_fast8_t AudioFrameskipControl = 0;
+uint_fast8_t SufficientAudioControl = 0;
uint_fast8_t UserFrameskipControl = 0;
uint_fast8_t FramesBordered = 0;
@@ -557,10 +558,15 @@ void ReGBA_RenderScreen(void)
SDL_Flip(OutputSurface);
- while (ReGBA_GetAudioSamplesAvailable() > AUDIO_OUTPUT_BUFFER_SIZE * 3 * OUTPUT_FREQUENCY_DIVISOR + (VideoFastForwarded - AudioFastForwarded) * ((int) (SOUND_FREQUENCY / 59.73)))
+ while (true)
{
- if (AudioFrameskip > 0)
- AudioFrameskip--;
+ unsigned int AudioFastForwardedCopy = AudioFastForwarded;
+ unsigned int FramesAhead = (VideoFastForwarded >= AudioFastForwardedCopy)
+ ? /* no overflow */ VideoFastForwarded - AudioFastForwardedCopy
+ : /* overflow */ 0x100 - (AudioFastForwardedCopy - VideoFastForwarded);
+ uint32_t Quota = AUDIO_OUTPUT_BUFFER_SIZE * 3 * OUTPUT_FREQUENCY_DIVISOR + (uint32_t) (FramesAhead * (SOUND_FREQUENCY / 59.73f));
+ if (ReGBA_GetAudioSamplesAvailable() <= Quota)
+ break;
usleep(1000);
}
}
@@ -569,29 +575,40 @@ void ReGBA_RenderScreen(void)
{
if (AudioFrameskip < MAX_AUTO_FRAMESKIP)
AudioFrameskip++;
+ SufficientAudioControl = 0;
+ }
+ else
+ {
+ SufficientAudioControl++;
+ if (SufficientAudioControl >= 10)
+ {
+ SufficientAudioControl = 0;
+ if (AudioFrameskip > 0)
+ AudioFrameskip--;
+ }
}
- if (FastForwardControl >= 60)
+ if (FastForwardFrameskip > 0 && FastForwardFrameskipControl > 0)
{
- FastForwardControl -= 60;
- VideoFastForwarded++;
+ FastForwardFrameskipControl--;
+ VideoFastForwarded = (VideoFastForwarded + 1) & 0xFF;
+ }
+ else
+ {
+ FastForwardFrameskipControl = FastForwardFrameskip;
+ if (UserFrameskip != 0)
+ {
+ if (UserFrameskipControl == 0)
+ UserFrameskipControl = UserFrameskip - 1;
+ else
+ UserFrameskipControl--;
+ }
}
- FastForwardControl += FastForwardValue;
if (AudioFrameskipControl > 0)
AudioFrameskipControl--;
- else if (AudioFrameskipControl == 0)
+ else
AudioFrameskipControl = AudioFrameskip;
-
- if (UserFrameskip != 0)
- {
- if (UserFrameskipControl == 0)
- UserFrameskipControl = UserFrameskip - 1;
- else
- UserFrameskipControl--;
- if (FastForwardControl < 60 && FastForwardValue + FastForwardControl >= 60)
- UserFrameskipControl = 0; // allow fast-forwarding even at FS 0
- }
}
u16 *copy_screen()
diff --git a/source/opendingux/draw.h b/source/opendingux/draw.h
index b0fae4d..aeea56d 100644
--- a/source/opendingux/draw.h
+++ b/source/opendingux/draw.h
@@ -15,6 +15,10 @@ extern uint_fast8_t AudioFrameskip;
extern uint_fast8_t AudioFrameskipControl;
extern uint_fast8_t UserFrameskipControl;
+// Incremented by the video thread when it decides to skip a frame due to
+// fast forwarding.
+extern volatile unsigned int VideoFastForwarded;
+
// How many back buffers have had ApplyScaleMode called upon them?
// At 3, even a triple-buffered surface has had ApplyScaleMode called on
// all back buffers, so stopping remanence with ApplyScaleMode is wasteful.
diff --git a/source/opendingux/od-input.c b/source/opendingux/od-input.c
index 0f244a8..a657e77 100644
--- a/source/opendingux/od-input.c
+++ b/source/opendingux/od-input.c
@@ -19,11 +19,11 @@
#include "common.h"
-uint_fast8_t FastForwardValue = 0;
+uint_fast8_t FastForwardFrameskip = 0;
uint32_t FastForwardTarget = 4; // 6x by default
-uint_fast8_t FastForwardControl = 0;
+uint_fast8_t FastForwardFrameskipControl = 0;
static SDL_Joystick* Joystick;
@@ -145,8 +145,8 @@ static void UpdateOpenDinguxButtons()
void ProcessSpecialKeys()
{
- FastForwardValue = (Hotkeys[0] != 0 && (Hotkeys[0] & LastButtons) == Hotkeys[0])
- ? 60 - (60 / (2 + FastForwardTarget))
+ FastForwardFrameskip = (Hotkeys[0] != 0 && (Hotkeys[0] & LastButtons) == Hotkeys[0])
+ ? FastForwardTarget + 1
: 0;
}
diff --git a/source/opendingux/od-input.h b/source/opendingux/od-input.h
index a01680a..431bb8b 100644
--- a/source/opendingux/od-input.h
+++ b/source/opendingux/od-input.h
@@ -49,30 +49,21 @@ enum GUI_Action {
};
// 0 if not fast-forwarding.
-// Otherwise, the amount of frames to skip per second.
-// 30 amounts to targetting 200% real-time;
-// 40 amounts to targetting 300% real-time;
-// 45 amounts to targetting 400% real-time;
-// 48 amounts to targetting 500% real-time;
-// 50 amounts to targetting 600% real-time.
-extern uint_fast8_t FastForwardValue;
-
-// The number of times to target while fast-forwarding. (UI option)
+// Otherwise, the amount of frames to skip per rendered frame.
+// 1 amounts to targetting 200% real-time;
+// 2 amounts to targetting 300% real-time;
+// 3 amounts to targetting 400% real-time;
+// 4 amounts to targetting 500% real-time;
+// 5 amounts to targetting 600% real-time.
+extern uint_fast8_t FastForwardFrameskip;
+
+// The number of times to target while fast-forwarding is enabled. (UI option)
// 0 means 2x, 1 means 3x, ... 4 means 6x.
extern uint32_t FastForwardTarget;
-// Incremented by FastForwardValue every frame. If it's over 60,
-// a frame is skipped, 60 is removed, then FastForwardValue is added again.
-extern uint_fast8_t FastForwardControl;
-
-// Incremented by the video thread when it decides to skip a frame due to
-// fast forwarding.
-extern volatile uint_fast8_t VideoFastForwarded;
-
-// Modified by the audio thread to match VideoFastForwarded after it finds
-// that the video thread has skipped a frame. The audio thread must deal
-// with the condition as soon as possible.
-extern volatile uint_fast8_t AudioFastForwarded;
+// If this is greater than 0, a frame and its audio are skipped.
+// The value then goes to FastForwardFrameskip and is decremented until 0.
+extern uint_fast8_t FastForwardFrameskipControl;
/*
* Gets the current value of the analog horizontal axis.
diff --git a/source/opendingux/od-sound.c b/source/opendingux/od-sound.c
index 4354136..d7e237d 100644
--- a/source/opendingux/od-sound.c
+++ b/source/opendingux/od-sound.c
@@ -3,7 +3,7 @@
#include "common.h"
#include "../sound.h"
-volatile uint_fast8_t AudioFastForwarded;
+volatile unsigned int AudioFastForwarded;
#define DAMPEN_SAMPLE_COUNT (AUDIO_OUTPUT_BUFFER_SIZE / 32)
@@ -65,12 +65,17 @@ void feed_buffer(void *udata, Uint8 *buffer, int len)
}
Samples -= Requested / 2;
- // Discard sound until half the requested length is left, if fast-forwarding.
+ // Discard as many samples as are generated in 1 frame, if fast-forwarding.
bool Skipped = false;
- uint_fast8_t VideoFastForwardedCopy = VideoFastForwarded;
+ unsigned int VideoFastForwardedCopy = VideoFastForwarded;
if (VideoFastForwardedCopy != AudioFastForwarded)
{
- uint32_t SamplesToSkip = Samples - (Requested * 3 - Requested / 2);
+ unsigned int FramesToSkip = (VideoFastForwardedCopy > AudioFastForwarded)
+ ? /* no overflow */ VideoFastForwardedCopy - AudioFastForwarded
+ : /* overflow */ 0x100 - (AudioFastForwarded - VideoFastForwardedCopy);
+ uint32_t SamplesToSkip = (uint32_t) (FramesToSkip * (OUTPUT_SOUND_FREQUENCY / 59.73f));
+ if (SamplesToSkip > Samples - (Requested * 3 - Requested / 2))
+ SamplesToSkip = Samples - (Requested * 3 - Requested / 2);
ReGBA_DiscardAudioSamples(SamplesToSkip * OUTPUT_FREQUENCY_DIVISOR);
Samples -= SamplesToSkip;
AudioFastForwarded = VideoFastForwardedCopy;
diff --git a/source/opendingux/od-sound.h b/source/opendingux/od-sound.h
index 2cf42a4..1921856 100644
--- a/source/opendingux/od-sound.h
+++ b/source/opendingux/od-sound.h
@@ -3,7 +3,10 @@
void init_sdlaudio();
-extern int audio_discardflag;
+// Modified by the audio thread to match VideoFastForwarded after it finds
+// that the video thread has skipped a frame. The audio thread must deal
+// with the condition as soon as possible.
+extern volatile unsigned int AudioFastForwarded;
#define AUDIO_OUTPUT_BUFFER_SIZE 1476
diff --git a/source/opendingux/port.c b/source/opendingux/port.c
index 6fd4229..70e9844 100644
--- a/source/opendingux/port.c
+++ b/source/opendingux/port.c
@@ -133,10 +133,20 @@ void ReGBA_LoadRTCTime(struct ReGBA_RTC* RTCData)
bool ReGBA_IsRenderingNextFrame()
{
- if (UserFrameskip == 0) /* automatic */
- return FastForwardControl < 60 && AudioFrameskipControl == 0;
-
- return FastForwardControl < 60 && UserFrameskipControl == 0; /* manual, draw this frame */
+ if (FastForwardFrameskip != 0) /* fast-forwarding */
+ {
+ if (UserFrameskip != 0) /* fast-forwarding on user frameskip */
+ return FastForwardFrameskipControl == 0 && UserFrameskipControl == 0;
+ else /* fast-forwarding on automatic frameskip */
+ return FastForwardFrameskipControl == 0 && AudioFrameskipControl == 0;
+ }
+ else
+ {
+ if (UserFrameskip != 0) /* user frameskip */
+ return UserFrameskipControl == 0;
+ else /* automatic frameskip */
+ return AudioFrameskipControl == 0;
+ }
}
const char* GetFileName(const char* Path)