• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023, Alliance for Open Media. All rights reserved
3  *
4  * This source code is subject to the terms of the BSD 3-Clause Clear License
5  * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
6  * License was not distributed with this source code in the LICENSE file, you
7  * can obtain it at www.aomedia.org/license/software-license/bsd-3-c-c. If the
8  * Alliance for Open Media Patent License 1.0 was not distributed with this
9  * source code in the PATENTS file, you can obtain it at
10  * www.aomedia.org/license/patent.
11  */
12 #include "iamf/cli/demixing_module.h"
13 
14 #include <algorithm>
15 #include <climits>
16 #include <cmath>
17 #include <cstddef>
18 #include <cstdint>
19 #include <list>
20 #include <utility>
21 #include <variant>
22 #include <vector>
23 
24 #include "absl/container/flat_hash_map.h"
25 #include "absl/container/flat_hash_set.h"
26 #include "absl/log/check.h"
27 #include "absl/log/log.h"
28 #include "absl/status/status.h"
29 #include "absl/status/statusor.h"
30 #include "absl/strings/str_cat.h"
31 #include "absl/strings/string_view.h"
32 #include "iamf/cli/audio_element_with_data.h"
33 #include "iamf/cli/audio_frame_decoder.h"
34 #include "iamf/cli/audio_frame_with_data.h"
35 #include "iamf/cli/channel_label.h"
36 #include "iamf/cli/cli_util.h"
37 #include "iamf/common/utils/macros.h"
38 #include "iamf/common/utils/numeric_utils.h"
39 #include "iamf/obu/audio_element.h"
40 #include "iamf/obu/audio_frame.h"
41 #include "iamf/obu/demixing_info_parameter_data.h"
42 #include "iamf/obu/types.h"
43 
44 namespace iamf_tools {
45 
46 namespace {
47 
48 using enum ChannelLabel::Label;
49 
50 using DemixingMetadataForAudioElementId =
51     DemixingModule::DemixingMetadataForAudioElementId;
52 
S7ToS5DownMixer(const DownMixingParams & down_mixing_params,LabelSamplesMap & label_to_samples)53 absl::Status S7ToS5DownMixer(const DownMixingParams& down_mixing_params,
54                              LabelSamplesMap& label_to_samples) {
55   LOG_FIRST_N(INFO, 1) << "S7 to S5";
56 
57   // Check input to perform this down-mixing exist.
58   if (label_to_samples.find(kL7) == label_to_samples.end() ||
59       label_to_samples.find(kR7) == label_to_samples.end() ||
60       label_to_samples.find(kLss7) == label_to_samples.end() ||
61       label_to_samples.find(kLrs7) == label_to_samples.end() ||
62       label_to_samples.find(kRss7) == label_to_samples.end() ||
63       label_to_samples.find(kRrs7) == label_to_samples.end()) {
64     return absl::InvalidArgumentError("Missing some input channels");
65   }
66 
67   const auto& l7_samples = label_to_samples[kL7];
68   const auto& lss7_samples = label_to_samples[kLss7];
69   const auto& lrs7_samples = label_to_samples[kLrs7];
70   const auto& r7_samples = label_to_samples[kR7];
71   const auto& rss7_samples = label_to_samples[kRss7];
72   const auto& rrs7_samples = label_to_samples[kRrs7];
73 
74   auto& l5_samples = label_to_samples[kL5];
75   auto& r5_samples = label_to_samples[kR5];
76   auto& ls5_samples = label_to_samples[kLs5];
77   auto& rs5_samples = label_to_samples[kRs5];
78 
79   // Directly copy L7/R7 to L5/R5, because they are the same.
80   l5_samples = l7_samples;
81   r5_samples = r7_samples;
82 
83   // Handle Ls5 and Rs5.
84   ls5_samples.resize(lss7_samples.size());
85   rs5_samples.resize(rss7_samples.size());
86   for (int i = 0; i < ls5_samples.size(); i++) {
87     ls5_samples[i] = down_mixing_params.alpha * lss7_samples[i] +
88                      down_mixing_params.beta * lrs7_samples[i];
89     rs5_samples[i] = down_mixing_params.alpha * rss7_samples[i] +
90                      down_mixing_params.beta * rrs7_samples[i];
91   }
92 
93   return absl::OkStatus();
94 }
95 
S5ToS7Demixer(const DownMixingParams & down_mixing_params,LabelSamplesMap & label_to_samples)96 absl::Status S5ToS7Demixer(const DownMixingParams& down_mixing_params,
97                            LabelSamplesMap& label_to_samples) {
98   LOG_FIRST_N(INFO, 1) << "S5 to S7";
99 
100   const std::vector<InternalSampleType>* l5_samples;
101   const std::vector<InternalSampleType>* ls5_samples;
102   const std::vector<InternalSampleType>* lss7_samples;
103   const std::vector<InternalSampleType>* r5_samples;
104   const std::vector<InternalSampleType>* rs5_samples;
105   const std::vector<InternalSampleType>* rss7_samples;
106   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
107       kL5, label_to_samples, &l5_samples));
108   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
109       kLs5, label_to_samples, &ls5_samples));
110   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
111       kLss7, label_to_samples, &lss7_samples));
112   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
113       kR5, label_to_samples, &r5_samples));
114   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
115       kRs5, label_to_samples, &rs5_samples));
116   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
117       kRss7, label_to_samples, &rss7_samples));
118 
119   auto& l7_samples = label_to_samples[kDemixedL7];
120   auto& r7_samples = label_to_samples[kDemixedR7];
121   auto& lrs7_samples = label_to_samples[kDemixedLrs7];
122   auto& rrs7_samples = label_to_samples[kDemixedRrs7];
123 
124   // Directly copy L5/R5 to L7/R7, because they are the same.
125   l7_samples = *l5_samples;
126   r7_samples = *r5_samples;
127 
128   // Handle Lrs7 and Rrs7.
129   const size_t num_ticks = l5_samples->size();
130   lrs7_samples.resize(num_ticks, 0.0);
131   rrs7_samples.resize(num_ticks, 0.0);
132   for (int i = 0; i < num_ticks; i++) {
133     lrs7_samples[i] =
134         ((*ls5_samples)[i] - down_mixing_params.alpha * (*lss7_samples)[i]) /
135         down_mixing_params.beta;
136     rrs7_samples[i] =
137         ((*rs5_samples)[i] - down_mixing_params.alpha * (*rss7_samples)[i]) /
138         down_mixing_params.beta;
139   }
140 
141   return absl::OkStatus();
142 }
143 
S5ToS3DownMixer(const DownMixingParams & down_mixing_params,LabelSamplesMap & label_to_samples)144 absl::Status S5ToS3DownMixer(const DownMixingParams& down_mixing_params,
145                              LabelSamplesMap& label_to_samples) {
146   LOG_FIRST_N(INFO, 1) << "S5 to S3";
147 
148   // Check input to perform this down-mixing exist.
149   if (label_to_samples.find(kL5) == label_to_samples.end() ||
150       label_to_samples.find(kLs5) == label_to_samples.end() ||
151       label_to_samples.find(kR5) == label_to_samples.end() ||
152       label_to_samples.find(kRs5) == label_to_samples.end()) {
153     return absl::InvalidArgumentError("Missing some input channels");
154   }
155 
156   const auto& l5_samples = label_to_samples[kL5];
157   const auto& ls5_samples = label_to_samples[kLs5];
158   const auto& r5_samples = label_to_samples[kR5];
159   const auto& rs5_samples = label_to_samples[kRs5];
160 
161   auto& l3_samples = label_to_samples[kL3];
162   auto& r3_samples = label_to_samples[kR3];
163   l3_samples.resize(l5_samples.size());
164   r3_samples.resize(r5_samples.size());
165   for (int i = 0; i < l3_samples.size(); i++) {
166     l3_samples[i] = l5_samples[i] + down_mixing_params.delta * ls5_samples[i];
167     r3_samples[i] = r5_samples[i] + down_mixing_params.delta * rs5_samples[i];
168   }
169 
170   return absl::OkStatus();
171 }
172 
S3ToS5Demixer(const DownMixingParams & down_mixing_params,LabelSamplesMap & label_to_samples)173 absl::Status S3ToS5Demixer(const DownMixingParams& down_mixing_params,
174                            LabelSamplesMap& label_to_samples) {
175   LOG_FIRST_N(INFO, 1) << "S3 to S5";
176 
177   const std::vector<InternalSampleType>* l3_samples;
178   const std::vector<InternalSampleType>* l5_samples;
179   const std::vector<InternalSampleType>* r3_samples;
180   const std::vector<InternalSampleType>* r5_samples;
181   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
182       kL3, label_to_samples, &l3_samples));
183   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
184       kL5, label_to_samples, &l5_samples));
185   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
186       kR3, label_to_samples, &r3_samples));
187   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
188       kR5, label_to_samples, &r5_samples));
189 
190   auto& ls5_samples = label_to_samples[kDemixedLs5];
191   auto& rs5_samples = label_to_samples[kDemixedRs5];
192 
193   const size_t num_ticks = l3_samples->size();
194   ls5_samples.resize(num_ticks, 0.0);
195   rs5_samples.resize(num_ticks, 0.0);
196   for (int i = 0; i < num_ticks; i++) {
197     ls5_samples[i] =
198         ((*l3_samples)[i] - (*l5_samples)[i]) / down_mixing_params.delta;
199     rs5_samples[i] =
200         ((*r3_samples)[i] - (*r5_samples)[i]) / down_mixing_params.delta;
201   }
202 
203   return absl::OkStatus();
204 }
205 
S3ToS2DownMixer(const DownMixingParams &,LabelSamplesMap & label_to_samples)206 absl::Status S3ToS2DownMixer(const DownMixingParams& /*down_mixing_params*/,
207                              LabelSamplesMap& label_to_samples) {
208   LOG_FIRST_N(INFO, 1) << "S3 to S2";
209 
210   // Check input to perform this down-mixing exist.
211   if (label_to_samples.find(kL3) == label_to_samples.end() ||
212       label_to_samples.find(kR3) == label_to_samples.end() ||
213       label_to_samples.find(kCentre) == label_to_samples.end()) {
214     return absl::InvalidArgumentError("Missing some input channels");
215   }
216 
217   const auto& l3_samples = label_to_samples[kL3];
218   const auto& r3_samples = label_to_samples[kR3];
219   const auto& c_samples = label_to_samples[kCentre];
220 
221   auto& l2_samples = label_to_samples[kL2];
222   auto& r2_samples = label_to_samples[kR2];
223   l2_samples.resize(l3_samples.size());
224   r2_samples.resize(r3_samples.size());
225   for (int i = 0; i < l2_samples.size(); i++) {
226     l2_samples[i] = l3_samples[i] + 0.707 * c_samples[i];
227     r2_samples[i] = r3_samples[i] + 0.707 * c_samples[i];
228   }
229 
230   return absl::OkStatus();
231 }
232 
S2ToS3Demixer(const DownMixingParams &,LabelSamplesMap & label_to_samples)233 absl::Status S2ToS3Demixer(const DownMixingParams& /*down_mixing_params*/,
234                            LabelSamplesMap& label_to_samples) {
235   LOG_FIRST_N(INFO, 1) << "S2 to S3";
236 
237   const std::vector<InternalSampleType>* l2_samples;
238   const std::vector<InternalSampleType>* r2_samples;
239   const std::vector<InternalSampleType>* c_samples;
240   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
241       kL2, label_to_samples, &l2_samples));
242   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
243       kR2, label_to_samples, &r2_samples));
244   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
245       kCentre, label_to_samples, &c_samples));
246 
247   auto& l3_samples = label_to_samples[kDemixedL3];
248   auto& r3_samples = label_to_samples[kDemixedR3];
249 
250   const size_t num_ticks = c_samples->size();
251   l3_samples.resize(num_ticks, 0.0);
252   r3_samples.resize(num_ticks, 0.0);
253   for (int i = 0; i < num_ticks; i++) {
254     l3_samples[i] = ((*l2_samples)[i] - 0.707 * (*c_samples)[i]);
255     r3_samples[i] = ((*r2_samples)[i] - 0.707 * (*c_samples)[i]);
256   }
257 
258   return absl::OkStatus();
259 }
260 
S2ToS1DownMixer(const DownMixingParams &,LabelSamplesMap & label_to_samples)261 absl::Status S2ToS1DownMixer(const DownMixingParams& /*down_mixing_params*/,
262                              LabelSamplesMap& label_to_samples) {
263   LOG_FIRST_N(INFO, 1) << "S2 to S1";
264 
265   // Check input to perform this down-mixing exist.
266   if (label_to_samples.find(kL2) == label_to_samples.end() ||
267       label_to_samples.find(kR2) == label_to_samples.end()) {
268     return absl::UnknownError("Missing some input channels");
269   }
270 
271   const auto& l2_samples = label_to_samples[kL2];
272   const auto& r2_samples = label_to_samples[kR2];
273 
274   auto& mono_samples = label_to_samples[kMono];
275   mono_samples.resize(l2_samples.size());
276   for (int i = 0; i < mono_samples.size(); i++) {
277     mono_samples[i] = 0.5 * (l2_samples[i] + r2_samples[i]);
278   }
279 
280   return absl::OkStatus();
281 }
282 
S1ToS2Demixer(const DownMixingParams &,LabelSamplesMap & label_to_samples)283 absl::Status S1ToS2Demixer(const DownMixingParams& /*down_mixing_params*/,
284                            LabelSamplesMap& label_to_samples) {
285   LOG_FIRST_N(INFO, 1) << "S1 to S2";
286 
287   const std::vector<InternalSampleType>* l2_samples;
288   const std::vector<InternalSampleType>* mono_samples;
289   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
290       kL2, label_to_samples, &l2_samples));
291   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
292       kMono, label_to_samples, &mono_samples));
293 
294   auto& r2_samples = label_to_samples[kDemixedR2];
295   const size_t num_ticks = mono_samples->size();
296   r2_samples.resize(num_ticks, 0.0);
297   for (int i = 0; i < num_ticks; i++) {
298     r2_samples[i] = 2.0 * (*mono_samples)[i] - (*l2_samples)[i];
299   }
300 
301   return absl::OkStatus();
302 }
303 
T4ToT2DownMixer(const DownMixingParams & down_mixing_params,LabelSamplesMap & label_to_samples)304 absl::Status T4ToT2DownMixer(const DownMixingParams& down_mixing_params,
305                              LabelSamplesMap& label_to_samples) {
306   LOG_FIRST_N(INFO, 1) << "T4 to T2";
307 
308   // Check input to perform this down-mixing exist.
309   if (label_to_samples.find(kLtf4) == label_to_samples.end() ||
310       label_to_samples.find(kLtb4) == label_to_samples.end() ||
311       label_to_samples.find(kRtf4) == label_to_samples.end() ||
312       label_to_samples.find(kRtb4) == label_to_samples.end()) {
313     return absl::UnknownError("Missing some input channels");
314   }
315 
316   const auto& ltf4_samples = label_to_samples[kLtf4];
317   const auto& ltb4_samples = label_to_samples[kLtb4];
318   const auto& rtf4_samples = label_to_samples[kRtf4];
319   const auto& rtb4_samples = label_to_samples[kRtb4];
320 
321   auto& ltf2_samples = label_to_samples[kLtf2];
322   auto& rtf2_samples = label_to_samples[kRtf2];
323   ltf2_samples.resize(ltf4_samples.size());
324   rtf2_samples.resize(rtf4_samples.size());
325   for (int i = 0; i < ltf2_samples.size(); i++) {
326     ltf2_samples[i] =
327         ltf4_samples[i] + down_mixing_params.gamma * ltb4_samples[i];
328     rtf2_samples[i] =
329         rtf4_samples[i] + down_mixing_params.gamma * rtb4_samples[i];
330   }
331 
332   return absl::OkStatus();
333 }
334 
T2ToT4Demixer(const DownMixingParams & down_mixing_params,LabelSamplesMap & label_to_samples)335 absl::Status T2ToT4Demixer(const DownMixingParams& down_mixing_params,
336                            LabelSamplesMap& label_to_samples) {
337   LOG_FIRST_N(INFO, 1) << "T2 to T4";
338 
339   const std::vector<InternalSampleType>* ltf2_samples;
340   const std::vector<InternalSampleType>* ltf4_samples;
341   const std::vector<InternalSampleType>* rtf2_samples;
342   const std::vector<InternalSampleType>* rtf4_samples;
343   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
344       kLtf2, label_to_samples, &ltf2_samples));
345   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
346       kLtf4, label_to_samples, &ltf4_samples));
347   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
348       kRtf2, label_to_samples, &rtf2_samples));
349   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
350       kRtf4, label_to_samples, &rtf4_samples));
351 
352   auto& ltb4_samples = label_to_samples[kDemixedLtb4];
353   auto& rtb4_samples = label_to_samples[kDemixedRtb4];
354   const size_t num_ticks = ltf2_samples->size();
355   ltb4_samples.resize(num_ticks, 0.0);
356   rtb4_samples.resize(num_ticks, 0.0);
357   for (int i = 0; i < num_ticks; i++) {
358     ltb4_samples[i] =
359         ((*ltf2_samples)[i] - (*ltf4_samples)[i]) / down_mixing_params.gamma;
360     rtb4_samples[i] =
361         ((*rtf2_samples)[i] - (*rtf4_samples)[i]) / down_mixing_params.gamma;
362   }
363 
364   return absl::OkStatus();
365 }
366 
T2ToTf2DownMixer(const DownMixingParams & down_mixing_params,LabelSamplesMap & label_to_samples)367 absl::Status T2ToTf2DownMixer(const DownMixingParams& down_mixing_params,
368                               LabelSamplesMap& label_to_samples) {
369   LOG_FIRST_N(INFO, 1) << "T2 to TF2";
370 
371   // Check input to perform this down-mixing exist.
372   if (label_to_samples.find(kLtf2) == label_to_samples.end() ||
373       label_to_samples.find(kLs5) == label_to_samples.end() ||
374       label_to_samples.find(kRtf2) == label_to_samples.end() ||
375       label_to_samples.find(kRs5) == label_to_samples.end()) {
376     return absl::UnknownError("Missing some input channels");
377   }
378 
379   const auto& ltf2_samples = label_to_samples[kLtf2];
380   const auto& ls5_samples = label_to_samples[kLs5];
381   const auto& rtf2_samples = label_to_samples[kRtf2];
382   const auto& rs5_samples = label_to_samples[kRs5];
383 
384   auto& ltf3_samples = label_to_samples[kLtf3];
385   auto& rtf3_samples = label_to_samples[kRtf3];
386   ltf3_samples.resize(ltf2_samples.size());
387   rtf3_samples.resize(rtf2_samples.size());
388   for (int i = 0; i < ltf2_samples.size(); i++) {
389     ltf3_samples[i] = ltf2_samples[i] + down_mixing_params.w *
390                                             down_mixing_params.delta *
391                                             ls5_samples[i];
392     rtf3_samples[i] = rtf2_samples[i] + down_mixing_params.w *
393                                             down_mixing_params.delta *
394                                             rs5_samples[i];
395   }
396 
397   return absl::OkStatus();
398 }
399 
Tf2ToT2Demixer(const DownMixingParams & down_mixing_params,LabelSamplesMap & label_to_samples)400 absl::Status Tf2ToT2Demixer(const DownMixingParams& down_mixing_params,
401                             LabelSamplesMap& label_to_samples) {
402   LOG_FIRST_N(INFO, 1) << "TF2 to T2";
403 
404   const std::vector<InternalSampleType>* ltf3_samples;
405   const std::vector<InternalSampleType>* l3_samples;
406   const std::vector<InternalSampleType>* l5_samples;
407   const std::vector<InternalSampleType>* rtf3_samples;
408   const std::vector<InternalSampleType>* r3_samples;
409   const std::vector<InternalSampleType>* r5_samples;
410   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
411       kLtf3, label_to_samples, &ltf3_samples));
412   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
413       kL3, label_to_samples, &l3_samples));
414   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
415       kL5, label_to_samples, &l5_samples));
416   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
417       kRtf3, label_to_samples, &rtf3_samples));
418   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
419       kR3, label_to_samples, &r3_samples));
420   RETURN_IF_NOT_OK(DemixingModule::FindSamplesOrDemixedSamples(
421       kR5, label_to_samples, &r5_samples));
422 
423   auto& ltf2_samples = label_to_samples[kDemixedLtf2];
424   auto& rtf2_samples = label_to_samples[kDemixedRtf2];
425   const size_t num_ticks = ltf3_samples->size();
426   ltf2_samples.resize(num_ticks, 0.0);
427   rtf2_samples.resize(num_ticks, 0.0);
428   for (int i = 0; i < num_ticks; i++) {
429     ltf2_samples[i] =
430         (*ltf3_samples)[i] -
431         down_mixing_params.w * ((*l3_samples)[i] - (*l5_samples)[i]);
432     rtf2_samples[i] =
433         (*rtf3_samples)[i] -
434         down_mixing_params.w * ((*r3_samples)[i] - (*r5_samples)[i]);
435   }
436 
437   return absl::OkStatus();
438 }
439 
440 // Helper to fill in the fields of `DemixingMetadataForAudioElementId`.
FillRequiredDemixingMetadata(const absl::flat_hash_set<ChannelLabel::Label> & labels_to_demix,const SubstreamIdLabelsMap & substream_id_to_labels,const LabelGainMap & label_to_output_gain,DemixingMetadataForAudioElementId & demixing_metadata)441 absl::Status FillRequiredDemixingMetadata(
442     const absl::flat_hash_set<ChannelLabel::Label>& labels_to_demix,
443     const SubstreamIdLabelsMap& substream_id_to_labels,
444     const LabelGainMap& label_to_output_gain,
445     DemixingMetadataForAudioElementId& demixing_metadata) {
446   auto& down_mixers = demixing_metadata.down_mixers;
447   auto& demixers = demixing_metadata.demixers;
448 
449   if (!down_mixers.empty() || !demixers.empty()) {
450     return absl::UnknownError(
451         "`FillRequiredDemixingMetadata()` should only be called once per Audio "
452         "Element ID");
453   }
454   demixing_metadata.substream_id_to_labels = substream_id_to_labels;
455   demixing_metadata.label_to_output_gain = label_to_output_gain;
456 
457   // Find the input surround number.
458   int input_surround_number = 0;
459   if (labels_to_demix.contains(kL7)) {
460     input_surround_number = 7;
461   } else if (labels_to_demix.contains(kL5)) {
462     input_surround_number = 5;
463   } else if (labels_to_demix.contains(kL3)) {
464     input_surround_number = 3;
465   } else if (labels_to_demix.contains(kL2)) {
466     input_surround_number = 2;
467   } else if (labels_to_demix.contains(kMono)) {
468     input_surround_number = 1;
469   }
470 
471   // Find the lowest output surround number.
472   int output_lowest_surround_number = INT_MAX;
473   for (const auto& [substream_id, labels] :
474        demixing_metadata.substream_id_to_labels) {
475     if (std::find(labels.begin(), labels.end(), kL7) != labels.end() &&
476         output_lowest_surround_number > 7) {
477       output_lowest_surround_number = 7;
478     } else if (std::find(labels.begin(), labels.end(), kL5) != labels.end() &&
479                output_lowest_surround_number > 5) {
480       output_lowest_surround_number = 5;
481     } else if (std::find(labels.begin(), labels.end(), kL3) != labels.end() &&
482                output_lowest_surround_number > 3) {
483       output_lowest_surround_number = 3;
484     } else if (std::find(labels.begin(), labels.end(), kL2) != labels.end() &&
485                output_lowest_surround_number > 2) {
486       output_lowest_surround_number = 2;
487     } else if (std::find(labels.begin(), labels.end(), kMono) != labels.end() &&
488                output_lowest_surround_number > 1) {
489       output_lowest_surround_number = 1;
490       // This is the lowest possible value, abort.
491       break;
492     }
493   }
494   LOG(INFO) << "Surround down-mixers from S" << input_surround_number << " to S"
495             << output_lowest_surround_number << " needed:";
496   for (int surround_number = input_surround_number;
497        surround_number > output_lowest_surround_number; surround_number--) {
498     if (surround_number == 7) {
499       down_mixers.push_back(S7ToS5DownMixer);
500       LOG(INFO) << "  S7ToS5DownMixer added";
501       demixers.push_front(S5ToS7Demixer);
502       LOG(INFO) << "  S5ToS7Demixer added";
503     } else if (surround_number == 5) {
504       down_mixers.push_back(S5ToS3DownMixer);
505       LOG(INFO) << "  S5ToS3DownMixer added";
506       demixers.push_front(S3ToS5Demixer);
507       LOG(INFO) << "  S3ToS5Demixer added";
508     } else if (surround_number == 3) {
509       down_mixers.push_back(S3ToS2DownMixer);
510       LOG(INFO) << "  S3ToS2DownMixer added";
511       demixers.push_front(S2ToS3Demixer);
512       LOG(INFO) << "  S2ToS3Demixer added";
513     } else if (surround_number == 2) {
514       down_mixers.push_back(S2ToS1DownMixer);
515       LOG(INFO) << "  S2ToS1DownMixer added";
516       demixers.push_front(S1ToS2Demixer);
517       LOG(INFO) << "  S1ToS2Demixer added";
518     }
519   }
520 
521   // Find the input height number. Artificially defining the height number of
522   // "TF2" as 1.
523   int input_height_number = 0;
524   if (labels_to_demix.contains(kLtf4)) {
525     input_height_number = 4;
526   } else if (labels_to_demix.contains(kLtf2)) {
527     input_height_number = 2;
528   } else if (labels_to_demix.contains(kLtf3)) {
529     input_height_number = 1;
530   }
531 
532   // Find the lowest output height number.
533   int output_lowest_height_number = INT_MAX;
534   for (const auto& [substream_id, labels] :
535        demixing_metadata.substream_id_to_labels) {
536     if (std::find(labels.begin(), labels.end(), kLtf4) != labels.end() &&
537         output_lowest_height_number > 4) {
538       output_lowest_height_number = 4;
539     } else if (std::find(labels.begin(), labels.end(), kLtf2) != labels.end() &&
540                output_lowest_height_number > 2) {
541       output_lowest_height_number = 2;
542     } else if (std::find(labels.begin(), labels.end(), kLtf3) != labels.end() &&
543                output_lowest_height_number > 1) {
544       output_lowest_height_number = 1;
545       // This is the lowest possible value, abort.
546       break;
547     }
548   }
549 
550   // Collect demixers in a separate list first and append the list to the
551   // output later. Height demixers need to be in reverse order as height
552   // down-mixers but should go after the surround demixers.
553   LOG(INFO) << "Height down-mixers from T" << input_height_number << " to "
554             << (output_lowest_height_number == 2 ? "T2" : "TF3") << " needed:";
555   std::list<Demixer> height_demixers;
556   for (int height_number = input_height_number;
557        height_number > output_lowest_height_number; height_number--) {
558     if (height_number == 4) {
559       down_mixers.push_back(T4ToT2DownMixer);
560       LOG(INFO) << "  T4ToT2DownMixer added";
561       height_demixers.push_front(T2ToT4Demixer);
562       LOG(INFO) << "  T2ToT4Demixer added";
563     } else if (height_number == 2) {
564       down_mixers.push_back(T2ToTf2DownMixer);
565       LOG(INFO) << "  T2ToTf2DownMixer added";
566       height_demixers.push_front(Tf2ToT2Demixer);
567       LOG(INFO) << "  Tf2ToT2Demixer added";
568     }
569   }
570   demixers.splice(demixers.end(), height_demixers);
571 
572   return absl::OkStatus();
573 }
574 
ConfigureLabeledFrame(const AudioFrameWithData & audio_frame,LabeledFrame & labeled_frame)575 void ConfigureLabeledFrame(const AudioFrameWithData& audio_frame,
576                            LabeledFrame& labeled_frame) {
577   labeled_frame.end_timestamp = audio_frame.end_timestamp;
578   labeled_frame.samples_to_trim_at_end =
579       audio_frame.obu.header_.num_samples_to_trim_at_end;
580   labeled_frame.samples_to_trim_at_start =
581       audio_frame.obu.header_.num_samples_to_trim_at_start;
582   labeled_frame.demixing_params = audio_frame.down_mixing_params;
583 }
584 
ConfigureLabeledFrame(const DecodedAudioFrame & decoded_audio_frame,LabeledFrame & labeled_decoded_frame)585 void ConfigureLabeledFrame(const DecodedAudioFrame& decoded_audio_frame,
586                            LabeledFrame& labeled_decoded_frame) {
587   labeled_decoded_frame.end_timestamp = decoded_audio_frame.end_timestamp;
588   labeled_decoded_frame.samples_to_trim_at_end =
589       decoded_audio_frame.samples_to_trim_at_end;
590   labeled_decoded_frame.samples_to_trim_at_start =
591       decoded_audio_frame.samples_to_trim_at_start;
592   labeled_decoded_frame.demixing_params =
593       decoded_audio_frame.down_mixing_params;
594 }
595 
GetSubstreamId(const AudioFrameWithData & audio_frame_with_data)596 uint32_t GetSubstreamId(const AudioFrameWithData& audio_frame_with_data) {
597   return audio_frame_with_data.obu.GetSubstreamId();
598 }
599 
GetSubstreamId(const DecodedAudioFrame & audio_frame_with_data)600 uint32_t GetSubstreamId(const DecodedAudioFrame& audio_frame_with_data) {
601   return audio_frame_with_data.substream_id;
602 }
603 
GetSamples(const AudioFrameWithData & audio_frame_with_data)604 const std::vector<std::vector<int32_t>>* GetSamples(
605     const AudioFrameWithData& audio_frame_with_data) {
606   if (!audio_frame_with_data.pcm_samples.has_value()) {
607     return nullptr;
608   }
609   return &audio_frame_with_data.pcm_samples.value();
610 }
611 
GetSamples(const DecodedAudioFrame & audio_frame_with_data)612 const std::vector<std::vector<int32_t>>* GetSamples(
613     const DecodedAudioFrame& audio_frame_with_data) {
614   return &audio_frame_with_data.decoded_samples;
615 }
616 
617 // NOOP function if the frame is not a DecodedAudioFrame.
PassThroughReconGainData(const AudioFrameWithData &,LabeledFrame &)618 absl::Status PassThroughReconGainData(const AudioFrameWithData& /*audio_frame*/,
619                                       LabeledFrame& /*labeled_frame*/) {
620   return absl::OkStatus();
621 }
622 
PassThroughReconGainData(const DecodedAudioFrame & decoded_audio_frame,LabeledFrame & labeled_decoded_frame)623 absl::Status PassThroughReconGainData(
624     const DecodedAudioFrame& decoded_audio_frame,
625     LabeledFrame& labeled_decoded_frame) {
626   if (decoded_audio_frame.audio_element_with_data == nullptr) {
627     LOG(INFO)
628         << "No audio element with data found, thus layer info is inaccessible.";
629     return absl::OkStatus();
630   }
631   auto layout_config = std::get_if<ScalableChannelLayoutConfig>(
632       &decoded_audio_frame.audio_element_with_data->obu.config_);
633   if (layout_config == nullptr) {
634     LOG_IF(INFO, decoded_audio_frame.start_timestamp == 0)
635         << "No scalable channel layout config found, thus recon gain "
636            "info is not necessary.";
637     return absl::OkStatus();
638   }
639   auto& loudspeaker_layout_per_layer =
640       labeled_decoded_frame.loudspeaker_layout_per_layer;
641   loudspeaker_layout_per_layer.clear();
642   loudspeaker_layout_per_layer.reserve(
643       layout_config->channel_audio_layer_configs.size());
644   for (const auto& channel_audio_layer_config :
645        layout_config->channel_audio_layer_configs) {
646     loudspeaker_layout_per_layer.push_back(
647         channel_audio_layer_config.loudspeaker_layout);
648   }
649   labeled_decoded_frame.recon_gain_info_parameter_data =
650       decoded_audio_frame.recon_gain_info_parameter_data;
651   return absl::OkStatus();
652 }
653 
654 // TODO(b/377553811): Unify `AudioFrameWithData` and `DecodedAudioFrame`.
655 template <typename T>
StoreSamplesForAudioElementId(const std::list<T> & audio_frames_or_decoded_audio_frames,const SubstreamIdLabelsMap & substream_id_to_labels,LabeledFrame & labeled_frame)656 absl::Status StoreSamplesForAudioElementId(
657     const std::list<T>& audio_frames_or_decoded_audio_frames,
658     const SubstreamIdLabelsMap& substream_id_to_labels,
659     LabeledFrame& labeled_frame) {
660   if (audio_frames_or_decoded_audio_frames.empty()) {
661     return absl::OkStatus();
662   }
663   const int32_t common_start_timestamp =
664       audio_frames_or_decoded_audio_frames.begin()->start_timestamp;
665 
666   for (auto& audio_frame : audio_frames_or_decoded_audio_frames) {
667     const auto substream_id = GetSubstreamId(audio_frame);
668     auto substream_id_labels_iter = substream_id_to_labels.find(substream_id);
669     if (substream_id_labels_iter == substream_id_to_labels.end()) {
670       // This audio frame might belong to a different audio element; skip it.
671       continue;
672     }
673 
674     // Validate that the frames are all aligned in time.
675     RETURN_IF_NOT_OK(CompareTimestamps(common_start_timestamp,
676                                        audio_frame.start_timestamp,
677                                        "In StoreSamplesForAudioElementId(): "));
678 
679     const auto& labels = substream_id_labels_iter->second;
680     int channel_index = 0;
681     for (const auto& label : labels) {
682       const auto* input_samples = GetSamples(audio_frame);
683       if (input_samples == nullptr) {
684         return absl::InvalidArgumentError(
685             "Input samples are not available for down-mixing.");
686       }
687       const size_t num_ticks = input_samples->size();
688 
689       ConfigureLabeledFrame(audio_frame, labeled_frame);
690 
691       auto& samples = labeled_frame.label_to_samples[label];
692       samples.resize(num_ticks, 0);
693       for (int t = 0; t < samples.size(); t++) {
694         samples[t] = Int32ToNormalizedFloatingPoint<InternalSampleType>(
695             (*input_samples)[t][channel_index]);
696       }
697       channel_index++;
698     }
699     RETURN_IF_NOT_OK(PassThroughReconGainData(audio_frame, labeled_frame));
700   }
701 
702   return absl::OkStatus();
703 }
704 
ApplyDemixers(const std::list<Demixer> & demixers,LabeledFrame & labeled_frame)705 absl::Status ApplyDemixers(const std::list<Demixer>& demixers,
706                            LabeledFrame& labeled_frame) {
707   for (const auto& demixer : demixers) {
708     RETURN_IF_NOT_OK(
709         demixer(labeled_frame.demixing_params, labeled_frame.label_to_samples));
710   }
711   return absl::OkStatus();
712 }
713 
GetDemixerMetadata(const DecodedUleb128 audio_element_id,const absl::flat_hash_map<DecodedUleb128,DemixingMetadataForAudioElementId> & audio_element_id_to_demixing_metadata,const DemixingMetadataForAudioElementId * & demixing_metadata)714 absl::Status GetDemixerMetadata(
715     const DecodedUleb128 audio_element_id,
716     const absl::flat_hash_map<DecodedUleb128,
717                               DemixingMetadataForAudioElementId>&
718         audio_element_id_to_demixing_metadata,
719     const DemixingMetadataForAudioElementId*& demixing_metadata) {
720   const auto iter =
721       audio_element_id_to_demixing_metadata.find(audio_element_id);
722   if (iter == audio_element_id_to_demixing_metadata.end()) {
723     return absl::InvalidArgumentError(absl::StrCat(
724         "Demxiing metadata for Audio Element ID= ", audio_element_id,
725         " not found"));
726   }
727   demixing_metadata = &iter->second;
728   return absl::OkStatus();
729 }
730 
731 absl::StatusOr<absl::flat_hash_set<ChannelLabel::Label>>
LookupLabelsToReconstruct(const AudioElementObu & obu)732 LookupLabelsToReconstruct(const AudioElementObu& obu) {
733   switch (obu.GetAudioElementType()) {
734     using enum AudioElementObu::AudioElementType;
735     case kAudioElementChannelBased: {
736       const auto& channel_audio_layer_configs =
737           std::get<ScalableChannelLayoutConfig>(obu.config_)
738               .channel_audio_layer_configs;
739       if (channel_audio_layer_configs.empty()) {
740         return absl::InvalidArgumentError(absl::StrCat(
741             "Expected non-empty channel audio layer configs for Audio "
742             "Element ID= ",
743             obu.GetAudioElementId()));
744       }
745 
746       // Reconstruct the highest layer.
747       return ChannelLabel::
748           LookupLabelsToReconstructFromScalableLoudspeakerLayout(
749               channel_audio_layer_configs.back().loudspeaker_layout,
750               channel_audio_layer_configs.back().expanded_loudspeaker_layout);
751     }
752     case kAudioElementSceneBased:
753       // OK. Ambisonics does not have any channels to be reconstructed.
754       return absl::flat_hash_set<ChannelLabel::Label>{};
755       break;
756     default:
757       return absl::UnimplementedError(absl::StrCat(
758           "Unsupported audio element type= ", obu.GetAudioElementType()));
759   }
760 }
LogForAudioElementId(absl::string_view log_prefix,DecodedUleb128 audio_element_id,const IdLabeledFrameMap & id_to_labeled_frame)761 void LogForAudioElementId(absl::string_view log_prefix,
762                           DecodedUleb128 audio_element_id,
763                           const IdLabeledFrameMap& id_to_labeled_frame) {
764   if (!id_to_labeled_frame.contains(audio_element_id)) {
765     return;
766   }
767   for (const auto& [label, samples] :
768        id_to_labeled_frame.at(audio_element_id).label_to_samples) {
769     LOG_FIRST_N(INFO, 1) << "  Channel " << label << ":\t" << log_prefix
770                          << " frame size= " << samples.size() << ".";
771   }
772 }
773 
774 }  // namespace
775 
FindSamplesOrDemixedSamples(ChannelLabel::Label label,const LabelSamplesMap & label_to_samples,const std::vector<InternalSampleType> ** samples)776 absl::Status DemixingModule::FindSamplesOrDemixedSamples(
777     ChannelLabel::Label label, const LabelSamplesMap& label_to_samples,
778     const std::vector<InternalSampleType>** samples) {
779   if (label_to_samples.find(label) != label_to_samples.end()) {
780     *samples = &label_to_samples.at(label);
781     return absl::OkStatus();
782   }
783 
784   auto demixed_label = ChannelLabel::GetDemixedLabel(label);
785   if (!demixed_label.ok()) {
786     return demixed_label.status();
787   }
788   if (label_to_samples.find(*demixed_label) != label_to_samples.end()) {
789     *samples = &label_to_samples.at(*demixed_label);
790     return absl::OkStatus();
791   } else {
792     *samples = nullptr;
793     return absl::UnknownError(
794         absl::StrCat("Channel ", label, " or ", *demixed_label, " not found"));
795   }
796 }
797 
798 absl::StatusOr<DemixingModule>
CreateForDownMixingAndReconstruction(const absl::flat_hash_map<DecodedUleb128,DownmixingAndReconstructionConfig> && id_to_config_map)799 DemixingModule::CreateForDownMixingAndReconstruction(
800     const absl::flat_hash_map<
801         DecodedUleb128, DownmixingAndReconstructionConfig>&& id_to_config_map) {
802   absl::flat_hash_map<DecodedUleb128, DemixingMetadataForAudioElementId>
803       audio_element_id_to_demixing_metadata;
804 
805   for (const auto& [audio_element_id, config] : id_to_config_map) {
806     RETURN_IF_NOT_OK(FillRequiredDemixingMetadata(
807         config.user_labels, config.substream_id_to_labels,
808         config.label_to_output_gain,
809         audio_element_id_to_demixing_metadata[audio_element_id]));
810   }
811 
812   return DemixingModule(DemixingMode::kDownMixingAndReconstruction,
813                         std::move(audio_element_id_to_demixing_metadata));
814 }
815 
CreateForReconstruction(const absl::flat_hash_map<DecodedUleb128,AudioElementWithData> & audio_elements)816 absl::StatusOr<DemixingModule> DemixingModule::CreateForReconstruction(
817     const absl::flat_hash_map<DecodedUleb128, AudioElementWithData>&
818         audio_elements) {
819   absl::flat_hash_map<DecodedUleb128, DemixingMetadataForAudioElementId>
820       audio_element_id_to_demixing_metadata;
821   for (const auto& [audio_element_id, audio_element_with_data] :
822        audio_elements) {
823     const auto labels_to_reconstruct =
824         LookupLabelsToReconstruct(audio_element_with_data.obu);
825     if (!labels_to_reconstruct.ok()) {
826       return labels_to_reconstruct.status();
827     }
828 
829     auto [iter, inserted] = audio_element_id_to_demixing_metadata.insert(
830         {audio_element_id, DemixingMetadataForAudioElementId()});
831     CHECK(inserted) << "The target map was initially empty, iterating over "
832                        "`audio_elements` cannot produce a duplicate key.";
833     RETURN_IF_NOT_OK(FillRequiredDemixingMetadata(
834         *labels_to_reconstruct, audio_element_with_data.substream_id_to_labels,
835         audio_element_with_data.label_to_output_gain, iter->second));
836     iter->second.down_mixers.clear();
837   }
838 
839   return DemixingModule(DemixingMode::kReconstruction,
840                         std::move(audio_element_id_to_demixing_metadata));
841 }
842 
DownMixSamplesToSubstreams(DecodedUleb128 audio_element_id,const DownMixingParams & down_mixing_params,LabelSamplesMap & input_label_to_samples,absl::flat_hash_map<uint32_t,SubstreamData> & substream_id_to_substream_data) const843 absl::Status DemixingModule::DownMixSamplesToSubstreams(
844     DecodedUleb128 audio_element_id, const DownMixingParams& down_mixing_params,
845     LabelSamplesMap& input_label_to_samples,
846     absl::flat_hash_map<uint32_t, SubstreamData>&
847         substream_id_to_substream_data) const {
848   const DemixingMetadataForAudioElementId* demixing_metadata = nullptr;
849   RETURN_IF_NOT_OK(GetDemixerMetadata(audio_element_id,
850                                       audio_element_id_to_demixing_metadata_,
851                                       demixing_metadata));
852 
853   // First perform all the down mixing.
854   for (const auto& down_mixer : demixing_metadata->down_mixers) {
855     RETURN_IF_NOT_OK(down_mixer(down_mixing_params, input_label_to_samples));
856   }
857 
858   const size_t num_time_ticks = input_label_to_samples.begin()->second.size();
859 
860   for (const auto& [substream_id, output_channel_labels] :
861        demixing_metadata->substream_id_to_labels) {
862     std::vector<std::vector<int32_t>> substream_samples(
863         num_time_ticks,
864         // One or two channels.
865         std::vector<int32_t>(output_channel_labels.size(), 0));
866     // Output gains to be applied to the (one or two) channels.
867     std::vector<double> output_gains_linear(output_channel_labels.size());
868     int channel_index = 0;
869     for (const auto& output_channel_label : output_channel_labels) {
870       auto iter = input_label_to_samples.find(output_channel_label);
871       if (iter == input_label_to_samples.end()) {
872         return absl::UnknownError(absl::StrCat(
873             "Samples do not exist for channel: ", output_channel_label));
874       }
875       for (int t = 0; t < num_time_ticks; t++) {
876         RETURN_IF_NOT_OK(NormalizedFloatingPointToInt32(
877             iter->second[t], substream_samples[t][channel_index]));
878       }
879 
880       // Compute and store the linear output gains.
881       auto gain_iter =
882           demixing_metadata->label_to_output_gain.find(output_channel_label);
883       output_gains_linear[channel_index] = 1.0;
884       if (gain_iter != demixing_metadata->label_to_output_gain.end()) {
885         output_gains_linear[channel_index] =
886             std::pow(10.0, gain_iter->second / 20.0);
887       }
888 
889       channel_index++;
890     }
891 
892     // Find the `SubstreamData` with this `substream_id`.
893     auto substream_data_iter =
894         substream_id_to_substream_data.find(substream_id);
895     if (substream_data_iter == substream_id_to_substream_data.end()) {
896       return absl::UnknownError(absl::StrCat(
897           "Failed to find substream data for substream ID= ", substream_id));
898     }
899     auto& substream_data = substream_data_iter->second;
900 
901     // Add all down mixed samples to both queues.
902 
903     for (const auto& channel_samples : substream_samples) {
904       substream_data.samples_obu.push_back(channel_samples);
905 
906       // Apply output gains to the samples going to the encoder.
907       std::vector<int32_t> attenuated_channel_samples(channel_samples.size());
908       for (int i = 0; i < channel_samples.size(); ++i) {
909         // Intermediate computation is a `double`. But both `channel_samples`
910         // and `attenuated_channel_samples` are `int32_t`.
911         const double attenuated_sample =
912             static_cast<double>(channel_samples[i]) / output_gains_linear[i];
913         RETURN_IF_NOT_OK(ClipDoubleToInt32(attenuated_sample,
914                                            attenuated_channel_samples[i]));
915       }
916       substream_data.samples_encode.push_back(attenuated_channel_samples);
917     }
918   }
919 
920   return absl::OkStatus();
921 }
922 
923 // TODO(b/288240600): Down-mix audio samples in a standalone function too.
DemixOriginalAudioSamples(const std::list<AudioFrameWithData> & audio_frames) const924 absl::StatusOr<IdLabeledFrameMap> DemixingModule::DemixOriginalAudioSamples(
925     const std::list<AudioFrameWithData>& audio_frames) const {
926   if (demixing_mode_ == DemixingMode::kReconstruction) {
927     return absl::FailedPreconditionError(
928         "Demixing original audio samples is not available in reconstruction "
929         "mode.");
930   }
931   IdLabeledFrameMap id_to_labeled_frame;
932   for (const auto& [audio_element_id, demixing_metadata] :
933        audio_element_id_to_demixing_metadata_) {
934     // Process the original audio frames.
935     LabeledFrame labeled_frame;
936     RETURN_IF_NOT_OK(StoreSamplesForAudioElementId(
937         audio_frames, demixing_metadata.substream_id_to_labels, labeled_frame));
938     if (!labeled_frame.label_to_samples.empty()) {
939       RETURN_IF_NOT_OK(
940           ApplyDemixers(demixing_metadata.demixers, labeled_frame));
941       id_to_labeled_frame[audio_element_id] = std::move(labeled_frame);
942     }
943 
944     LogForAudioElementId("Original", audio_element_id, id_to_labeled_frame);
945   }
946 
947   return id_to_labeled_frame;
948 }
949 
DemixDecodedAudioSamples(const std::list<DecodedAudioFrame> & decoded_audio_frames) const950 absl::StatusOr<IdLabeledFrameMap> DemixingModule::DemixDecodedAudioSamples(
951     const std::list<DecodedAudioFrame>& decoded_audio_frames) const {
952   IdLabeledFrameMap id_to_labeled_decoded_frame;
953   for (const auto& [audio_element_id, demixing_metadata] :
954        audio_element_id_to_demixing_metadata_) {
955     // Process the decoded audio frames.
956     LabeledFrame labeled_decoded_frame;
957     RETURN_IF_NOT_OK(StoreSamplesForAudioElementId(
958         decoded_audio_frames, demixing_metadata.substream_id_to_labels,
959         labeled_decoded_frame));
960     if (!labeled_decoded_frame.label_to_samples.empty()) {
961       RETURN_IF_NOT_OK(
962           ApplyDemixers(demixing_metadata.demixers, labeled_decoded_frame));
963       id_to_labeled_decoded_frame[audio_element_id] =
964           std::move(labeled_decoded_frame);
965     }
966 
967     LogForAudioElementId("Decoded", audio_element_id,
968                          id_to_labeled_decoded_frame);
969   }
970 
971   return id_to_labeled_decoded_frame;
972 }
973 
GetDownMixers(DecodedUleb128 audio_element_id,const std::list<Demixer> * & down_mixers) const974 absl::Status DemixingModule::GetDownMixers(
975     DecodedUleb128 audio_element_id,
976     const std::list<Demixer>*& down_mixers) const {
977   const DemixingMetadataForAudioElementId* demixing_metadata = nullptr;
978   RETURN_IF_NOT_OK(GetDemixerMetadata(audio_element_id,
979                                       audio_element_id_to_demixing_metadata_,
980                                       demixing_metadata));
981   down_mixers = &demixing_metadata->down_mixers;
982   return absl::OkStatus();
983 }
984 
GetDemixers(DecodedUleb128 audio_element_id,const std::list<Demixer> * & demixers) const985 absl::Status DemixingModule::GetDemixers(
986     DecodedUleb128 audio_element_id,
987     const std::list<Demixer>*& demixers) const {
988   const DemixingMetadataForAudioElementId* demixing_metadata = nullptr;
989   RETURN_IF_NOT_OK(GetDemixerMetadata(audio_element_id,
990                                       audio_element_id_to_demixing_metadata_,
991                                       demixing_metadata));
992   demixers = &demixing_metadata->demixers;
993   return absl::OkStatus();
994 }
995 
996 }  // namespace iamf_tools
997