shithub: cstory

Download patch

ref: edc9299007e124b184a1b68b23898b630a423a96
parent: a7ebdb75e5e120374c98e1a11bcb5bda427e952e
author: Clownacy <Clownacy@users.noreply.github.com>
date: Thu Apr 16 18:42:33 EDT 2020

Fix the game using too many Wii U voices

Now it just allocates channels on-demand, rather than ahead-of-time.

--- a/src/Backends/Audio/WiiU.cpp
+++ b/src/Backends/Audio/WiiU.cpp
@@ -18,7 +18,12 @@
 struct AudioBackend_Sound
 {
 	unsigned char *samples;
+	size_t length;
 	AXVoice *voice;
+	unsigned int frequency;
+	unsigned short volume;
+	unsigned short pan_l;
+	unsigned short pan_r;
 };
 
 static double MillibelToScale(long volume)
@@ -59,53 +64,21 @@
 
 		if (samples_copy != NULL)
 		{
+			// Convert to signed
 			for (size_t i = 0; i < length; ++i)
 				samples_copy[i] = samples[i] - 0x80;
 
 			DCStoreRange(samples_copy, length);
 
-			AXVoice *voice = AXAcquireVoice(31, NULL, NULL);
+			sound->samples = samples_copy;
+			sound->length = length;
+			sound->voice = NULL;
+			sound->frequency = frequency;
+			sound->volume = 0x8000;
+			sound->pan_l = 0x8000;
+			sound->pan_r = 0x8000;
 
-			if (voice != NULL)
-			{
-				AXVoiceOffsets offs;
-				AXVoiceVeData vol = {
-					.volume = 0x8000,
-				};
-
-				AXVoiceBegin(voice);
-
-				AXSetVoiceType(voice, 0);
-				AXSetVoiceVe(voice, &vol);
-
-				static AXVoiceDeviceMixData mix_data[1][6];
-				mix_data[0][0].bus[0].volume = 0x8000;
-				mix_data[0][1].bus[0].volume = 0x8000;
-
-				AXSetVoiceDeviceMix(voice, AX_DEVICE_TYPE_DRC, 0, mix_data[0]);
-				AXSetVoiceDeviceMix(voice, AX_DEVICE_TYPE_TV, 0, mix_data[0]);
-
-				float srcratio = (float)frequency / (float)AXGetInputSamplesPerSec();
-				AXSetVoiceSrcRatio(voice, srcratio);
-				AXSetVoiceSrcType(voice, AX_VOICE_SRC_TYPE_LINEAR);
-
-				offs.dataType = AX_VOICE_FORMAT_LPCM8;
-				offs.endOffset = length;
-				offs.loopingEnabled = AX_VOICE_LOOP_DISABLED;
-				offs.loopOffset = 0;
-				offs.currentOffset = 0;
-				offs.data = samples_copy;
-				AXSetVoiceOffsets(voice, &offs);
-
-				AXVoiceEnd(voice);
-
-				sound->samples = samples_copy;
-				sound->voice = voice;
-
-				return sound;
-			}
-
-			free(samples_copy);
+			return sound;
 		}
 
 		free(sound);
@@ -116,7 +89,8 @@
 
 void AudioBackend_DestroySound(AudioBackend_Sound *sound)
 {
-	AXFreeVoice(sound->voice);
+	AudioBackend_StopSound(sound);
+
 	free(sound->samples);
 	free(sound);
 }
