// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "audio_core/audio_core.h" #include "audio_core/audio_manager.h" #include "audio_core/device/audio_buffer.h" #include "audio_core/device/device_session.h" #include "audio_core/sink/sink_stream.h" #include "core/core.h" #include "core/memory.h" namespace AudioCore { DeviceSession::DeviceSession(Core::System& system_) : system{system_} {} DeviceSession::~DeviceSession() { Finalize(); } Result DeviceSession::Initialize(std::string_view name_, SampleFormat sample_format_, u16 channel_count_, size_t session_id_, u32 handle_, u64 applet_resource_user_id_, Sink::StreamType type_) { if (stream) { Finalize(); } name = fmt::format("{}-{}", name_, session_id_); type = type_; sample_format = sample_format_; channel_count = channel_count_; session_id = session_id_; handle = handle_; applet_resource_user_id = applet_resource_user_id_; if (type == Sink::StreamType::In) { sink = &system.AudioCore().GetInputSink(); } else { sink = &system.AudioCore().GetOutputSink(); } stream = sink->AcquireSinkStream(system, channel_count, name, type); initialized = true; return ResultSuccess; } void DeviceSession::Finalize() { if (initialized) { Stop(); sink->CloseStream(stream); stream = nullptr; } } void DeviceSession::Start() { stream->SetPlayedSampleCount(played_sample_count); stream->Start(); } void DeviceSession::Stop() { if (stream) { played_sample_count = stream->GetPlayedSampleCount(); stream->Stop(); } } void DeviceSession::AppendBuffers(std::span buffers) const { auto& memory{system.Memory()}; for (size_t i = 0; i < buffers.size(); i++) { Sink::SinkBuffer new_buffer{ .frames = buffers[i].size / (channel_count * sizeof(s16)), .frames_played = 0, .tag = buffers[i].tag, .consumed = false, }; if (type == Sink::StreamType::In) { std::vector samples{}; stream->AppendBuffer(new_buffer, samples); } else { std::vector samples(buffers[i].size / sizeof(s16)); memory.ReadBlockUnsafe(buffers[i].samples, samples.data(), buffers[i].size); stream->AppendBuffer(new_buffer, samples); } } } void DeviceSession::ReleaseBuffer(AudioBuffer& buffer) const { if (type == Sink::StreamType::In) { auto& memory{system.Memory()}; auto samples{stream->ReleaseBuffer(buffer.size / sizeof(s16))}; memory.WriteBlockUnsafe(buffer.samples, samples.data(), buffer.size); } } bool DeviceSession::IsBufferConsumed(u64 tag) const { if (stream) { return stream->IsBufferConsumed(tag); } return true; } void DeviceSession::SetVolume(f32 volume) const { if (stream) { stream->SetSystemVolume(volume); } } u64 DeviceSession::GetPlayedSampleCount() const { if (stream) { return stream->GetPlayedSampleCount(); } return 0; } } // namespace AudioCore