1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <gtest/gtest.h>
17 #include <cmath>
18 #include <memory>
19 #include "hpae_process_cluster.h"
20 #include "test_case_common.h"
21 #include "audio_errors.h"
22 #include "hpae_sink_input_node.h"
23 #include "hpae_output_cluster.h"
24 using namespace testing::ext;
25 using namespace testing;
26 namespace OHOS {
27 namespace AudioStandard {
28 namespace HPAE {
29 constexpr uint32_t NODE_ID = 1243;
30 constexpr uint32_t SESSION_ID_1 = 12345;
31 constexpr uint32_t SESSION_ID_2 = 12346;
32 constexpr uint32_t FRAME_LEN = 960;
33 constexpr uint32_t FRAME_LEN_2 = 820;
34 constexpr uint32_t NUM_TWO = 2;
35 constexpr int32_t TEST_VALUE_1 = 300;
36 constexpr int32_t TEST_VALUE_2 = 400;
37
38 static std::string g_deviceClass = "file_io";
39 static std::string g_deviceNetId = "LocalDevice";
40
41
TestRendererRenderFrame(const char * data,uint64_t len)42 static int32_t TestRendererRenderFrame(const char *data, uint64_t len)
43 {
44 float curGain = 0.0f;
45 float targetGain = 1.0f;
46 uint64_t frameLen = len / (SAMPLE_F32LE * STEREO);
47 float stepGain = (targetGain - curGain) / frameLen;
48
49 const float *tempData = reinterpret_cast<const float *>(data);
50 for (int32_t i = 0; i < frameLen; i++) {
51 const float left = tempData[NUM_TWO * i];
52 const float right = tempData[NUM_TWO * i + 1];
53 const float expectedValue = TEST_VALUE_1 * (curGain + i * stepGain) + TEST_VALUE_2 * (curGain + i * stepGain);
54 EXPECT_EQ(left, expectedValue);
55 EXPECT_EQ(right, expectedValue);
56 }
57 return 0;
58 }
59
InitHpaeWriteDataOutSessionTest(HpaeNodeInfo & nodeInfo,HpaeSinkInfo & dummySinkInfo)60 static void InitHpaeWriteDataOutSessionTest(HpaeNodeInfo &nodeInfo, HpaeSinkInfo &dummySinkInfo)
61 {
62 nodeInfo.nodeId = NODE_ID;
63 nodeInfo.frameLen = FRAME_LEN;
64 nodeInfo.samplingRate = SAMPLE_RATE_48000;
65 nodeInfo.channels = STEREO;
66 nodeInfo.format = SAMPLE_F32LE;
67
68 dummySinkInfo.frameLen = FRAME_LEN;
69 dummySinkInfo.samplingRate = SAMPLE_RATE_48000;
70 dummySinkInfo.channels = STEREO;
71 dummySinkInfo.format = SAMPLE_F32LE;
72 dummySinkInfo.deviceClass = g_deviceClass;
73 dummySinkInfo.deviceNetId = g_deviceNetId;
74 }
75
76 class HpaeOutputClusterTest : public testing::Test {
77 public:
78 void SetUp();
79 void TearDown();
80 };
81
SetUp()82 void HpaeOutputClusterTest::SetUp()
83 {}
84
TearDown()85 void HpaeOutputClusterTest::TearDown()
86 {}
87
88 HWTEST_F(HpaeOutputClusterTest, constructHpaeOutputClusterNode, TestSize.Level0)
89 {
90 HpaeNodeInfo nodeInfo;
91 nodeInfo.nodeId = NODE_ID;
92 nodeInfo.frameLen = FRAME_LEN;
93 nodeInfo.sessionId = SESSION_ID_1;
94 nodeInfo.samplingRate = SAMPLE_RATE_48000;
95 nodeInfo.channels = STEREO;
96 nodeInfo.format = SAMPLE_F32LE;
97 int32_t syncId = 123;
98
99 std::shared_ptr<HpaeOutputCluster> hpaeoutputCluster = std::make_shared<HpaeOutputCluster>(nodeInfo);
100 EXPECT_EQ(hpaeoutputCluster->GetSampleRate(), nodeInfo.samplingRate);
101 EXPECT_EQ(hpaeoutputCluster->GetFrameLen(), nodeInfo.frameLen);
102 EXPECT_EQ(hpaeoutputCluster->GetChannelCount(), nodeInfo.channels);
103 EXPECT_EQ(hpaeoutputCluster->GetBitWidth(), nodeInfo.format);
104
105 std::shared_ptr<HpaeSinkInputNode> hpaeSinkInputNode = std::make_shared<HpaeSinkInputNode>(nodeInfo);
106 hpaeoutputCluster->Connect(hpaeSinkInputNode);
107 EXPECT_EQ(hpaeSinkInputNode.use_count(), NUM_TWO);
108 EXPECT_EQ(hpaeoutputCluster->GetConverterNodeCount(), 1);
109 nodeInfo.frameLen = FRAME_LEN_2;
110 nodeInfo.sessionId = SESSION_ID_2;
111 nodeInfo.samplingRate = SAMPLE_RATE_44100;
112 std::shared_ptr<HpaeSinkInputNode> hpaeSinkInputNode1 = std::make_shared<HpaeSinkInputNode>(nodeInfo);
113 hpaeoutputCluster->Connect(hpaeSinkInputNode1);
114 EXPECT_EQ(hpaeSinkInputNode1.use_count(), NUM_TWO);
115 EXPECT_EQ(hpaeoutputCluster->GetConverterNodeCount(), 1);
116 EXPECT_EQ(hpaeoutputCluster->SetSyncId(syncId), SUCCESS);
117 }
118
119 HWTEST_F(HpaeOutputClusterTest, testHpaeWriteDataOutSessionTest, TestSize.Level0)
120 {
121 HpaeNodeInfo nodeInfo;
122 HpaeSinkInfo dummySinkInfo;
123 InitHpaeWriteDataOutSessionTest(nodeInfo, dummySinkInfo);
124 std::shared_ptr<HpaeOutputCluster> hpaeOutputCluster = std::make_shared<HpaeOutputCluster>(nodeInfo);
125 nodeInfo.sessionId = SESSION_ID_1;
126 nodeInfo.streamType = STREAM_MUSIC;
127 if (hpaeOutputCluster->mixerNode_) {
128 hpaeOutputCluster->mixerNode_->limiter_ = nullptr;
129 }
130 std::shared_ptr<HpaeSinkInputNode> musicSinkInputNode = std::make_shared<HpaeSinkInputNode>(nodeInfo);
131 nodeInfo.sessionId = SESSION_ID_2;
132 nodeInfo.streamType = STREAM_RING;
133 std::shared_ptr<HpaeSinkInputNode> ringSinkInputNode = std::make_shared<HpaeSinkInputNode>(nodeInfo);
134 nodeInfo.sceneType = HPAE_SCENE_MUSIC;
135 std::shared_ptr<HpaeProcessCluster> muiscProcessCluster =
136 std::make_shared<HpaeProcessCluster>(nodeInfo, dummySinkInfo);
137 nodeInfo.sceneType = HPAE_SCENE_RING;
138 std::shared_ptr<HpaeProcessCluster> ringProcessCluster =
139 std::make_shared<HpaeProcessCluster>(nodeInfo, dummySinkInfo);
140 muiscProcessCluster->Connect(musicSinkInputNode);
141 ringProcessCluster->Connect(ringSinkInputNode);
142 hpaeOutputCluster->Connect(muiscProcessCluster);
143 hpaeOutputCluster->Connect(ringProcessCluster);
144
145 EXPECT_EQ(ringProcessCluster->GetGainNodeCount(), 1);
146 EXPECT_EQ(muiscProcessCluster->GetGainNodeCount(), 1);
147 EXPECT_EQ(muiscProcessCluster->GetConverterNodeCount(), 1);
148 EXPECT_EQ(ringProcessCluster->GetConverterNodeCount(), 1);
149 EXPECT_EQ(hpaeOutputCluster->GetConverterNodeCount(), NUM_TWO);
150 EXPECT_EQ(hpaeOutputCluster->GetPreOutNum(), NUM_TWO);
151
152 EXPECT_EQ(hpaeOutputCluster->GetInstance(g_deviceClass, g_deviceNetId), 0);
153 EXPECT_EQ(musicSinkInputNode.use_count(), NUM_TWO);
154 EXPECT_EQ(ringSinkInputNode.use_count(), NUM_TWO);
155 EXPECT_EQ(muiscProcessCluster.use_count(), 1);
156 std::shared_ptr<WriteFixedValueCb> writeFixedValueCb0 =
157 std::make_shared<WriteFixedValueCb>(SAMPLE_F32LE, TEST_VALUE_1);
158 musicSinkInputNode->RegisterWriteCallback(writeFixedValueCb0);
159 std::shared_ptr<WriteFixedValueCb> writeFixedValueCb1 =
160 std::make_shared<WriteFixedValueCb>(SAMPLE_F32LE, TEST_VALUE_2);
161 ringSinkInputNode->RegisterWriteCallback(writeFixedValueCb1);
162 hpaeOutputCluster->DoProcess();
163 TestRendererRenderFrame(hpaeOutputCluster->GetFrameData(),
164 nodeInfo.frameLen * nodeInfo.channels * GetSizeFromFormat(nodeInfo.format));
165 muiscProcessCluster->DisConnect(musicSinkInputNode);
166 EXPECT_EQ(musicSinkInputNode.use_count(), 1);
167 EXPECT_EQ(muiscProcessCluster->GetGainNodeCount(), 0);
168 ringProcessCluster->DisConnect(ringSinkInputNode);
169 EXPECT_EQ(ringSinkInputNode.use_count(), 1);
170 hpaeOutputCluster->DisConnect(muiscProcessCluster);
171 EXPECT_EQ(hpaeOutputCluster->GetPreOutNum(), 1);
172 hpaeOutputCluster->DisConnect(ringProcessCluster);
173 EXPECT_EQ(hpaeOutputCluster->GetPreOutNum(), 0);
174 }
175 } // namespace HPAE
176 } // namespace AudioStandard
177 } // namespace OHOS