code:
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "core/hle/service/cmif_types.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/service.h"

namespace Core {
class System;
}

namespace Kernel {
class KEvent;
}

namespace Service::AOC {

class IPurchaseEventManager;

class IAddOnContentManager final : public ServiceFramework<IAddOnContentManager> {
public:
    explicit IAddOnContentManager(Core::System& system);
    ~IAddOnContentManager() override;

    Result CountAddOnContent(Out<u32> out_count, ClientProcessId process_id);
    Result ListAddOnContent(Out<u32> out_count, OutBuffer<BufferAttr_HipcMapAlias> out_addons,
                            u32 offset, u32 count, ClientProcessId process_id);
    Result GetAddOnContentBaseId(Out<u64> out_title_id, ClientProcessId process_id);
    Result PrepareAddOnContent(s32 addon_index, ClientProcessId process_id);
    Result GetAddOnContentListChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
    Result GetAddOnContentListChangedEventWithProcessId(
        OutCopyHandle<Kernel::KReadableEvent> out_event, ClientProcessId process_id);
    Result NotifyMountAddOnContent();
    Result NotifyUnmountAddOnContent();
    Result CheckAddOnContentMountStatus();
    Result CreateEcPurchasedEventManager(OutInterface<IPurchaseEventManager> out_interface);
    Result CreatePermanentEcPurchasedEventManager(
        OutInterface<IPurchaseEventManager> out_interface);

private:
    std::vector<u64> add_on_content;
    KernelHelpers::ServiceContext service_context;

    Kernel::KEvent* aoc_change_event;
};

void LoopProcess(Core::System& system);

} // namespace Service::AOC


code:
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "core/hle/service/aoc/purchase_event_manager.h"
#include "core/hle/service/cmif_serialization.h"

namespace Service::AOC {

constexpr Result ResultNoPurchasedProductInfoAvailable{ErrorModule::NIMShop, 400};

IPurchaseEventManager::IPurchaseEventManager(Core::System& system_)
    : ServiceFramework{system_, "IPurchaseEventManager"}, service_context{system,
                                                                          "IPurchaseEventManager"} {
    // clang-format off
        static const FunctionInfo functions[] = {
            {0, D<&IPurchaseEventManager::SetDefaultDeliveryTarget>, "SetDefaultDeliveryTarget"},
            {1, D<&IPurchaseEventManager::SetDeliveryTarget>, "SetDeliveryTarget"},
            {2, D<&IPurchaseEventManager::GetPurchasedEvent>, "GetPurchasedEvent"},
            {3, D<&IPurchaseEventManager::PopPurchasedProductInfo>, "PopPurchasedProductInfo"},
            {4, D<&IPurchaseEventManager::PopPurchasedProductInfoWithUid>, "PopPurchasedProductInfoWithUid"},
        };
    // clang-format on

    RegisterHandlers(functions);

    purchased_event = service_context.CreateEvent("IPurchaseEventManager:PurchasedEvent");
}

IPurchaseEventManager::~IPurchaseEventManager() {
    service_context.CloseEvent(purchased_event);
}

Result IPurchaseEventManager::SetDefaultDeliveryTarget(
    ClientProcessId process_id, InBuffer<BufferAttr_HipcMapAlias> in_buffer) {
    LOG_WARNING(Service_AOC, "(STUBBED) called, process_id={}", process_id.pid);

    R_SUCCEED();
}

Result IPurchaseEventManager::SetDeliveryTarget(u64 unknown,
                                                InBuffer<BufferAttr_HipcMapAlias> in_buffer) {
    LOG_WARNING(Service_AOC, "(STUBBED) called, unknown={}", unknown);

    R_SUCCEED();
}

Result IPurchaseEventManager::GetPurchasedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
    LOG_WARNING(Service_AOC, "called");

    *out_event = &purchased_event->GetReadableEvent();

    R_SUCCEED();
}

Result IPurchaseEventManager::PopPurchasedProductInfo() {
    LOG_DEBUG(Service_AOC, "(STUBBED) called");

    R_RETURN(ResultNoPurchasedProductInfoAvailable);
}

Result IPurchaseEventManager::PopPurchasedProductInfoWithUid() {
    LOG_DEBUG(Service_AOC, "(STUBBED) called");

    R_RETURN(ResultNoPurchasedProductInfoAvailable);
}

} // namespace Service::AOC

repo_name: litucks/torzu

license: mit


code:
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "core/hle/service/cmif_types.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/os/event.h"
#include "core/hle/service/service.h"

namespace Service::AOC {

class IPurchaseEventManager final : public ServiceFramework<IPurchaseEventManager> {
public:
    explicit IPurchaseEventManager(Core::System& system_);
    ~IPurchaseEventManager() override;

    Result SetDefaultDeliveryTarget(ClientProcessId process_id,
                                    InBuffer<BufferAttr_HipcMapAlias> in_buffer);
    Result SetDeliveryTarget(u64 unknown, InBuffer<BufferAttr_HipcMapAlias> in_buffer);
    Result GetPurchasedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
    Result PopPurchasedProductInfo();
    Result PopPurchasedProductInfoWithUid();

private:
    KernelHelpers::ServiceContext service_context;
    Kernel::KEvent* purchased_event;
};

} // namespace Service::AOC


code:
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "core/core.h"
#include "core/hle/service/apm/apm.h"
#include "core/hle/service/apm/apm_interface.h"
#include "core/hle/service/server_manager.h"

namespace Service::APM {

Module::Module() = default;
Module::~Module() = default;

void LoopProcess(Core::System& system) {
    auto module = std::make_shared<Module>();
    auto server_manager = std::make_unique<ServerManager>(system);

    server_manager->RegisterNamedService(
        "apm", std::make_shared<APM>(system, module, system.GetAPMController(), "apm"));
    server_manager->RegisterNamedService(
        "apm:am", std::make_shared<APM>(system, module, system.GetAPMController(), "apm:am"));
    server_manager->RegisterNamedService(
        "apm:sys", std::make_shared<APM_Sys>(system, system.GetAPMController()));
    ServerManager::RunServer(std::move(server_manager));
}

} // namespace Service::APM


code:
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

namespace Core {
class System;
}

namespace Service::APM {

class Module final {
public:
    Module();
    ~Module();
};

void LoopProcess(Core::System& system);

} // namespace Service::APM


code:
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include <algorithm>
#include <array>
#include <utility>

#include "common/logging/log.h"
#include "common/settings.h"
#include "common/settings_enums.h"
#include "core/core_timing.h"
#include "core/hle/service/apm/apm_controller.h"

namespace Service::APM {

constexpr auto DEFAULT_PERFORMANCE_CONFIGURATION = PerformanceConfiguration::Config7;

Controller::Controller(Core::Timing::CoreTiming& core_timing_)
    : core_timing{core_timing_}, configs{
                                     {PerformanceMode::Normal, DEFAULT_PERFORMANCE_CONFIGURATION},
                                     {PerformanceMode::Boost, DEFAULT_PERFORMANCE_CONFIGURATION},
                                 } {}

Controller::~Controller() = default;

void Controller::SetPerformanceConfiguration(PerformanceMode mode,
                                             PerformanceConfiguration config) {
    static constexpr std::array<std::pair<PerformanceConfiguration, u32>, 16> config_to_speed{{
        {PerformanceConfiguration::Config1, 1020},
        {PerformanceConfiguration::Config2, 1020},
        {PerformanceConfiguration::Config3, 1224},
        {PerformanceConfiguration::Config4, 1020},
        {PerformanceConfiguration::Config5, 1020},
        {PerformanceConfiguration::Config6, 1224},
        {PerformanceConfiguration::Config7, 1020},
        {PerformanceConfiguration::Config8, 1020},
        {PerformanceConfiguration::Config9, 1020},
        {PerformanceConfiguration::Config10, 1020},
        {PerformanceConfiguration::Config11, 1020},
        {PerformanceConfiguration::Config12, 1020},
        {PerformanceConfiguration::Config13, 1785},
        {PerformanceConfiguration::Config14, 1785},
        {PerformanceConfiguration::Config15, 1020},
        {PerformanceConfiguration::Config16, 1020},
    }};

    const auto iter = std::find_if(config_to_speed.cbegin(), config_to_speed.cend(),
                                   [config](const auto& entry) { return entry.first == config; });

    if (iter == config_to_speed.cend()) {
        LOG_ERROR(Service_APM, "Invalid performance configuration value provided: {}", config);
        return;
    }

    SetClockSpeed(iter->second);
    configs.insert_or_assign(mode, config);
}

void Controller::SetFromCpuBoostMode(CpuBoostMode mode) {
    static constexpr std::array<PerformanceConfiguration, 3> BOOST_MODE_TO_CONFIG_MAP{{
        PerformanceConfiguration::Config7,
        PerformanceConfiguration::Config13,
        PerformanceConfiguration::Config15,
    }};

    SetPerformanceConfiguration(PerformanceMode::Boost,
                                BOOST_MODE_TO_CONFIG_MAP.at(static_cast<u32>(mode)));
}

PerformanceMode Controller::GetCurrentPerformanceMode() const {
    return Settings::IsDockedMode() ? PerformanceMode::Boost : PerformanceMode::Normal;
}

PerformanceConfiguration Controller::GetCurrentPerformanceConfiguration(PerformanceMode mode) {
    if (configs.find(mode) == configs.end()) {
        configs.insert_or_assign(mode, DEFAULT_PERFORMANCE_CONFIGURATION);
    }

    return configs[mode];
}

void Controller::SetClockSpeed(u32 mhz) {
    LOG_DEBUG(Service_APM, "called, mhz={:08X}", mhz);
    // TODO(DarkLordZach): Actually signal core_timing to change clock speed.
    // TODO(Rodrigo): Remove [[maybe_unused]] when core_timing is used.
}

} // namespace Service::APM


code:
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <map>
#include "common/common_types.h"

namespace Core::Timing {
class CoreTiming;
}

namespace Service::APM {

enum class PerformanceConfiguration : u32 {
    Config1 = 0x00010000,
    Config2 = 0x00010001,
    Config3 = 0x00010002,
    Config4 = 0x00020000,
    Config5 = 0x00020001,
    Config6 = 0x00020002,
    Config7 = 0x00020003,
    Config8 = 0x00020004,
    Config9 = 0x00020005,
    Config10 = 0x00020006,
    Config11 = 0x92220007,
    Config12 = 0x92220008,
    Config13 = 0x92220009,
    Config14 = 0x9222000A,
    Config15 = 0x9222000B,
    Config16 = 0x9222000C,
};

// This is nn::oe::CpuBoostMode
enum class CpuBoostMode : u32 {
    Normal = 0,   // Boost mode disabled
    FastLoad = 1, // CPU + GPU -> Config 13, 14, 15, or 16
    Partial = 2,  // GPU Only -> Config 15 or 16
};

// This is nn::oe::PerformanceMode
enum class PerformanceMode : s32 {
    Invalid = -1,
    Normal = 0,
    Boost = 1,
};

// Class to manage the state and change of the emulated system performance.
// Specifically, this deals with PerformanceMode, which corresponds to the system being docked or
// undocked, and PerformanceConfig which specifies the exact CPU, GPU, and Memory clocks to operate
// at. Additionally, this manages 'Boost Mode', which allows games to temporarily overclock the
// system during times of high load -- this simply maps to different PerformanceConfigs to use.
class Controller {
public:
    explicit Controller(Core::Timing::CoreTiming& core_timing_);
    ~Controller();

    void SetPerformanceConfiguration(PerformanceMode mode, PerformanceConfiguration config);
    void SetFromCpuBoostMode(CpuBoostMode mode);

    PerformanceMode GetCurrentPerformanceMode() const;
    PerformanceConfiguration GetCurrentPerformanceConfiguration(PerformanceMode mode);

private:
    void SetClockSpeed(u32 mhz);

    [[maybe_unused]] Core::Timing::CoreTiming& core_timing;

    std::map<PerformanceMode, PerformanceConfiguration> configs;
};

} // namespace Service::APM


