diff options
author | Nebuleon <nebuleon@alakazam> | 2013-10-20 03:57:54 +0000 |
---|---|---|
committer | Nebuleon <nebuleon@alakazam> | 2013-10-20 03:57:54 +0000 |
commit | c8a6cefc73f2e65e2a100785749b9578355e3c8c (patch) | |
tree | aa87814e6c5af52a792d4f8d1e31d91521074dc2 | |
parent | 7b55a50eea79105f508ada053d0470f8c97b6f60 (diff) | |
download | ReGBA-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.c | 55 | ||||
-rw-r--r-- | source/opendingux/draw.h | 4 | ||||
-rw-r--r-- | source/opendingux/od-input.c | 8 | ||||
-rw-r--r-- | source/opendingux/od-input.h | 33 | ||||
-rw-r--r-- | source/opendingux/od-sound.c | 13 | ||||
-rw-r--r-- | source/opendingux/od-sound.h | 5 | ||||
-rw-r--r-- | source/opendingux/port.c | 18 |
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) |