@@ -123,34 +97,92 @@
 
 void AudioBackend_PlaySound(AudioBackend_Sound *sound, bool looping)
 {
-	AXSetVoiceLoop(sound->voice, looping ? AX_VOICE_LOOP_ENABLED : AX_VOICE_LOOP_DISABLED);
-	AXSetVoiceState(sound->voice, AX_VOICE_STATE_PLAYING);
+	if (sound->voice == NULL)
+	{
+		AXVoice *voice = AXAcquireVoice(31, NULL, NULL);
+
+		if (voice != NULL)
+		{
+			AXVoiceOffsets offs;
+			AXVoiceVeData vol = {
+				.volume = sound->volume,
+			};
+
+			AXVoiceBegin(voice);
+
+			AXSetVoiceType(voice, 0);
+			AXSetVoiceVe(voice, &vol);
+
+			static AXVoiceDeviceMixData mix_data[1][6];
+			mix_data[0][0].bus[0].volume = sound->pan_l;
+			mix_data[0][1].bus[0].volume = sound->pan_r;
+
+			AXSetVoiceDeviceMix(voice, AX_DEVICE_TYPE_DRC, 0, mix_data[0]);
+			AXSetVoiceDeviceMix(voice, AX_DEVICE_TYPE_TV, 0, mix_data[0]);
+
+			float srcratio = (float)sound->frequency / (float)AXGetInputSamplesPerSec();
+			AXSetVoiceSrcRatio(voice, srcratio);
+			AXSetVoiceSrcType(voice, AX_VOICE_SRC_TYPE_LINEAR);
+
+			offs.dataType = AX_VOICE_FORMAT_LPCM8;
+			offs.endOffset = sound->length;
+			offs.loopingEnabled = AX_VOICE_LOOP_DISABLED;
+			offs.loopOffset = 0;
+			offs.currentOffset = 0;
+			offs.data = sound->samples;
+			AXSetVoiceOffsets(voice, &offs);
+
+			AXVoiceEnd(voice);
+
+			sound->voice = voice;
+		}
+	}
+
+	if (sound->voice != NULL)
+	{
+		AXSetVoiceLoop(sound->voice, looping ? AX_VOICE_LOOP_ENABLED : AX_VOICE_LOOP_DISABLED);
+		AXSetVoiceState(sound->voice, AX_VOICE_STATE_PLAYING);
+	}
 }
 
 void AudioBackend_StopSound(AudioBackend_Sound *sound)
 {
-	AXSetVoiceState(sound->voice, AX_VOICE_STATE_STOPPED);
-	AXSetVoiceCurrentOffset(sound->voice, 0);
+	if (sound->voice != NULL)
+	{
+		AXFreeVoice(sound->voice);
+		sound->voice = NULL;
+	}
 }
 
 void AudioBackend_RewindSound(AudioBackend_Sound *sound)
 {
-	AXSetVoiceCurrentOffset(sound->voice, 0);
+	if (sound->voice != NULL)
+		AXSetVoiceCurrentOffset(sound->voice, 0);
 }
 
 void AudioBackend_SetSoundFrequency(AudioBackend_Sound *sound, unsigned int frequency)
 {
-	float srcratio = (float)frequency / (float)AXGetInputSamplesPerSec();
-	AXSetVoiceSrcRatio(sound->voice, srcratio);
+	sound->frequency = frequency;
+
+	if (sound->voice != NULL)
+	{
+		float srcratio = (float)frequency / (float)AXGetInputSamplesPerSec();
+		AXSetVoiceSrcRatio(sound->voice, srcratio);
+	}
 }
 
 void AudioBackend_SetSoundVolume(AudioBackend_Sound *sound, long volume)
 {
-	AXVoiceVeData vol = {
-		.volume = (unsigned short)(0x8000 * MillibelToScale(volume)),
-	};
+	sound->volume = (unsigned short)(0x8000 * MillibelToScale(volume));
 
-	AXSetVoiceVe(sound->voice, &vol);
+	if (sound->voice != NULL)
+	{
+		AXVoiceVeData vol = {
+			.volume = sound->volume,
+		};
+
+		AXSetVoiceVe(sound->voice, &vol);
+	}
 }
 
 void AudioBackend_SetSoundPan(AudioBackend_Sound *sound, long pan)
@@ -159,8 +191,11 @@
 	mix_data[0][0].bus[0].volume = (unsigned short)(0x8000 * MillibelToScale(-pan));
 	mix_data[0][1].bus[0].volume = (unsigned short)(0x8000 * MillibelToScale(pan));
 
-	AXSetVoiceDeviceMix(sound->voice, AX_DEVICE_TYPE_DRC, 0, mix_data[0]);
-	AXSetVoiceDeviceMix(sound->voice, AX_DEVICE_TYPE_TV, 0, mix_data[0]);
+	if (sound->voice != NULL)
+	{
+		AXSetVoiceDeviceMix(sound->voice, AX_DEVICE_TYPE_DRC, 0, mix_data[0]);
+		AXSetVoiceDeviceMix(sound->voice, AX_DEVICE_TYPE_TV, 0, mix_data[0]);
+	}
 }
 
 void AudioBackend_SetOrganyaCallback(void (*callback)(void), unsigned int milliseconds)