code:
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "common/logging/log.h"
#include "core/hle/service/apm/apm.h"
#include "core/hle/service/apm/apm_controller.h"
#include "core/hle/service/apm/apm_interface.h"
#include "core/hle/service/ipc_helpers.h"

namespace Service::APM {

class ISession final : public ServiceFramework<ISession> {
public:
    explicit ISession(Core::System& system_, Controller& controller_)
        : ServiceFramework{system_, "ISession"}, controller{controller_} {
        static const FunctionInfo functions[] = {
            {0, &ISession::SetPerformanceConfiguration, "SetPerformanceConfiguration"},
            {1, &ISession::GetPerformanceConfiguration, "GetPerformanceConfiguration"},
            {2, &ISession::SetCpuOverclockEnabled, "SetCpuOverclockEnabled"},
        };
        RegisterHandlers(functions);
    }

private:
    void SetPerformanceConfiguration(HLERequestContext& ctx) {
        IPC::RequestParser rp{ctx};

        const auto mode = rp.PopEnum<PerformanceMode>();
        const auto config = rp.PopEnum<PerformanceConfiguration>();
        LOG_DEBUG(Service_APM, "called mode={} config={}", mode, config);

        controller.SetPerformanceConfiguration(mode, config);

        IPC::ResponseBuilder rb{ctx, 2};
        rb.Push(ResultSuccess);
    }

    void GetPerformanceConfiguration(HLERequestContext& ctx) {
        IPC::RequestParser rp{ctx};

        const auto mode = rp.PopEnum<PerformanceMode>();
        LOG_DEBUG(Service_APM, "called mode={}", mode);

        IPC::ResponseBuilder rb{ctx, 3};
        rb.Push(ResultSuccess);
        rb.PushEnum(controller.GetCurrentPerformanceConfiguration(mode));
    }

    void SetCpuOverclockEnabled(HLERequestContext& ctx) {
        IPC::RequestParser rp{ctx};

        const auto cpu_overclock_enabled = rp.Pop<bool>();

        LOG_WARNING(Service_APM, "(STUBBED) called, cpu_overclock_enabled={}",
                    cpu_overclock_enabled);

        IPC::ResponseBuilder rb{ctx, 2};
        rb.Push(ResultSuccess);
    }

    Controller& controller;
};

APM::APM(Core::System& system_, std::shared_ptr<Module> apm_, Controller& controller_,
         const char* name)
    : ServiceFramework{system_, name}, apm(std::move(apm_)), controller{controller_} {
    static const FunctionInfo functions[] = {
        {0, &APM::OpenSession, "OpenSession"},
        {1, &APM::GetPerformanceMode, "GetPerformanceMode"},
        {6, &APM::IsCpuOverclockEnabled, "IsCpuOverclockEnabled"},
    };
    RegisterHandlers(functions);
}

APM::~APM() = default;

void APM::OpenSession(HLERequestContext& ctx) {
    LOG_DEBUG(Service_APM, "called");

    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
    rb.Push(ResultSuccess);
    rb.PushIpcInterface<ISession>(system, controller);
}

void APM::GetPerformanceMode(HLERequestContext& ctx) {
    LOG_DEBUG(Service_APM, "called");

    IPC::ResponseBuilder rb{ctx, 2};
    rb.PushEnum(controller.GetCurrentPerformanceMode());
}

void APM::IsCpuOverclockEnabled(HLERequestContext& ctx) {
    LOG_WARNING(Service_APM, "(STUBBED) called");

    IPC::ResponseBuilder rb{ctx, 3};
    rb.Push(ResultSuccess);
    rb.Push(false);
}

APM_Sys::APM_Sys(Core::System& system_, Controller& controller_)
    : ServiceFramework{system_, "apm:sys"}, controller{controller_} {
    // clang-format off
    static const FunctionInfo functions[] = {
        {0, nullptr, "RequestPerformanceMode"},
        {1, &APM_Sys::GetPerformanceEvent, "GetPerformanceEvent"},
        {2, nullptr, "GetThrottlingState"},
        {3, nullptr, "GetLastThrottlingState"},
        {4, nullptr, "ClearLastThrottlingState"},
        {5, nullptr, "LoadAndApplySettings"},
        {6, &APM_Sys::SetCpuBoostMode, "SetCpuBoostMode"},
        {7, &APM_Sys::GetCurrentPerformanceConfiguration, "GetCurrentPerformanceConfiguration"},
    };
    // clang-format on

    RegisterHandlers(functions);
}

APM_Sys::~APM_Sys() = default;

void APM_Sys::GetPerformanceEvent(HLERequestContext& ctx) {
    LOG_DEBUG(Service_APM, "called");

    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
    rb.Push(ResultSuccess);
    rb.PushIpcInterface<ISession>(system, controller);
}

void APM_Sys::SetCpuBoostMode(HLERequestContext& ctx) {
    IPC::RequestParser rp{ctx};
    const auto mode = rp.PopEnum<CpuBoostMode>();

    LOG_DEBUG(Service_APM, "called, mode={:08X}", mode);

    controller.SetFromCpuBoostMode(mode);

    IPC::ResponseBuilder rb{ctx, 2};
    rb.Push(ResultSuccess);
}

void APM_Sys::GetCurrentPerformanceConfiguration(HLERequestContext& ctx) {
    LOG_DEBUG(Service_APM, "called");

    IPC::ResponseBuilder rb{ctx, 3};
    rb.Push(ResultSuccess);
    rb.PushEnum(
        controller.GetCurrentPerformanceConfiguration(controller.GetCurrentPerformanceMode()));
}

} // namespace Service::APM


code:
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "core/hle/service/service.h"

namespace Service::APM {

class Controller;
class Module;

class APM final : public ServiceFramework<APM> {
public:
    explicit APM(Core::System& system_, std::shared_ptr<Module> apm_, Controller& controller_,
                 const char* name);
    ~APM() override;

private:
    void OpenSession(HLERequestContext& ctx);
    void GetPerformanceMode(HLERequestContext& ctx);
    void IsCpuOverclockEnabled(HLERequestContext& ctx);

    std::shared_ptr<Module> apm;
    Controller& controller;
};

class APM_Sys final : public ServiceFramework<APM_Sys> {
public:
    explicit APM_Sys(Core::System& system_, Controller& controller);
    ~APM_Sys() override;

    void SetCpuBoostMode(HLERequestContext& ctx);

private:
    void GetPerformanceEvent(HLERequestContext& ctx);
    void GetCurrentPerformanceConfiguration(HLERequestContext& ctx);

    Controller& controller;
};

} // namespace Service::APM


code:
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "core/core.h"
#include "core/hle/service/audio/audio.h"
#include "core/hle/service/audio/audio_controller.h"
#include "core/hle/service/audio/audio_in_manager.h"
#include "core/hle/service/audio/audio_out_manager.h"
#include "core/hle/service/audio/audio_renderer_manager.h"
#include "core/hle/service/audio/final_output_recorder_manager.h"
#include "core/hle/service/audio/final_output_recorder_manager_for_applet.h"
#include "core/hle/service/audio/hardware_opus_decoder_manager.h"
#include "core/hle/service/server_manager.h"
#include "core/hle/service/service.h"

namespace Service::Audio {

void LoopProcess(Core::System& system) {
    auto server_manager = std::make_unique<ServerManager>(system);

    server_manager->RegisterNamedService("audctl", std::make_shared<IAudioController>(system));
    server_manager->RegisterNamedService("audin:u", std::make_shared<IAudioInManager>(system));
    server_manager->RegisterNamedService("audout:u", std::make_shared<IAudioOutManager>(system));
    server_manager->RegisterNamedService(
        "audrec:a", std::make_shared<IFinalOutputRecorderManagerForApplet>(system));
    server_manager->RegisterNamedService("audrec:u",
                                         std::make_shared<IFinalOutputRecorderManager>(system));
    server_manager->RegisterNamedService("audren:u",
                                         std::make_shared<IAudioRendererManager>(system));
    server_manager->RegisterNamedService("hwopus",
                                         std::make_shared<IHardwareOpusDecoderManager>(system));
    ServerManager::RunServer(std::move(server_manager));
}

} // namespace Service::Audio


code:
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

namespace Core {
class System;
}

namespace Service::SM {
class ServiceManager;
}

namespace Service::Audio {

void LoopProcess(Core::System& system);

} // namespace Service::Audio


code:
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "common/logging/log.h"
#include "core/hle/service/audio/audio_controller.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/set/system_settings_server.h"
#include "core/hle/service/sm/sm.h"

