[APU] Add ALSA apu on Linux

This commit is contained in:
Herman S.
2025-09-27 18:38:27 +09:00
parent 48c13be2d5
commit fade0cd889
9 changed files with 929 additions and 6 deletions

View File

@@ -0,0 +1,94 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2025. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/apu/alsa/alsa_audio_system.h"
#include <alsa/asoundlib.h>
#include "xenia/apu/alsa/alsa_audio_driver.h"
#include "xenia/apu/apu_flags.h"
#include "xenia/base/logging.h"
namespace xe {
namespace apu {
namespace alsa {
ALSAAudioSystem::ALSAAudioSystem(cpu::Processor* processor)
: AudioSystem(processor) {}
ALSAAudioSystem::~ALSAAudioSystem() {}
bool ALSAAudioSystem::IsAvailable() {
// Check if ALSA is available by trying to open a dummy PCM device
snd_pcm_t* pcm = nullptr;
int err =
snd_pcm_open(&pcm, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
if (err >= 0 && pcm) {
snd_pcm_close(pcm);
return true;
}
return false;
}
void ALSAAudioSystem::Initialize() {}
std::unique_ptr<AudioSystem> ALSAAudioSystem::Create(
cpu::Processor* processor) {
if (!IsAvailable()) {
XELOGE("ALSA is not available on this system");
return nullptr;
}
return std::make_unique<ALSAAudioSystem>(processor);
}
X_RESULT ALSAAudioSystem::CreateDriver(size_t index,
xe::threading::Semaphore* semaphore,
AudioDriver** out_driver) {
assert_not_null(out_driver);
XELOGI("ALSAAudioSystem::CreateDriver for client index {}", index);
// Create a new driver for each client
// ALSA's dmix plugin should handle mixing multiple streams
auto driver = new ALSAAudioDriver(semaphore);
if (!driver->Initialize()) {
XELOGE("Failed to initialize ALSA driver for client index {}", index);
delete driver;
*out_driver = nullptr;
return X_ERROR_NOT_FOUND;
}
*out_driver = driver;
XELOGI("Successfully created ALSA driver for client index {}", index);
return X_ERROR_SUCCESS;
}
AudioDriver* ALSAAudioSystem::CreateDriver(xe::threading::Semaphore* semaphore,
uint32_t frequency,
uint32_t channels,
bool need_format_conversion) {
auto driver = new ALSAAudioDriver(semaphore, frequency, channels,
need_format_conversion);
if (!driver->Initialize()) {
delete driver;
return nullptr;
}
return driver;
}
void ALSAAudioSystem::DestroyDriver(AudioDriver* driver) {
assert_not_null(driver);
ALSAAudioDriver* alsa_driver = static_cast<ALSAAudioDriver*>(driver);
alsa_driver->Shutdown();
delete alsa_driver;
}
} // namespace alsa
} // namespace apu
} // namespace xe