ref: e470b915016f65ab4b13fce7035e490b82be5926
parent: a112001886c765812966655668b054a483ffb781
author: Clownacy <Clownacy@users.noreply.github.com>
date: Sun Apr 19 22:44:24 EDT 2020
Cleanup and documentation
--- a/src/Backends/Audio/WiiU-Software.cpp
+++ b/src/Backends/Audio/WiiU-Software.cpp
@@ -77,11 +77,14 @@
static void FrameCallback(void)
{
- // Just assume both voices are in-sync
+ // We use a double-buffer: while the Wii U is busy playing one half of the buffer, we update the other.
+ // The buffer is 10ms long in total, and this function runs every 3ms.
+
+ // Just assume both voices are in-sync, and only check the first one
AXVoiceOffsets offsets;
AXGetVoiceOffsets(voices[0], &offsets);
- unsigned int current_buffer = offsets.currentOffset > (buffer_length / 2) ? 1 : 0;
+ unsigned int current_buffer = offsets.currentOffset > (buffer_length / 2) ? 1 : 0; // TODO - should probably be '>='
static unsigned int last_buffer = 1;
@@ -91,8 +94,10 @@
for (unsigned int i = 0; i < buffer_length; ++i)
stream_buffer_float[i] = 0.0f;
+ // Fill mixer buffer
FillMixerBuffer(stream_buffer_float, buffer_length / 2);
+ // Deinterlate samples, convert them to S16, and write them to the double-buffers
short *left_output_buffer = &stream_buffers[0][(buffer_length / 2) * last_buffer];
short *right_output_buffer = &stream_buffers[1][(buffer_length / 2) * last_buffer];
@@ -116,11 +121,12 @@
else if (right_sample > 1.0f)
right_sample = 1.0f;
- // Deinterlate, and convert to S16
+ // Convert to S16 and store in double-buffers
*left_output_buffer_pointer++ = left_sample * 32767.0f;
*right_output_buffer_pointer++ = right_sample * 32767.0f;
}
+ // Make sure the sound hardware can see our data
DCStoreRange(left_output_buffer, buffer_length / 2 * sizeof(short));
DCStoreRange(right_output_buffer, buffer_length / 2 * sizeof(short));
@@ -149,8 +155,13 @@
buffer_length = output_frequency / 100; // 10ms buffer
- stream_buffer_float = (float*)malloc(buffer_length * sizeof(float) * 2);
+ // Create and initialise two 'voices': each one will stream its own
+ // audio - one for the left speaker, and one for the right.
+ // The software-mixer outputs interlaced float samples, so create
+ // a buffer for it here.
+ stream_buffer_float = (float*)malloc(buffer_length * sizeof(float) * 2); // TODO - should probably by divided by two
+
if (stream_buffer_float != NULL)
{
stream_buffers[0] = (short*)malloc(buffer_length * sizeof(short));
@@ -189,14 +200,14 @@
AXSetVoiceSrcRatio(voices[i], 1.0f); // We use the native sample rate
AXSetVoiceSrcType(voices[i], AX_VOICE_SRC_TYPE_NONE);
-
- AXVoiceOffsets offs;
- offs.dataType = AX_VOICE_FORMAT_LPCM16;
- offs.endOffset = buffer_length;
- offs.loopingEnabled = AX_VOICE_LOOP_ENABLED;
- offs.loopOffset = 0;
- offs.currentOffset = 0;
- offs.data = stream_buffers[i];
+ AXVoiceOffsets offs = {
+ .dataType = AX_VOICE_FORMAT_LPCM16,
+ .loopingEnabled = AX_VOICE_LOOP_ENABLED,
+ .loopOffset = 0,
+ .endOffset = buffer_length,
+ .currentOffset = 0,
+ .data = stream_buffers[i]
+ };
AXSetVoiceOffsets(voices[i], &offs);
AXSetVoiceState(voices[i], AX_VOICE_STATE_PLAYING);
@@ -204,6 +215,9 @@
AXVoiceEnd(voices[i]);
}
+ // Register the frame callback.
+ // Apparently, this fires every 3ms - we will use
+ // it to update the stream buffers when needed.
AXRegisterAppFrameCallback(FrameCallback);
return true;
--- a/src/Backends/WiiU/Window-Software-Polygon.cpp
+++ b/src/Backends/WiiU/Window-Software-Polygon.cpp
@@ -164,6 +164,7 @@
ATTRIBUTE_HOT void WindowBackend_Software_Display(void)
{
+ // Convert frame from RGB24 to RGBA32, and upload it to the GPU texture
unsigned char *framebuffer = (unsigned char*)GX2RLockSurfaceEx(&screen_texture.surface, 0, (GX2RResourceFlags)0);
const unsigned char *in_pointer = fake_framebuffer;
@@ -184,6 +185,7 @@
WHBGfxBeginRender();
+ // Draw to the TV
WHBGfxBeginRenderTV();
WHBGfxClearColor(0.0f, 0.0f, 0.0f, 1.0f);
GX2SetPixelTexture(&screen_texture, shader_group.pixelShader->samplerVars[0].location);
@@ -196,6 +198,7 @@
GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, 4, 0, 1);
WHBGfxFinishRenderTV();
+ // Draw to the gamepad
WHBGfxBeginRenderDRC();
WHBGfxClearColor(0.0f, 0.0f, 0.0f, 1.0f);
GX2SetPixelTexture(&screen_texture, shader_group.pixelShader->samplerVars[0].location);