mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 05:19:56 +00:00
libretro: Rip out the audio speed control logic, libretro should handle that internally.
This commit is contained in:
parent
ecfd4759dd
commit
1d0afd4867
@ -69,13 +69,6 @@
|
||||
|
||||
#define SAMPLERATE 44100
|
||||
|
||||
#define AUDIO_RING_BUFFER_SIZE (1 << 16)
|
||||
#define AUDIO_RING_BUFFER_SIZE_MASK (AUDIO_RING_BUFFER_SIZE - 1)
|
||||
// An alpha factor of 1/180 is *somewhat* equivalent
|
||||
// to calculating the average for the last 180
|
||||
// frames, or 3 seconds of runtime...
|
||||
#define AUDIO_FRAMES_MOVING_AVG_ALPHA (1.0f / 180.0f)
|
||||
|
||||
// Calculated swap interval is 'stable' if the same
|
||||
// value is recorded for a number of retro_run()
|
||||
// calls equal to VSYNC_SWAP_INTERVAL_FRAMES
|
||||
@ -104,10 +97,7 @@ namespace Libretro
|
||||
static retro_audio_sample_batch_t audio_batch_cb;
|
||||
static retro_input_poll_t input_poll_cb;
|
||||
static retro_input_state_t input_state_cb;
|
||||
} // namespace Libretro
|
||||
|
||||
namespace Libretro
|
||||
{
|
||||
static bool detectVsyncSwapInterval = false;
|
||||
static bool detectVsyncSwapIntervalOptShown = true;
|
||||
|
||||
@ -239,149 +229,6 @@ namespace Libretro
|
||||
}
|
||||
} // namespace Libretro
|
||||
|
||||
namespace Libretro
|
||||
{
|
||||
static std::mutex audioSampleLock_;
|
||||
static int16_t audioRingBuffer[AUDIO_RING_BUFFER_SIZE] = {0};
|
||||
static uint32_t audioRingBufferBase = 0;
|
||||
static uint32_t audioRingBufferIndex = 0;
|
||||
|
||||
static int16_t *audioOutBuffer = NULL;
|
||||
static uint32_t audioOutBufferSize = 0;
|
||||
static float audioOutFramesAvg = 0.0f;
|
||||
// Set this to an arbitrarily large value,
|
||||
// it will be fine tuned in AudioUploadSamples()
|
||||
static uint32_t audioBatchFramesMax = AUDIO_RING_BUFFER_SIZE >> 1;
|
||||
|
||||
static void AudioBufferFlush()
|
||||
{
|
||||
const std::lock_guard<std::mutex> lock(audioSampleLock_);
|
||||
audioRingBufferBase = 0;
|
||||
audioRingBufferIndex = 0;
|
||||
audioOutFramesAvg = (float)SAMPLERATE / (60.0f / 1.001f);
|
||||
}
|
||||
|
||||
static void AudioBufferInit()
|
||||
{
|
||||
audioOutFramesAvg = (float)SAMPLERATE / (60.0f / 1.001f);
|
||||
audioOutBufferSize = ((uint32_t)audioOutFramesAvg + 1) * 2;
|
||||
audioOutBuffer = (int16_t *)malloc(audioOutBufferSize * sizeof(int16_t));
|
||||
audioBatchFramesMax = AUDIO_RING_BUFFER_SIZE >> 1;
|
||||
|
||||
AudioBufferFlush();
|
||||
}
|
||||
|
||||
static void AudioBufferDeinit()
|
||||
{
|
||||
if (audioOutBuffer)
|
||||
free(audioOutBuffer);
|
||||
audioOutBuffer = NULL;
|
||||
audioOutBufferSize = 0;
|
||||
audioOutFramesAvg = 0.0f;
|
||||
audioBatchFramesMax = AUDIO_RING_BUFFER_SIZE >> 1;
|
||||
|
||||
AudioBufferFlush();
|
||||
}
|
||||
|
||||
static uint32_t AudioBufferOccupancy()
|
||||
{
|
||||
const std::lock_guard<std::mutex> lock(audioSampleLock_);
|
||||
uint32_t occupancy = (audioRingBufferIndex - audioRingBufferBase) &
|
||||
AUDIO_RING_BUFFER_SIZE_MASK;
|
||||
return occupancy >> 1;
|
||||
}
|
||||
|
||||
static void AudioBufferWrite(int16_t *audio, uint32_t frames)
|
||||
{
|
||||
const std::lock_guard<std::mutex> lock(audioSampleLock_);
|
||||
uint32_t frameIndex;
|
||||
uint32_t bufferIndex = audioRingBufferIndex;
|
||||
|
||||
for (frameIndex = 0; frameIndex < frames; frameIndex++)
|
||||
{
|
||||
audioRingBuffer[audioRingBufferIndex] = *(audio++);
|
||||
audioRingBuffer[audioRingBufferIndex + 1] = *(audio++);
|
||||
audioRingBufferIndex = (audioRingBufferIndex + 2) % AUDIO_RING_BUFFER_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t AudioBufferRead(int16_t *audio, uint32_t frames)
|
||||
{
|
||||
const std::lock_guard<std::mutex> lock(audioSampleLock_);
|
||||
uint32_t framesAvailable = ((audioRingBufferIndex - audioRingBufferBase) &
|
||||
AUDIO_RING_BUFFER_SIZE_MASK) >> 1;
|
||||
uint32_t frameIndex;
|
||||
|
||||
if (frames > framesAvailable)
|
||||
frames = framesAvailable;
|
||||
|
||||
for(frameIndex = 0; frameIndex < frames; frameIndex++)
|
||||
{
|
||||
uint32_t bufferIndex = (audioRingBufferBase + (frameIndex << 1)) &
|
||||
AUDIO_RING_BUFFER_SIZE_MASK;
|
||||
*(audio++) = audioRingBuffer[bufferIndex];
|
||||
*(audio++) = audioRingBuffer[bufferIndex + 1];
|
||||
}
|
||||
|
||||
audioRingBufferBase += frames << 1;
|
||||
audioRingBufferBase &= AUDIO_RING_BUFFER_SIZE_MASK;
|
||||
|
||||
return frames;
|
||||
}
|
||||
|
||||
static void AudioUploadSamples()
|
||||
{
|
||||
|
||||
// - If 'Detect Frame Rate Changes' is disabled, then
|
||||
// the core specifies a fixed frame rate of (60.0f / 1.001f)
|
||||
// - At the audio sample rate of 44100, this means the
|
||||
// frontend expects exactly 735.735 sample frames per call of
|
||||
// retro_run()
|
||||
// - If g_Config.bRenderDuplicateFrames is enabled and
|
||||
// frameskip is disabled, the mean of the buffer occupancy
|
||||
// willapproximate to this value in most cases
|
||||
uint32_t framesAvailable = AudioBufferOccupancy();
|
||||
|
||||
if (framesAvailable > 0)
|
||||
{
|
||||
// Update 'running average' of buffer occupancy.
|
||||
// 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).
|
||||
audioOutFramesAvg = (AUDIO_FRAMES_MOVING_AVG_ALPHA * (float)framesAvailable) +
|
||||
((1.0f - AUDIO_FRAMES_MOVING_AVG_ALPHA) * audioOutFramesAvg);
|
||||
uint32_t frames = (uint32_t)audioOutFramesAvg;
|
||||
|
||||
if (audioOutBufferSize < (frames << 1))
|
||||
{
|
||||
audioOutBufferSize = (frames << 1);
|
||||
audioOutBuffer = (int16_t *)realloc(audioOutBuffer,
|
||||
audioOutBufferSize * sizeof(int16_t));
|
||||
}
|
||||
|
||||
frames = AudioBufferRead(audioOutBuffer, frames);
|
||||
|
||||
int16_t *audioOutBufferPtr = audioOutBuffer;
|
||||
while (frames > 0)
|
||||
{
|
||||
uint32_t framesToWrite = (frames > audioBatchFramesMax) ?
|
||||
audioBatchFramesMax : frames;
|
||||
uint32_t framesWritten = audio_batch_cb(audioOutBufferPtr,
|
||||
framesToWrite);
|
||||
|
||||
if ((framesWritten < framesToWrite) &&
|
||||
(framesWritten > 0))
|
||||
audioBatchFramesMax = framesWritten;
|
||||
|
||||
frames -= framesToWrite;
|
||||
audioOutBufferPtr += framesToWrite << 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace Libretro
|
||||
|
||||
using namespace Libretro;
|
||||
|
||||
class PrintfLogger : public LogListener
|
||||
@ -1197,7 +1044,6 @@ void retro_set_input_state(retro_input_state_t cb) { input_state_cb = cb; }
|
||||
void retro_init(void)
|
||||
{
|
||||
VsyncSwapIntervalReset();
|
||||
AudioBufferInit();
|
||||
|
||||
g_threadManager.Init(cpu_info.num_cores, cpu_info.logical_cpu_count);
|
||||
|
||||
@ -1279,7 +1125,6 @@ void retro_deinit(void)
|
||||
libretro_supports_option_categories = false;
|
||||
|
||||
VsyncSwapIntervalReset();
|
||||
AudioBufferDeinit();
|
||||
}
|
||||
|
||||
void retro_set_controller_port_device(unsigned port, unsigned device)
|
||||
@ -1385,7 +1230,7 @@ namespace Libretro
|
||||
|
||||
// Need to keep eating frames to allow the EmuThread to exit correctly.
|
||||
while (ctx->ThreadFrame())
|
||||
AudioBufferFlush();
|
||||
;
|
||||
|
||||
emuThread.join();
|
||||
emuThread = std::thread();
|
||||
@ -1400,7 +1245,6 @@ namespace Libretro
|
||||
emuThreadState = EmuThreadState::PAUSE_REQUESTED;
|
||||
|
||||
ctx->ThreadFrame(); // Eat 1 frame
|
||||
AudioBufferFlush();
|
||||
|
||||
while (emuThreadState != EmuThreadState::PAUSED)
|
||||
sleep_ms(1);
|
||||
@ -1590,7 +1434,6 @@ void retro_run(void)
|
||||
emuThreadState == EmuThreadState::PAUSE_REQUESTED)
|
||||
{
|
||||
VsyncSwapIntervalDetect();
|
||||
AudioUploadSamples();
|
||||
ctx->SwapBuffers();
|
||||
return;
|
||||
}
|
||||
@ -1601,7 +1444,6 @@ void retro_run(void)
|
||||
if (!ctx->ThreadFrame())
|
||||
{
|
||||
VsyncSwapIntervalDetect();
|
||||
AudioUploadSamples();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1609,7 +1451,6 @@ void retro_run(void)
|
||||
EmuFrame();
|
||||
|
||||
VsyncSwapIntervalDetect();
|
||||
AudioUploadSamples();
|
||||
ctx->SwapBuffers();
|
||||
}
|
||||
|
||||
@ -1646,15 +1487,14 @@ bool retro_serialize(void *data, size_t size)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool retVal;
|
||||
SaveState::SaveStart state;
|
||||
// TODO: Libretro API extension to use the savestate queue
|
||||
if (useEmuThread)
|
||||
EmuThreadPause(); // Does nothing if already paused
|
||||
|
||||
size_t measuredSize;
|
||||
SaveState::SaveStart state;
|
||||
auto err = CChunkFileReader::MeasureAndSavePtr(state, (u8 **)&data, &measuredSize);
|
||||
retVal = err == CChunkFileReader::ERROR_NONE;
|
||||
bool retVal = err == CChunkFileReader::ERROR_NONE;
|
||||
|
||||
if (useEmuThread)
|
||||
{
|
||||
@ -1662,21 +1502,18 @@ bool retro_serialize(void *data, size_t size)
|
||||
sleep_ms(4);
|
||||
}
|
||||
|
||||
AudioBufferFlush();
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
bool retro_unserialize(const void *data, size_t size)
|
||||
{
|
||||
bool retVal;
|
||||
SaveState::SaveStart state;
|
||||
// TODO: Libretro API extension to use the savestate queue
|
||||
if (useEmuThread)
|
||||
EmuThreadPause(); // Does nothing if already paused
|
||||
|
||||
std::string errorString;
|
||||
retVal = CChunkFileReader::LoadPtr((u8 *)data, state, &errorString)
|
||||
SaveState::SaveStart state;
|
||||
bool retVal = CChunkFileReader::LoadPtr((u8 *)data, state, &errorString)
|
||||
== CChunkFileReader::ERROR_NONE;
|
||||
|
||||
if (useEmuThread)
|
||||
@ -1685,8 +1522,6 @@ bool retro_unserialize(const void *data, size_t size)
|
||||
sleep_ms(4);
|
||||
}
|
||||
|
||||
AudioBufferFlush();
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@ -1877,7 +1712,13 @@ void System_AudioPushSamples(const int32_t *audio, int numSamples) {
|
||||
buffer[i * 2] = Clamp16(audio[i * 2]);
|
||||
buffer[i * 2 + 1] = Clamp16(audio[i * 2 + 1]);
|
||||
}
|
||||
AudioBufferWrite(buffer, blockSize);
|
||||
|
||||
int framesToWrite = blockSize;
|
||||
uint32_t framesWritten = audio_batch_cb(buffer, framesToWrite);
|
||||
if (framesWritten != framesToWrite) {
|
||||
// Let's just stop, and eat any left-over samples.
|
||||
break;
|
||||
}
|
||||
numSamples -= blockSize;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user