Permalink
Browse files

PSP2: Fix RingFIFO misuse causing bad audio

  • Loading branch information...
endrift committed Jan 29, 2018
1 parent 4a3c942 commit c657255009d8a3143e1a2ecd390f9f895374f60c
Showing with 56 additions and 44 deletions.
  1. +1 −0 CHANGES
  2. +1 −1 src/platform/psp2/main.c
  3. +54 −43 src/platform/psp2/psp2-context.c
View
@@ -44,6 +44,7 @@ Bugfixes:
- Core: Fix ROM patches not being unloaded when disabled (fixes mgba.io/i/962)
- GBA I/O: Fix writing to DISPCNT CGB flag (fixes mgba.io/i/902)
- GBA Memory: Partially revert prefetch changes (fixes mgba.io/i/840)
+ - PSP2: Fix issues causing poor audio
Misc:
- GBA Timer: Use global cycles for timers
- GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722)
View
@@ -153,7 +153,7 @@ int main() {
.teardown = mPSP2Teardown,
.gameLoaded = mPSP2LoadROM,
.gameUnloaded = mPSP2UnloadROM,
- .prepareForFrame = mPSP2PrepareForFrame,
+ .prepareForFrame = NULL,
.drawFrame = mPSP2Draw,
.drawScreenshot = mPSP2DrawScreenshot,
.paused = mPSP2Paused,
@@ -21,7 +21,6 @@
#include <mgba-util/memory.h>
#include <mgba-util/circle-buffer.h>
#include <mgba-util/math.h>
-#include <mgba-util/ring-fifo.h>
#include <mgba-util/threading.h>
#include <mgba-util/vfs.h>
#include <mgba-util/platform/psp2/sce-vfs.h>
@@ -71,16 +70,20 @@ static struct mSceImageSource {
size_t bufferOffset;
} camera;
+static struct mAVStream stream;
+
bool frameLimiter = true;
extern const uint8_t _binary_backdrop_png_start[];
static vita2d_texture* backdrop = 0;
-#define PSP2_SAMPLES 256
-#define PSP2_AUDIO_BUFFER_SIZE (PSP2_SAMPLES * 20)
+#define PSP2_SAMPLES 512
+#define PSP2_AUDIO_BUFFER_SIZE (PSP2_SAMPLES * 16)
static struct mPSP2AudioContext {
- struct RingFIFO buffer;
+ struct GBAStereoSample buffer[PSP2_AUDIO_BUFFER_SIZE];
+ size_t writeOffset;
+ size_t readOffset;
size_t samples;
Mutex mutex;
Condition cond;
@@ -93,26 +96,25 @@ void mPSP2MapKey(struct mInputMap* map, int pspKey, int key) {
static THREAD_ENTRY _audioThread(void* context) {
struct mPSP2AudioContext* audio = (struct mPSP2AudioContext*) context;
+ uint32_t zeroBuffer[PSP2_SAMPLES] = {0};
int audioPort = sceAudioOutOpenPort(SCE_AUDIO_OUT_PORT_TYPE_MAIN, PSP2_SAMPLES, 48000, SCE_AUDIO_OUT_MODE_STEREO);
while (audio->running) {
MutexLock(&audio->mutex);
- int len = audio->samples;
- if (len > PSP2_SAMPLES) {
- len = PSP2_SAMPLES;
+ void* buffer;
+ if (audio->samples >= PSP2_SAMPLES) {
+ buffer = &audio->buffer[audio->readOffset];
+ audio->samples -= PSP2_SAMPLES;
+ audio->readOffset += PSP2_SAMPLES;
+ if (audio->readOffset >= PSP2_AUDIO_BUFFER_SIZE) {
+ audio->readOffset = 0;
+ }
+ ConditionWake(&audio->cond);
+ } else {
+ buffer = zeroBuffer;
}
- struct GBAStereoSample* buffer = audio->buffer.readPtr;
- RingFIFORead(&audio->buffer, NULL, len * 4);
- audio->samples -= len;
- ConditionWake(&audio->cond);
-
MutexUnlock(&audio->mutex);
- sceAudioOutOutput(audioPort, buffer);
- MutexLock(&audio->mutex);
- if (audio->samples < PSP2_SAMPLES) {
- ConditionWait(&audio->cond, &audio->mutex);
- }
- MutexUnlock(&audio->mutex);
+ sceAudioOutOutput(audioPort, buffer);
}
sceAudioOutReleasePort(audioPort);
return 0;
@@ -229,6 +231,29 @@ static void _requestImage(struct mImageSource* source, const void** buffer, size
sceCameraRead(imageSource->cam - 1, &read);
}
+static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* right) {
+ UNUSED(stream);
+ MutexLock(&audioContext.mutex);
+ struct GBAStereoSample* samples = &audioContext.buffer[audioContext.writeOffset];
+ while (audioContext.samples == PSP2_AUDIO_BUFFER_SIZE) {
+ if (!frameLimiter) {
+ blip_clear(left);
+ blip_clear(right);
+ MutexUnlock(&audioContext.mutex);
+ return;
+ }
+ ConditionWait(&audioContext.cond, &audioContext.mutex);
+ }
+ blip_read_samples(left, &samples[0].left, PSP2_SAMPLES, true);
+ blip_read_samples(right, &samples[0].right, PSP2_SAMPLES, true);
+ audioContext.samples += PSP2_SAMPLES;
+ audioContext.writeOffset += PSP2_SAMPLES;
+ if (audioContext.writeOffset >= PSP2_AUDIO_BUFFER_SIZE) {
+ audioContext.writeOffset = 0;
+ }
+ MutexUnlock(&audioContext.mutex);
+}
+
uint16_t mPSP2PollInput(struct mGUIRunner* runner) {
SceCtrlData pad;
sceCtrlPeekBufferPositive(0, &pad, 1);
@@ -285,6 +310,7 @@ void mPSP2Setup(struct mGUIRunner* runner) {
outputBuffer = vita2d_texture_get_datap(tex);
runner->core->setVideoBuffer(runner->core, outputBuffer, 256);
+ runner->core->setAudioBufferSize(runner->core, PSP2_SAMPLES);
rotation.d.sample = _sampleRotation;
rotation.d.readTiltX = _readTiltX;
@@ -303,6 +329,13 @@ void mPSP2Setup(struct mGUIRunner* runner) {
camera.cam = 1;
runner->core->setPeripheral(runner->core, mPERIPH_IMAGE_SOURCE, &camera.d);
+
+ stream.videoDimensionsChanged = NULL;
+ stream.postAudioFrame = NULL;
+ stream.postAudioBuffer = _postAudioBuffer;
+ stream.postVideoFrame = NULL;
+ runner->core->setAVStream(runner->core, &stream);
+
frameLimiter = true;
backdrop = vita2d_load_PNG_buffer(_binary_backdrop_png_start);
@@ -341,37 +374,15 @@ void mPSP2LoadROM(struct mGUIRunner* runner) {
break;
}
- RingFIFOInit(&audioContext.buffer, PSP2_AUDIO_BUFFER_SIZE * sizeof(struct GBAStereoSample));
MutexInit(&audioContext.mutex);
ConditionInit(&audioContext.cond);
+ memset(audioContext.buffer, 0, sizeof(audioContext.buffer));
+ audioContext.readOffset = 0;
+ audioContext.writeOffset = 0;
audioContext.running = true;
ThreadCreate(&audioThread, _audioThread, &audioContext);
}
-void mPSP2PrepareForFrame(struct mGUIRunner* runner) {
- int nSamples = 0;
- while (blip_samples_avail(runner->core->getAudioChannel(runner->core, 0)) >= PSP2_SAMPLES) {
- struct GBAStereoSample* samples = audioContext.buffer.writePtr;
- if (nSamples > (PSP2_AUDIO_BUFFER_SIZE >> 2) + (PSP2_AUDIO_BUFFER_SIZE >> 1)) { // * 0.75
- if (!frameLimiter) {
- blip_clear(runner->core->getAudioChannel(runner->core, 0));
- blip_clear(runner->core->getAudioChannel(runner->core, 1));
- break;
- }
- }
- blip_read_samples(runner->core->getAudioChannel(runner->core, 0), &samples[0].left, PSP2_SAMPLES, true);
- blip_read_samples(runner->core->getAudioChannel(runner->core, 1), &samples[0].right, PSP2_SAMPLES, true);
- while (!RingFIFOWrite(&audioContext.buffer, NULL, PSP2_SAMPLES * 4)) {
- ConditionWake(&audioContext.cond);
- // Spinloooooooop!
- }
- MutexLock(&audioContext.mutex);
- audioContext.samples += PSP2_SAMPLES;
- nSamples = audioContext.samples;
- ConditionWake(&audioContext.cond);
- MutexUnlock(&audioContext.mutex);
- }
-}
void mPSP2UnloadROM(struct mGUIRunner* runner) {
switch (runner->core->platform(runner->core)) {

0 comments on commit c657255

Please sign in to comment.