Cleanup and documentation

This commit is contained in:
Clownacy 2020-04-20 02:44:24 +01:00
parent a112001886
commit e470b91501
2 changed files with 29 additions and 12 deletions

View file

@ -77,11 +77,14 @@ static void FillMixerBuffer(float *stream, size_t frames_total)
static void FrameCallback(void) 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; AXVoiceOffsets offsets;
AXGetVoiceOffsets(voices[0], &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; static unsigned int last_buffer = 1;
@ -91,8 +94,10 @@ static void FrameCallback(void)
for (unsigned int i = 0; i < buffer_length; ++i) for (unsigned int i = 0; i < buffer_length; ++i)
stream_buffer_float[i] = 0.0f; stream_buffer_float[i] = 0.0f;
// Fill mixer buffer
FillMixerBuffer(stream_buffer_float, buffer_length / 2); 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 *left_output_buffer = &stream_buffers[0][(buffer_length / 2) * last_buffer];
short *right_output_buffer = &stream_buffers[1][(buffer_length / 2) * last_buffer]; short *right_output_buffer = &stream_buffers[1][(buffer_length / 2) * last_buffer];
@ -116,11 +121,12 @@ static void FrameCallback(void)
else if (right_sample > 1.0f) else if (right_sample > 1.0f)
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; *left_output_buffer_pointer++ = left_sample * 32767.0f;
*right_output_buffer_pointer++ = right_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(left_output_buffer, buffer_length / 2 * sizeof(short));
DCStoreRange(right_output_buffer, buffer_length / 2 * sizeof(short)); DCStoreRange(right_output_buffer, buffer_length / 2 * sizeof(short));
@ -149,7 +155,12 @@ bool AudioBackend_Init(void)
buffer_length = output_frequency / 100; // 10ms buffer 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) if (stream_buffer_float != NULL)
{ {
@ -189,14 +200,14 @@ bool AudioBackend_Init(void)
AXSetVoiceSrcRatio(voices[i], 1.0f); // We use the native sample rate AXSetVoiceSrcRatio(voices[i], 1.0f); // We use the native sample rate
AXSetVoiceSrcType(voices[i], AX_VOICE_SRC_TYPE_NONE); AXSetVoiceSrcType(voices[i], AX_VOICE_SRC_TYPE_NONE);
AXVoiceOffsets offs = {
AXVoiceOffsets offs; .dataType = AX_VOICE_FORMAT_LPCM16,
offs.dataType = AX_VOICE_FORMAT_LPCM16; .loopingEnabled = AX_VOICE_LOOP_ENABLED,
offs.endOffset = buffer_length; .loopOffset = 0,
offs.loopingEnabled = AX_VOICE_LOOP_ENABLED; .endOffset = buffer_length,
offs.loopOffset = 0; .currentOffset = 0,
offs.currentOffset = 0; .data = stream_buffers[i]
offs.data = stream_buffers[i]; };
AXSetVoiceOffsets(voices[i], &offs); AXSetVoiceOffsets(voices[i], &offs);
AXSetVoiceState(voices[i], AX_VOICE_STATE_PLAYING); AXSetVoiceState(voices[i], AX_VOICE_STATE_PLAYING);
@ -204,6 +215,9 @@ bool AudioBackend_Init(void)
AXVoiceEnd(voices[i]); 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); AXRegisterAppFrameCallback(FrameCallback);
return true; return true;

View file

@ -164,6 +164,7 @@ unsigned char* WindowBackend_Software_GetFramebuffer(size_t *pitch)
ATTRIBUTE_HOT void WindowBackend_Software_Display(void) 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); unsigned char *framebuffer = (unsigned char*)GX2RLockSurfaceEx(&screen_texture.surface, 0, (GX2RResourceFlags)0);
const unsigned char *in_pointer = fake_framebuffer; const unsigned char *in_pointer = fake_framebuffer;
@ -184,6 +185,7 @@ ATTRIBUTE_HOT void WindowBackend_Software_Display(void)
WHBGfxBeginRender(); WHBGfxBeginRender();
// Draw to the TV
WHBGfxBeginRenderTV(); WHBGfxBeginRenderTV();
WHBGfxClearColor(0.0f, 0.0f, 0.0f, 1.0f); WHBGfxClearColor(0.0f, 0.0f, 0.0f, 1.0f);
GX2SetPixelTexture(&screen_texture, shader_group.pixelShader->samplerVars[0].location); GX2SetPixelTexture(&screen_texture, shader_group.pixelShader->samplerVars[0].location);
@ -196,6 +198,7 @@ ATTRIBUTE_HOT void WindowBackend_Software_Display(void)
GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, 4, 0, 1); GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, 4, 0, 1);
WHBGfxFinishRenderTV(); WHBGfxFinishRenderTV();
// Draw to the gamepad
WHBGfxBeginRenderDRC(); WHBGfxBeginRenderDRC();
WHBGfxClearColor(0.0f, 0.0f, 0.0f, 1.0f); WHBGfxClearColor(0.0f, 0.0f, 0.0f, 1.0f);
GX2SetPixelTexture(&screen_texture, shader_group.pixelShader->samplerVars[0].location); GX2SetPixelTexture(&screen_texture, shader_group.pixelShader->samplerVars[0].location);