Skip to content

Linux: no audio output, games hang at boot (default audio API is DirectSound) #2033

Description

@smllb

Hi, i couldn't start the Zelda BOTW at all (it was freezing on the first screen), and sound was linked to the issue. I let DS4Flash running in loop till it fixed it locally, here's the resume if it helps:

Symptom

On Linux, Cemu logs the following during title boot and then hangs at the
loading screen:

can't initialize tv audio: failed to find selected device while trying to create audio device

No audio output is produced. This happens with any audio device selected
("default", a specific sink, etc.).

Root cause

  1. CemuConfig::audio_api defaults to 0
    (src/config/CemuConfig.h) and is loaded with the same fallback
    (src/config/CemuConfig.cpp: audio_api = audio.get("api", 0)).

  2. The AudioAPI enum (src/audio/IAudioAPI.h) is:

    enum AudioAPI
    {
        DirectSound = 0,
        XAudio27,
        XAudio2,
        Cubeb,
        AudioAPIEnd,
    };

    So audio_api = 0 selects DirectSound.

  3. DirectSound is a Windows-only backend. On non-Windows builds it is correctly
    not reported as available (src/audio/IAudioAPI.cpp, guarded by
    #if BOOST_OS_WINDOWS).

  4. In IAudioAPI::CreateDeviceFromConfig
    (src/audio/IAudioAPI.cpp), the device lookup is only performed when the
    configured API is available:

    if (IAudioAPI::IsAudioAPIAvailable(audio_api))
    {
        auto devices = IAudioAPI::GetDevices(audio_api);
        const auto it = std::find_if(devices.begin(), devices.end(),
            [&selectedDevice](const auto& d) { return d->GetIdentifier() == selectedDevice; });
        if (it != devices.end())
            device_description = *it;
    }
    if (!device_description)
        throw std::runtime_error("failed to find selected device while trying to create audio device");

    With audio_api = DirectSound (unavailable on Linux) the lookup is skipped
    entirely, device_description stays nullptr, and the function throws
    failed to find selected device ....

  5. The exception is caught and logged by the audio init path
    (src/Cafe/OS/libs/snd_core/ax_out.cpp), but no audio device / mixer is
    ever created. Games wait for their audio subsystem during boot, so they
    hang at the loading screen indefinitely.

Why the selected device name is irrelevant

Because the device lookup is skipped when the API is unavailable, every device
string fails identically (default, a real sink name, etc.). This is why
keys.txt, the GPU backend, and the audio device all appeared to be the
problem before the API selection was investigated.

Workaround (no rebuild)

In settings.xml, force the Cubeb backend:

<Audio>
    <api>3</api>
    <TVDevice>default</TVDevice>
</Audio>

(3 = Cubeb.) This is what makes audio work on Linux today.

The fix

  1. Default audio_api to Cubeb on non-Windows platforms.

    • src/config/CemuConfig.h — struct member default.
    • src/config/CemuConfig.cppaudio.get("api", ...) fallback.

    On Windows the default remains DirectSound.

  2. Fall back to an available audio API instead of failing.
    In IAudioAPI::CreateDeviceFromConfig, if the configured API is not
    available on this platform (e.g. a stale DirectSound value in an existing
    settings.xml), select the first available API instead of skipping the
    lookup and throwing.

  3. Run without audio instead of throwing when nothing usable exists.
    If no audio backend or device is available, return an empty device (silent
    audio) — matching the existing behavior of an unset output device — rather
    than throwing and letting the game hang at boot.

Files changed

  • src/config/CemuConfig.h
  • src/config/CemuConfig.cpp
  • src/audio/IAudioAPI.cpp

Testing

  • Linux (PipeWire + PulseAudio): game boots with audio, Cemu Cubeb stream
    visible in pactl list sink-inputs.
  • Linux with an existing settings.xml containing <api>0</api>: audio
    still works via the API fallback.
  • Windows: unchanged (DirectSound remains the default and is available).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions