mirror of
https://github.com/jorio/Pomme.git
synced 2025-04-11 07:37:06 +00:00
Port sound mixer and input to SDL3
This commit is contained in:
parent
1acfd09704
commit
ced44f27ee
@ -120,16 +120,16 @@ endif()
|
||||
|
||||
add_library(${PROJECT_NAME} ${POMME_SOURCES})
|
||||
|
||||
find_package(SDL2 REQUIRED)
|
||||
# Input and SoundManager require SDL3.
|
||||
# Linking with SDL3 will also expose its include directory to us.
|
||||
if (NOT POMME_NO_INPUT OR NOT POMME_NO_SOUND_MIXER)
|
||||
find_package(SDL3 REQUIRED)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC SDL3::SDL3)
|
||||
endif()
|
||||
|
||||
add_compile_definitions(
|
||||
"$<$<CONFIG:DEBUG>:_DEBUG>"
|
||||
)
|
||||
add_compile_definitions("$<$<CONFIG:DEBUG>:_DEBUG>")
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
${SDL2_INCLUDE_DIRS}
|
||||
${POMME_SRCDIR}
|
||||
)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ${POMME_SRCDIR})
|
||||
|
||||
if(MSVC)
|
||||
# By default, MSVC may add /EHsc to CMAKE_CXX_FLAGS, which we don't want (we use /EHs below)
|
||||
|
@ -3,8 +3,8 @@
|
||||
#include "Pomme.h"
|
||||
#include "PommeInput.h"
|
||||
|
||||
#include <SDL_events.h>
|
||||
#include <SDL_keyboard.h>
|
||||
#include <SDL3/SDL_events.h>
|
||||
#include <SDL3/SDL_keyboard.h>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Input
|
||||
@ -157,7 +157,7 @@ void GetKeys(KeyMap km)
|
||||
|
||||
SDL_PumpEvents();
|
||||
int numkeys = 0;
|
||||
const UInt8* keystate = SDL_GetKeyboardState(&numkeys);
|
||||
const bool* keystate = SDL_GetKeyboardState(&numkeys);
|
||||
|
||||
numkeys = std::min((int) sizeof(scancodeLookupTable), numkeys);
|
||||
|
||||
@ -181,11 +181,11 @@ void GetKeys(KeyMap km)
|
||||
|
||||
void GetMouse(Point* mouseLoc)
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
float x;
|
||||
float y;
|
||||
SDL_GetMouseState(&x, &y);
|
||||
mouseLoc->h = x;
|
||||
mouseLoc->v = y;
|
||||
mouseLoc->h = (int) x;
|
||||
mouseLoc->v = (int) y;
|
||||
}
|
||||
|
||||
Boolean Button(void)
|
||||
@ -198,17 +198,17 @@ Boolean Button(void)
|
||||
|
||||
void InitCursor()
|
||||
{
|
||||
SDL_ShowCursor(1);
|
||||
SDL_ShowCursor();
|
||||
}
|
||||
|
||||
void HideCursor()
|
||||
{
|
||||
SDL_ShowCursor(0);
|
||||
SDL_HideCursor();
|
||||
}
|
||||
|
||||
void ShowCursor()
|
||||
{
|
||||
SDL_ShowCursor(1);
|
||||
SDL_ShowCursor();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -24,8 +24,9 @@
|
||||
|
||||
#include "cmixer.h"
|
||||
#include "Utilities/structpack.h"
|
||||
#include <SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <list>
|
||||
@ -50,16 +51,17 @@ using namespace cmixer;
|
||||
|
||||
static struct Mixer
|
||||
{
|
||||
SDL_mutex* sdlAudioMutex;
|
||||
SDL_Mutex* sdlAudioMutex;
|
||||
|
||||
std::list<Source*> sources; // Linked list of active (playing) sources
|
||||
int32_t pcmmixbuf[BUFFER_SIZE]; // Internal master buffer
|
||||
int16_t pcmclipbuf[BUFFER_SIZE]; // Internal clip buffer
|
||||
int samplerate; // Master samplerate
|
||||
int gain; // Master gain (fixed point)
|
||||
|
||||
void Init(int samplerate);
|
||||
|
||||
void Process(int16_t* dst, int len);
|
||||
void Process(SDL_AudioStream* stream, int len);
|
||||
|
||||
void Lock();
|
||||
|
||||
@ -74,39 +76,71 @@ static struct Mixer
|
||||
static bool sdlAudioSubSystemInited = false;
|
||||
static SDL_AudioDeviceID sdlDeviceID = 0;
|
||||
|
||||
static void SDLCALL AudioCallback(void *userData, SDL_AudioStream *stream, int additionalAmount, int totalAmount)
|
||||
{
|
||||
(void) totalAmount;
|
||||
(void) userData;
|
||||
|
||||
// Calculate a little more audio here, write it to `stream`
|
||||
if (additionalAmount > 0)
|
||||
{
|
||||
gMixer.Process(stream, additionalAmount / 2);
|
||||
}
|
||||
}
|
||||
|
||||
// SDL2 used to offer SDL_AUDIO_ALLOW_FREQUENCY_CHANGE to avoid crackles and
|
||||
// pops if the hardware doesn't work at the exact frequency we've asked for
|
||||
// (typically we'd ask for 44100 and get back 48000).
|
||||
// I couldn't find an equivalent to SDL_AUDIO_ALLOW_FREQUENCY_CHANGE in SDL3.
|
||||
// So, use this function before opening the audio device to query the hardware
|
||||
// for its preferred frequency (sample rate).
|
||||
static int GetHardwareFrequency(void)
|
||||
{
|
||||
SDL_AudioStream* stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, NULL, NULL, NULL);
|
||||
if (!stream)
|
||||
throw std::runtime_error(SDL_GetError());
|
||||
|
||||
SDL_AudioSpec spec;
|
||||
bool success = SDL_GetAudioStreamFormat(stream, NULL, &spec);
|
||||
if (!success)
|
||||
throw std::runtime_error(SDL_GetError());
|
||||
|
||||
sdlDeviceID = SDL_GetAudioStreamDevice(stream);
|
||||
if (!sdlDeviceID)
|
||||
throw std::runtime_error("invalid audio stream device");
|
||||
SDL_CloseAudioDevice(sdlDeviceID);
|
||||
|
||||
return spec.freq;
|
||||
}
|
||||
|
||||
void cmixer::InitWithSDL()
|
||||
{
|
||||
if (sdlAudioSubSystemInited)
|
||||
throw std::runtime_error("SDL audio subsystem already inited");
|
||||
|
||||
if (0 != SDL_InitSubSystem(SDL_INIT_AUDIO))
|
||||
if (!SDL_InitSubSystem(SDL_INIT_AUDIO))
|
||||
throw std::runtime_error("couldn't init SDL audio subsystem");
|
||||
|
||||
sdlAudioSubSystemInited = true;
|
||||
|
||||
// Init SDL audio
|
||||
SDL_AudioSpec fmt = {};
|
||||
fmt.freq = 44100;
|
||||
fmt.format = AUDIO_S16SYS;
|
||||
fmt.channels = 2;
|
||||
fmt.samples = 1024;
|
||||
fmt.callback = [](void* udata, Uint8* stream, int size)
|
||||
{
|
||||
(void) udata;
|
||||
gMixer.Process((int16_t*) stream, size / 2);
|
||||
};
|
||||
SDL_AudioSpec spec = {.format=SDL_AUDIO_S16, .channels=2, .freq=GetHardwareFrequency()};
|
||||
|
||||
SDL_AudioSpec got;
|
||||
sdlDeviceID = SDL_OpenAudioDevice(NULL, 0, &fmt, &got, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
||||
if (!sdlDeviceID)
|
||||
SDL_AudioStream* stream = SDL_OpenAudioDeviceStream(
|
||||
SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK,
|
||||
&spec,
|
||||
AudioCallback,
|
||||
nullptr);
|
||||
if (!stream)
|
||||
throw std::runtime_error(SDL_GetError());
|
||||
sdlDeviceID = SDL_GetAudioStreamDevice(stream);
|
||||
|
||||
// Init library
|
||||
gMixer.Init(got.freq);
|
||||
gMixer.Init(spec.freq);
|
||||
gMixer.SetMasterGain(0.5);
|
||||
|
||||
// Start audio
|
||||
SDL_PauseAudioDevice(sdlDeviceID, 0);
|
||||
SDL_ResumeAudioDevice(sdlDeviceID);
|
||||
}
|
||||
|
||||
void cmixer::ShutdownWithSDL()
|
||||
@ -166,13 +200,12 @@ void Mixer::SetMasterGain(double newGain)
|
||||
gain = (int) FX_FROM_FLOAT(newGain);
|
||||
}
|
||||
|
||||
void Mixer::Process(int16_t* dst, int len)
|
||||
void Mixer::Process(SDL_AudioStream* stream, int len)
|
||||
{
|
||||
// Process in chunks of BUFFER_SIZE if `len` is larger than BUFFER_SIZE
|
||||
while (len > BUFFER_SIZE)
|
||||
{
|
||||
Process(dst, BUFFER_SIZE);
|
||||
dst += BUFFER_SIZE;
|
||||
Process(stream, BUFFER_SIZE);
|
||||
len -= BUFFER_SIZE;
|
||||
}
|
||||
|
||||
@ -202,8 +235,11 @@ void Mixer::Process(int16_t* dst, int len)
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
int x = (pcmmixbuf[i] * gain) >> FX_BITS;
|
||||
dst[i] = CLAMP(x, -32768, 32767);
|
||||
pcmclipbuf[i] = CLAMP(x, -32768, 32767);
|
||||
}
|
||||
|
||||
// Feed SDL audio stream
|
||||
SDL_PutAudioStreamData(stream, pcmclipbuf, len * 2);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
Loading…
x
Reference in New Issue
Block a user