diff options
-rw-r--r-- | src/core/hle/service/audio/hwopus.cpp | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp index dffb890d5..11eba4a12 100644 --- a/src/core/hle/service/audio/hwopus.cpp +++ b/src/core/hle/service/audio/hwopus.cpp @@ -37,7 +37,7 @@ public: {3, nullptr, "SetContextForMultiStream"}, {4, &IHardwareOpusDecoderManager::DecodeInterleavedWithPerfOld, "DecodeInterleavedWithPerfOld"}, {5, nullptr, "DecodeInterleavedForMultiStreamWithPerfOld"}, - {6, nullptr, "DecodeInterleaved"}, + {6, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleaved"}, {7, nullptr, "DecodeInterleavedForMultiStream"}, }; // clang-format on @@ -46,24 +46,49 @@ public: } private: + /// Describes extra behavior that may be asked of the decoding context. + enum class ExtraBehavior { + /// No extra behavior. + None, + + /// Resets the decoder context back to a freshly initialized state. + ResetContext, + }; + void DecodeInterleavedOld(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Audio, "called"); - DecodeInterleavedHelper(ctx, nullptr); + DecodeInterleavedHelper(ctx, nullptr, ExtraBehavior::None); } void DecodeInterleavedWithPerfOld(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Audio, "called"); u64 performance = 0; - DecodeInterleavedHelper(ctx, &performance); + DecodeInterleavedHelper(ctx, &performance, ExtraBehavior::None); + } + + void DecodeInterleaved(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Audio, "called"); + + IPC::RequestParser rp{ctx}; + const auto extra_behavior = + rp.Pop<bool>() ? ExtraBehavior::ResetContext : ExtraBehavior::None; + + u64 performance = 0; + DecodeInterleavedHelper(ctx, &performance, extra_behavior); } - void DecodeInterleavedHelper(Kernel::HLERequestContext& ctx, u64* performance) { + void DecodeInterleavedHelper(Kernel::HLERequestContext& ctx, u64* performance, + ExtraBehavior extra_behavior) { u32 consumed = 0; u32 sample_count = 0; std::vector<opus_int16> samples(ctx.GetWriteBufferSize() / sizeof(opus_int16)); + if (extra_behavior == ExtraBehavior::ResetContext) { + ResetDecoderContext(); + } + if (!Decoder_DecodeInterleaved(consumed, sample_count, ctx.ReadBuffer(), samples, performance)) { LOG_ERROR(Audio, "Failed to decode opus data"); @@ -136,6 +161,12 @@ private: return true; } + void ResetDecoderContext() { + ASSERT(decoder != nullptr); + + opus_decoder_ctl(decoder.get(), OPUS_RESET_STATE); + } + struct OpusHeader { u32_be sz; // Needs to be BE for some odd reason INSERT_PADDING_WORDS(1); |