summaryrefslogtreecommitdiffstats
path: root/src/audio_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio_core')
-rw-r--r--src/audio_core/audio_out.cpp5
-rw-r--r--src/audio_core/audio_out.h8
-rw-r--r--src/audio_core/audio_renderer.cpp7
-rw-r--r--src/audio_core/audio_renderer.h20
-rw-r--r--src/audio_core/buffer.h2
-rw-r--r--src/audio_core/codec.cpp4
-rw-r--r--src/audio_core/cubeb_sink.cpp23
-rw-r--r--src/audio_core/cubeb_sink.h4
-rw-r--r--src/audio_core/stream.cpp14
-rw-r--r--src/audio_core/stream.h30
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>;