namespace Service::Audio {

IAudioController::IAudioController(Core::System& system_)
    : ServiceFramework{system_, "audctl"}, service_context{system, "audctl"} {
    // clang-format off
    static const FunctionInfo functions[] = {
        {0, nullptr, "GetTargetVolume"},
        {1, nullptr, "SetTargetVolume"},
        {2, D<&IAudioController::GetTargetVolumeMin>, "GetTargetVolumeMin"},
        {3, D<&IAudioController::GetTargetVolumeMax>, "GetTargetVolumeMax"},
        {4, nullptr, "IsTargetMute"},
        {5, nullptr, "SetTargetMute"},
        {6, nullptr, "IsTargetConnected"},
        {7, nullptr, "SetDefaultTarget"},
        {8, nullptr, "GetDefaultTarget"},
        {9, D<&IAudioController::GetAudioOutputMode>, "GetAudioOutputMode"},
        {10, D<&IAudioController::SetAudioOutputMode>, "SetAudioOutputMode"},
        {11, nullptr, "SetForceMutePolicy"},
        {12, D<&IAudioController::GetForceMutePolicy>, "GetForceMutePolicy"},
        {13, D<&IAudioController::GetOutputModeSetting>, "GetOutputModeSetting"},
        {14, D<&IAudioController::SetOutputModeSetting>, "SetOutputModeSetting"},
        {15, nullptr, "SetOutputTarget"},
        {16, nullptr, "SetInputTargetForceEnabled"},
        {17, D<&IAudioController::SetHeadphoneOutputLevelMode>, "SetHeadphoneOutputLevelMode"},
        {18, D<&IAudioController::GetHeadphoneOutputLevelMode>, "GetHeadphoneOutputLevelMode"},
        {19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"},
        {20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"},
        {21, nullptr, "GetAudioOutputTargetForPlayReport"},
        {22, D<&IAudioController::NotifyHeadphoneVolumeWarningDisplayedEvent>, "NotifyHeadphoneVolumeWarningDisplayedEvent"},
        {23, nullptr, "SetSystemOutputMasterVolume"},
        {24, nullptr, "GetSystemOutputMasterVolume"},
        {25, nullptr, "GetAudioVolumeDataForPlayReport"},
        {26, nullptr, "UpdateHeadphoneSettings"},
        {27, nullptr, "SetVolumeMappingTableForDev"},
        {28, nullptr, "GetAudioOutputChannelCountForPlayReport"},
        {29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
        {30, D<&IAudioController::SetSpeakerAutoMuteEnabled>, "SetSpeakerAutoMuteEnabled"},
        {31, D<&IAudioController::IsSpeakerAutoMuteEnabled>, "IsSpeakerAutoMuteEnabled"},
        {32, nullptr, "GetActiveOutputTarget"},
        {33, nullptr, "GetTargetDeviceInfo"},
        {34, D<&IAudioController::AcquireTargetNotification>, "AcquireTargetNotification"},
        {35, nullptr, "SetHearingProtectionSafeguardTimerRemainingTimeForDebug"},
        {36, nullptr, "GetHearingProtectionSafeguardTimerRemainingTimeForDebug"},
        {37, nullptr, "SetHearingProtectionSafeguardEnabled"},
        {38, nullptr, "IsHearingProtectionSafeguardEnabled"},
        {39, nullptr, "IsHearingProtectionSafeguardMonitoringOutputForDebug"},
        {40, nullptr, "GetSystemInformationForDebug"},
        {41, nullptr, "SetVolumeButtonLongPressTime"},
        {42, nullptr, "SetNativeVolumeForDebug"},
        {10000, nullptr, "NotifyAudioOutputTargetForPlayReport"},
        {10001, nullptr, "NotifyAudioOutputChannelCountForPlayReport"},
        {10002, nullptr, "NotifyUnsupportedUsbOutputDeviceAttachedForPlayReport"},
        {10100, nullptr, "GetAudioVolumeDataForPlayReport"},
        {10101, nullptr, "BindAudioVolumeUpdateEventForPlayReport"},
        {10102, nullptr, "BindAudioOutputTargetUpdateEventForPlayReport"},
        {10103, nullptr, "GetAudioOutputTargetForPlayReport"},
        {10104, nullptr, "GetAudioOutputChannelCountForPlayReport"},
        {10105, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
        {10106, nullptr, "GetDefaultAudioOutputTargetForPlayReport"},
        {50000, nullptr, "SetAnalogInputBoostGainForPrototyping"},
    };
    // clang-format on

    RegisterHandlers(functions);

    m_set_sys =
        system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
    notification_event = service_context.CreateEvent("IAudioController:NotificationEvent");
}

IAudioController::~IAudioController() {
    service_context.CloseEvent(notification_event);
};

Result IAudioController::GetTargetVolumeMin(Out<s32> out_target_min_volume) {
    LOG_DEBUG(Audio, "called.");

    // This service function is currently hardcoded on the
    // actual console to this value (as of 8.0.0).
    *out_target_min_volume = 0;
    R_SUCCEED();
}

Result IAudioController::GetTargetVolumeMax(Out<s32> out_target_max_volume) {
    LOG_DEBUG(Audio, "called.");

    // This service function is currently hardcoded on the
    // actual console to this value (as of 8.0.0).
    *out_target_max_volume = 15;
    R_SUCCEED();
}

Result IAudioController::GetAudioOutputMode(Out<Set::AudioOutputMode> out_output_mode,
                                            Set::AudioOutputModeTarget target) {
    const auto result = m_set_sys->GetAudioOutputMode(out_output_mode, target);

    LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, *out_output_mode);
    R_RETURN(result);
}

Result IAudioController::SetAudioOutputMode(Set::AudioOutputModeTarget target,
                                            Set::AudioOutputMode output_mode) {
    LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);

    R_RETURN(m_set_sys->SetAudioOutputMode(target, output_mode));
}

Result IAudioController::GetForceMutePolicy(Out<ForceMutePolicy> out_mute_policy) {
    LOG_WARNING(Audio, "(STUBBED) called");

    // Removed on FW 13.2.1+
    *out_mute_policy = ForceMutePolicy::Disable;
    R_SUCCEED();
}

Result IAudioController::GetOutputModeSetting(Out<Set::AudioOutputMode> out_output_mode,
                                              Set::AudioOutputModeTarget target) {
    LOG_WARNING(Audio, "(STUBBED) called, target={}", target);

    *out_output_mode = Set::AudioOutputMode::ch_7_1;
    R_SUCCEED();
}

Result IAudioController::SetOutputModeSetting(Set::AudioOutputModeTarget target,
                                              Set::AudioOutputMode output_mode) {
    LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
    R_SUCCEED();
}

Result IAudioController::SetHeadphoneOutputLevelMode(HeadphoneOutputLevelMode output_level_mode) {
    LOG_WARNING(Audio, "(STUBBED) called, output_level_mode={}", output_level_mode);
    R_SUCCEED();
}

Result IAudioController::GetHeadphoneOutputLevelMode(
    Out<HeadphoneOutputLevelMode> out_output_level_mode) {
    LOG_INFO(Audio, "called");

    *out_output_level_mode = HeadphoneOutputLevelMode::Normal;
    R_SUCCEED();
}

Result IAudioController::NotifyHeadphoneVolumeWarningDisplayedEvent() {
    LOG_WARNING(Service_Audio, "(STUBBED) called");
    R_SUCCEED();
}

Result IAudioController::SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled) {
    LOG_INFO(Audio, "called, is_speaker_auto_mute_enabled={}", is_speaker_auto_mute_enabled);

    R_RETURN(m_set_sys->SetSpeakerAutoMuteFlag(is_speaker_auto_mute_enabled));
}

Result IAudioController::IsSpeakerAutoMuteEnabled(Out<bool> out_is_speaker_auto_mute_enabled) {
    const auto result = m_set_sys->GetSpeakerAutoMuteFlag(out_is_speaker_auto_mute_enabled);

    LOG_INFO(Audio, "called, is_speaker_auto_mute_enabled={}", *out_is_speaker_auto_mute_enabled);
    R_RETURN(result);
}

Result IAudioController::AcquireTargetNotification(
    OutCopyHandle<Kernel::KReadableEvent> out_notification_event) {
    LOG_WARNING(Service_AM, "(STUBBED) called");

    *out_notification_event = &notification_event->GetReadableEvent();
    R_SUCCEED();
}

} // namespace Service::Audio


code:
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
#include "core/hle/service/set/settings_types.h"

namespace Core {
class System;
}

namespace Service::Set {
class ISystemSettingsServer;
}

namespace Service::Audio {

class IAudioController final : public ServiceFramework<IAudioController> {
public:
    explicit IAudioController(Core::System& system_);
    ~IAudioController() override;

private:
    enum class ForceMutePolicy {
        Disable,
        SpeakerMuteOnHeadphoneUnplugged,
    };

    enum class HeadphoneOutputLevelMode {
        Normal,
        HighPower,
    };

    Result GetTargetVolumeMin(Out<s32> out_target_min_volume);
    Result GetTargetVolumeMax(Out<s32> out_target_max_volume);
    Result GetAudioOutputMode(Out<Set::AudioOutputMode> out_output_mode,
                              Set::AudioOutputModeTarget target);
    Result SetAudioOutputMode(Set::AudioOutputModeTarget target, Set::AudioOutputMode output_mode);
    Result GetForceMutePolicy(Out<ForceMutePolicy> out_mute_policy);
    Result GetOutputModeSetting(Out<Set::AudioOutputMode> out_output_mode,
                                Set::AudioOutputModeTarget target);
    Result SetOutputModeSetting(Set::AudioOutputModeTarget target,
                                Set::AudioOutputMode output_mode);
    Result SetHeadphoneOutputLevelMode(HeadphoneOutputLevelMode output_level_mode);
    Result GetHeadphoneOutputLevelMode(Out<HeadphoneOutputLevelMode> out_output_level_mode);
    Result NotifyHeadphoneVolumeWarningDisplayedEvent();
    Result SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled);
    Result IsSpeakerAutoMuteEnabled(Out<bool> out_is_speaker_auto_mute_enabled);
    Result AcquireTargetNotification(OutCopyHandle<Kernel::KReadableEvent> out_notification_event);

    KernelHelpers::ServiceContext service_context;

    Kernel::KEvent* notification_event;
    std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
};

} // namespace Service::Audio


code:
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "audio_core/audio_core.h"
#include "common/string_util.h"
#include "core/hle/service/audio/audio_device.h"
#include "core/hle/service/cmif_serialization.h"

namespace Service::Audio {
using namespace AudioCore::Renderer;

IAudioDevice::IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u32 revision,
                           u32 device_num)
    : ServiceFramework{system_, "IAudioDevice"}, service_context{system_, "IAudioDevice"},
      impl{std::make_unique<AudioDevice>(system_, applet_resource_user_id, revision)},
      event{service_context.CreateEvent(fmt::format("IAudioDeviceEvent-{}", device_num))} {
    static const FunctionInfo functions[] = {
        {0, D<&IAudioDevice::ListAudioDeviceName>, "ListAudioDeviceName"},
        {1, D<&IAudioDevice::SetAudioDeviceOutputVolume>, "SetAudioDeviceOutputVolume"},
        {2, D<&IAudioDevice::GetAudioDeviceOutputVolume>, "GetAudioDeviceOutputVolume"},
        {3, D<&IAudioDevice::GetActiveAudioDeviceName>, "GetActiveAudioDeviceName"},
        {4, D<&IAudioDevice::QueryAudioDeviceSystemEvent>, "QueryAudioDeviceSystemEvent"},
        {5, D<&IAudioDevice::GetActiveChannelCount>, "GetActiveChannelCount"},
        {6, D<&IAudioDevice::ListAudioDeviceNameAuto>, "ListAudioDeviceNameAuto"},
        {7, D<&IAudioDevice::SetAudioDeviceOutputVolumeAuto>, "SetAudioDeviceOutputVolumeAuto"},
        {8, D<&IAudioDevice::GetAudioDeviceOutputVolumeAuto>, "GetAudioDeviceOutputVolumeAuto"},
        {10, D<&IAudioDevice::GetActiveAudioDeviceNameAuto>, "GetActiveAudioDeviceNameAuto"},
        {11, D<&IAudioDevice::QueryAudioDeviceInputEvent>, "QueryAudioDeviceInputEvent"},
        {12, D<&IAudioDevice::QueryAudioDeviceOutputEvent>, "QueryAudioDeviceOutputEvent"},
        {13, D<&IAudioDevice::GetActiveAudioDeviceName>, "GetActiveAudioOutputDeviceName"},
        {14, D<&IAudioDevice::ListAudioOutputDeviceName>, "ListAudioOutputDeviceName"},
    };
    RegisterHandlers(functions);

    event->Signal();
}

IAudioDevice::~IAudioDevice() {
    service_context.CloseEvent(event);
}

Result IAudioDevice::ListAudioDeviceName(
    OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_names, Out<s32> out_count) {
    R_RETURN(this->ListAudioDeviceNameAuto(out_names, out_count));
}

Result IAudioDevice::SetAudioDeviceOutputVolume(
    InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> name, f32 volume) {
    R_RETURN(this->SetAudioDeviceOutputVolumeAuto(name, volume));
}

Result IAudioDevice::GetAudioDeviceOutputVolume(
    Out<f32> out_volume, InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> name) {
    R_RETURN(this->GetAudioDeviceOutputVolumeAuto(out_volume, name));
}

Result IAudioDevice::GetActiveAudioDeviceName(
    OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_name) {
    R_RETURN(this->GetActiveAudioDeviceNameAuto(out_name));
}

Result IAudioDevice::ListAudioDeviceNameAuto(
    OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> out_names,
    Out<s32> out_count) {
    *out_count = impl->ListAudioDeviceName(out_names);

    std::string out{};
    for (s32 i = 0; i < *out_count; i++) {
        std::string a{};
        u32 j = 0;
        while (out_names[i].name[j] != '\0') {
            a += out_names[i].name[j];
            j++;
        }
        out += "\n\t" + a;
    }

    LOG_DEBUG(Service_Audio, "called.\nNames={}", out);
    R_SUCCEED();
}

Result IAudioDevice::SetAudioDeviceOutputVolumeAuto(
    InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> name, f32 volume) {
    R_UNLESS(!name.empty(), Audio::ResultInsufficientBuffer);

    const std::string device_name = Common::StringFromBuffer(name[0].name);
    LOG_DEBUG(Service_Audio, "called. name={}, volume={}", device_name, volume);

    if (device_name == "AudioTvOutput") {
        impl->SetDeviceVolumes(volume);
    }

    R_SUCCEED();
}

Result IAudioDevice::GetAudioDeviceOutputVolumeAuto(
    Out<f32> out_volume, InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> name) {
    R_UNLESS(!name.empty(), Audio::ResultInsufficientBuffer);

    const std::string device_name = Common::StringFromBuffer(name[0].name);
    LOG_DEBUG(Service_Audio, "called. Name={}", device_name);

    *out_volume = 1.0f;
    if (device_name == "AudioTvOutput") {
        *out_volume = impl->GetDeviceVolume(device_name);
    }

    R_SUCCEED();
}

Result IAudioDevice::GetActiveAudioDeviceNameAuto(
    OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> out_name) {
    R_UNLESS(!out_name.empty(), Audio::ResultInsufficientBuffer);
    out_name[0] = AudioDevice::AudioDeviceName("AudioTvOutput");
    LOG_DEBUG(Service_Audio, "(STUBBED) called");
    R_SUCCEED();
}

