diff options
| author | 2022-07-16 23:48:45 +0100 | |
|---|---|---|
| committer | 2022-07-22 01:11:32 +0100 | |
| commit | 458da8a94877677f086f06cdeecf959ec4283a33 (patch) | |
| tree | 583166d77602ad90a0d552f37de8729ad80fd6c1 /src/audio_core/in | |
| parent | Merge pull request #8598 from Link4565/recv-dontwait (diff) | |
| download | yuzu-458da8a94877677f086f06cdeecf959ec4283a33.tar.gz yuzu-458da8a94877677f086f06cdeecf959ec4283a33.tar.xz yuzu-458da8a94877677f086f06cdeecf959ec4283a33.zip | |
Project Andio
Diffstat (limited to 'src/audio_core/in')
| -rw-r--r-- | src/audio_core/in/audio_in.cpp | 100 | ||||
| -rw-r--r-- | src/audio_core/in/audio_in.h | 147 | ||||
| -rw-r--r-- | src/audio_core/in/audio_in_system.cpp | 213 | ||||
| -rw-r--r-- | src/audio_core/in/audio_in_system.h | 275 |
4 files changed, 735 insertions, 0 deletions
diff --git a/src/audio_core/in/audio_in.cpp b/src/audio_core/in/audio_in.cpp new file mode 100644 index 000000000..c946895d6 --- /dev/null +++ b/src/audio_core/in/audio_in.cpp | |||
| @@ -0,0 +1,100 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "audio_core/audio_in_manager.h" | ||
| 5 | #include "audio_core/in/audio_in.h" | ||
| 6 | #include "core/hle/kernel/k_event.h" | ||
| 7 | |||
| 8 | namespace AudioCore::AudioIn { | ||
| 9 | |||
| 10 | In::In(Core::System& system_, Manager& manager_, Kernel::KEvent* event_, size_t session_id_) | ||
| 11 | : manager{manager_}, parent_mutex{manager.mutex}, event{event_}, system{system_, event, | ||
| 12 | session_id_} {} | ||
| 13 | |||
| 14 | void In::Free() { | ||
| 15 | std::scoped_lock l{parent_mutex}; | ||
| 16 | manager.ReleaseSessionId(system.GetSessionId()); | ||
| 17 | } | ||
| 18 | |||
| 19 | System& In::GetSystem() { | ||
| 20 | return system; | ||
| 21 | } | ||
| 22 | |||
| 23 | AudioIn::State In::GetState() { | ||
| 24 | std::scoped_lock l{parent_mutex}; | ||
| 25 | return system.GetState(); | ||
| 26 | } | ||
| 27 | |||
| 28 | Result In::StartSystem() { | ||
| 29 | std::scoped_lock l{parent_mutex}; | ||
| 30 | return system.Start(); | ||
| 31 | } | ||
| 32 | |||
| 33 | void In::StartSession() { | ||
| 34 | std::scoped_lock l{parent_mutex}; | ||
| 35 | system.StartSession(); | ||
| 36 | } | ||
| 37 | |||
| 38 | Result In::StopSystem() { | ||
| 39 | std::scoped_lock l{parent_mutex}; | ||
| 40 | return system.Stop(); | ||
| 41 | } | ||
| 42 | |||
| 43 | Result In::AppendBuffer(const AudioInBuffer& buffer, u64 tag) { | ||
| 44 | std::scoped_lock l{parent_mutex}; | ||
| 45 | |||
| 46 | if (system.AppendBuffer(buffer, tag)) { | ||
| 47 | return ResultSuccess; | ||
| 48 | } | ||
| 49 | return Service::Audio::ERR_BUFFER_COUNT_EXCEEDED; | ||
| 50 | } | ||
| 51 | |||
| 52 | void In::ReleaseAndRegisterBuffers() { | ||
| 53 | std::scoped_lock l{parent_mutex}; | ||
| 54 | if (system.GetState() == State::Started) { | ||
| 55 | system.ReleaseBuffers(); | ||
| 56 | system.RegisterBuffers(); | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 60 | bool In::FlushAudioInBuffers() { | ||
| 61 | std::scoped_lock l{parent_mutex}; | ||
| 62 | return system.FlushAudioInBuffers(); | ||
| 63 | } | ||
| 64 | |||
| 65 | u32 In::GetReleasedBuffers(std::span<u64> tags) { | ||
| 66 | std::scoped_lock l{parent_mutex}; | ||
| 67 | return system.GetReleasedBuffers(tags); | ||
| 68 | } | ||
| 69 | |||
| 70 | Kernel::KReadableEvent& In::GetBufferEvent() { | ||
| 71 | std::scoped_lock l{parent_mutex}; | ||
| 72 | return event->GetReadableEvent(); | ||
| 73 | } | ||
| 74 | |||
| 75 | f32 In::GetVolume() { | ||
| 76 | std::scoped_lock l{parent_mutex}; | ||
| 77 | return system.GetVolume(); | ||
| 78 | } | ||
| 79 | |||
| 80 | void In::SetVolume(f32 volume) { | ||
| 81 | std::scoped_lock l{parent_mutex}; | ||
| 82 | system.SetVolume(volume); | ||
| 83 | } | ||
| 84 | |||
| 85 | bool In::ContainsAudioBuffer(u64 tag) { | ||
| 86 | std::scoped_lock l{parent_mutex}; | ||
| 87 | return system.ContainsAudioBuffer(tag); | ||
| 88 | } | ||
| 89 | |||
| 90 | u32 In::GetBufferCount() { | ||
| 91 | std::scoped_lock l{parent_mutex}; | ||
| 92 | return system.GetBufferCount(); | ||
| 93 | } | ||
| 94 | |||
| 95 | u64 In::GetPlayedSampleCount() { | ||
| 96 | std::scoped_lock l{parent_mutex}; | ||
| 97 | return system.GetPlayedSampleCount(); | ||
| 98 | } | ||
| 99 | |||
| 100 | } // namespace AudioCore::AudioIn | ||
diff --git a/src/audio_core/in/audio_in.h b/src/audio_core/in/audio_in.h new file mode 100644 index 000000000..6253891d5 --- /dev/null +++ b/src/audio_core/in/audio_in.h | |||
| @@ -0,0 +1,147 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <mutex> | ||
| 7 | |||
| 8 | #include "audio_core/in/audio_in_system.h" | ||
| 9 | |||
| 10 | namespace Core { | ||
| 11 | class System; | ||
| 12 | } | ||
| 13 | |||
| 14 | namespace Kernel { | ||
| 15 | class KEvent; | ||
| 16 | class KReadableEvent; | ||
| 17 | } // namespace Kernel | ||
| 18 | |||
| 19 | namespace AudioCore::AudioIn { | ||
| 20 | class Manager; | ||
| 21 | |||
| 22 | /** | ||
| 23 | * Interface between the service and audio in system. Mainly responsible for forwarding service | ||
| 24 | * calls to the system. | ||
| 25 | */ | ||
| 26 | class In { | ||
| 27 | public: | ||
| 28 | explicit In(Core::System& system, Manager& manager, Kernel::KEvent* event, size_t session_id); | ||
| 29 | |||
| 30 | /** | ||
| 31 | * Free this audio in from the audio in manager. | ||
| 32 | */ | ||
| 33 | void Free(); | ||
| 34 | |||
| 35 | /** | ||
| 36 | * Get this audio in's system. | ||
| 37 | */ | ||
| 38 | System& GetSystem(); | ||
| 39 | |||
| 40 | /** | ||
| 41 | * Get the current state. | ||
| 42 | * | ||
| 43 | * @return Started or Stopped. | ||
| 44 | */ | ||
| 45 | AudioIn::State GetState(); | ||
| 46 | |||
| 47 | /** | ||
| 48 | * Start the system | ||
| 49 | * | ||
| 50 | * @return Result code | ||
| 51 | */ | ||
| 52 | Result StartSystem(); | ||
| 53 | |||
| 54 | /** | ||
| 55 | * Start the system's device session. | ||
| 56 | */ | ||
| 57 | void StartSession(); | ||
| 58 | |||
| 59 | /** | ||
| 60 | * Stop the system. | ||
| 61 | * | ||
| 62 | * @return Result code | ||
| 63 | */ | ||
| 64 | Result StopSystem(); | ||
| 65 | |||
| 66 | /** | ||
| 67 | * Append a new buffer to the system, the buffer event will be signalled when it is filled. | ||
| 68 | * | ||
| 69 | * @param buffer - The new buffer to append. | ||
| 70 | * @param tag - Unique tag for this buffer. | ||
| 71 | * @return Result code. | ||
| 72 | */ | ||
| 73 | Result AppendBuffer(const AudioInBuffer& buffer, u64 tag); | ||
| 74 | |||
| 75 | /** | ||
| 76 | * Release all completed buffers, and register any appended. | ||
| 77 | */ | ||
| 78 | void ReleaseAndRegisterBuffers(); | ||
| 79 | |||
| 80 | /** | ||
| 81 | * Flush all buffers. | ||
| 82 | */ | ||
| 83 | bool FlushAudioInBuffers(); | ||
| 84 | |||
| 85 | /** | ||
| 86 | * Get all of the currently released buffers. | ||
| 87 | * | ||
| 88 | * @param tags - Output container for the buffer tags which were released. | ||
| 89 | * @return The number of buffers released. | ||
| 90 | */ | ||
| 91 | u32 GetReleasedBuffers(std::span<u64> tags); | ||
| 92 | |||
| 93 | /** | ||
| 94 | * Get the buffer event for this audio in, this event will be signalled when a buffer is filled. | ||
| 95 | * | ||
| 96 | * @return The buffer event. | ||
| 97 | */ | ||
| 98 | Kernel::KReadableEvent& GetBufferEvent(); | ||
| 99 | |||
| 100 | /** | ||
| 101 | * Get the current system volume. | ||
| 102 | * | ||
| 103 | * @return The current volume. | ||
| 104 | */ | ||
| 105 | f32 GetVolume(); | ||
| 106 | |||
| 107 | /** | ||
| 108 | * Set the system volume. | ||
| 109 | * | ||
| 110 | * @param volume - The volume to set. | ||
| 111 | */ | ||
| 112 | void SetVolume(f32 volume); | ||
| 113 | |||
| 114 | /** | ||
| 115 | * Check if a buffer is in the system. | ||
| 116 | * | ||
| 117 | * @param tag - The tag to search for. | ||
| 118 | * @return True if the buffer is in the system, otherwise false. | ||
| 119 | */ | ||
| 120 | bool ContainsAudioBuffer(u64 tag); | ||
| 121 | |||
| 122 | /** | ||
| 123 | * Get the maximum number of buffers. | ||
| 124 | * | ||
| 125 | * @return The maximum number of buffers. | ||
| 126 | */ | ||
| 127 | u32 GetBufferCount(); | ||
| 128 | |||
| 129 | /** | ||
| 130 | * Get the total played sample count for this audio in. | ||
| 131 | * | ||
| 132 | * @return The played sample count. | ||
| 133 | */ | ||
| 134 | u64 GetPlayedSampleCount(); | ||
| 135 | |||
| 136 | private: | ||
| 137 | /// The AudioIn::Manager this audio in is registered with | ||
| 138 | Manager& manager; | ||
| 139 | /// Manager's mutex | ||
| 140 | std::recursive_mutex& parent_mutex; | ||
| 141 | /// Buffer event, signalled when buffers are ready to be released | ||
| 142 | Kernel::KEvent* event; | ||
| 143 | /// Main audio in system | ||
| 144 | System system; | ||
| 145 | }; | ||
| 146 | |||
| 147 | } // namespace AudioCore::AudioIn | ||
diff --git a/src/audio_core/in/audio_in_system.cpp b/src/audio_core/in/audio_in_system.cpp new file mode 100644 index 000000000..ec5d37ed4 --- /dev/null +++ b/src/audio_core/in/audio_in_system.cpp | |||
| @@ -0,0 +1,213 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <mutex> | ||
| 5 | #include "audio_core/audio_event.h" | ||
| 6 | #include "audio_core/audio_manager.h" | ||
| 7 | #include "audio_core/in/audio_in_system.h" | ||
| 8 | #include "common/logging/log.h" | ||
| 9 | #include "core/core.h" | ||
| 10 | #include "core/core_timing.h" | ||
| 11 | #include "core/hle/kernel/k_event.h" | ||
| 12 | |||
| 13 | namespace AudioCore::AudioIn { | ||
| 14 | |||
| 15 | System::System(Core::System& system_, Kernel::KEvent* event_, const size_t session_id_) | ||
| 16 | : system{system_}, buffer_event{event_}, | ||
| 17 | session_id{session_id_}, session{std::make_unique<DeviceSession>(system_)} {} | ||
| 18 | |||
| 19 | System::~System() { | ||
| 20 | Finalize(); | ||
| 21 | } | ||
| 22 | |||
| 23 | void System::Finalize() { | ||
| 24 | Stop(); | ||
| 25 | session->Finalize(); | ||
| 26 | buffer_event->GetWritableEvent().Signal(); | ||
| 27 | } | ||
| 28 | |||
| 29 | void System::StartSession() { | ||
| 30 | session->Start(); | ||
| 31 | } | ||
| 32 | |||
| 33 | size_t System::GetSessionId() const { | ||
| 34 | return session_id; | ||
| 35 | } | ||
| 36 | |||
| 37 | std::string_view System::GetDefaultDeviceName() { | ||
| 38 | return "BuiltInHeadset"; | ||
| 39 | } | ||
| 40 | |||
| 41 | std::string_view System::GetDefaultUacDeviceName() { | ||
| 42 | return "Uac"; | ||
| 43 | } | ||
| 44 | |||
| 45 | Result System::IsConfigValid(const std::string_view device_name, | ||
| 46 | const AudioInParameter& in_params) { | ||
| 47 | if ((device_name.size() > 0) && | ||
| 48 | (device_name != GetDefaultDeviceName() && device_name != GetDefaultUacDeviceName())) { | ||
| 49 | return Service::Audio::ERR_INVALID_DEVICE_NAME; | ||
| 50 | } | ||
| 51 | |||
| 52 | if (in_params.sample_rate != TargetSampleRate && in_params.sample_rate > 0) { | ||
| 53 | return Service::Audio::ERR_INVALID_SAMPLE_RATE; | ||
| 54 | } | ||
| 55 | |||
| 56 | return ResultSuccess; | ||
| 57 | } | ||
| 58 | |||
| 59 | Result System::Initialize(std::string& device_name, const AudioInParameter& in_params, | ||
| 60 | const u32 handle_, const u64 applet_resource_user_id_) { | ||
| 61 | auto result{IsConfigValid(device_name, in_params)}; | ||
| 62 | if (result.IsError()) { | ||
| 63 | return result; | ||
| 64 | } | ||
| 65 | |||
| 66 | handle = handle_; | ||
| 67 | applet_resource_user_id = applet_resource_user_id_; | ||
| 68 | if (device_name.empty() || device_name[0] == '\0') { | ||
| 69 | name = std::string(GetDefaultDeviceName()); | ||
| 70 | } else { | ||
| 71 | name = std::move(device_name); | ||
| 72 | } | ||
| 73 | |||
| 74 | sample_rate = TargetSampleRate; | ||
| 75 | sample_format = SampleFormat::PcmInt16; | ||
| 76 | channel_count = in_params.channel_count <= 2 ? 2 : 6; | ||
| 77 | volume = 1.0f; | ||
| 78 | is_uac = name == "Uac"; | ||
| 79 | return ResultSuccess; | ||
| 80 | } | ||
| 81 | |||
| 82 | Result System::Start() { | ||
| 83 | if (state != State::Stopped) { | ||
| 84 | return Service::Audio::ERR_OPERATION_FAILED; | ||
| 85 | } | ||
| 86 | |||
| 87 | session->Initialize(name, sample_format, channel_count, session_id, handle, | ||
| 88 | applet_resource_user_id, Sink::StreamType::In); | ||
| 89 | session->SetVolume(volume); | ||
| 90 | session->Start(); | ||
| 91 | state = State::Started; | ||
| 92 | |||
| 93 | std::vector<AudioBuffer> buffers_to_flush{}; | ||
| 94 | buffers.RegisterBuffers(buffers_to_flush); | ||
| 95 | session->AppendBuffers(buffers_to_flush); | ||
| 96 | |||
| 97 | return ResultSuccess; | ||
| 98 | } | ||
| 99 | |||
| 100 | Result System::Stop() { | ||
| 101 | if (state == State::Started) { | ||
| 102 | session->Stop(); | ||
| 103 | session->SetVolume(0.0f); | ||
| 104 | state = State::Stopped; | ||
| 105 | } | ||
| 106 | |||
| 107 | return ResultSuccess; | ||
| 108 | } | ||
| 109 | |||
| 110 | bool System::AppendBuffer(const AudioInBuffer& buffer, const u64 tag) { | ||
| 111 | if (buffers.GetTotalBufferCount() == BufferCount) { | ||
| 112 | return false; | ||
| 113 | } | ||
| 114 | |||
| 115 | AudioBuffer new_buffer{ | ||
| 116 | .played_timestamp = 0, .samples = buffer.samples, .tag = tag, .size = buffer.size}; | ||
| 117 | |||
| 118 | buffers.AppendBuffer(new_buffer); | ||
| 119 | RegisterBuffers(); | ||
| 120 | |||
| 121 | return true; | ||
| 122 | } | ||
| 123 | |||
| 124 | void System::RegisterBuffers() { | ||
| 125 | if (state == State::Started) { | ||
| 126 | std::vector<AudioBuffer> registered_buffers{}; | ||
| 127 | buffers.RegisterBuffers(registered_buffers); | ||
| 128 | session->AppendBuffers(registered_buffers); | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 132 | void System::ReleaseBuffers() { | ||
| 133 | bool signal{buffers.ReleaseBuffers(system.CoreTiming(), *session)}; | ||
| 134 | |||
| 135 | if (signal) { | ||
| 136 | // Signal if any buffer was released, or if none are registered, we need more. | ||
| 137 | buffer_event->GetWritableEvent().Signal(); | ||
| 138 | } | ||
| 139 | } | ||
| 140 | |||
| 141 | u32 System::GetReleasedBuffers(std::span<u64> tags) { | ||
| 142 | return buffers.GetReleasedBuffers(tags); | ||
| 143 | } | ||
| 144 | |||
| 145 | bool System::FlushAudioInBuffers() { | ||
| 146 | if (state != State::Started) { | ||
| 147 | return false; | ||
| 148 | } | ||
| 149 | |||
| 150 | u32 buffers_released{}; | ||
| 151 | buffers.FlushBuffers(buffers_released); | ||
| 152 | |||
| 153 | if (buffers_released > 0) { | ||
| 154 | buffer_event->GetWritableEvent().Signal(); | ||
| 155 | } | ||
| 156 | return true; | ||
| 157 | } | ||
| 158 | |||
| 159 | u16 System::GetChannelCount() const { | ||
| 160 | return channel_count; | ||
| 161 | } | ||
| 162 | |||
| 163 | u32 System::GetSampleRate() const { | ||
| 164 | return sample_rate; | ||
| 165 | } | ||
| 166 | |||
| 167 | SampleFormat System::GetSampleFormat() const { | ||
| 168 | return sample_format; | ||
| 169 | } | ||
| 170 | |||
| 171 | State System::GetState() { | ||
| 172 | switch (state) { | ||
| 173 | case State::Started: | ||
| 174 | case State::Stopped: | ||
| 175 | return state; | ||
| 176 | default: | ||
| 177 | LOG_ERROR(Service_Audio, "AudioIn invalid state!"); | ||
| 178 | state = State::Stopped; | ||
| 179 | break; | ||
| 180 | } | ||
| 181 | return state; | ||
| 182 | } | ||
| 183 | |||
| 184 | std::string System::GetName() const { | ||
| 185 | return name; | ||
| 186 | } | ||
| 187 | |||
| 188 | f32 System::GetVolume() const { | ||
| 189 | return volume; | ||
| 190 | } | ||
| 191 | |||
| 192 | void System::SetVolume(const f32 volume_) { | ||
| 193 | volume = volume_; | ||
| 194 | session->SetVolume(volume_); | ||
| 195 | } | ||
| 196 | |||
| 197 | bool System::ContainsAudioBuffer(const u64 tag) { | ||
| 198 | return buffers.ContainsBuffer(tag); | ||
| 199 | } | ||
| 200 | |||
| 201 | u32 System::GetBufferCount() { | ||
| 202 | return buffers.GetAppendedRegisteredCount(); | ||
| 203 | } | ||
| 204 | |||
| 205 | u64 System::GetPlayedSampleCount() const { | ||
| 206 | return session->GetPlayedSampleCount(); | ||
| 207 | } | ||
| 208 | |||
| 209 | bool System::IsUac() const { | ||
| 210 | return is_uac; | ||
| 211 | } | ||
| 212 | |||
| 213 | } // namespace AudioCore::AudioIn | ||
diff --git a/src/audio_core/in/audio_in_system.h b/src/audio_core/in/audio_in_system.h new file mode 100644 index 000000000..165e35d83 --- /dev/null +++ b/src/audio_core/in/audio_in_system.h | |||
| @@ -0,0 +1,275 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <atomic> | ||
| 7 | #include <memory> | ||
| 8 | #include <span> | ||
| 9 | #include <string> | ||
| 10 | |||
| 11 | #include "audio_core/common/common.h" | ||
| 12 | #include "audio_core/device/audio_buffers.h" | ||
| 13 | #include "audio_core/device/device_session.h" | ||
| 14 | #include "core/hle/service/audio/errors.h" | ||
| 15 | |||
| 16 | namespace Core { | ||
| 17 | class System; | ||
| 18 | } | ||
| 19 | |||
| 20 | namespace Kernel { | ||
| 21 | class KEvent; | ||
| 22 | } | ||
| 23 | |||
| 24 | namespace AudioCore::AudioIn { | ||
| 25 | |||
| 26 | constexpr SessionTypes SessionType = SessionTypes::AudioIn; | ||
| 27 | |||
| 28 | struct AudioInParameter { | ||
| 29 | /* 0x0 */ s32_le sample_rate; | ||
| 30 | /* 0x4 */ u16_le channel_count; | ||
| 31 | /* 0x6 */ u16_le reserved; | ||
| 32 | }; | ||
| 33 | static_assert(sizeof(AudioInParameter) == 0x8, "AudioInParameter is an invalid size"); | ||
| 34 | |||
| 35 | struct AudioInParameterInternal { | ||
| 36 | /* 0x0 */ u32_le sample_rate; | ||
| 37 | /* 0x4 */ u32_le channel_count; | ||
| 38 | /* 0x8 */ u32_le sample_format; | ||
| 39 | /* 0xC */ u32_le state; | ||
| 40 | }; | ||
| 41 | static_assert(sizeof(AudioInParameterInternal) == 0x10, | ||
| 42 | "AudioInParameterInternal is an invalid size"); | ||
| 43 | |||
| 44 | struct AudioInBuffer { | ||
| 45 | /* 0x00 */ AudioInBuffer* next; | ||
| 46 | /* 0x08 */ VAddr samples; | ||
| 47 | /* 0x10 */ u64 capacity; | ||
| 48 | /* 0x18 */ u64 size; | ||
| 49 | /* 0x20 */ u64 offset; | ||
| 50 | }; | ||
| 51 | static_assert(sizeof(AudioInBuffer) == 0x28, "AudioInBuffer is an invalid size"); | ||
| 52 | |||
| 53 | enum class State { | ||
| 54 | Started, | ||
| 55 | Stopped, | ||
| 56 | }; | ||
| 57 | |||
| 58 | /** | ||
| 59 | * Controls and drives audio input. | ||
| 60 | */ | ||
| 61 | class System { | ||
| 62 | public: | ||
| 63 | explicit System(Core::System& system, Kernel::KEvent* event, size_t session_id); | ||
| 64 | ~System(); | ||
| 65 | |||
| 66 | /** | ||
| 67 | * Get the default audio input device name. | ||
| 68 | * | ||
| 69 | * @return The default audio input device name. | ||
| 70 | */ | ||
| 71 | std::string_view GetDefaultDeviceName(); | ||
| 72 | |||
| 73 | /** | ||
| 74 | * Get the default USB audio input device name. | ||
| 75 | * This is preferred over non-USB as some games refuse to work with the BuiltInHeadset | ||
| 76 | * (e.g Let's Sing). | ||
| 77 | * | ||
| 78 | * @return The default USB audio input device name. | ||
| 79 | */ | ||
| 80 | std::string_view GetDefaultUacDeviceName(); | ||
| 81 | |||
| 82 | /** | ||
| 83 | * Is the given initialize config valid? | ||
| 84 | * | ||
| 85 | * @param device_name - The name of the requested input device. | ||
| 86 | * @param in_params - Input parameters, see AudioInParameter. | ||
| 87 | * @return Result code. | ||
| 88 | */ | ||
| 89 | Result IsConfigValid(std::string_view device_name, const AudioInParameter& in_params); | ||
| 90 | |||
| 91 | /** | ||
| 92 | * Initialize this system. | ||
| 93 | * | ||
| 94 | * @param device_name - The name of the requested input device. | ||
| 95 | * @param in_params - Input parameters, see AudioInParameter. | ||
| 96 | * @param handle - Unused. | ||
| 97 | * @param applet_resource_user_id - Unused. | ||
| 98 | * @return Result code. | ||
| 99 | */ | ||
| 100 | Result Initialize(std::string& device_name, const AudioInParameter& in_params, u32 handle, | ||
| 101 | u64 applet_resource_user_id); | ||
| 102 | |||
| 103 | /** | ||
| 104 | * Start this system. | ||
| 105 | * | ||
| 106 | * @return Result code. | ||
| 107 | */ | ||
| 108 | Result Start(); | ||
| 109 | |||
| 110 | /** | ||
| 111 | * Stop this system. | ||
| 112 | * | ||
| 113 | * @return Result code. | ||
| 114 | */ | ||
| 115 | Result Stop(); | ||
| 116 | |||
| 117 | /** | ||
| 118 | * Finalize this system. | ||
| 119 | */ | ||
| 120 | void Finalize(); | ||
| 121 | |||
| 122 | /** | ||
| 123 | * Start this system's device session. | ||
| 124 | */ | ||
| 125 | void StartSession(); | ||
| 126 | |||
| 127 | /** | ||
| 128 | * Get this system's id. | ||
| 129 | */ | ||
| 130 | size_t GetSessionId() const; | ||
| 131 | |||
| 132 | /** | ||
| 133 | * Append a new buffer to the device. | ||
| 134 | * | ||
| 135 | * @param buffer - New buffer to append. | ||
| 136 | * @param tag - Unique tag of the buffer. | ||
| 137 | * @return True if the buffer was appended, otherwise false. | ||
| 138 | */ | ||
| 139 | bool AppendBuffer(const AudioInBuffer& buffer, u64 tag); | ||
| 140 | |||
| 141 | /** | ||
| 142 | * Register all appended buffers. | ||
| 143 | */ | ||
| 144 | void RegisterBuffers(); | ||
| 145 | |||
| 146 | /** | ||
| 147 | * Release all registered buffers. | ||
| 148 | */ | ||
| 149 | void ReleaseBuffers(); | ||
| 150 | |||
| 151 | /** | ||
| 152 | * Get all released buffers. | ||
| 153 | * | ||
| 154 | * @param tags - Container to be filled with the released buffers' tags. | ||
| 155 | * @return The number of buffers released. | ||
| 156 | */ | ||
| 157 | u32 GetReleasedBuffers(std::span<u64> tags); | ||
| 158 | |||
| 159 | /** | ||
| 160 | * Flush all appended and registered buffers. | ||
| 161 | * | ||
| 162 | * @return True if buffers were successfully flushed, otherwise false. | ||
| 163 | */ | ||
| 164 | bool FlushAudioInBuffers(); | ||
| 165 | |||
| 166 | /** | ||
| 167 | * Get this system's current channel count. | ||
| 168 | * | ||
| 169 | * @return The channel count. | ||
| 170 | */ | ||
| 171 | u16 GetChannelCount() const; | ||
| 172 | |||
| 173 | /** | ||
| 174 | * Get this system's current sample rate. | ||
| 175 | * | ||
| 176 | * @return The sample rate. | ||
| 177 | */ | ||
| 178 | u32 GetSampleRate() const; | ||
| 179 | |||
| 180 | /** | ||
| 181 | * Get this system's current sample format. | ||
| 182 | * | ||
| 183 | * @return The sample format. | ||
| 184 | */ | ||
| 185 | SampleFormat GetSampleFormat() const; | ||
| 186 | |||
| 187 | /** | ||
| 188 | * Get this system's current state. | ||
| 189 | * | ||
| 190 | * @return The current state. | ||
| 191 | */ | ||
| 192 | State GetState(); | ||
| 193 | |||
| 194 | /** | ||
| 195 | * Get this system's name. | ||
| 196 | * | ||
| 197 | * @return The system's name. | ||
| 198 | */ | ||
| 199 | std::string GetName() const; | ||
| 200 | |||
| 201 | /** | ||
| 202 | * Get this system's current volume. | ||
| 203 | * | ||
| 204 | * @return The system's current volume. | ||
| 205 | */ | ||
| 206 | f32 GetVolume() const; | ||
| 207 | |||
| 208 | /** | ||
| 209 | * Set this system's current volume. | ||
| 210 | * | ||
| 211 | * @param The new volume. | ||
| 212 | */ | ||
| 213 | void SetVolume(f32 volume); | ||
| 214 | |||
| 215 | /** | ||
| 216 | * Does the system contain this buffer? | ||
| 217 | * | ||
| 218 | * @param tag - Unique tag to search for. | ||
| 219 | * @return True if the buffer is in the system, otherwise false. | ||
| 220 | */ | ||
| 221 | bool ContainsAudioBuffer(u64 tag); | ||
| 222 | |||
| 223 | /** | ||
| 224 | * Get the maximum number of usable buffers (default 32). | ||
| 225 | * | ||
| 226 | * @return The number of buffers. | ||
| 227 | */ | ||
| 228 | u32 GetBufferCount(); | ||
| 229 | |||
| 230 | /** | ||
| 231 | * Get the total number of samples played by this system. | ||
| 232 | * | ||
| 233 | * @return The number of samples. | ||
| 234 | */ | ||
| 235 | u64 GetPlayedSampleCount() const; | ||
| 236 | |||
| 237 | /** | ||
| 238 | * Is this system using a USB device? | ||
| 239 | * | ||
| 240 | * @return True if using a USB device, otherwise false. | ||
| 241 | */ | ||
| 242 | bool IsUac() const; | ||
| 243 | |||
| 244 | private: | ||
| 245 | /// Core system | ||
| 246 | Core::System& system; | ||
| 247 | /// (Unused) | ||
| 248 | u32 handle{}; | ||
| 249 | /// (Unused) | ||
| 250 | u64 applet_resource_user_id{}; | ||
| 251 | /// Buffer event, signalled when a buffer is ready | ||
| 252 | Kernel::KEvent* buffer_event; | ||
| 253 | /// Session id of this system | ||
| 254 | size_t session_id{}; | ||
| 255 | /// Device session for this system | ||
| 256 | std::unique_ptr<DeviceSession> session; | ||
| 257 | /// Audio buffers in use by this system | ||
| 258 | AudioBuffers<BufferCount> buffers{BufferCount}; | ||
| 259 | /// Sample rate of this system | ||
| 260 | u32 sample_rate{}; | ||
| 261 | /// Sample format of this system | ||
| 262 | SampleFormat sample_format{SampleFormat::PcmInt16}; | ||
| 263 | /// Channel count of this system | ||
| 264 | u16 channel_count{}; | ||
| 265 | /// State of this system | ||
| 266 | std::atomic<State> state{State::Stopped}; | ||
| 267 | /// Name of this system | ||
| 268 | std::string name{}; | ||
| 269 | /// Volume of this system | ||
| 270 | f32 volume{1.0f}; | ||
| 271 | /// Is this system's device USB? | ||
| 272 | bool is_uac{false}; | ||
| 273 | }; | ||
| 274 | |||
| 275 | } // namespace AudioCore::AudioIn | ||