Added unfinished Wii U audio backend
Currently doesn't produce sound unless you stop Organya from calling AudioBackend_CreateSound, because it exhausts the Wii U's 150-sound pool before the SFX get any of them.
This commit is contained in:
parent
6bd4e89f9d
commit
a7ebdb75e5
3 changed files with 176 additions and 1 deletions
|
@ -18,7 +18,7 @@ option(DEBUG_SAVE "Re-enable the ability to drag-and-drop save files onto the wi
|
|||
option(BUILD_DOCONFIG "Compile a DoConfig clone tool - not useful for console ports" ON)
|
||||
|
||||
set(BACKEND_RENDERER "SDLTexture" CACHE STRING "Which renderer the game should use: 'OpenGL3' for an OpenGL 3.2 renderer, 'OpenGLES2' for an OpenGL ES 2.0 renderer, 'SDLTexture' for SDL2's hardware-accelerated Texture API, 'SDLSurface' for SDL2's software-rendered Surface API, or 'Software' for a handwritten software renderer")
|
||||
set(BACKEND_AUDIO "SDL2" CACHE STRING "Which audio backend the game should use: 'SDL2', 'miniaudio', or 'Null'")
|
||||
set(BACKEND_AUDIO "SDL2" CACHE STRING "Which audio backend the game should use: 'SDL2', 'miniaudio', 'WiiU', or 'Null'")
|
||||
set(BACKEND_PLATFORM "SDL2" CACHE STRING "Which platform backend the game should use: 'SDL2', 'GLFW3', 'WiiU', or 'Null'")
|
||||
|
||||
option(LTO "Enable link-time optimisation" OFF)
|
||||
|
@ -330,6 +330,10 @@ elseif(BACKEND_AUDIO MATCHES "miniaudio")
|
|||
endif()
|
||||
|
||||
target_link_libraries(CSE2 PRIVATE ${CMAKE_DL_LIBS})
|
||||
elseif(BACKEND_AUDIO MATCHES "WiiU")
|
||||
target_sources(CSE2 PRIVATE
|
||||
"src/Backends/Audio/WiiU.cpp"
|
||||
)
|
||||
elseif(BACKEND_AUDIO MATCHES "Null")
|
||||
target_sources(CSE2 PRIVATE
|
||||
"src/Backends/Audio/Null.cpp"
|
||||
|
|
|
@ -75,6 +75,7 @@ Name | Function
|
|||
`-DBACKEND_RENDERER=Software` | Use the handwritten software renderer
|
||||
`-DBACKEND_AUDIO=SDL2` | Use the SDL2-driven software audio-mixer
|
||||
`-DBACKEND_AUDIO=miniaudio` | Use the miniaudio-driven software audio-mixer
|
||||
`-DBACKEND_AUDIO=WiiU` | Use the hardware-accelerated audio backend for the Wii U
|
||||
`-DBACKEND_AUDIO=Null` | Use the dummy audio backend (doesn't produce any sound)
|
||||
`-DBACKEND_PLATFORM=SDL2` | Use SDL2 for windowing and OS-abstraction
|
||||
`-DBACKEND_PLATFORM=GLFW3` | Use GLFW3 for windowing and OS-abstraction
|
||||
|
|
170
src/Backends/Audio/WiiU.cpp
Normal file
170
src/Backends/Audio/WiiU.cpp
Normal file
|
@ -0,0 +1,170 @@
|
|||
#include "../Audio.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <coreinit/cache.h>
|
||||
|
||||
#include <sndcore2/core.h>
|
||||
#include <sndcore2/voice.h>
|
||||
#include <sndcore2/drcvs.h>
|
||||
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define CLAMP(x, y, z) MIN(MAX((x), (y)), (z))
|
||||
|
||||
struct AudioBackend_Sound
|
||||
{
|
||||
unsigned char *samples;
|
||||
AXVoice *voice;
|
||||
};
|
||||
|
||||
static double MillibelToScale(long volume)
|
||||
{
|
||||
// Volume is in hundredths of a decibel, from 0 to -10000
|
||||
volume = CLAMP(volume, -10000, 0);
|
||||
return pow(10.0, volume / 2000.0);
|
||||
}
|
||||
|
||||
bool AudioBackend_Init(void)
|
||||
{
|
||||
if (!AXIsInit())
|
||||
{
|
||||
static AXInitParams initparams =
|
||||
{
|
||||
.renderer = AX_INIT_RENDERER_48KHZ,
|
||||
.pipeline = AX_INIT_PIPELINE_SINGLE,
|
||||
};
|
||||
|
||||
AXInitWithParams(&initparams);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AudioBackend_Deinit(void)
|
||||
{
|
||||
AXQuit();
|
||||
}
|
||||
|
||||
AudioBackend_Sound* AudioBackend_CreateSound(unsigned int frequency, const unsigned char *samples, size_t length)
|
||||
{
|
||||
AudioBackend_Sound *sound = (AudioBackend_Sound*)malloc(sizeof(AudioBackend_Sound));
|
||||
|
||||
if (sound != NULL)
|
||||
{
|
||||
unsigned char *samples_copy = (unsigned char*)malloc(length);
|
||||
|
||||
if (samples_copy != NULL)
|
||||
{
|
||||
for (size_t i = 0; i < length; ++i)
|
||||
samples_copy[i] = samples[i] - 0x80;
|
||||
|
||||
DCStoreRange(samples_copy, length);
|
||||
|
||||
AXVoice *voice = AXAcquireVoice(31, NULL, NULL);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
free(sound);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void AudioBackend_DestroySound(AudioBackend_Sound *sound)
|
||||
{
|
||||
AXFreeVoice(sound->voice);
|
||||
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);
|
||||
}
|
||||
|
||||
void AudioBackend_StopSound(AudioBackend_Sound *sound)
|
||||
{
|
||||
AXSetVoiceState(sound->voice, AX_VOICE_STATE_STOPPED);
|
||||
AXSetVoiceCurrentOffset(sound->voice, 0);
|
||||
}
|
||||
|
||||
void AudioBackend_RewindSound(AudioBackend_Sound *sound)
|
||||
{
|
||||
AXSetVoiceCurrentOffset(sound->voice, 0);
|
||||
}
|
||||
|
||||
void AudioBackend_SetSoundFrequency(AudioBackend_Sound *sound, unsigned int frequency)
|
||||
{
|
||||
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)),
|
||||
};
|
||||
|
||||
AXSetVoiceVe(sound->voice, &vol);
|
||||
}
|
||||
|
||||
void AudioBackend_SetSoundPan(AudioBackend_Sound *sound, long pan)
|
||||
{
|
||||
static AXVoiceDeviceMixData mix_data[1][6];
|
||||
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]);
|
||||
}
|
||||
|
||||
void AudioBackend_SetOrganyaCallback(void (*callback)(void), unsigned int milliseconds)
|
||||
{
|
||||
(void)callback;
|
||||
(void)milliseconds;
|
||||
}
|
Loading…
Add table
Reference in a new issue