Result IAudioDevice::QueryAudioDeviceSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
    LOG_DEBUG(Service_Audio, "(STUBBED) called");
    event->Signal();
    *out_event = &event->GetReadableEvent();
    R_SUCCEED();
}

Result IAudioDevice::QueryAudioDeviceInputEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
    LOG_DEBUG(Service_Audio, "(STUBBED) called");
    *out_event = &event->GetReadableEvent();
    R_SUCCEED();
}

Result IAudioDevice::QueryAudioDeviceOutputEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
    LOG_DEBUG(Service_Audio, "called");
    *out_event = &event->GetReadableEvent();
    R_SUCCEED();
}

Result IAudioDevice::GetActiveChannelCount(Out<u32> out_active_channel_count) {
    *out_active_channel_count = system.AudioCore().GetOutputSink().GetSystemChannels();
    LOG_DEBUG(Service_Audio, "(STUBBED) called. Channels={}", *out_active_channel_count);
    R_SUCCEED();
}

Result IAudioDevice::ListAudioOutputDeviceName(
    OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_names, Out<s32> out_count) {
    *out_count = impl->ListAudioOutputDeviceName(out_names);

    std::string out{};
    for (s32 i = 0; i < *out_count; i++) {
        std::string a{};
        u32 j = 0;
        while (out_names[i].name[j] != '\0') {
            a += out_names[i].name[j];
            j++;
        }
        out += "\n\t" + a;
    }

    LOG_DEBUG(Service_Audio, "called.\nNames={}", out);
    R_SUCCEED();
}

} // namespace Service::Audio


code:
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "audio_core/renderer/audio_device.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/service.h"

namespace Kernel {
class KReadableEvent;
}

namespace Service::Audio {

using AudioCore::Renderer::AudioDevice;

class IAudioDevice final : public ServiceFramework<IAudioDevice> {

public:
    explicit IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u32 revision,
                          u32 device_num);
    ~IAudioDevice() override;

private:
    Result ListAudioDeviceName(
        OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_names,
        Out<s32> out_count);
    Result SetAudioDeviceOutputVolume(
        InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> name, f32 volume);
    Result GetAudioDeviceOutputVolume(
        Out<f32> out_volume, InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> name);
    Result GetActiveAudioDeviceName(
        OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_name);
    Result ListAudioDeviceNameAuto(
        OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> out_names,
        Out<s32> out_count);
    Result SetAudioDeviceOutputVolumeAuto(
        InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> name, f32 volume);
    Result GetAudioDeviceOutputVolumeAuto(
        Out<f32> out_volume, InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> name);
    Result GetActiveAudioDeviceNameAuto(
        OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> out_name);
    Result QueryAudioDeviceSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
    Result QueryAudioDeviceInputEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
    Result QueryAudioDeviceOutputEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
    Result GetActiveChannelCount(Out<u32> out_active_channel_count);
    Result ListAudioOutputDeviceName(
        OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_names,
        Out<s32> out_count);

    KernelHelpers::ServiceContext service_context;
    std::unique_ptr<AudioCore::Renderer::AudioDevice> impl;
    Kernel::KEvent* event;
};

} // namespace Service::Audio


code:
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "core/hle/service/audio/audio_in.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/ipc_helpers.h"

namespace Service::Audio {
using namespace AudioCore::AudioIn;

IAudioIn::IAudioIn(Core::System& system_, Manager& manager, size_t session_id,
                   const std::string& device_name, const AudioInParameter& in_params,
                   Kernel::KProcess* handle, u64 applet_resource_user_id)
    : ServiceFramework{system_, "IAudioIn"}, process{handle}, service_context{system_, "IAudioIn"},
      event{service_context.CreateEvent("AudioInEvent")}, impl{std::make_shared<In>(system_,
                                                                                manager, event,
                                                                                session_id)} {
    // clang-format off
    static const FunctionInfo functions[] = {
        {0, D<&IAudioIn::GetAudioInState>, "GetAudioInState"},
        {1, D<&IAudioIn::Start>, "Start"},
        {2, D<&IAudioIn::Stop>, "Stop"},
        {3, D<&IAudioIn::AppendAudioInBuffer>, "AppendAudioInBuffer"},
        {4, D<&IAudioIn::RegisterBufferEvent>, "RegisterBufferEvent"},
        {5, D<&IAudioIn::GetReleasedAudioInBuffers>, "GetReleasedAudioInBuffers"},
        {6, D<&IAudioIn::ContainsAudioInBuffer>, "ContainsAudioInBuffer"},
        {7, D<&IAudioIn::AppendAudioInBuffer>, "AppendUacInBuffer"},
        {8, D<&IAudioIn::AppendAudioInBufferAuto>, "AppendAudioInBufferAuto"},
        {9, D<&IAudioIn::GetReleasedAudioInBuffersAuto>, "GetReleasedAudioInBuffersAuto"},
        {10, D<&IAudioIn::AppendAudioInBufferAuto>, "AppendUacInBufferAuto"},
        {11, D<&IAudioIn::GetAudioInBufferCount>, "GetAudioInBufferCount"},
        {12, D<&IAudioIn::SetDeviceGain>, "SetDeviceGain"},
        {13, D<&IAudioIn::GetDeviceGain>, "GetDeviceGain"},
        {14, D<&IAudioIn::FlushAudioInBuffers>, "FlushAudioInBuffers"},
    };
    // clang-format on

    RegisterHandlers(functions);

    process->Open();

    if (impl->GetSystem()
            .Initialize(device_name, in_params, handle, applet_resource_user_id)
            .IsError()) {
        LOG_ERROR(Service_Audio, "Failed to initialize the AudioIn System!");
    }
}

IAudioIn::~IAudioIn() {
    impl->Free();
    service_context.CloseEvent(event);
    process->Close();
}

Result IAudioIn::GetAudioInState(Out<u32> out_state) {
    *out_state = static_cast<u32>(impl->GetState());
    LOG_DEBUG(Service_Audio, "called. state={}", *out_state);
    R_SUCCEED();
}

Result IAudioIn::Start() {
    LOG_DEBUG(Service_Audio, "called");
    R_RETURN(impl->StartSystem());
}

Result IAudioIn::Stop() {
    LOG_DEBUG(Service_Audio, "called");
    R_RETURN(impl->StopSystem());
}

Result IAudioIn::AppendAudioInBuffer(InArray<AudioInBuffer, BufferAttr_HipcMapAlias> buffer,
                                     u64 buffer_client_ptr) {
    R_RETURN(this->AppendAudioInBufferAuto(buffer, buffer_client_ptr));
}

Result IAudioIn::AppendAudioInBufferAuto(InArray<AudioInBuffer, BufferAttr_HipcAutoSelect> buffer,
                                         u64 buffer_client_ptr) {
    if (buffer.empty()) {
        LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioInBuffer!");
        R_THROW(Audio::ResultInsufficientBuffer);
    }

    [[maybe_unused]] const auto session_id{impl->GetSystem().GetSessionId()};
    LOG_TRACE(Service_Audio, "called. Session {} Appending buffer {:08X}", session_id,
              buffer_client_ptr);

    R_RETURN(impl->AppendBuffer(buffer[0], buffer_client_ptr));
}

Result IAudioIn::RegisterBufferEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
    LOG_DEBUG(Service_Audio, "called");
    *out_event = &impl->GetBufferEvent();
    R_SUCCEED();
}

Result IAudioIn::GetReleasedAudioInBuffers(OutArray<u64, BufferAttr_HipcMapAlias> out_audio_buffer,
                                           Out<u32> out_count) {
    R_RETURN(this->GetReleasedAudioInBuffersAuto(out_audio_buffer, out_count));
}

Result IAudioIn::GetReleasedAudioInBuffersAuto(
    OutArray<u64, BufferAttr_HipcAutoSelect> out_audio_buffer, Out<u32> out_count) {

    if (!out_audio_buffer.empty()) {
        out_audio_buffer[0] = 0;
    }
    *out_count = impl->GetReleasedBuffers(out_audio_buffer);

    LOG_TRACE(Service_Audio, "called. Session {} released {} buffers",
              impl->GetSystem().GetSessionId(), *out_count);
    R_SUCCEED();
}

Result IAudioIn::ContainsAudioInBuffer(Out<bool> out_contains_buffer, u64 buffer_client_ptr) {
    *out_contains_buffer = impl->ContainsAudioBuffer(buffer_client_ptr);

    LOG_DEBUG(Service_Audio, "called. Is buffer {:08X} registered? {}", buffer_client_ptr,
              *out_contains_buffer);
    R_SUCCEED();
}

Result IAudioIn::GetAudioInBufferCount(Out<u32> out_buffer_count) {
    *out_buffer_count = impl->GetBufferCount();
    LOG_DEBUG(Service_Audio, "called. Buffer count={}", *out_buffer_count);
    R_SUCCEED();
}

Result IAudioIn::SetDeviceGain(f32 device_gain) {
    impl->SetVolume(device_gain);
    LOG_DEBUG(Service_Audio, "called. Gain {}", device_gain);
    R_SUCCEED();
}

Result IAudioIn::GetDeviceGain(Out<f32> out_device_gain) {
    *out_device_gain = impl->GetVolume();
    LOG_DEBUG(Service_Audio, "called. Gain {}", *out_device_gain);
    R_SUCCEED();
}

Result IAudioIn::FlushAudioInBuffers(Out<bool> out_flushed) {
    *out_flushed = impl->FlushAudioInBuffers();
    LOG_DEBUG(Service_Audio, "called. Were any buffers flushed? {}", *out_flushed);
    R_SUCCEED();
}

} // namespace Service::Audio


code:
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "audio_core/in/audio_in.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/service.h"

namespace Service::Audio {

class IAudioIn final : public ServiceFramework<IAudioIn> {
public:
    explicit IAudioIn(Core::System& system_, AudioCore::AudioIn::Manager& manager,
                      size_t session_id, const std::string& device_name,
                      const AudioCore::AudioIn::AudioInParameter& in_params,
                      Kernel::KProcess* handle, u64 applet_resource_user_id);
    ~IAudioIn() override;

    std::shared_ptr<AudioCore::AudioIn::In> GetImpl() {
        return impl;
    }

    Result GetAudioInState(Out<u32> out_state);
    Result Start();
    Result Stop();
    Result AppendAudioInBuffer(
        InArray<AudioCore::AudioIn::AudioInBuffer, BufferAttr_HipcMapAlias> buffer,
        u64 buffer_client_ptr);
    Result AppendAudioInBufferAuto(
        InArray<AudioCore::AudioIn::AudioInBuffer, BufferAttr_HipcAutoSelect> buffer,
        u64 buffer_client_ptr);
    Result RegisterBufferEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
    Result GetReleasedAudioInBuffers(OutArray<u64, BufferAttr_HipcMapAlias> out_audio_buffer,
                                     Out<u32> out_count);
    Result GetReleasedAudioInBuffersAuto(OutArray<u64, BufferAttr_HipcAutoSelect> out_audio_buffer,
                                         Out<u32> out_count);
    Result ContainsAudioInBuffer(Out<bool> out_contains_buffer, u64 buffer_client_ptr);
    Result GetAudioInBufferCount(Out<u32> out_buffer_count);
    Result SetDeviceGain(f32 device_gain);
    Result GetDeviceGain(Out<f32> out_device_gain);
    Result FlushAudioInBuffers(Out<bool> out_flushed);

private:
    Kernel::KProcess* process;
    KernelHelpers::ServiceContext service_context;
    Kernel::KEvent* event;
    std::shared_ptr<AudioCore::AudioIn::In> impl;
    Common::ScratchBuffer<u64> released_buffer;
};

} // namespace Service::Audio


code:
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "common/string_util.h"
#include "core/hle/service/audio/audio_in.h"
#include "core/hle/service/audio/audio_in_manager.h"
#include "core/hle/service/cmif_serialization.h"

