diff options
| author | 2023-12-17 02:01:25 -0500 | |
|---|---|---|
| committer | 2023-12-17 10:10:14 -0500 | |
| commit | e01c5351781f7c0a8f5e6469a33563f26f8f0779 (patch) | |
| tree | 421411782728e7b5a43027a765ce76d4f3768e64 /src/audio_core/sink | |
| parent | android: add oboe audio sink (diff) | |
| download | yuzu-e01c5351781f7c0a8f5e6469a33563f26f8f0779.tar.gz yuzu-e01c5351781f7c0a8f5e6469a33563f26f8f0779.tar.xz yuzu-e01c5351781f7c0a8f5e6469a33563f26f8f0779.zip | |
oboe_sink: implement channel count querying
Diffstat (limited to 'src/audio_core/sink')
| -rw-r--r-- | src/audio_core/sink/oboe_sink.cpp | 47 |
1 files changed, 35 insertions, 12 deletions
diff --git a/src/audio_core/sink/oboe_sink.cpp b/src/audio_core/sink/oboe_sink.cpp index fc62faaee..c502205e1 100644 --- a/src/audio_core/sink/oboe_sink.cpp +++ b/src/audio_core/sink/oboe_sink.cpp | |||
| @@ -20,11 +20,10 @@ class OboeSinkStream final : public SinkStream, | |||
| 20 | public oboe::AudioStreamErrorCallback { | 20 | public oboe::AudioStreamErrorCallback { |
| 21 | public: | 21 | public: |
| 22 | explicit OboeSinkStream(Core::System& system_, StreamType type_, const std::string& name_, | 22 | explicit OboeSinkStream(Core::System& system_, StreamType type_, const std::string& name_, |
| 23 | u32 device_channels_, u32 system_channels_) | 23 | u32 system_channels_) |
| 24 | : SinkStream(system_, type_) { | 24 | : SinkStream(system_, type_) { |
| 25 | name = name_; | 25 | name = name_; |
| 26 | system_channels = system_channels_; | 26 | system_channels = system_channels_; |
| 27 | device_channels = device_channels_; | ||
| 28 | 27 | ||
| 29 | this->OpenStream(); | 28 | this->OpenStream(); |
| 30 | } | 29 | } |
| @@ -62,6 +61,21 @@ public: | |||
| 62 | } | 61 | } |
| 63 | } | 62 | } |
| 64 | 63 | ||
| 64 | public: | ||
| 65 | static s32 QueryChannelCount(oboe::Direction direction) { | ||
| 66 | std::shared_ptr<oboe::AudioStream> temp_stream; | ||
| 67 | oboe::AudioStreamBuilder builder; | ||
| 68 | |||
| 69 | const auto result = builder.setDirection(direction) | ||
| 70 | ->setSampleRate(TargetSampleRate) | ||
| 71 | ->setFormat(oboe::AudioFormat::I16) | ||
| 72 | ->setFormatConversionAllowed(true) | ||
| 73 | ->openStream(temp_stream); | ||
| 74 | ASSERT(result == oboe::Result::OK); | ||
| 75 | |||
| 76 | return temp_stream->getChannelCount() >= 6 ? 6 : 2; | ||
| 77 | } | ||
| 78 | |||
| 65 | protected: | 79 | protected: |
| 66 | oboe::DataCallbackResult onAudioReady(oboe::AudioStream*, void* audio_data, | 80 | oboe::DataCallbackResult onAudioReady(oboe::AudioStream*, void* audio_data, |
| 67 | s32 num_buffer_frames) override { | 81 | s32 num_buffer_frames) override { |
| @@ -105,8 +119,9 @@ private: | |||
| 105 | } | 119 | } |
| 106 | }(); | 120 | }(); |
| 107 | 121 | ||
| 108 | const auto channel_mask = [&]() { | 122 | const auto expected_channels = QueryChannelCount(direction); |
| 109 | switch (device_channels) { | 123 | const auto expected_mask = [&]() { |
| 124 | switch (expected_channels) { | ||
| 110 | case 1: | 125 | case 1: |
| 111 | return oboe::ChannelMask::Mono; | 126 | return oboe::ChannelMask::Mono; |
| 112 | case 2: | 127 | case 2: |
| @@ -122,25 +137,33 @@ private: | |||
| 122 | oboe::AudioStreamBuilder builder; | 137 | oboe::AudioStreamBuilder builder; |
| 123 | const auto result = builder.setDirection(direction) | 138 | const auto result = builder.setDirection(direction) |
| 124 | ->setSampleRate(TargetSampleRate) | 139 | ->setSampleRate(TargetSampleRate) |
| 125 | ->setChannelCount(device_channels) | 140 | ->setChannelCount(expected_channels) |
| 126 | ->setChannelMask(channel_mask) | 141 | ->setChannelMask(expected_mask) |
| 127 | ->setFormat(oboe::AudioFormat::I16) | 142 | ->setFormat(oboe::AudioFormat::I16) |
| 128 | ->setFormatConversionAllowed(true) | 143 | ->setFormatConversionAllowed(true) |
| 129 | ->setDataCallback(this) | 144 | ->setDataCallback(this) |
| 130 | ->setErrorCallback(this) | 145 | ->setErrorCallback(this) |
| 131 | ->openStream(m_stream); | 146 | ->openStream(m_stream); |
| 132 | |||
| 133 | ASSERT(result == oboe::Result::OK); | 147 | ASSERT(result == oboe::Result::OK); |
| 134 | return result == oboe::Result::OK; | 148 | return result == oboe::Result::OK && this->SetStreamProperties(); |
| 149 | } | ||
| 150 | |||
| 151 | bool SetStreamProperties() { | ||
| 152 | ASSERT(m_stream); | ||
| 153 | |||
| 154 | device_channels = m_stream->getChannelCount(); | ||
| 155 | LOG_INFO(Audio_Sink, "Opened Oboe stream with {} channels", device_channels); | ||
| 156 | |||
| 157 | return true; | ||
| 135 | } | 158 | } |
| 136 | 159 | ||
| 137 | std::shared_ptr<oboe::AudioStream> m_stream{}; | 160 | std::shared_ptr<oboe::AudioStream> m_stream{}; |
| 138 | }; | 161 | }; |
| 139 | 162 | ||
| 140 | OboeSink::OboeSink() { | 163 | OboeSink::OboeSink() { |
| 141 | // TODO: how do we get the number of channels, or device list? | 164 | // TODO: This is not generally knowable |
| 142 | // This seems to be missing from NDK. | 165 | // The channel count is distinct based on direction and can change |
| 143 | device_channels = 2; | 166 | device_channels = OboeSinkStream::QueryChannelCount(oboe::Direction::Output); |
| 144 | } | 167 | } |
| 145 | 168 | ||
| 146 | OboeSink::~OboeSink() = default; | 169 | OboeSink::~OboeSink() = default; |
| @@ -148,7 +171,7 @@ OboeSink::~OboeSink() = default; | |||
| 148 | SinkStream* OboeSink::AcquireSinkStream(Core::System& system, u32 system_channels, | 171 | SinkStream* OboeSink::AcquireSinkStream(Core::System& system, u32 system_channels, |
| 149 | const std::string& name, StreamType type) { | 172 | const std::string& name, StreamType type) { |
| 150 | SinkStreamPtr& stream = sink_streams.emplace_back( | 173 | SinkStreamPtr& stream = sink_streams.emplace_back( |
| 151 | std::make_unique<OboeSinkStream>(system, type, name, device_channels, system_channels)); | 174 | std::make_unique<OboeSinkStream>(system, type, name, system_channels)); |
| 152 | 175 | ||
| 153 | return stream.get(); | 176 | return stream.get(); |
| 154 | } | 177 | } |