summaryrefslogtreecommitdiff
path: root/src/audio_core/opus/decoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio_core/opus/decoder.cpp')
-rw-r--r--src/audio_core/opus/decoder.cpp358
1 files changed, 179 insertions, 179 deletions
diff --git a/src/audio_core/opus/decoder.cpp b/src/audio_core/opus/decoder.cpp
index 5b23fce14..c6fd45f47 100644
--- a/src/audio_core/opus/decoder.cpp
+++ b/src/audio_core/opus/decoder.cpp
@@ -1,179 +1,179 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "audio_core/opus/decoder.h" 4#include "audio_core/opus/decoder.h"
5#include "audio_core/opus/hardware_opus.h" 5#include "audio_core/opus/hardware_opus.h"
6#include "audio_core/opus/parameters.h" 6#include "audio_core/opus/parameters.h"
7#include "common/alignment.h" 7#include "common/alignment.h"
8#include "common/swap.h" 8#include "common/swap.h"
9#include "core/core.h" 9#include "core/core.h"
10 10
11namespace AudioCore::OpusDecoder { 11namespace AudioCore::OpusDecoder {
12using namespace Service::Audio; 12using namespace Service::Audio;
13namespace { 13namespace {
14OpusPacketHeader ReverseHeader(OpusPacketHeader header) { 14OpusPacketHeader ReverseHeader(OpusPacketHeader header) {
15 OpusPacketHeader out; 15 OpusPacketHeader out;
16 out.size = Common::swap32(header.size); 16 out.size = Common::swap32(header.size);
17 out.final_range = Common::swap32(header.final_range); 17 out.final_range = Common::swap32(header.final_range);
18 return out; 18 return out;
19} 19}
20} // namespace 20} // namespace
21 21
22OpusDecoder::OpusDecoder(Core::System& system_, HardwareOpus& hardware_opus_) 22OpusDecoder::OpusDecoder(Core::System& system_, HardwareOpus& hardware_opus_)
23 : system{system_}, hardware_opus{hardware_opus_} {} 23 : system{system_}, hardware_opus{hardware_opus_} {}
24 24
25OpusDecoder::~OpusDecoder() { 25OpusDecoder::~OpusDecoder() {
26 if (decode_object_initialized) { 26 if (decode_object_initialized) {
27 hardware_opus.ShutdownDecodeObject(shared_buffer.get(), shared_buffer_size); 27 hardware_opus.ShutdownDecodeObject(shared_buffer.get(), shared_buffer_size);
28 } 28 }
29} 29}
30 30
31Result OpusDecoder::Initialize(OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory, 31Result OpusDecoder::Initialize(OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory,
32 u64 transfer_memory_size) { 32 u64 transfer_memory_size) {
33 auto frame_size{params.use_large_frame_size ? 5760 : 1920}; 33 auto frame_size{params.use_large_frame_size ? 5760 : 1920};
34 shared_buffer_size = transfer_memory_size; 34 shared_buffer_size = transfer_memory_size;
35 shared_buffer = std::make_unique<u8[]>(shared_buffer_size); 35 shared_buffer = std::make_unique<u8[]>(shared_buffer_size);
36 shared_memory_mapped = true; 36 shared_memory_mapped = true;
37 37
38 buffer_size = 38 buffer_size =
39 Common::AlignUp((frame_size * params.channel_count) / (48'000 / params.sample_rate), 16); 39 Common::AlignUp((frame_size * params.channel_count) / (48'000 / params.sample_rate), 16);
40 40
41 out_data = {shared_buffer.get() + shared_buffer_size - buffer_size, buffer_size}; 41 out_data = {shared_buffer.get() + shared_buffer_size - buffer_size, buffer_size};
42 size_t in_data_size{0x600u}; 42 size_t in_data_size{0x600u};
43 in_data = {out_data.data() - in_data_size, in_data_size}; 43 in_data = {out_data.data() - in_data_size, in_data_size};
44 44
45 ON_RESULT_FAILURE { 45 ON_RESULT_FAILURE {
46 if (shared_memory_mapped) { 46 if (shared_memory_mapped) {
47 shared_memory_mapped = false; 47 shared_memory_mapped = false;
48 ASSERT(R_SUCCEEDED(hardware_opus.UnmapMemory(shared_buffer.get(), shared_buffer_size))); 48 ASSERT(R_SUCCEEDED(hardware_opus.UnmapMemory(shared_buffer.get(), shared_buffer_size)));
49 } 49 }
50 }; 50 };
51 51
52 R_TRY(hardware_opus.InitializeDecodeObject(params.sample_rate, params.channel_count, 52 R_TRY(hardware_opus.InitializeDecodeObject(params.sample_rate, params.channel_count,
53 shared_buffer.get(), shared_buffer_size)); 53 shared_buffer.get(), shared_buffer_size));
54 54
55 sample_rate = params.sample_rate; 55 sample_rate = params.sample_rate;
56 channel_count = params.channel_count; 56 channel_count = params.channel_count;
57 use_large_frame_size = params.use_large_frame_size; 57 use_large_frame_size = params.use_large_frame_size;
58 decode_object_initialized = true; 58 decode_object_initialized = true;
59 R_SUCCEED(); 59 R_SUCCEED();
60} 60}
61 61
62Result OpusDecoder::Initialize(OpusMultiStreamParametersEx& params, 62Result OpusDecoder::Initialize(OpusMultiStreamParametersEx& params,
63 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size) { 63 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size) {
64 auto frame_size{params.use_large_frame_size ? 5760 : 1920}; 64 auto frame_size{params.use_large_frame_size ? 5760 : 1920};
65 shared_buffer_size = transfer_memory_size; 65 shared_buffer_size = transfer_memory_size;
66 shared_buffer = std::make_unique<u8[]>(shared_buffer_size); 66 shared_buffer = std::make_unique<u8[]>(shared_buffer_size);
67 shared_memory_mapped = true; 67 shared_memory_mapped = true;
68 68
69 buffer_size = 69 buffer_size =
70 Common::AlignUp((frame_size * params.channel_count) / (48'000 / params.sample_rate), 16); 70 Common::AlignUp((frame_size * params.channel_count) / (48'000 / params.sample_rate), 16);
71 71
72 out_data = {shared_buffer.get() + shared_buffer_size - buffer_size, buffer_size}; 72 out_data = {shared_buffer.get() + shared_buffer_size - buffer_size, buffer_size};
73 size_t in_data_size{Common::AlignUp(1500ull * params.total_stream_count, 64u)}; 73 size_t in_data_size{Common::AlignUp(1500ull * params.total_stream_count, 64u)};
74 in_data = {out_data.data() - in_data_size, in_data_size}; 74 in_data = {out_data.data() - in_data_size, in_data_size};
75 75
76 ON_RESULT_FAILURE { 76 ON_RESULT_FAILURE {
77 if (shared_memory_mapped) { 77 if (shared_memory_mapped) {
78 shared_memory_mapped = false; 78 shared_memory_mapped = false;
79 ASSERT(R_SUCCEEDED(hardware_opus.UnmapMemory(shared_buffer.get(), shared_buffer_size))); 79 ASSERT(R_SUCCEEDED(hardware_opus.UnmapMemory(shared_buffer.get(), shared_buffer_size)));
80 } 80 }
81 }; 81 };
82 82
83 R_TRY(hardware_opus.InitializeMultiStreamDecodeObject( 83 R_TRY(hardware_opus.InitializeMultiStreamDecodeObject(
84 params.sample_rate, params.channel_count, params.total_stream_count, 84 params.sample_rate, params.channel_count, params.total_stream_count,
85 params.stereo_stream_count, params.mappings.data(), shared_buffer.get(), 85 params.stereo_stream_count, params.mappings.data(), shared_buffer.get(),
86 shared_buffer_size)); 86 shared_buffer_size));
87 87
88 sample_rate = params.sample_rate; 88 sample_rate = params.sample_rate;
89 channel_count = params.channel_count; 89 channel_count = params.channel_count;
90 total_stream_count = params.total_stream_count; 90 total_stream_count = params.total_stream_count;
91 stereo_stream_count = params.stereo_stream_count; 91 stereo_stream_count = params.stereo_stream_count;
92 use_large_frame_size = params.use_large_frame_size; 92 use_large_frame_size = params.use_large_frame_size;
93 decode_object_initialized = true; 93 decode_object_initialized = true;
94 R_SUCCEED(); 94 R_SUCCEED();
95} 95}
96 96
97Result OpusDecoder::DecodeInterleaved(u32* out_data_size, u64* out_time_taken, 97Result OpusDecoder::DecodeInterleaved(u32* out_data_size, u64* out_time_taken,
98 u32* out_sample_count, std::span<const u8> input_data, 98 u32* out_sample_count, std::span<const u8> input_data,
99 std::span<u8> output_data, bool reset) { 99 std::span<u8> output_data, bool reset) {
100 u32 out_samples; 100 u32 out_samples;
101 u64 time_taken{}; 101 u64 time_taken{};
102 102
103 R_UNLESS(input_data.size_bytes() > sizeof(OpusPacketHeader), ResultInputDataTooSmall); 103 R_UNLESS(input_data.size_bytes() > sizeof(OpusPacketHeader), ResultInputDataTooSmall);
104 104
105 auto* header_p{reinterpret_cast<const OpusPacketHeader*>(input_data.data())}; 105 auto* header_p{reinterpret_cast<const OpusPacketHeader*>(input_data.data())};
106 OpusPacketHeader header{ReverseHeader(*header_p)}; 106 OpusPacketHeader header{ReverseHeader(*header_p)};
107 107
108 R_UNLESS(in_data.size_bytes() >= header.size && 108 R_UNLESS(in_data.size_bytes() >= header.size &&
109 header.size + sizeof(OpusPacketHeader) <= input_data.size_bytes(), 109 header.size + sizeof(OpusPacketHeader) <= input_data.size_bytes(),
110 ResultBufferTooSmall); 110 ResultBufferTooSmall);
111 111
112 if (!shared_memory_mapped) { 112 if (!shared_memory_mapped) {
113 R_TRY(hardware_opus.MapMemory(shared_buffer.get(), shared_buffer_size)); 113 R_TRY(hardware_opus.MapMemory(shared_buffer.get(), shared_buffer_size));
114 shared_memory_mapped = true; 114 shared_memory_mapped = true;
115 } 115 }
116 116
117 std::memcpy(in_data.data(), input_data.data() + sizeof(OpusPacketHeader), header.size); 117 std::memcpy(in_data.data(), input_data.data() + sizeof(OpusPacketHeader), header.size);
118 118
119 R_TRY(hardware_opus.DecodeInterleaved(out_samples, out_data.data(), out_data.size_bytes(), 119 R_TRY(hardware_opus.DecodeInterleaved(out_samples, out_data.data(), out_data.size_bytes(),
120 channel_count, in_data.data(), header.size, 120 channel_count, in_data.data(), header.size,
121 shared_buffer.get(), time_taken, reset)); 121 shared_buffer.get(), time_taken, reset));
122 122
123 std::memcpy(output_data.data(), out_data.data(), out_samples * channel_count * sizeof(s16)); 123 std::memcpy(output_data.data(), out_data.data(), out_samples * channel_count * sizeof(s16));
124 124
125 *out_data_size = header.size + sizeof(OpusPacketHeader); 125 *out_data_size = header.size + sizeof(OpusPacketHeader);
126 *out_sample_count = out_samples; 126 *out_sample_count = out_samples;
127 if (out_time_taken) { 127 if (out_time_taken) {
128 *out_time_taken = time_taken / 1000; 128 *out_time_taken = time_taken / 1000;
129 } 129 }
130 R_SUCCEED(); 130 R_SUCCEED();
131} 131}
132 132
133Result OpusDecoder::SetContext([[maybe_unused]] std::span<const u8> context) { 133Result OpusDecoder::SetContext([[maybe_unused]] std::span<const u8> context) {
134 R_SUCCEED_IF(shared_memory_mapped); 134 R_SUCCEED_IF(shared_memory_mapped);
135 shared_memory_mapped = true; 135 shared_memory_mapped = true;
136 R_RETURN(hardware_opus.MapMemory(shared_buffer.get(), shared_buffer_size)); 136 R_RETURN(hardware_opus.MapMemory(shared_buffer.get(), shared_buffer_size));
137} 137}
138 138
139Result OpusDecoder::DecodeInterleavedForMultiStream(u32* out_data_size, u64* out_time_taken, 139Result OpusDecoder::DecodeInterleavedForMultiStream(u32* out_data_size, u64* out_time_taken,
140 u32* out_sample_count, 140 u32* out_sample_count,
141 std::span<const u8> input_data, 141 std::span<const u8> input_data,
142 std::span<u8> output_data, bool reset) { 142 std::span<u8> output_data, bool reset) {
143 u32 out_samples; 143 u32 out_samples;
144 u64 time_taken{}; 144 u64 time_taken{};
145 145
146 R_UNLESS(input_data.size_bytes() > sizeof(OpusPacketHeader), ResultInputDataTooSmall); 146 R_UNLESS(input_data.size_bytes() > sizeof(OpusPacketHeader), ResultInputDataTooSmall);
147 147
148 auto* header_p{reinterpret_cast<const OpusPacketHeader*>(input_data.data())}; 148 auto* header_p{reinterpret_cast<const OpusPacketHeader*>(input_data.data())};
149 OpusPacketHeader header{ReverseHeader(*header_p)}; 149 OpusPacketHeader header{ReverseHeader(*header_p)};
150 150
151 LOG_ERROR(Service_Audio, "header size 0x{:X} input data size 0x{:X} in_data size 0x{:X}", 151 LOG_ERROR(Service_Audio, "header size 0x{:X} input data size 0x{:X} in_data size 0x{:X}",
152 header.size, input_data.size_bytes(), in_data.size_bytes()); 152 header.size, input_data.size_bytes(), in_data.size_bytes());
153 153
154 R_UNLESS(in_data.size_bytes() >= header.size && 154 R_UNLESS(in_data.size_bytes() >= header.size &&
155 header.size + sizeof(OpusPacketHeader) <= input_data.size_bytes(), 155 header.size + sizeof(OpusPacketHeader) <= input_data.size_bytes(),
156 ResultBufferTooSmall); 156 ResultBufferTooSmall);
157 157
158 if (!shared_memory_mapped) { 158 if (!shared_memory_mapped) {
159 R_TRY(hardware_opus.MapMemory(shared_buffer.get(), shared_buffer_size)); 159 R_TRY(hardware_opus.MapMemory(shared_buffer.get(), shared_buffer_size));
160 shared_memory_mapped = true; 160 shared_memory_mapped = true;
161 } 161 }
162 162
163 std::memcpy(in_data.data(), input_data.data() + sizeof(OpusPacketHeader), header.size); 163 std::memcpy(in_data.data(), input_data.data() + sizeof(OpusPacketHeader), header.size);
164 164
165 R_TRY(hardware_opus.DecodeInterleavedForMultiStream( 165 R_TRY(hardware_opus.DecodeInterleavedForMultiStream(
166 out_samples, out_data.data(), out_data.size_bytes(), channel_count, in_data.data(), 166 out_samples, out_data.data(), out_data.size_bytes(), channel_count, in_data.data(),
167 header.size, shared_buffer.get(), time_taken, reset)); 167 header.size, shared_buffer.get(), time_taken, reset));
168 168
169 std::memcpy(output_data.data(), out_data.data(), out_samples * channel_count * sizeof(s16)); 169 std::memcpy(output_data.data(), out_data.data(), out_samples * channel_count * sizeof(s16));
170 170
171 *out_data_size = header.size + sizeof(OpusPacketHeader); 171 *out_data_size = header.size + sizeof(OpusPacketHeader);
172 *out_sample_count = out_samples; 172 *out_sample_count = out_samples;
173 if (out_time_taken) { 173 if (out_time_taken) {
174 *out_time_taken = time_taken / 1000; 174 *out_time_taken = time_taken / 1000;
175 } 175 }
176 R_SUCCEED(); 176 R_SUCCEED();
177} 177}
178 178
179} // namespace AudioCore::OpusDecoder 179} // namespace AudioCore::OpusDecoder