namespace Service::Audio {
using namespace AudioCore::AudioIn;

IAudioInManager::IAudioInManager(Core::System& system_)
    : ServiceFramework{system_, "audin:u"}, impl{std::make_unique<AudioCore::AudioIn::Manager>(
                                                system_)} {
    // clang-format off
    static const FunctionInfo functions[] = {
        {0, D<&IAudioInManager::ListAudioIns>, "ListAudioIns"},
        {1, D<&IAudioInManager::OpenAudioIn>, "OpenAudioIn"},
        {2, D<&IAudioInManager::ListAudioIns>, "ListAudioInsAuto"},
        {3, D<&IAudioInManager::OpenAudioIn>, "OpenAudioInAuto"},
        {4, D<&IAudioInManager::ListAudioInsAutoFiltered>, "ListAudioInsAutoFiltered"},
        {5, D<&IAudioInManager::OpenAudioInProtocolSpecified>, "OpenAudioInProtocolSpecified"},
    };
    // clang-format on

    RegisterHandlers(functions);
}

IAudioInManager::~IAudioInManager() = default;

Result IAudioInManager::ListAudioIns(
    OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_audio_ins, Out<u32> out_count) {
    LOG_DEBUG(Service_Audio, "called");
    R_RETURN(this->ListAudioInsAutoFiltered(out_audio_ins, out_count));
}

Result IAudioInManager::OpenAudioIn(Out<AudioInParameterInternal> out_parameter_internal,
                                    Out<SharedPointer<IAudioIn>> out_audio_in,
                                    OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name,
                                    InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name,
                                    AudioInParameter parameter,
                                    InCopyHandle<Kernel::KProcess> process_handle,
                                    ClientAppletResourceUserId aruid) {
    LOG_DEBUG(Service_Audio, "called");
    R_RETURN(this->OpenAudioInProtocolSpecified(out_parameter_internal, out_audio_in, out_name,
                                                name, {}, parameter, process_handle, aruid));
}

Result IAudioInManager::ListAudioInsAuto(
    OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins, Out<u32> out_count) {
    LOG_DEBUG(Service_Audio, "called");
    R_RETURN(this->ListAudioInsAutoFiltered(out_audio_ins, out_count));
}

Result IAudioInManager::OpenAudioInAuto(
    Out<AudioInParameterInternal> out_parameter_internal, Out<SharedPointer<IAudioIn>> out_audio_in,
    OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
    InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, AudioInParameter parameter,
    InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid) {
    LOG_DEBUG(Service_Audio, "called");
    R_RETURN(this->OpenAudioInProtocolSpecified(out_parameter_internal, out_audio_in, out_name,
                                                name, {}, parameter, process_handle, aruid));
}

Result IAudioInManager::ListAudioInsAutoFiltered(
    OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins, Out<u32> out_count) {
    LOG_DEBUG(Service_Audio, "called");
    *out_count = impl->GetDeviceNames(out_audio_ins, true);
    R_SUCCEED();
}

Result IAudioInManager::OpenAudioInProtocolSpecified(
    Out<AudioInParameterInternal> out_parameter_internal, Out<SharedPointer<IAudioIn>> out_audio_in,
    OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
    InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, Protocol protocol,
    AudioInParameter parameter, InCopyHandle<Kernel::KProcess> process_handle,
    ClientAppletResourceUserId aruid) {
    LOG_DEBUG(Service_Audio, "called");

    if (!process_handle) {
        LOG_ERROR(Service_Audio, "Failed to get process handle");
        R_THROW(ResultUnknown);
    }
    if (name.empty() || out_name.empty()) {
        LOG_ERROR(Service_Audio, "Invalid buffers");
        R_THROW(ResultUnknown);
    }

    std::scoped_lock l{impl->mutex};

    size_t new_session_id{};

    R_TRY(impl->LinkToManager());
    R_TRY(impl->AcquireSessionId(new_session_id));

    LOG_DEBUG(Service_Audio, "Opening new AudioIn, session_id={}, free sessions={}", new_session_id,
              impl->num_free_sessions);

    const auto device_name = Common::StringFromBuffer(name[0].name);
    *out_audio_in = std::make_shared<IAudioIn>(system, *impl, new_session_id, device_name,
                                               parameter, process_handle.Get(), aruid.pid);
    impl->sessions[new_session_id] = (*out_audio_in)->GetImpl();
    impl->applet_resource_user_ids[new_session_id] = aruid.pid;

    auto& out_system = impl->sessions[new_session_id]->GetSystem();
    *out_parameter_internal =
        AudioInParameterInternal{.sample_rate = out_system.GetSampleRate(),
                                 .channel_count = out_system.GetChannelCount(),
                                 .sample_format = static_cast<u32>(out_system.GetSampleFormat()),
                                 .state = static_cast<u32>(out_system.GetState())};

    out_name[0] = AudioDeviceName(out_system.GetName());

    if (protocol == Protocol{}) {
        if (out_system.IsUac()) {
            out_name[0] = AudioDeviceName("UacIn");
        } else {
            out_name[0] = AudioDeviceName("DeviceIn");
        }
    }

    R_SUCCEED();
}

} // namespace Service::Audio


code:
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "audio_core/audio_in_manager.h"
#include "audio_core/in/audio_in_system.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"

namespace Service::Audio {

using AudioDeviceName = AudioCore::Renderer::AudioDevice::AudioDeviceName;
using Protocol = std::array<u32, 2>;

class IAudioIn;

class IAudioInManager final : public ServiceFramework<IAudioInManager> {
public:
    explicit IAudioInManager(Core::System& system_);
    ~IAudioInManager() override;

private:
    Result ListAudioIns(OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_audio_ins,
                        Out<u32> out_count);
    Result OpenAudioIn(Out<AudioCore::AudioIn::AudioInParameterInternal> out_parameter_internal,
                       Out<SharedPointer<IAudioIn>> out_audio_in,
                       OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name,
                       InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name,
                       AudioCore::AudioIn::AudioInParameter parameter,
                       InCopyHandle<Kernel::KProcess> process_handle,
                       ClientAppletResourceUserId aruid);

    Result ListAudioInsAuto(OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins,
                            Out<u32> out_count);
    Result OpenAudioInAuto(Out<AudioCore::AudioIn::AudioInParameterInternal> out_parameter_internal,
                           Out<SharedPointer<IAudioIn>> out_audio_in,
                           OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
                           InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name,
                           AudioCore::AudioIn::AudioInParameter parameter,
                           InCopyHandle<Kernel::KProcess> process_handle,
                           ClientAppletResourceUserId aruid);

    Result ListAudioInsAutoFiltered(
        OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins, Out<u32> out_count);
    Result OpenAudioInProtocolSpecified(
        Out<AudioCore::AudioIn::AudioInParameterInternal> out_parameter_internal,
        Out<SharedPointer<IAudioIn>> out_audio_in,
        OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
        InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, Protocol protocol,
        AudioCore::AudioIn::AudioInParameter parameter,
        InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid);

    std::unique_ptr<AudioCore::AudioIn::Manager> impl;
};

} // namespace Service::Audio


code:
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "audio_core/out/audio_out.h"
#include "audio_core/out/audio_out_system.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/service/audio/audio_out.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/service.h"

namespace Service::Audio {
using namespace AudioCore::AudioOut;

IAudioOut::IAudioOut(Core::System& system_, Manager& manager, size_t session_id,
                     const std::string& device_name, const AudioOutParameter& in_params,
                     Kernel::KProcess* handle, u64 applet_resource_user_id)
    : ServiceFramework{system_, "IAudioOut"}, service_context{system_, "IAudioOut"},
      event{service_context.CreateEvent("AudioOutEvent")}, process{handle},
      impl{std::make_shared<AudioCore::AudioOut::Out>(system_, manager, event, session_id)} {

    // clang-format off
    static const FunctionInfo functions[] = {
        {0, D<&IAudioOut::GetAudioOutState>, "GetAudioOutState"},
        {1, D<&IAudioOut::Start>, "Start"},
        {2, D<&IAudioOut::Stop>, "Stop"},
        {3, D<&IAudioOut::AppendAudioOutBuffer>, "AppendAudioOutBuffer"},
        {4, D<&IAudioOut::RegisterBufferEvent>, "RegisterBufferEvent"},
        {5, D<&IAudioOut::GetReleasedAudioOutBuffers>, "GetReleasedAudioOutBuffers"},
        {6, D<&IAudioOut::ContainsAudioOutBuffer>, "ContainsAudioOutBuffer"},
        {7, D<&IAudioOut::AppendAudioOutBufferAuto>, "AppendAudioOutBufferAuto"},
        {8, D<&IAudioOut::GetReleasedAudioOutBuffersAuto>, "GetReleasedAudioOutBuffersAuto"},
        {9, D<&IAudioOut::GetAudioOutBufferCount>, "GetAudioOutBufferCount"},
        {10, D<&IAudioOut::GetAudioOutPlayedSampleCount>, "GetAudioOutPlayedSampleCount"},
        {11, D<&IAudioOut::FlushAudioOutBuffers>, "FlushAudioOutBuffers"},
        {12, D<&IAudioOut::SetAudioOutVolume>, "SetAudioOutVolume"},
        {13, D<&IAudioOut::GetAudioOutVolume>, "GetAudioOutVolume"},
    };
    // clang-format on
    RegisterHandlers(functions);

    process->Open();
}

IAudioOut::~IAudioOut() {
    impl->Free();
    service_context.CloseEvent(event);
    process->Close();
}

Result IAudioOut::GetAudioOutState(Out<u32> out_state) {
    *out_state = static_cast<u32>(impl->GetState());
    LOG_DEBUG(Service_Audio, "called. state={}", *out_state);
    R_SUCCEED();
}

Result IAudioOut::Start() {
    LOG_DEBUG(Service_Audio, "called");
    R_RETURN(impl->StartSystem());
}

Result IAudioOut::Stop() {
    LOG_DEBUG(Service_Audio, "called");
    R_RETURN(impl->StopSystem());
}

Result IAudioOut::AppendAudioOutBuffer(
    InArray<AudioOutBuffer, BufferAttr_HipcMapAlias> audio_out_buffer, u64 buffer_client_ptr) {
    R_RETURN(this->AppendAudioOutBufferAuto(audio_out_buffer, buffer_client_ptr));
}

Result IAudioOut::AppendAudioOutBufferAuto(
    InArray<AudioOutBuffer, BufferAttr_HipcAutoSelect> audio_out_buffer, u64 buffer_client_ptr) {
    if (audio_out_buffer.empty()) {
        LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioOutBuffer!");
        R_THROW(Audio::ResultInsufficientBuffer);
    }

    LOG_TRACE(Service_Audio, "called. Session {} Appending buffer {:08X}",
              impl->GetSystem().GetSessionId(), buffer_client_ptr);
    R_RETURN(impl->AppendBuffer(audio_out_buffer[0], buffer_client_ptr));
}

Result IAudioOut::RegisterBufferEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
    LOG_DEBUG(Service_Audio, "called");
    *out_event = &impl->GetBufferEvent();
    R_SUCCEED();
}

Result IAudioOut::GetReleasedAudioOutBuffers(
    OutArray<u64, BufferAttr_HipcMapAlias> out_audio_buffer, Out<u32> out_count) {
    R_RETURN(this->GetReleasedAudioOutBuffersAuto(out_audio_buffer, out_count));
}

Result IAudioOut::GetReleasedAudioOutBuffersAuto(
    OutArray<u64, BufferAttr_HipcAutoSelect> out_audio_buffer, Out<u32> out_count) {

    if (!out_audio_buffer.empty()) {
        out_audio_buffer[0] = 0;
    }
    *out_count = impl->GetReleasedBuffers(out_audio_buffer);

    LOG_TRACE(Service_Audio, "called. Session {} released {} buffers",
              impl->GetSystem().GetSessionId(), *out_count);
    R_SUCCEED();
}

Result IAudioOut::ContainsAudioOutBuffer(Out<bool> out_contains_buffer, u64 buffer_client_ptr) {
    *out_contains_buffer = impl->ContainsAudioBuffer(buffer_client_ptr);

    LOG_DEBUG(Service_Audio, "called. Is buffer {:08X} registered? {}", buffer_client_ptr,
              *out_contains_buffer);
    R_SUCCEED();
}

