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)