Fix the game using too many Wii U voices

Now it just allocates channels on-demand, rather than ahead-of-time.
This commit is contained in:
Clownacy 2020-04-16 22:42:33 +01:00
parent a7ebdb75e5
commit edc9299007

View file

@ -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 @@ AudioBackend_Sound* AudioBackend_CreateSound(unsigned int frequency, const unsig
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,41 +89,100 @@ AudioBackend_Sound* AudioBackend_CreateSound(unsigned int frequency, const unsig
void AudioBackend_DestroySound(AudioBackend_Sound *sound)
{
AXFreeVoice(sound->voice);
AudioBackend_StopSound(sound);
free(sound->samples);
free(sound);
}
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 @@ void AudioBackend_SetSoundPan(AudioBackend_Sound *sound, long pan)
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)