Result IAudioOut::GetAudioOutBufferCount(Out<u32> out_buffer_count) {
    *out_buffer_count = impl->GetBufferCount();
    LOG_DEBUG(Service_Audio, "called. Buffer count={}", *out_buffer_count);
    R_SUCCEED();
}

Result IAudioOut::GetAudioOutPlayedSampleCount(Out<u64> out_played_sample_count) {
    *out_played_sample_count = impl->GetPlayedSampleCount();
    LOG_DEBUG(Service_Audio, "called. Played samples={}", *out_played_sample_count);
    R_SUCCEED();
}

Result IAudioOut::FlushAudioOutBuffers(Out<bool> out_flushed) {
    *out_flushed = impl->FlushAudioOutBuffers();
    LOG_DEBUG(Service_Audio, "called. Were any buffers flushed? {}", *out_flushed);
    R_SUCCEED();
}

Result IAudioOut::SetAudioOutVolume(f32 volume) {
    LOG_DEBUG(Service_Audio, "called. Volume={}", volume);
    impl->SetVolume(volume);
    R_SUCCEED();
}

Result IAudioOut::GetAudioOutVolume(Out<f32> out_volume) {
    *out_volume = impl->GetVolume();
    LOG_DEBUG(Service_Audio, "called. Volume={}", *out_volume);
    R_SUCCEED();
}

} // namespace Service::Audio


code:
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "audio_core/audio_out_manager.h"
#include "audio_core/out/audio_out_system.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/service.h"

namespace Kernel {
class KReadableEvent;
}

namespace Service::Audio {

class IAudioOut : public ServiceFramework<IAudioOut> {
public:
    explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager,
                       size_t session_id, const std::string& device_name,
                       const AudioCore::AudioOut::AudioOutParameter& in_params,
                       Kernel::KProcess* handle, u64 applet_resource_user_id);
    ~IAudioOut() override;

    std::shared_ptr<AudioCore::AudioOut::Out> GetImpl() {
        return impl;
    }

    Result GetAudioOutState(Out<u32> out_state);
    Result Start();
    Result Stop();
    Result AppendAudioOutBuffer(
        InArray<AudioCore::AudioOut::AudioOutBuffer, BufferAttr_HipcMapAlias> audio_out_buffer,
        u64 buffer_client_ptr);
    Result AppendAudioOutBufferAuto(
        InArray<AudioCore::AudioOut::AudioOutBuffer, BufferAttr_HipcAutoSelect> audio_out_buffer,
        u64 buffer_client_ptr);
    Result RegisterBufferEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
    Result GetReleasedAudioOutBuffers(OutArray<u64, BufferAttr_HipcMapAlias> out_audio_buffer,
                                      Out<u32> out_count);
    Result GetReleasedAudioOutBuffersAuto(OutArray<u64, BufferAttr_HipcAutoSelect> out_audio_buffer,
                                          Out<u32> out_count);
    Result ContainsAudioOutBuffer(Out<bool> out_contains_buffer, u64 buffer_client_ptr);
    Result GetAudioOutBufferCount(Out<u32> out_buffer_count);
    Result GetAudioOutPlayedSampleCount(Out<u64> out_played_sample_count);
    Result FlushAudioOutBuffers(Out<bool> out_flushed);
    Result SetAudioOutVolume(f32 volume);
    Result GetAudioOutVolume(Out<f32> out_volume);

private:
    KernelHelpers::ServiceContext service_context;
    Kernel::KEvent* event;
    Kernel::KProcess* process;
    std::shared_ptr<AudioCore::AudioOut::Out> impl;
};

} // namespace Service::Audio


code:
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "common/string_util.h"
#include "core/hle/service/audio/audio_out.h"
#include "core/hle/service/audio/audio_out_manager.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/memory.h"

namespace Service::Audio {
using namespace AudioCore::AudioOut;

IAudioOutManager::IAudioOutManager(Core::System& system_)
    : ServiceFramework{system_, "audout:u"}, impl{std::make_unique<Manager>(system_)} {
    // clang-format off
    static const FunctionInfo functions[] = {
        {0, D<&IAudioOutManager::ListAudioOuts>, "ListAudioOuts"},
        {1, D<&IAudioOutManager::OpenAudioOut>, "OpenAudioOut"},
        {2, D<&IAudioOutManager::ListAudioOutsAuto>, "ListAudioOutsAuto"},
        {3, D<&IAudioOutManager::OpenAudioOutAuto>, "OpenAudioOutAuto"},
    };
    // clang-format on

    RegisterHandlers(functions);
}

IAudioOutManager::~IAudioOutManager() = default;

Result IAudioOutManager::ListAudioOuts(
    OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_audio_outs, Out<u32> out_count) {
    R_RETURN(this->ListAudioOutsAuto(out_audio_outs, out_count));
}

Result IAudioOutManager::OpenAudioOut(Out<AudioOutParameterInternal> out_parameter_internal,
                                      Out<SharedPointer<IAudioOut>> out_audio_out,
                                      OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name,
                                      InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name,
                                      AudioOutParameter parameter,
                                      InCopyHandle<Kernel::KProcess> process_handle,
                                      ClientAppletResourceUserId aruid) {
    R_RETURN(this->OpenAudioOutAuto(out_parameter_internal, out_audio_out, out_name, name,
                                    parameter, process_handle, aruid));
}

Result IAudioOutManager::ListAudioOutsAuto(
    OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_outs, Out<u32> out_count) {
    if (!out_audio_outs.empty()) {
        out_audio_outs[0] = AudioDeviceName("DeviceOut");
        *out_count = 1;
        LOG_DEBUG(Service_Audio, "called. \nName=DeviceOut");
    } else {
        *out_count = 0;
        LOG_DEBUG(Service_Audio, "called. Empty buffer passed in.");
    }

    R_SUCCEED();
}

Result IAudioOutManager::OpenAudioOutAuto(
    Out<AudioOutParameterInternal> out_parameter_internal,
    Out<SharedPointer<IAudioOut>> out_audio_out,
    OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
    InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, AudioOutParameter parameter,
    InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid) {
    if (!process_handle) {
        LOG_ERROR(Service_Audio, "Failed to get process handle");
        R_THROW(ResultUnknown);
    }
    if (name.empty() || out_name.empty()) {
        LOG_ERROR(Service_Audio, "Invalid buffers");
        R_THROW(ResultUnknown);
    }

    size_t new_session_id{};
    R_TRY(impl->LinkToManager());
    R_TRY(impl->AcquireSessionId(new_session_id));

    const auto device_name = Common::StringFromBuffer(name[0].name);
    LOG_DEBUG(Service_Audio, "Opening new AudioOut, sessionid={}, free sessions={}", new_session_id,
              impl->num_free_sessions);

    auto audio_out = std::make_shared<IAudioOut>(system, *impl, new_session_id, device_name,
                                                 parameter, process_handle.Get(), aruid.pid);
    R_TRY(audio_out->GetImpl()->GetSystem().Initialize(device_name, parameter, process_handle.Get(),
                                                       aruid.pid));

    *out_audio_out = audio_out;
    impl->sessions[new_session_id] = audio_out->GetImpl();
    impl->applet_resource_user_ids[new_session_id] = aruid.pid;

    auto& out_system = impl->sessions[new_session_id]->GetSystem();
    *out_parameter_internal =
        AudioOutParameterInternal{.sample_rate = out_system.GetSampleRate(),
                                  .channel_count = out_system.GetChannelCount(),
                                  .sample_format = static_cast<u32>(out_system.GetSampleFormat()),
                                  .state = static_cast<u32>(out_system.GetState())};

    R_SUCCEED();
}

} // namespace Service::Audio


code:
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "audio_core/audio_out_manager.h"
#include "audio_core/out/audio_out.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"

namespace Service::Audio {

using AudioDeviceName = AudioCore::Renderer::AudioDevice::AudioDeviceName;
class IAudioOut;

class IAudioOutManager final : public ServiceFramework<IAudioOutManager> {
public:
    explicit IAudioOutManager(Core::System& system_);
    ~IAudioOutManager() override;

private:
    Result ListAudioOuts(OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_audio_outs,
                         Out<u32> out_count);
    Result OpenAudioOut(Out<AudioCore::AudioOut::AudioOutParameterInternal> out_parameter_internal,
                        Out<SharedPointer<IAudioOut>> out_audio_out,
                        OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name,
                        InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name,
                        AudioCore::AudioOut::AudioOutParameter parameter,
                        InCopyHandle<Kernel::KProcess> process_handle,
                        ClientAppletResourceUserId aruid);
    Result ListAudioOutsAuto(OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_outs,
                             Out<u32> out_count);
    Result OpenAudioOutAuto(
        Out<AudioCore::AudioOut::AudioOutParameterInternal> out_parameter_internal,
        Out<SharedPointer<IAudioOut>> out_audio_out,
        OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
        InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name,
        AudioCore::AudioOut::AudioOutParameter parameter,
        InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid);

    std::unique_ptr<AudioCore::AudioOut::Manager> impl;
};

} // namespace Service::Audio


code:
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "core/hle/service/audio/audio_renderer.h"
#include "core/hle/service/cmif_serialization.h"

namespace Service::Audio {
using namespace AudioCore::Renderer;

IAudioRenderer::IAudioRenderer(Core::System& system_, Manager& manager_,
                               AudioCore::AudioRendererParameterInternal& params,
                               Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
                               Kernel::KProcess* process_handle_, u64 applet_resource_user_id,
                               s32 session_id)
    : ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"},
      rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_},
      impl{std::make_unique<Renderer>(system_, manager, rendered_event)}, process_handle{
                                                                              process_handle_} {
    // clang-format off
    static const FunctionInfo functions[] = {
        {0, D<&IAudioRenderer::GetSampleRate>, "GetSampleRate"},
        {1, D<&IAudioRenderer::GetSampleCount>, "GetSampleCount"},
        {2, D<&IAudioRenderer::GetMixBufferCount>, "GetMixBufferCount"},
        {3, D<&IAudioRenderer::GetState>, "GetState"},
        {4, D<&IAudioRenderer::RequestUpdate>, "RequestUpdate"},
        {5, D<&IAudioRenderer::Start>, "Start"},
        {6, D<&IAudioRenderer::Stop>, "Stop"},
        {7, D<&IAudioRenderer::QuerySystemEvent>, "QuerySystemEvent"},
        {8, D<&IAudioRenderer::SetRenderingTimeLimit>, "SetRenderingTimeLimit"},
        {9, D<&IAudioRenderer::GetRenderingTimeLimit>, "GetRenderingTimeLimit"},
        {10, D<&IAudioRenderer::RequestUpdateAuto>, "RequestUpdateAuto"},
        {11, nullptr, "ExecuteAudioRendererRendering"},
        {12, D<&IAudioRenderer::SetVoiceDropParameter>, "SetVoiceDropParameter"},
        {13, D<&IAudioRenderer::GetVoiceDropParameter>, "GetVoiceDropParameter"},
    };
    // clang-format on
    RegisterHandlers(functions);

    process_handle->Open();
    impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle,
                     applet_resource_user_id, session_id);
}

IAudioRenderer::~IAudioRenderer() {
    impl->Finalize();
    service_context.CloseEvent(rendered_event);
    process_handle->Close();
}

Result IAudioRenderer::GetSampleRate(Out<u32> out_sample_rate) {
    *out_sample_rate = impl->GetSystem().GetSampleRate();
    LOG_DEBUG(Service_Audio, "called. Sample rate {}", *out_sample_rate);
    R_SUCCEED();
}

Result IAudioRenderer::GetSampleCount(Out<u32> out_sample_count) {
    *out_sample_count = impl->GetSystem().GetSampleCount();
    LOG_DEBUG(Service_Audio, "called. Sample count {}", *out_sample_count);
    R_SUCCEED();
}

Result IAudioRenderer::GetState(Out<u32> out_state) {
    *out_state = !impl->GetSystem().IsActive();
    LOG_DEBUG(Service_Audio, "called, state {}", *out_state);
    R_SUCCEED();
}

