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:
parent
a7ebdb75e5
commit
edc9299007
1 changed files with 90 additions and 55 deletions
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue