• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024, 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/parameters_manager.h"
13 
14 #include <cstdint>
15 #include <memory>
16 #include <utility>
17 #include <vector>
18 
19 #include "absl/container/flat_hash_map.h"
20 #include "absl/status/status.h"
21 #include "absl/status/status_matchers.h"
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24 #include "iamf/cli/audio_element_with_data.h"
25 #include "iamf/cli/parameter_block_with_data.h"
26 #include "iamf/cli/tests/cli_test_utils.h"
27 #include "iamf/obu/audio_element.h"
28 #include "iamf/obu/codec_config.h"
29 #include "iamf/obu/demixing_info_parameter_data.h"
30 #include "iamf/obu/demixing_param_definition.h"
31 #include "iamf/obu/obu_header.h"
32 #include "iamf/obu/param_definitions.h"
33 #include "iamf/obu/parameter_block.h"
34 #include "iamf/obu/recon_gain_info_parameter_data.h"
35 #include "iamf/obu/types.h"
36 
37 namespace iamf_tools {
38 namespace {
39 
40 using ::absl_testing::IsOk;
41 
42 constexpr DecodedUleb128 kCodecConfigId = 1450;
43 constexpr DecodedUleb128 kSampleRate = 16000;
44 constexpr DecodedUleb128 kAudioElementId = 157;
45 constexpr DecodedUleb128 kFirstSubstreamId = 0;
46 constexpr DecodedUleb128 kSecondSubstreamId = 1;
47 constexpr DecodedUleb128 kParameterId = 995;
48 constexpr DecodedUleb128 kSecondParameterId = 996;
49 constexpr DecodedUleb128 kDuration = 8;
50 constexpr InternalTimestamp kDurationAsInternalTimestamp = 8;
51 
52 constexpr DemixingInfoParameterData::DMixPMode kDMixPMode =
53     DemixingInfoParameterData::kDMixPMode3_n;
54 
AppendParameterBlock(DecodedUleb128 parameter_id,InternalTimestamp start_timestamp,const ParamDefinition & param_definition,std::vector<ParameterBlockWithData> & parameter_blocks)55 absl::Status AppendParameterBlock(
56     DecodedUleb128 parameter_id, InternalTimestamp start_timestamp,
57     const ParamDefinition& param_definition,
58     std::vector<ParameterBlockWithData>& parameter_blocks) {
59   parameter_blocks.emplace_back(ParameterBlockWithData{
60       std::make_unique<ParameterBlockObu>(ObuHeader(), parameter_id,
61                                           param_definition),
62       start_timestamp, start_timestamp + kDurationAsInternalTimestamp});
63   ParameterBlockObu& parameter_block_obu = *parameter_blocks.back().obu;
64   absl::Status status = parameter_block_obu.InitializeSubblocks();
65   return status;
66 }
67 
AddOneDemixingParameterBlock(const ParamDefinition & param_definition,InternalTimestamp start_timestamp,std::vector<ParameterBlockWithData> & parameter_blocks)68 absl::Status AddOneDemixingParameterBlock(
69     const ParamDefinition& param_definition, InternalTimestamp start_timestamp,
70     std::vector<ParameterBlockWithData>& parameter_blocks) {
71   auto status = AppendParameterBlock(kParameterId, start_timestamp,
72                                      param_definition, parameter_blocks);
73   auto demixing_info_param_data = std::make_unique<DemixingInfoParameterData>();
74   demixing_info_param_data->dmixp_mode = kDMixPMode;
75   ParameterBlockObu& parameter_block_obu = *parameter_blocks.back().obu;
76   parameter_block_obu.subblocks_[0].param_data =
77       std::move(demixing_info_param_data);
78 
79   return status;
80 }
81 
AddOneReconGainParameterBlock(const ParamDefinition & param_definition,InternalTimestamp start_timestamp,std::vector<ParameterBlockWithData> & parameter_blocks)82 absl::Status AddOneReconGainParameterBlock(
83     const ParamDefinition& param_definition, InternalTimestamp start_timestamp,
84     std::vector<ParameterBlockWithData>& parameter_blocks) {
85   auto status = AppendParameterBlock(kSecondParameterId, start_timestamp,
86                                      param_definition, parameter_blocks);
87 
88   auto recon_gain_info_parameter_data =
89       std::make_unique<ReconGainInfoParameterData>();
90   recon_gain_info_parameter_data->recon_gain_elements.emplace_back(
91       ReconGainElement{
92           .recon_gain_flag = DecodedUleb128(1),
93           .recon_gain = {0},
94       });
95   ParameterBlockObu& parameter_block_obu = *parameter_blocks.back().obu;
96   parameter_block_obu.subblocks_[0].param_data =
97       std::move(recon_gain_info_parameter_data);
98   return status;
99 }
100 
101 class ParametersManagerTest : public testing::Test {
102  public:
ParametersManagerTest()103   ParametersManagerTest() {
104     AddLpcmCodecConfigWithIdAndSampleRate(kCodecConfigId, kSampleRate,
105                                           codec_config_obus_);
106     AddAmbisonicsMonoAudioElementWithSubstreamIds(
107         kAudioElementId, kCodecConfigId, {kFirstSubstreamId},
108         codec_config_obus_, audio_elements_);
109 
110     auto& audio_element_obu = audio_elements_.at(kAudioElementId).obu;
111     AddDemixingParamDefinition(kParameterId, kSampleRate, kDuration,
112                                audio_element_obu);
113 
114     EXPECT_THAT(
115         AddOneDemixingParameterBlock(
116             std::get<DemixingParamDefinition>(
117                 audio_element_obu.audio_element_params_[0].param_definition),
118             /*start_timestamp=*/0, demixing_parameter_blocks_),
119         IsOk());
120   }
121 
122  protected:
123   absl::flat_hash_map<uint32_t, CodecConfigObu> codec_config_obus_;
124   absl::flat_hash_map<DecodedUleb128, AudioElementWithData> audio_elements_;
125   std::vector<ParameterBlockWithData> demixing_parameter_blocks_;
126   std::vector<ParameterBlockWithData> recon_gain_parameter_blocks_;
127   std::unique_ptr<ParametersManager> parameters_manager_;
128 };
129 
TEST_F(ParametersManagerTest,InitializeSucceeds)130 TEST_F(ParametersManagerTest, InitializeSucceeds) {
131   parameters_manager_ = std::make_unique<ParametersManager>(audio_elements_);
132   EXPECT_THAT(parameters_manager_->Initialize(), IsOk());
133 }
134 
TEST_F(ParametersManagerTest,InitializeWithTwoDemixingParametersFails)135 TEST_F(ParametersManagerTest, InitializeWithTwoDemixingParametersFails) {
136   // Add one more demixing parameter definition, which is disallowed.
137   AddDemixingParamDefinition(kParameterId, kSampleRate, kDuration,
138                              audio_elements_.at(kAudioElementId).obu);
139 
140   parameters_manager_ = std::make_unique<ParametersManager>(audio_elements_);
141   EXPECT_FALSE(parameters_manager_->Initialize().ok());
142 }
143 
TEST_F(ParametersManagerTest,InitializeWithReconGainParameterSucceeds)144 TEST_F(ParametersManagerTest, InitializeWithReconGainParameterSucceeds) {
145   // Remove existng param definitions added in the constructor of the
146   // test fixture.
147   audio_elements_.at(kAudioElementId).obu.audio_element_params_.clear();
148   AddReconGainParamDefinition(kSecondParameterId, kSampleRate, kDuration,
149                               audio_elements_.at(kAudioElementId).obu);
150   EXPECT_THAT(
151       AddOneReconGainParameterBlock(
152           std::get<ReconGainParamDefinition>(audio_elements_.at(kAudioElementId)
153                                                  .obu.audio_element_params_[0]
154                                                  .param_definition),
155           /*start_timestamp=*/0, recon_gain_parameter_blocks_),
156       IsOk());
157   parameters_manager_ = std::make_unique<ParametersManager>(audio_elements_);
158   EXPECT_THAT(parameters_manager_->Initialize(), IsOk());
159 }
160 
TEST_F(ParametersManagerTest,DemixingParamDefinitionIsAvailable)161 TEST_F(ParametersManagerTest, DemixingParamDefinitionIsAvailable) {
162   parameters_manager_ = std::make_unique<ParametersManager>(audio_elements_);
163   ASSERT_THAT(parameters_manager_->Initialize(), IsOk());
164 
165   EXPECT_TRUE(
166       parameters_manager_->DemixingParamDefinitionAvailable(kAudioElementId));
167 }
168 
TEST_F(ParametersManagerTest,GetDownMixingParametersSucceeds)169 TEST_F(ParametersManagerTest, GetDownMixingParametersSucceeds) {
170   parameters_manager_ = std::make_unique<ParametersManager>(audio_elements_);
171   ASSERT_THAT(parameters_manager_->Initialize(), IsOk());
172   parameters_manager_->AddDemixingParameterBlock(
173       &demixing_parameter_blocks_[0]);
174 
175   DownMixingParams down_mixing_params;
176   EXPECT_THAT(parameters_manager_->GetDownMixingParameters(kAudioElementId,
177                                                            down_mixing_params),
178               IsOk());
179 
180   // Validate the values correspond to `kDMixPMode3_n`.
181   EXPECT_FLOAT_EQ(down_mixing_params.alpha, 1.0);
182   EXPECT_FLOAT_EQ(down_mixing_params.beta, 0.866);
183   EXPECT_FLOAT_EQ(down_mixing_params.gamma, 0.866);
184   EXPECT_FLOAT_EQ(down_mixing_params.delta, 0.866);
185   EXPECT_EQ(down_mixing_params.w_idx_offset, 1);
186   EXPECT_EQ(down_mixing_params.w_idx_used, 0);
187   EXPECT_FLOAT_EQ(down_mixing_params.w, 0.0);
188 }
189 
TEST_F(ParametersManagerTest,GetReconGainInfoParameterDataSucceeds)190 TEST_F(ParametersManagerTest, GetReconGainInfoParameterDataSucceeds) {
191   AddReconGainParamDefinition(kSecondParameterId, kSampleRate, kDuration,
192                               audio_elements_.at(kAudioElementId).obu);
193   ASSERT_THAT(
194       AddOneReconGainParameterBlock(
195           std::get<ReconGainParamDefinition>(audio_elements_.at(kAudioElementId)
196                                                  .obu.audio_element_params_[1]
197                                                  .param_definition),
198           /*start_timestamp=*/0, recon_gain_parameter_blocks_),
199       IsOk());
200   parameters_manager_ = std::make_unique<ParametersManager>(audio_elements_);
201   ASSERT_THAT(parameters_manager_->Initialize(), IsOk());
202   parameters_manager_->AddReconGainParameterBlock(
203       &recon_gain_parameter_blocks_[0]);
204 
205   ReconGainInfoParameterData recon_gain_info_parameter_data;
206   EXPECT_THAT(
207       parameters_manager_->GetReconGainInfoParameterData(
208           kAudioElementId, /*num_layers=*/1, recon_gain_info_parameter_data),
209       IsOk());
210 
211   EXPECT_EQ(recon_gain_info_parameter_data.recon_gain_elements.size(), 1);
212   ASSERT_TRUE(
213       recon_gain_info_parameter_data.recon_gain_elements[0].has_value());
214   EXPECT_EQ(
215       recon_gain_info_parameter_data.recon_gain_elements[0]->recon_gain_flag,
216       DecodedUleb128(1));
217   EXPECT_EQ(
218       recon_gain_info_parameter_data.recon_gain_elements[0]->recon_gain[0], 0);
219 }
220 
TEST_F(ParametersManagerTest,GetReconGainInfoParameterDataSucceedsWithNoParameterBlocks)221 TEST_F(ParametersManagerTest,
222        GetReconGainInfoParameterDataSucceedsWithNoParameterBlocks) {
223   AddReconGainParamDefinition(kSecondParameterId, kSampleRate, kDuration,
224                               audio_elements_.at(kAudioElementId).obu);
225   parameters_manager_ = std::make_unique<ParametersManager>(audio_elements_);
226   ASSERT_THAT(parameters_manager_->Initialize(), IsOk());
227 
228   ReconGainInfoParameterData recon_gain_info_parameter_data;
229   EXPECT_THAT(
230       parameters_manager_->GetReconGainInfoParameterData(
231           kAudioElementId, /*num_layers=*/1, recon_gain_info_parameter_data),
232       IsOk());
233 
234   EXPECT_EQ(recon_gain_info_parameter_data.recon_gain_elements.size(), 1);
235   ASSERT_TRUE(
236       recon_gain_info_parameter_data.recon_gain_elements[0].has_value());
237   EXPECT_EQ(
238       recon_gain_info_parameter_data.recon_gain_elements[0]->recon_gain_flag,
239       DecodedUleb128(0));
240   EXPECT_EQ(
241       recon_gain_info_parameter_data.recon_gain_elements[0]->recon_gain[0],
242       255);
243 }
244 
TEST_F(ParametersManagerTest,GetReconGainInfoParameterDataSucceedsWithNoParamDefinition)245 TEST_F(ParametersManagerTest,
246        GetReconGainInfoParameterDataSucceedsWithNoParamDefinition) {
247   parameters_manager_ = std::make_unique<ParametersManager>(audio_elements_);
248   ASSERT_THAT(parameters_manager_->Initialize(), IsOk());
249 
250   ReconGainInfoParameterData recon_gain_info_parameter_data;
251   EXPECT_THAT(
252       parameters_manager_->GetReconGainInfoParameterData(
253           kAudioElementId, /*num_layers=*/1, recon_gain_info_parameter_data),
254       IsOk());
255 
256   EXPECT_EQ(recon_gain_info_parameter_data.recon_gain_elements.size(), 1);
257   ASSERT_TRUE(
258       recon_gain_info_parameter_data.recon_gain_elements[0].has_value());
259   EXPECT_EQ(
260       recon_gain_info_parameter_data.recon_gain_elements[0]->recon_gain_flag,
261       DecodedUleb128(0));
262   EXPECT_EQ(
263       recon_gain_info_parameter_data.recon_gain_elements[0]->recon_gain[0],
264       255);
265 }
266 
TEST_F(ParametersManagerTest,GetMultipleReconGainParametersSucceeds)267 TEST_F(ParametersManagerTest, GetMultipleReconGainParametersSucceeds) {
268   // Tests that multiple recon gain parameters are returned correctly when there
269   // are multiple recon gain parameter blocks within the same substream, with
270   // consecutive timestamps.
271   AddReconGainParamDefinition(kSecondParameterId, kSampleRate, kDuration,
272                               audio_elements_.at(kAudioElementId).obu);
273   ASSERT_THAT(
274       AddOneReconGainParameterBlock(
275           std::get<ReconGainParamDefinition>(audio_elements_.at(kAudioElementId)
276                                                  .obu.audio_element_params_[1]
277                                                  .param_definition),
278           /*start_timestamp=*/0, recon_gain_parameter_blocks_),
279       IsOk());
280   parameters_manager_ = std::make_unique<ParametersManager>(audio_elements_);
281   ASSERT_THAT(parameters_manager_->Initialize(), IsOk());
282   parameters_manager_->AddReconGainParameterBlock(
283       &recon_gain_parameter_blocks_[0]);
284 
285   // First recon gain parameter block.
286   ReconGainInfoParameterData recon_gain_parameter_data_0;
287   EXPECT_THAT(
288       parameters_manager_->GetReconGainInfoParameterData(
289           kAudioElementId, /*num_layers=*/1, recon_gain_parameter_data_0),
290       IsOk());
291   EXPECT_EQ(recon_gain_parameter_data_0.recon_gain_elements.size(), 1);
292   ASSERT_TRUE(recon_gain_parameter_data_0.recon_gain_elements[0].has_value());
293   EXPECT_EQ(recon_gain_parameter_data_0.recon_gain_elements[0]->recon_gain_flag,
294             DecodedUleb128(1));
295   EXPECT_EQ(recon_gain_parameter_data_0.recon_gain_elements[0]->recon_gain[0],
296             0);
297 
298   EXPECT_THAT(parameters_manager_->UpdateReconGainState(
299                   kAudioElementId,
300                   /*expected_next_timestamp=*/kDuration),
301               IsOk());
302 
303   // Second recon gain parameter block.
304   ASSERT_THAT(
305       AddOneReconGainParameterBlock(
306           std::get<ReconGainParamDefinition>(audio_elements_.at(kAudioElementId)
307                                                  .obu.audio_element_params_[1]
308                                                  .param_definition),
309           /*start_timestamp=*/kDurationAsInternalTimestamp,
310           recon_gain_parameter_blocks_),
311       IsOk());
312   parameters_manager_->AddReconGainParameterBlock(
313       &recon_gain_parameter_blocks_[1]);
314   ReconGainInfoParameterData recon_gain_parameter_data_1;
315   EXPECT_THAT(
316       parameters_manager_->GetReconGainInfoParameterData(
317           kAudioElementId, /*num_layers=*/1, recon_gain_parameter_data_1),
318       IsOk());
319   EXPECT_EQ(recon_gain_parameter_data_1.recon_gain_elements.size(), 1);
320   ASSERT_TRUE(recon_gain_parameter_data_1.recon_gain_elements[0].has_value());
321   EXPECT_EQ(recon_gain_parameter_data_1.recon_gain_elements[0]->recon_gain_flag,
322             DecodedUleb128(1));
323   EXPECT_EQ(recon_gain_parameter_data_1.recon_gain_elements[0]->recon_gain[0],
324             0);
325   // Updating should succeed a second time with the expected timestamp now
326   // offset by the duration of the parameter block.
327   EXPECT_THAT(parameters_manager_->UpdateReconGainState(
328                   kAudioElementId,
329                   /*expected_next_timestamp=*/kDuration + kDuration),
330               IsOk());
331 }
332 
TEST_F(ParametersManagerTest,GetMultipleReconGainParametersFailsWithoutUpdatingState)333 TEST_F(ParametersManagerTest,
334        GetMultipleReconGainParametersFailsWithoutUpdatingState) {
335   AddReconGainParamDefinition(kSecondParameterId, kSampleRate, kDuration,
336                               audio_elements_.at(kAudioElementId).obu);
337   ASSERT_THAT(
338       AddOneReconGainParameterBlock(
339           std::get<ReconGainParamDefinition>(audio_elements_.at(kAudioElementId)
340                                                  .obu.audio_element_params_[1]
341                                                  .param_definition),
342           /*start_timestamp=*/0, recon_gain_parameter_blocks_),
343       IsOk());
344   parameters_manager_ = std::make_unique<ParametersManager>(audio_elements_);
345   ASSERT_THAT(parameters_manager_->Initialize(), IsOk());
346   parameters_manager_->AddReconGainParameterBlock(
347       &recon_gain_parameter_blocks_[0]);
348 
349   // First recon gain parameter block.
350   ReconGainInfoParameterData recon_gain_parameter_data_0;
351   EXPECT_THAT(
352       parameters_manager_->GetReconGainInfoParameterData(
353           kAudioElementId, /*num_layers=*/1, recon_gain_parameter_data_0),
354       IsOk());
355 
356   // Second recon gain parameter block.
357   ASSERT_THAT(
358       AddOneReconGainParameterBlock(
359           std::get<ReconGainParamDefinition>(audio_elements_.at(kAudioElementId)
360                                                  .obu.audio_element_params_[1]
361                                                  .param_definition),
362           /*start_timestamp=*/kDurationAsInternalTimestamp,
363           recon_gain_parameter_blocks_),
364       IsOk());
365   parameters_manager_->AddReconGainParameterBlock(
366       &recon_gain_parameter_blocks_[1]);
367   ReconGainInfoParameterData recon_gain_parameter_data_1;
368   EXPECT_FALSE(parameters_manager_
369                    ->GetReconGainInfoParameterData(kAudioElementId,
370                                                    /*num_layers=*/1,
371                                                    recon_gain_parameter_data_1)
372                    .ok());
373 }
374 
TEST_F(ParametersManagerTest,ParameterBlocksRunOutReturnsDefault)375 TEST_F(ParametersManagerTest, ParameterBlocksRunOutReturnsDefault) {
376   parameters_manager_ = std::make_unique<ParametersManager>(audio_elements_);
377   ASSERT_THAT(parameters_manager_->Initialize(), IsOk());
378 
379   parameters_manager_->AddDemixingParameterBlock(
380       &demixing_parameter_blocks_[0]);
381 
382   DownMixingParams down_mixing_params;
383   EXPECT_THAT(parameters_manager_->GetDownMixingParameters(kAudioElementId,
384                                                            down_mixing_params),
385               IsOk());
386 
387   EXPECT_THAT(parameters_manager_->UpdateDemixingState(
388                   kAudioElementId,
389                   /*expected_next_timestamp=*/kDurationAsInternalTimestamp),
390               IsOk());
391 
392   // Get the parameters for the second time. Since there is only one
393   // parameter block and is already used up the previous time, the function
394   // will not find a parameter block and will return default values.
395   EXPECT_THAT(parameters_manager_->GetDownMixingParameters(kAudioElementId,
396                                                            down_mixing_params),
397               IsOk());
398 
399   // Validate the values correspond to `kDMixPMode1` and `default_w = 10`,
400   // which are the default set in `AddDemixingParamDefinition()`.
401   EXPECT_FLOAT_EQ(down_mixing_params.alpha, 1.0);
402   EXPECT_FLOAT_EQ(down_mixing_params.beta, 1.0);
403   EXPECT_FLOAT_EQ(down_mixing_params.gamma, 0.707);
404   EXPECT_FLOAT_EQ(down_mixing_params.delta, 0.707);
405   EXPECT_EQ(down_mixing_params.w_idx_offset, -1);
406   EXPECT_EQ(down_mixing_params.w_idx_used, 10);
407   EXPECT_FLOAT_EQ(down_mixing_params.w, 0.5);
408 
409   // `UpdateDemixingState()` also succeeds with some arbitrary timestamp,
410   // because technically there's nothing to update.
411   const DecodedUleb128 kArbitraryTimestamp = 972;
412   EXPECT_THAT(parameters_manager_->UpdateDemixingState(
413                   kAudioElementId,
414                   /*expected_next_timestamp=*/kArbitraryTimestamp),
415               IsOk());
416 }
417 
TEST_F(ParametersManagerTest,ParameterIdNotFoundReturnsDefault)418 TEST_F(ParametersManagerTest, ParameterIdNotFoundReturnsDefault) {
419   // Modify the parameter definition of the audio element so it does not
420   // correspond to any parameter blocks inside `parameter_blocks_`.
421   std::get<DemixingParamDefinition>(audio_elements_.at(kAudioElementId)
422                                         .obu.audio_element_params_[0]
423                                         .param_definition)
424       .parameter_id_ = kParameterId + 1;
425 
426   // Create the parameters manager and get down mixing parameters; default
427   // values are returned because the parameter ID is different from those
428   // in the `parameter_blocks_`.
429   parameters_manager_ = std::make_unique<ParametersManager>(audio_elements_);
430   ASSERT_THAT(parameters_manager_->Initialize(), IsOk());
431   parameters_manager_->AddDemixingParameterBlock(
432       &demixing_parameter_blocks_[0]);
433 
434   DownMixingParams down_mixing_params;
435   EXPECT_THAT(parameters_manager_->GetDownMixingParameters(kAudioElementId,
436                                                            down_mixing_params),
437               IsOk());
438 
439   // Validate the values correspond to `kDMixPMode1` and `default_w = 10`,
440   // which are the default set in `AddDemixingParamDefinition()`.
441   EXPECT_FLOAT_EQ(down_mixing_params.alpha, 1.0);
442   EXPECT_FLOAT_EQ(down_mixing_params.beta, 1.0);
443   EXPECT_FLOAT_EQ(down_mixing_params.gamma, 0.707);
444   EXPECT_FLOAT_EQ(down_mixing_params.delta, 0.707);
445   EXPECT_EQ(down_mixing_params.w_idx_offset, -1);
446   EXPECT_EQ(down_mixing_params.w_idx_used, 10);
447   EXPECT_FLOAT_EQ(down_mixing_params.w, 0.5);
448 }
449 
TEST_F(ParametersManagerTest,GetDownMixingParametersTwiceDifferentW)450 TEST_F(ParametersManagerTest, GetDownMixingParametersTwiceDifferentW) {
451   // Add another parameter block, so we can get down-mix parameters twice.
452   ASSERT_THAT(
453       AddOneDemixingParameterBlock(
454           std::get<DemixingParamDefinition>(audio_elements_.at(kAudioElementId)
455                                                 .obu.audio_element_params_[0]
456                                                 .param_definition),
457           /*start_timestamp=*/kDuration, demixing_parameter_blocks_),
458       IsOk());
459 
460   parameters_manager_ = std::make_unique<ParametersManager>(audio_elements_);
461   ASSERT_THAT(parameters_manager_->Initialize(), IsOk());
462   parameters_manager_->AddDemixingParameterBlock(
463       &demixing_parameter_blocks_[0]);
464 
465   // Get down-mix parameters for the first time.
466   DownMixingParams down_mixing_params;
467   ASSERT_THAT(parameters_manager_->GetDownMixingParameters(kAudioElementId,
468                                                            down_mixing_params),
469               IsOk());
470   EXPECT_THAT(parameters_manager_->UpdateDemixingState(
471                   kAudioElementId,
472                   /*expected_next_timestamp=*/kDuration),
473               IsOk());
474 
475   // The first time `w_idx` is 0, and the corresponding `w` is 0.
476   const double kWFirst = 0.0;
477   const double kWSecond = 0.0179;
478   EXPECT_FLOAT_EQ(down_mixing_params.w, kWFirst);
479 
480   // Add and get down-mix parameters for the second time.
481   parameters_manager_->AddDemixingParameterBlock(
482       &demixing_parameter_blocks_[1]);
483   EXPECT_THAT(parameters_manager_->GetDownMixingParameters(kAudioElementId,
484                                                            down_mixing_params),
485               IsOk());
486 
487   // Validate the values correspond to `kDMixPMode3_n`. Since `w_idx` has
488   // been updated to 1, `w` becomes 0.0179.
489   EXPECT_FLOAT_EQ(down_mixing_params.alpha, 1.0);
490   EXPECT_FLOAT_EQ(down_mixing_params.beta, 0.866);
491   EXPECT_FLOAT_EQ(down_mixing_params.gamma, 0.866);
492   EXPECT_FLOAT_EQ(down_mixing_params.delta, 0.866);
493   EXPECT_EQ(down_mixing_params.w_idx_offset, 1);
494   EXPECT_EQ(down_mixing_params.w_idx_used, 1);
495 
496   // Updated `w`, different from the first time above.
497   EXPECT_FLOAT_EQ(down_mixing_params.w, kWSecond);
498 }
499 
TEST_F(ParametersManagerTest,GetDownMixingParametersTwiceWithoutUpdateSameW)500 TEST_F(ParametersManagerTest, GetDownMixingParametersTwiceWithoutUpdateSameW) {
501   // Add another parameter block, so it is possible to get down-mix parameters
502   // twice.
503   ASSERT_THAT(
504       AddOneDemixingParameterBlock(
505           std::get<DemixingParamDefinition>(audio_elements_.at(kAudioElementId)
506                                                 .obu.audio_element_params_[0]
507                                                 .param_definition),
508           /*start_timestamp=*/kDuration, demixing_parameter_blocks_),
509       IsOk());
510 
511   parameters_manager_ = std::make_unique<ParametersManager>(audio_elements_);
512   ASSERT_THAT(parameters_manager_->Initialize(), IsOk());
513   parameters_manager_->AddDemixingParameterBlock(
514       &demixing_parameter_blocks_[0]);
515 
516   // Get down-mix parameters twice without calling
517   // `AddDemixingParameterBlock()` and `UpdateDemixngState()`; the same
518   // down-mix parameters will be returned.
519   DownMixingParams down_mixing_params;
520   ASSERT_THAT(parameters_manager_->GetDownMixingParameters(kAudioElementId,
521                                                            down_mixing_params),
522               IsOk());
523 
524   // The first time `w_idx` is 0, and the corresponding `w` is 0.
525   EXPECT_EQ(down_mixing_params.w_idx_used, 0);
526   EXPECT_FLOAT_EQ(down_mixing_params.w, 0.0);
527 
528   EXPECT_THAT(parameters_manager_->GetDownMixingParameters(kAudioElementId,
529                                                            down_mixing_params),
530               IsOk());
531 
532   // Validate the values correspond to `kDMixPMode3_n`. Since `w_idx` has
533   // NOT been updated, `w` remains 0.0.
534   EXPECT_FLOAT_EQ(down_mixing_params.alpha, 1.0);
535   EXPECT_FLOAT_EQ(down_mixing_params.beta, 0.866);
536   EXPECT_FLOAT_EQ(down_mixing_params.gamma, 0.866);
537   EXPECT_FLOAT_EQ(down_mixing_params.delta, 0.866);
538   EXPECT_EQ(down_mixing_params.w_idx_offset, 1);
539   EXPECT_EQ(down_mixing_params.w_idx_used, 0);
540   EXPECT_FLOAT_EQ(down_mixing_params.w, 0.0);
541 }
542 
TEST_F(ParametersManagerTest,TwoAudioElementGettingParameterBlocksWithDifferentTimestampsFails)543 TEST_F(ParametersManagerTest,
544        TwoAudioElementGettingParameterBlocksWithDifferentTimestampsFails) {
545   // Add another parameter block, so we can get down-mix parameters twice.
546   ASSERT_THAT(
547       AddOneDemixingParameterBlock(
548           std::get<DemixingParamDefinition>(audio_elements_.at(kAudioElementId)
549                                                 .obu.audio_element_params_[0]
550                                                 .param_definition),
551           /*start_timestamp=*/kDuration, demixing_parameter_blocks_),
552       IsOk());
553 
554   // Add a second audio element sharing the same demixing parameter.
555   constexpr DecodedUleb128 kAudioElementId2 = kAudioElementId + 1;
556   AddAmbisonicsMonoAudioElementWithSubstreamIds(
557       kAudioElementId2, kCodecConfigId, {kSecondSubstreamId},
558       codec_config_obus_, audio_elements_);
559   auto& second_audio_element_obu = audio_elements_.at(kAudioElementId2).obu;
560   AddDemixingParamDefinition(kParameterId, kSampleRate, kDuration,
561                              second_audio_element_obu);
562 
563   parameters_manager_ = std::make_unique<ParametersManager>(audio_elements_);
564   ASSERT_THAT(parameters_manager_->Initialize(), IsOk());
565   parameters_manager_->AddDemixingParameterBlock(
566       &demixing_parameter_blocks_[0]);
567 
568   // Get down-mix parameters for the first audio element corresponding to the
569   // first frame; the `w` value is 0.
570   const double kWFirst = 0.0;
571   const double kWSecond = 0.0179;
572   DownMixingParams down_mixing_params;
573   ASSERT_THAT(parameters_manager_->GetDownMixingParameters(kAudioElementId,
574                                                            down_mixing_params),
575               IsOk());
576   EXPECT_THAT(parameters_manager_->UpdateDemixingState(
577                   kAudioElementId,
578                   /*expected_next_timestamp=*/kDuration),
579               IsOk());
580   EXPECT_FLOAT_EQ(down_mixing_params.w, kWFirst);
581 
582   // Add the parameter block for the first audio element corresponding to the
583   // second frame.
584   parameters_manager_->AddDemixingParameterBlock(
585       &demixing_parameter_blocks_[1]);
586   ASSERT_THAT(parameters_manager_->GetDownMixingParameters(kAudioElementId,
587                                                            down_mixing_params),
588               IsOk());
589   EXPECT_FLOAT_EQ(down_mixing_params.w, kWSecond);
590 
591   // Get down-mix parameters for the second audio element. The second audio
592   // element shares the same parameter ID, but is still expecting the
593   // parameter block for the first frame (while the manager is already
594   // holding the parameter block for the second frame). So the getter fails.
595   EXPECT_FALSE(
596       parameters_manager_
597           ->GetDownMixingParameters(kAudioElementId2, down_mixing_params)
598           .ok());
599 }
600 
TEST_F(ParametersManagerTest,DemixingParamDefinitionIsNotAvailableForWrongId)601 TEST_F(ParametersManagerTest, DemixingParamDefinitionIsNotAvailableForWrongId) {
602   parameters_manager_ = std::make_unique<ParametersManager>(audio_elements_);
603   ASSERT_THAT(parameters_manager_->Initialize(), IsOk());
604   parameters_manager_->AddDemixingParameterBlock(
605       &demixing_parameter_blocks_[0]);
606 
607   const DecodedUleb128 kWrongAudioElementId = kAudioElementId + 1;
608   EXPECT_FALSE(parameters_manager_->DemixingParamDefinitionAvailable(
609       kWrongAudioElementId));
610 
611   // However, `GetDownMixingParameters()` still succeeds.
612   DownMixingParams down_mixing_params;
613   EXPECT_THAT(parameters_manager_->GetDownMixingParameters(kWrongAudioElementId,
614                                                            down_mixing_params),
615               IsOk());
616 
617   // `UpdateDemixingState()` also succeeds.
618   EXPECT_THAT(parameters_manager_->UpdateDemixingState(
619                   kWrongAudioElementId,
620                   /*expected_next_timestamp=*/kDuration),
621               IsOk());
622 }
623 
TEST_F(ParametersManagerTest,UpdateFailsWithWrongTimestamps)624 TEST_F(ParametersManagerTest, UpdateFailsWithWrongTimestamps) {
625   parameters_manager_ = std::make_unique<ParametersManager>(audio_elements_);
626   ASSERT_THAT(parameters_manager_->Initialize(), IsOk());
627   parameters_manager_->AddDemixingParameterBlock(
628       &demixing_parameter_blocks_[0]);
629 
630   // The second frame starts with timestamp = 8, so updating with a different
631   // timestamp fails.
632   constexpr InternalTimestamp kWrongNextTimestamp = 17;
633   EXPECT_FALSE(parameters_manager_
634                    ->UpdateDemixingState(kAudioElementId, kWrongNextTimestamp)
635                    .ok());
636 }
637 
TEST_F(ParametersManagerTest,UpdateNotValidatingWhenParameterIdNotFound)638 TEST_F(ParametersManagerTest, UpdateNotValidatingWhenParameterIdNotFound) {
639   // Modify the parameter definition of the audio element so it does not
640   // correspond to any parameter blocks inside `parameter_blocks_`.
641   std::get<DemixingParamDefinition>(audio_elements_.at(kAudioElementId)
642                                         .obu.audio_element_params_[0]
643                                         .param_definition)
644       .parameter_id_ = kParameterId + 1;
645 
646   // Create the parameters manager and get down mixing parameters; default
647   // values are returned because the parameter ID is not found.
648   parameters_manager_ = std::make_unique<ParametersManager>(audio_elements_);
649   ASSERT_THAT(parameters_manager_->Initialize(), IsOk());
650   parameters_manager_->AddDemixingParameterBlock(
651       &demixing_parameter_blocks_[0]);
652 
653   // `UpdateDemixingState()` succeeds with any timestamp passed in,
654   // because no validation is performed.
655   for (const InternalTimestamp timestamp : {0, 8, -200, 61, 4772}) {
656     EXPECT_THAT(
657         parameters_manager_->UpdateDemixingState(kAudioElementId, timestamp),
658         IsOk());
659   }
660 }
661 
662 }  // namespace
663 }  // namespace iamf_tools
664