Result IAudioRenderer::GetMixBufferCount(Out<u32> out_mix_buffer_count) {
    LOG_DEBUG(Service_Audio, "called");
    *out_mix_buffer_count = impl->GetSystem().GetMixBufferCount();
    R_SUCCEED();
}

Result IAudioRenderer::RequestUpdate(OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
                                     OutBuffer<BufferAttr_HipcMapAlias> out_performance_buffer,
                                     InBuffer<BufferAttr_HipcMapAlias> input) {
    R_RETURN(this->RequestUpdateAuto(out_buffer, out_performance_buffer, input));
}

Result IAudioRenderer::RequestUpdateAuto(
    OutBuffer<BufferAttr_HipcAutoSelect> out_buffer,
    OutBuffer<BufferAttr_HipcAutoSelect> out_performance_buffer,
    InBuffer<BufferAttr_HipcAutoSelect> input) {
    LOG_TRACE(Service_Audio, "called");

    const auto result = impl->RequestUpdate(input, out_performance_buffer, out_buffer);
    if (result.IsFailure()) {
        LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!", result.GetDescription());
    }

    R_RETURN(result);
}

Result IAudioRenderer::Start() {
    LOG_DEBUG(Service_Audio, "called");
    impl->Start();
    R_SUCCEED();
}

Result IAudioRenderer::Stop() {
    LOG_DEBUG(Service_Audio, "called");
    impl->Stop();
    R_SUCCEED();
}

Result IAudioRenderer::QuerySystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
    LOG_DEBUG(Service_Audio, "called");
    R_UNLESS(impl->GetSystem().GetExecutionMode() != AudioCore::ExecutionMode::Manual,
             Audio::ResultNotSupported);
    *out_event = &rendered_event->GetReadableEvent();
    R_SUCCEED();
}

Result IAudioRenderer::SetRenderingTimeLimit(u32 rendering_time_limit) {
    LOG_DEBUG(Service_Audio, "called");
    impl->GetSystem().SetRenderingTimeLimit(rendering_time_limit);
    ;
    R_SUCCEED();
}

Result IAudioRenderer::GetRenderingTimeLimit(Out<u32> out_rendering_time_limit) {
    LOG_DEBUG(Service_Audio, "called");
    *out_rendering_time_limit = impl->GetSystem().GetRenderingTimeLimit();
    R_SUCCEED();
}

Result IAudioRenderer::SetVoiceDropParameter(f32 voice_drop_parameter) {
    LOG_DEBUG(Service_Audio, "called");
    impl->GetSystem().SetVoiceDropParameter(voice_drop_parameter);
    R_SUCCEED();
}

Result IAudioRenderer::GetVoiceDropParameter(Out<f32> out_voice_drop_parameter) {
    LOG_DEBUG(Service_Audio, "called");
    *out_voice_drop_parameter = impl->GetSystem().GetVoiceDropParameter();
    R_SUCCEED();
}

} // namespace Service::Audio


code:
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "audio_core/renderer/audio_renderer.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/service.h"

namespace Kernel {
class KReadableEvent;
}

namespace Service::Audio {

class IAudioRenderer final : public ServiceFramework<IAudioRenderer> {
public:
    explicit IAudioRenderer(Core::System& system_, AudioCore::Renderer::Manager& manager_,
                            AudioCore::AudioRendererParameterInternal& params,
                            Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
                            Kernel::KProcess* process_handle_, u64 applet_resource_user_id,
                            s32 session_id);
    ~IAudioRenderer() override;

private:
    Result GetSampleRate(Out<u32> out_sample_rate);
    Result GetSampleCount(Out<u32> out_sample_count);
    Result GetState(Out<u32> out_state);
    Result GetMixBufferCount(Out<u32> out_mix_buffer_count);
    Result RequestUpdate(OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
                         OutBuffer<BufferAttr_HipcMapAlias> out_performance_buffer,
                         InBuffer<BufferAttr_HipcMapAlias> input);
    Result RequestUpdateAuto(OutBuffer<BufferAttr_HipcAutoSelect> out_buffer,
                             OutBuffer<BufferAttr_HipcAutoSelect> out_performance_buffer,
                             InBuffer<BufferAttr_HipcAutoSelect> input);
    Result Start();
    Result Stop();
    Result QuerySystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
    Result SetRenderingTimeLimit(u32 rendering_time_limit);
    Result GetRenderingTimeLimit(Out<u32> out_rendering_time_limit);
    Result SetVoiceDropParameter(f32 voice_drop_parameter);
    Result GetVoiceDropParameter(Out<f32> out_voice_drop_parameter);

    KernelHelpers::ServiceContext service_context;
    Kernel::KEvent* rendered_event;
    AudioCore::Renderer::Manager& manager;
    std::unique_ptr<AudioCore::Renderer::Renderer> impl;
    Kernel::KProcess* process_handle;
    Common::ScratchBuffer<u8> output_buffer;
    Common::ScratchBuffer<u8> performance_buffer;
};

} // namespace Service::Audio


code:
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "audio_core/audio_render_manager.h"
#include "audio_core/common/feature_support.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_transfer_memory.h"
#include "core/hle/service/audio/audio_device.h"
#include "core/hle/service/audio/audio_renderer.h"
#include "core/hle/service/audio/audio_renderer_manager.h"
#include "core/hle/service/cmif_serialization.h"

namespace Service::Audio {

using namespace AudioCore::Renderer;

IAudioRendererManager::IAudioRendererManager(Core::System& system_)
    : ServiceFramework{system_, "audren:u"}, impl{std::make_unique<Manager>(system_)} {
    // clang-format off
    static const FunctionInfo functions[] = {
        {0, D<&IAudioRendererManager::OpenAudioRenderer>, "OpenAudioRenderer"},
        {1, D<&IAudioRendererManager::GetWorkBufferSize>, "GetWorkBufferSize"},
        {2, D<&IAudioRendererManager::GetAudioDeviceService>, "GetAudioDeviceService"},
        {3, nullptr, "OpenAudioRendererForManualExecution"},
        {4, D<&IAudioRendererManager::GetAudioDeviceServiceWithRevisionInfo>, "GetAudioDeviceServiceWithRevisionInfo"},
    };
    // clang-format on

    RegisterHandlers(functions);
}

IAudioRendererManager::~IAudioRendererManager() = default;

Result IAudioRendererManager::OpenAudioRenderer(
    Out<SharedPointer<IAudioRenderer>> out_audio_renderer,
    AudioCore::AudioRendererParameterInternal parameter,
    InCopyHandle<Kernel::KTransferMemory> tmem_handle, u64 tmem_size,
    InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid) {
    LOG_DEBUG(Service_Audio, "called");

    if (impl->GetSessionCount() + 1 > AudioCore::MaxRendererSessions) {
        LOG_ERROR(Service_Audio, "Too many AudioRenderer sessions open!");
        R_THROW(Audio::ResultOutOfSessions);
    }

    const auto session_id{impl->GetSessionId()};
    if (session_id == -1) {
        LOG_ERROR(Service_Audio, "Tried to open a session that's already in use!");
        R_THROW(Audio::ResultOutOfSessions);
    }

    LOG_DEBUG(Service_Audio, "Opened new AudioRenderer session {} sessions open {}", session_id,
              impl->GetSessionCount());

    *out_audio_renderer =
        std::make_shared<IAudioRenderer>(system, *impl, parameter, tmem_handle.Get(), tmem_size,
                                         process_handle.Get(), aruid.pid, session_id);
    R_SUCCEED();
}

Result IAudioRendererManager::GetWorkBufferSize(Out<u64> out_size,
                                                AudioCore::AudioRendererParameterInternal params) {
    LOG_DEBUG(Service_Audio, "called");

    R_TRY(impl->GetWorkBufferSize(params, *out_size))

    std::string output_info{};
    output_info += fmt::format("\tRevision {}", AudioCore::GetRevisionNum(params.revision));
    output_info +=
        fmt::format("\n\tSample Rate {}, Sample Count {}", params.sample_rate, params.sample_count);
    output_info += fmt::format("\n\tExecution Mode {}, Voice Drop Enabled {}",
                               static_cast<u32>(params.execution_mode), params.voice_drop_enabled);
    output_info += fmt::format(
        "\n\tSizes: Effects {:04X}, Mixes {:04X}, Sinks {:04X}, Submixes {:04X}, Splitter Infos "
        "{:04X}, Splitter Destinations {:04X}, Voices {:04X}, Performance Frames {:04X} External "
        "Context {:04X}",
        params.effects, params.mixes, params.sinks, params.sub_mixes, params.splitter_infos,
        params.splitter_destinations, params.voices, params.perf_frames,
        params.external_context_size);

    LOG_DEBUG(Service_Audio, "called.\nInput params:\n{}\nOutput params:\n\tWorkbuffer size {:08X}",
              output_info, *out_size);
    R_SUCCEED();
}

Result IAudioRendererManager::GetAudioDeviceService(
    Out<SharedPointer<IAudioDevice>> out_audio_device, ClientAppletResourceUserId aruid) {
    LOG_DEBUG(Service_Audio, "called, aruid={:#x}", aruid.pid);
    *out_audio_device = std::make_shared<IAudioDevice>(
        system, aruid.pid, Common::MakeMagic('R', 'E', 'V', '1'), num_audio_devices++);
    R_SUCCEED();
}

Result IAudioRendererManager::GetAudioDeviceServiceWithRevisionInfo(
    Out<SharedPointer<IAudioDevice>> out_audio_device, u32 revision,
    ClientAppletResourceUserId aruid) {
    LOG_DEBUG(Service_Audio, "called, revision={} aruid={:#x}", AudioCore::GetRevisionNum(revision),
              aruid.pid);
    *out_audio_device =
        std::make_shared<IAudioDevice>(system, aruid.pid, revision, num_audio_devices++);
    R_SUCCEED();
}

} // namespace Service::Audio


code:
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "audio_core/audio_render_manager.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"

namespace Service::Audio {

class IAudioDevice;
class IAudioRenderer;

class IAudioRendererManager final : public ServiceFramework<IAudioRendererManager> {
public:
    explicit IAudioRendererManager(Core::System& system_);
    ~IAudioRendererManager() override;

private:
    Result OpenAudioRenderer(Out<SharedPointer<IAudioRenderer>> out_audio_renderer,
                             AudioCore::AudioRendererParameterInternal parameter,
                             InCopyHandle<Kernel::KTransferMemory> tmem_handle, u64 tmem_size,
                             InCopyHandle<Kernel::KProcess> process_handle,
                             ClientAppletResourceUserId aruid);
    Result GetWorkBufferSize(Out<u64> out_size,
                             AudioCore::AudioRendererParameterInternal parameter);
    Result GetAudioDeviceService(Out<SharedPointer<IAudioDevice>> out_audio_device,
                                 ClientAppletResourceUserId aruid);
    Result GetAudioDeviceServiceWithRevisionInfo(Out<SharedPointer<IAudioDevice>> out_audio_device,
                                                 u32 revision, ClientAppletResourceUserId aruid);

    std::unique_ptr<AudioCore::Renderer::Manager> impl;
    u32 num_audio_devices{0};
};

} // namespace Service::Audio


code:
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "core/hle/result.h"

