diff options
Diffstat (limited to 'src/audio_core')
-rw-r--r-- | src/audio_core/audio_out.cpp | 5 | ||||
-rw-r--r-- | src/audio_core/audio_out.h | 8 | ||||
-rw-r--r-- | src/audio_core/audio_renderer.cpp | 7 | ||||
-rw-r--r-- | src/audio_core/audio_renderer.h | 20 | ||||
-rw-r--r-- | src/audio_core/buffer.h | 2 | ||||
-rw-r--r-- | src/audio_core/codec.cpp | 4 | ||||
-rw-r--r-- | src/audio_core/cubeb_sink.cpp | 23 | ||||
-rw-r--r-- | src/audio_core/cubeb_sink.h | 4 | ||||
-rw-r--r-- | src/audio_core/stream.cpp | 14 | ||||
-rw-r--r-- | src/audio_core/stream.h | 30 |
10 files changed, 75 insertions, 42 deletions
diff --git a/src/audio_core/audio_out.cpp b/src/audio_core/audio_out.cpp index 50d2a1ed3..8619a3f03 100644 --- a/src/audio_core/audio_out.cpp +++ b/src/audio_core/audio_out.cpp @@ -26,14 +26,15 @@ static Stream::Format ChannelsToStreamFormat(u32 num_channels) { return {}; } -StreamPtr AudioOut::OpenStream(u32 sample_rate, u32 num_channels, std::string&& name, +StreamPtr AudioOut::OpenStream(Core::Timing::CoreTiming& core_timing, u32 sample_rate, + u32 num_channels, std::string&& name, Stream::ReleaseCallback&& release_callback) { if (!sink) { sink = CreateSinkFromID(Settings::values.sink_id, Settings::values.audio_device_id); } return std::make_shared<Stream>( - sample_rate, ChannelsToStreamFormat(num_channels), std::move(release_callback), + core_timing, sample_rate, ChannelsToStreamFormat(num_channels), std::move(release_callback), sink->AcquireSinkStream(sample_rate, num_channels, name), std::move(name)); } diff --git a/src/audio_core/audio_out.h b/src/audio_core/audio_out.h index df9607ac7..b07588287 100644 --- a/src/audio_core/audio_out.h +++ b/src/audio_core/audio_out.h @@ -13,6 +13,10 @@ #include "audio_core/stream.h" #include "common/common_types.h" +namespace Core::Timing { +class CoreTiming; +} + namespace AudioCore { /** @@ -21,8 +25,8 @@ namespace AudioCore { class AudioOut { public: /// Opens a new audio stream - StreamPtr OpenStream(u32 sample_rate, u32 num_channels, std::string&& name, - Stream::ReleaseCallback&& release_callback); + StreamPtr OpenStream(Core::Timing::CoreTiming& core_timing, u32 sample_rate, u32 num_channels, + std::string&& name, Stream::ReleaseCallback&& release_callback); /// Returns a vector of recently released buffers specified by tag for the specified stream std::vector<Buffer::Tag> GetTagsAndReleaseBuffers(StreamPtr stream, std::size_t max_count); diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp index 00c026511..9a0939883 100644 --- a/src/audio_core/audio_renderer.cpp +++ b/src/audio_core/audio_renderer.cpp @@ -8,6 +8,7 @@ #include "audio_core/codec.h" #include "common/assert.h" #include "common/logging/log.h" +#include "core/core.h" #include "core/hle/kernel/writable_event.h" #include "core/memory.h" @@ -71,14 +72,14 @@ private: EffectOutStatus out_status{}; EffectInStatus info{}; }; -AudioRenderer::AudioRenderer(AudioRendererParameter params, +AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing, AudioRendererParameter params, Kernel::SharedPtr<Kernel::WritableEvent> buffer_event) : worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count), effects(params.effect_count) { audio_out = std::make_unique<AudioCore::AudioOut>(); - stream = audio_out->OpenStream(STREAM_SAMPLE_RATE, STREAM_NUM_CHANNELS, "AudioRenderer", - [=]() { buffer_event->Signal(); }); + stream = audio_out->OpenStream(core_timing, STREAM_SAMPLE_RATE, STREAM_NUM_CHANNELS, + "AudioRenderer", [=]() { buffer_event->Signal(); }); audio_out->StartStream(stream); QueueMixedBuffer(0); diff --git a/src/audio_core/audio_renderer.h b/src/audio_core/audio_renderer.h index 7826881bf..b2e5d336c 100644 --- a/src/audio_core/audio_renderer.h +++ b/src/audio_core/audio_renderer.h @@ -14,6 +14,10 @@ #include "common/swap.h" #include "core/hle/kernel/object.h" +namespace Core::Timing { +class CoreTiming; +} + namespace Kernel { class WritableEvent; } @@ -42,16 +46,18 @@ struct AudioRendererParameter { u32_le sample_rate; u32_le sample_count; u32_le mix_buffer_count; - u32_le unknown_c; + u32_le submix_count; u32_le voice_count; u32_le sink_count; u32_le effect_count; - u32_le unknown_1c; - u8 unknown_20; - INSERT_PADDING_BYTES(3); + u32_le performance_frame_count; + u8 is_voice_drop_enabled; + u8 unknown_21; + u8 unknown_22; + u8 execution_mode; u32_le splitter_count; - u32_le unknown_2c; - INSERT_PADDING_WORDS(1); + u32_le num_splitter_send_channels; + u32_le unknown_30; u32_le revision; }; static_assert(sizeof(AudioRendererParameter) == 52, "AudioRendererParameter is an invalid size"); @@ -208,7 +214,7 @@ static_assert(sizeof(UpdateDataHeader) == 0x40, "UpdateDataHeader has wrong size class AudioRenderer { public: - AudioRenderer(AudioRendererParameter params, + AudioRenderer(Core::Timing::CoreTiming& core_timing, AudioRendererParameter params, Kernel::SharedPtr<Kernel::WritableEvent> buffer_event); ~AudioRenderer(); diff --git a/src/audio_core/buffer.h b/src/audio_core/buffer.h index a323b23ec..5ee09e9aa 100644 --- a/src/audio_core/buffer.h +++ b/src/audio_core/buffer.h @@ -21,7 +21,7 @@ public: Buffer(Tag tag, std::vector<s16>&& samples) : tag{tag}, samples{std::move(samples)} {} /// Returns the raw audio data for the buffer - std::vector<s16>& Samples() { + std::vector<s16>& GetSamples() { return samples; } diff --git a/src/audio_core/codec.cpp b/src/audio_core/codec.cpp index 454de798b..c5a0d98ce 100644 --- a/src/audio_core/codec.cpp +++ b/src/audio_core/codec.cpp @@ -68,8 +68,8 @@ std::vector<s16> DecodeADPCM(const u8* const data, std::size_t size, const ADPCM } } - state.yn1 = yn1; - state.yn2 = yn2; + state.yn1 = static_cast<s16>(yn1); + state.yn2 = static_cast<s16>(yn2); return ret; } diff --git a/src/audio_core/cubeb_sink.cpp b/src/audio_core/cubeb_sink.cpp index 097328901..7047ed9cf 100644 --- a/src/audio_core/cubeb_sink.cpp +++ b/src/audio_core/cubeb_sink.cpp @@ -12,6 +12,10 @@ #include "common/ring_buffer.h" #include "core/settings.h" +#ifdef _WIN32 +#include <objbase.h> +#endif + namespace AudioCore { class CubebSinkStream final : public SinkStream { @@ -46,7 +50,7 @@ public: } } - ~CubebSinkStream() { + ~CubebSinkStream() override { if (!ctx) { return; } @@ -75,11 +79,11 @@ public: queue.Push(samples); } - std::size_t SamplesInQueue(u32 num_channels) const override { + std::size_t SamplesInQueue(u32 channel_count) const override { if (!ctx) return 0; - return queue.Size() / num_channels; + return queue.Size() / channel_count; } void Flush() override { @@ -98,7 +102,7 @@ private: u32 num_channels{}; Common::RingBuffer<s16, 0x10000> queue; - std::array<s16, 2> last_frame; + std::array<s16, 2> last_frame{}; std::atomic<bool> should_flush{}; TimeStretcher time_stretch; @@ -108,6 +112,11 @@ private: }; CubebSink::CubebSink(std::string_view target_device_name) { + // Cubeb requires COM to be initialized on the thread calling cubeb_init on Windows +#ifdef _WIN32 + com_init_result = CoInitializeEx(nullptr, COINIT_MULTITHREADED); +#endif + if (cubeb_init(&ctx, "yuzu", nullptr) != CUBEB_OK) { LOG_CRITICAL(Audio_Sink, "cubeb_init failed"); return; @@ -142,6 +151,12 @@ CubebSink::~CubebSink() { } cubeb_destroy(ctx); + +#ifdef _WIN32 + if (SUCCEEDED(com_init_result)) { + CoUninitialize(); + } +#endif } SinkStream& CubebSink::AcquireSinkStream(u32 sample_rate, u32 num_channels, diff --git a/src/audio_core/cubeb_sink.h b/src/audio_core/cubeb_sink.h index efb9d1634..7ce850f47 100644 --- a/src/audio_core/cubeb_sink.h +++ b/src/audio_core/cubeb_sink.h @@ -25,6 +25,10 @@ private: cubeb* ctx{}; cubeb_devid output_device{}; std::vector<SinkStreamPtr> sink_streams; + +#ifdef _WIN32 + u32 com_init_result = 0; +#endif }; std::vector<std::string> ListCubebSinkDevices(); diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp index 4ce2d374e..4b66a6786 100644 --- a/src/audio_core/stream.cpp +++ b/src/audio_core/stream.cpp @@ -32,12 +32,12 @@ u32 Stream::GetNumChannels() const { return {}; } -Stream::Stream(u32 sample_rate, Format format, ReleaseCallback&& release_callback, - SinkStream& sink_stream, std::string&& name_) +Stream::Stream(Core::Timing::CoreTiming& core_timing, u32 sample_rate, Format format, + ReleaseCallback&& release_callback, SinkStream& sink_stream, std::string&& name_) : sample_rate{sample_rate}, format{format}, release_callback{std::move(release_callback)}, - sink_stream{sink_stream}, name{std::move(name_)} { + sink_stream{sink_stream}, core_timing{core_timing}, name{std::move(name_)} { - release_event = CoreTiming::RegisterEvent( + release_event = core_timing.RegisterEvent( name, [this](u64 userdata, int cycles_late) { ReleaseActiveBuffer(); }); } @@ -57,7 +57,7 @@ Stream::State Stream::GetState() const { s64 Stream::GetBufferReleaseCycles(const Buffer& buffer) const { const std::size_t num_samples{buffer.GetSamples().size() / GetNumChannels()}; - return CoreTiming::usToCycles((static_cast<u64>(num_samples) * 1000000) / sample_rate); + return Core::Timing::usToCycles((static_cast<u64>(num_samples) * 1000000) / sample_rate); } static void VolumeAdjustSamples(std::vector<s16>& samples) { @@ -95,11 +95,11 @@ void Stream::PlayNextBuffer() { active_buffer = queued_buffers.front(); queued_buffers.pop(); - VolumeAdjustSamples(active_buffer->Samples()); + VolumeAdjustSamples(active_buffer->GetSamples()); sink_stream.EnqueueSamples(GetNumChannels(), active_buffer->GetSamples()); - CoreTiming::ScheduleEventThreadsafe(GetBufferReleaseCycles(*active_buffer), release_event, {}); + core_timing.ScheduleEventThreadsafe(GetBufferReleaseCycles(*active_buffer), release_event, {}); } void Stream::ReleaseActiveBuffer() { diff --git a/src/audio_core/stream.h b/src/audio_core/stream.h index aebfeb51d..05071243b 100644 --- a/src/audio_core/stream.h +++ b/src/audio_core/stream.h @@ -13,9 +13,10 @@ #include "audio_core/buffer.h" #include "common/common_types.h" -namespace CoreTiming { +namespace Core::Timing { +class CoreTiming; struct EventType; -} +} // namespace Core::Timing namespace AudioCore { @@ -42,8 +43,8 @@ public: /// Callback function type, used to change guest state on a buffer being released using ReleaseCallback = std::function<void()>; - Stream(u32 sample_rate, Format format, ReleaseCallback&& release_callback, - SinkStream& sink_stream, std::string&& name_); + Stream(Core::Timing::CoreTiming& core_timing, u32 sample_rate, Format format, + ReleaseCallback&& release_callback, SinkStream& sink_stream, std::string&& name_); /// Plays the audio stream void Play(); @@ -91,16 +92,17 @@ private: /// Gets the number of core cycles when the specified buffer will be released s64 GetBufferReleaseCycles(const Buffer& buffer) const; - u32 sample_rate; ///< Sample rate of the stream - Format format; ///< Format of the stream - ReleaseCallback release_callback; ///< Buffer release callback for the stream - State state{State::Stopped}; ///< Playback state of the stream - CoreTiming::EventType* release_event{}; ///< Core timing release event for the stream - BufferPtr active_buffer; ///< Actively playing buffer in the stream - std::queue<BufferPtr> queued_buffers; ///< Buffers queued to be played in the stream - std::queue<BufferPtr> released_buffers; ///< Buffers recently released from the stream - SinkStream& sink_stream; ///< Output sink for the stream - std::string name; ///< Name of the stream, must be unique + u32 sample_rate; ///< Sample rate of the stream + Format format; ///< Format of the stream + ReleaseCallback release_callback; ///< Buffer release callback for the stream + State state{State::Stopped}; ///< Playback state of the stream + Core::Timing::EventType* release_event{}; ///< Core timing release event for the stream + BufferPtr active_buffer; ///< Actively playing buffer in the stream + std::queue<BufferPtr> queued_buffers; ///< Buffers queued to be played in the stream + std::queue<BufferPtr> released_buffers; ///< Buffers recently released from the stream + SinkStream& sink_stream; ///< Output sink for the stream + Core::Timing::CoreTiming& core_timing; ///< Core timing instance. + std::string name; ///< Name of the stream, must be unique }; using StreamPtr = std::shared_ptr<Stream>; |