diff --git a/src/Backends/Audio/WiiU.cpp b/src/Backends/Audio/WiiU.cpp index 57f7f240..68fb4629 100644 --- 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 @@ 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)