namespace Service::Audio {

constexpr Result ResultNotFound{ErrorModule::Audio, 1};
constexpr Result ResultOperationFailed{ErrorModule::Audio, 2};
constexpr Result ResultInvalidSampleRate{ErrorModule::Audio, 3};
constexpr Result ResultInsufficientBuffer{ErrorModule::Audio, 4};
constexpr Result ResultOutOfSessions{ErrorModule::Audio, 5};
constexpr Result ResultBufferCountReached{ErrorModule::Audio, 8};
constexpr Result ResultInvalidChannelCount{ErrorModule::Audio, 10};
constexpr Result ResultInvalidUpdateInfo{ErrorModule::Audio, 41};
constexpr Result ResultInvalidAddressInfo{ErrorModule::Audio, 42};
constexpr Result ResultNotSupported{ErrorModule::Audio, 513};
constexpr Result ResultInvalidHandle{ErrorModule::Audio, 1536};
constexpr Result ResultInvalidRevision{ErrorModule::Audio, 1537};

constexpr Result ResultLibOpusAllocFail{ErrorModule::HwOpus, 7};
constexpr Result ResultInputDataTooSmall{ErrorModule::HwOpus, 8};
constexpr Result ResultLibOpusInvalidState{ErrorModule::HwOpus, 6};
constexpr Result ResultLibOpusUnimplemented{ErrorModule::HwOpus, 5};
constexpr Result ResultLibOpusInvalidPacket{ErrorModule::HwOpus, 17};
constexpr Result ResultLibOpusInternalError{ErrorModule::HwOpus, 4};
constexpr Result ResultBufferTooSmall{ErrorModule::HwOpus, 3};
constexpr Result ResultLibOpusBadArg{ErrorModule::HwOpus, 2};
constexpr Result ResultInvalidOpusDSPReturnCode{ErrorModule::HwOpus, 259};
constexpr Result ResultInvalidOpusSampleRate{ErrorModule::HwOpus, 1001};
constexpr Result ResultInvalidOpusChannelCount{ErrorModule::HwOpus, 1002};

} // namespace Service::Audio


code:
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "core/hle/service/audio/final_output_recorder_manager.h"

namespace Service::Audio {

class IFinalOutputRecorder final : public ServiceFramework<IFinalOutputRecorder> {
public:
    explicit IFinalOutputRecorder(Core::System& system_)
        : ServiceFramework{system_, "IFinalOutputRecorder"} {
        // clang-format off
        static const FunctionInfo functions[] = {
            {0, nullptr, "GetFinalOutputRecorderState"},
            {1, nullptr, "Start"},
            {2, nullptr, "Stop"},
            {3, nullptr, "AppendFinalOutputRecorderBuffer"},
            {4, nullptr, "RegisterBufferEvent"},
            {5, nullptr, "GetReleasedFinalOutputRecorderBuffers"},
            {6, nullptr, "ContainsFinalOutputRecorderBuffer"},
            {7, nullptr, "GetFinalOutputRecorderBufferEndTime"},
            {8, nullptr, "AppendFinalOutputRecorderBufferAuto"},
            {9, nullptr, "GetReleasedFinalOutputRecorderBufferAuto"},
            {10, nullptr, "FlushFinalOutputRecorderBuffers"},
            {11, nullptr, "AttachWorkBuffer"},
        };
        // clang-format on

        RegisterHandlers(functions);
    }
};

IFinalOutputRecorderManager::IFinalOutputRecorderManager(Core::System& system_)
    : ServiceFramework{system_, "audrec:u"} {
    static const FunctionInfo functions[] = {
        {0, nullptr, "OpenFinalOutputRecorder"},
    };
    RegisterHandlers(functions);
}

IFinalOutputRecorderManager::~IFinalOutputRecorderManager() = default;

} // namespace Service::Audio


code:
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "core/hle/service/service.h"

namespace Core {
class System;
}

namespace Service::Audio {

class IFinalOutputRecorderManager final : public ServiceFramework<IFinalOutputRecorderManager> {
public:
    explicit IFinalOutputRecorderManager(Core::System& system_);
    ~IFinalOutputRecorderManager() override;
};

} // namespace Service::Audio


code:
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "core/hle/service/audio/final_output_recorder_manager_for_applet.h"

namespace Service::Audio {

IFinalOutputRecorderManagerForApplet::IFinalOutputRecorderManagerForApplet(Core::System& system_)
    : ServiceFramework{system_, "audrec:a"} {
    // clang-format off
    static const FunctionInfo functions[] = {
        {0, nullptr, "RequestSuspend"},
        {1, nullptr, "RequestResume"},
    };
    // clang-format on

    RegisterHandlers(functions);
}

IFinalOutputRecorderManagerForApplet::~IFinalOutputRecorderManagerForApplet() = default;

} // namespace Service::Audio


code:
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "core/hle/service/service.h"

namespace Core {
class System;
}

namespace Service::Audio {

class IFinalOutputRecorderManagerForApplet final
    : public ServiceFramework<IFinalOutputRecorderManagerForApplet> {
public:
    explicit IFinalOutputRecorderManagerForApplet(Core::System& system_);
    ~IFinalOutputRecorderManagerForApplet() override;
};

} // namespace Service::Audio


code:
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "core/hle/service/audio/hardware_opus_decoder.h"
#include "core/hle/service/cmif_serialization.h"

namespace Service::Audio {

using namespace AudioCore::OpusDecoder;

IHardwareOpusDecoder::IHardwareOpusDecoder(Core::System& system_, HardwareOpus& hardware_opus)
    : ServiceFramework{system_, "IHardwareOpusDecoder"},
      impl{std::make_unique<AudioCore::OpusDecoder::OpusDecoder>(system_, hardware_opus)} {
    // clang-format off
    static const FunctionInfo functions[] = {
        {0, D<&IHardwareOpusDecoder::DecodeInterleavedOld>, "DecodeInterleavedOld"},
        {1, D<&IHardwareOpusDecoder::SetContext>, "SetContext"},
        {2, D<&IHardwareOpusDecoder::DecodeInterleavedForMultiStreamOld>, "DecodeInterleavedForMultiStreamOld"},
        {3, D<&IHardwareOpusDecoder::SetContextForMultiStream>, "SetContextForMultiStream"},
        {4, D<&IHardwareOpusDecoder::DecodeInterleavedWithPerfOld>, "DecodeInterleavedWithPerfOld"},
        {5, D<&IHardwareOpusDecoder::DecodeInterleavedForMultiStreamWithPerfOld>, "DecodeInterleavedForMultiStreamWithPerfOld"},
        {6, D<&IHardwareOpusDecoder::DecodeInterleavedWithPerfAndResetOld>, "DecodeInterleavedWithPerfAndResetOld"},
        {7, D<&IHardwareOpusDecoder::DecodeInterleavedForMultiStreamWithPerfAndResetOld>, "DecodeInterleavedForMultiStreamWithPerfAndResetOld"},
        {8, D<&IHardwareOpusDecoder::DecodeInterleaved>, "DecodeInterleaved"},
        {9, D<&IHardwareOpusDecoder::DecodeInterleavedForMultiStream>, "DecodeInterleavedForMultiStream"},
    };
    // clang-format on

    RegisterHandlers(functions);
}

IHardwareOpusDecoder::~IHardwareOpusDecoder() = default;

Result IHardwareOpusDecoder::Initialize(const OpusParametersEx& params,
                                        Kernel::KTransferMemory* transfer_memory,
                                        u64 transfer_memory_size) {
    return impl->Initialize(params, transfer_memory, transfer_memory_size);
}

Result IHardwareOpusDecoder::Initialize(const OpusMultiStreamParametersEx& params,
                                        Kernel::KTransferMemory* transfer_memory,
                                        u64 transfer_memory_size) {
    return impl->Initialize(params, transfer_memory, transfer_memory_size);
}

Result IHardwareOpusDecoder::DecodeInterleavedOld(OutBuffer<BufferAttr_HipcMapAlias> out_pcm_data,
                                                  Out<u32> out_data_size, Out<u32> out_sample_count,
                                                  InBuffer<BufferAttr_HipcMapAlias> opus_data) {
    R_TRY(impl->DecodeInterleaved(out_data_size, nullptr, out_sample_count, opus_data, out_pcm_data,
                                  false));
    LOG_DEBUG(Service_Audio, "bytes read {:#x} samples generated {}", *out_data_size,
              *out_sample_count);
    R_SUCCEED();
}

Result IHardwareOpusDecoder::SetContext(InBuffer<BufferAttr_HipcMapAlias> decoder_context) {
    LOG_DEBUG(Service_Audio, "called");
    R_RETURN(impl->SetContext(decoder_context));
}

Result IHardwareOpusDecoder::DecodeInterleavedForMultiStreamOld(
    OutBuffer<BufferAttr_HipcMapAlias> out_pcm_data, Out<u32> out_data_size,
    Out<u32> out_sample_count, InBuffer<BufferAttr_HipcMapAlias> opus_data) {
    R_TRY(impl->DecodeInterleavedForMultiStream(out_data_size, nullptr, out_sample_count, opus_data,
                                                out_pcm_data, false));
    LOG_DEBUG(Service_Audio, "bytes read {:#x} samples generated {}", *out_data_size,
              *out_sample_count);
    R_SUCCEED();
}

Result IHardwareOpusDecoder::SetContextForMultiStream(
    InBuffer<BufferAttr_HipcMapAlias> decoder_context) {
    LOG_DEBUG(Service_Audio, "called");
    R_RETURN(impl->SetContext(decoder_context));
}

Result IHardwareOpusDecoder::DecodeInterleavedWithPerfOld(
    OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
    Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
    InBuffer<BufferAttr_HipcMapAlias> opus_data) {
    R_TRY(impl->DecodeInterleaved(out_data_size, out_time_taken, out_sample_count, opus_data,
                                  out_pcm_data, false));
    LOG_DEBUG(Service_Audio, "bytes read {:#x} samples generated {} time taken {}", *out_data_size,
              *out_sample_count, *out_time_taken);
    R_SUCCEED();
}

Result IHardwareOpusDecoder::DecodeInterleavedForMultiStreamWithPerfOld(
    OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
    Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
    InBuffer<BufferAttr_HipcMapAlias> opus_data) {
    R_TRY(impl->DecodeInterleavedForMultiStream(out_data_size, out_time_taken, out_sample_count,
                                                opus_data, out_pcm_data, false));
    LOG_DEBUG(Service_Audio, "bytes read {:#x} samples generated {} time taken {}", *out_data_size,
              *out_sample_count, *out_time_taken);
    R_SUCCEED();
}

Result IHardwareOpusDecoder::DecodeInterleavedWithPerfAndResetOld(
    OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
    Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
    InBuffer<BufferAttr_HipcMapAlias> opus_data, bool reset) {
    R_TRY(impl->DecodeInterleaved(out_data_size, out_time_taken, out_sample_count, opus_data,
                                  out_pcm_data, reset));
    LOG_DEBUG(Service_Audio, "reset {} bytes read {:#x} samples generated {} time taken {}", reset,
              *out_data_size, *out_sample_count, *out_time_taken);
    R_SUCCEED();
}

Result IHardwareOpusDecoder::DecodeInterleavedForMultiStreamWithPerfAndResetOld(
    OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
    Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
    InBuffer<BufferAttr_HipcMapAlias> opus_data, bool reset) {
    R_TRY(impl->DecodeInterleavedForMultiStream(out_data_size, out_time_taken, out_sample_count,
                                                opus_data, out_pcm_data, reset));
    LOG_DEBUG(Service_Audio, "reset {} bytes read {:#x} samples generated {} time taken {}", reset,
              *out_data_size, *out_sample_count, *out_time_taken);
    R_SUCCEED();
}

Result IHardwareOpusDecoder::DecodeInterleaved(
    OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
    Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
    InBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> opus_data,
    bool reset) {
    R_TRY(impl->DecodeInterleaved(out_data_size, out_time_taken, out_sample_count, opus_data,
                                  out_pcm_data, reset));
    LOG_DEBUG(Service_Audio, "reset {} bytes read {:#x} samples generated {} time taken {}", reset,
              *out_data_size, *out_sample_count, *out_time_taken);
    R_SUCCEED();
}

Result IHardwareOpusDecoder::DecodeInterleavedForMultiStream(
    OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
    Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
    InBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> opus_data,
    bool reset) {
    R_TRY(impl->DecodeInterleavedForMultiStream(out_data_size, out_time_taken, out_sample_count,
                                                opus_data, out_pcm_data, reset));
    LOG_DEBUG(Service_Audio, "reset {} bytes read {:#x} samples generated {} time taken {}", reset,
              *out_data_size, *out_sample_count, *out_time_taken);
    R_SUCCEED();
}

} // namespace Service::Audio