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_sink_output_node.h"
24 #include "audio_effect.h"
25
26 using namespace OHOS;
27 using namespace AudioStandard;
28 using namespace HPAE;
29 using namespace testing::ext;
30 using namespace testing;
31
32 namespace OHOS {
33 namespace AudioStandard {
34
35 const int32_t DEFAULT_VALUE_TWO = 2;
36 const uint32_t DEFAULT_SESSIONID_NUM_FIRST = 12345;
37 const uint32_t DEFAULT_SESSIONID_NUM_SECOND = 12346;
38 const uint32_t DEFAULT_NODEID_NUM_FIRST = 1243;
39 const size_t DEFAULT_FRAMELEN_FIRST = 820;
40 const size_t DEFAULT_FRAMELEN_SECOND = 960;
41 const int32_t DEFAULT_TEST_VALUE_FIRST = 100;
42 const int32_t DEFAULT_TEST_VALUE_SECOND = 200;
43 const float LOUDNESS_GAIN = 1.0f;
44
45
46 class HpaeProcessClusterTest : public testing::Test {
47 public:
48 void SetUp();
49 void TearDown();
50 };
51
SetUp()52 void HpaeProcessClusterTest::SetUp()
53 {}
54
TearDown()55 void HpaeProcessClusterTest::TearDown()
56 {}
57
58 HWTEST_F(HpaeProcessClusterTest, constructHpaeProcessClusterNode, TestSize.Level0)
59 {
60 HpaeNodeInfo nodeInfo;
61 nodeInfo.nodeId = DEFAULT_NODEID_NUM_FIRST;
62 nodeInfo.frameLen = DEFAULT_FRAMELEN_SECOND;
63 nodeInfo.sessionId = DEFAULT_SESSIONID_NUM_FIRST;
64 nodeInfo.samplingRate = SAMPLE_RATE_48000;
65 nodeInfo.channels = STEREO;
66 nodeInfo.format = SAMPLE_F32LE;
67
68 HpaeSinkInfo dummySinkInfo;
69
70 std::shared_ptr<HpaeProcessCluster> hpaeProcessCluster =
71 std::make_shared<HpaeProcessCluster>(nodeInfo, dummySinkInfo);
72 EXPECT_EQ(hpaeProcessCluster->GetSampleRate(), nodeInfo.samplingRate);
73 EXPECT_EQ(hpaeProcessCluster->GetFrameLen(), nodeInfo.frameLen);
74 EXPECT_EQ(hpaeProcessCluster->GetChannelCount(), nodeInfo.channels);
75 EXPECT_EQ(hpaeProcessCluster->GetBitWidth(), nodeInfo.format);
76 HpaeNodeInfo &retNi = hpaeProcessCluster->GetNodeInfo();
77 EXPECT_EQ(retNi.samplingRate, nodeInfo.samplingRate);
78 EXPECT_EQ(retNi.frameLen, nodeInfo.frameLen);
79 EXPECT_EQ(retNi.channels, nodeInfo.channels);
80 EXPECT_EQ(retNi.format, nodeInfo.format);
81
82 std::shared_ptr<HpaeSinkInputNode> hpaeSinkInputNode = std::make_shared<HpaeSinkInputNode>(nodeInfo);
83 hpaeProcessCluster->Connect(hpaeSinkInputNode);
84 EXPECT_EQ(hpaeSinkInputNode.use_count(), static_cast<long>(DEFAULT_VALUE_TWO));
85 EXPECT_EQ(hpaeProcessCluster->GetGainNodeCount(), 1);
86 EXPECT_EQ(hpaeProcessCluster->GetConverterNodeCount(), 1);
87 nodeInfo.frameLen = DEFAULT_FRAMELEN_FIRST;
88 nodeInfo.sessionId = DEFAULT_SESSIONID_NUM_SECOND;
89 nodeInfo.samplingRate = SAMPLE_RATE_44100;
90 std::shared_ptr<HpaeSinkInputNode> hpaeSinkInputNode1 = std::make_shared<HpaeSinkInputNode>(nodeInfo);
91 hpaeProcessCluster->Connect(hpaeSinkInputNode1);
92 EXPECT_EQ(hpaeSinkInputNode1.use_count(), static_cast<long>(DEFAULT_VALUE_TWO));
93 EXPECT_EQ(hpaeProcessCluster->GetGainNodeCount(), (DEFAULT_VALUE_TWO));
94 EXPECT_EQ(hpaeProcessCluster->GetConverterNodeCount(), 1 + 1);
95 }
96 static int32_t g_testValue1 = 0;
97 static int32_t g_testValue2 = 0;
TestRendererRenderFrame(const char * data,uint64_t len)98 static int32_t TestRendererRenderFrame(const char *data, uint64_t len)
99 {
100 float curGain = 0.0f;
101 float targetGain = 1.0f;
102 uint64_t frameLen = len / (SAMPLE_F32LE * STEREO);
103 float stepGain = (targetGain - curGain) / frameLen;
104 for (int32_t i = 0; i < frameLen; i++) {
105 EXPECT_EQ(*((float *)data + i * STEREO + 1), (g_testValue1 * (curGain + i * stepGain) +
106 g_testValue2 * (curGain + i * stepGain)));
107 EXPECT_EQ(*((float *)data + i * STEREO), (g_testValue1 * (curGain + i * stepGain) +
108 g_testValue2 * (curGain + i * stepGain)));
109 }
110 return 0;
111 }
CreateHpaeInfo(HpaeNodeInfo & nodeInfo,HpaeSinkInfo & dummySinkInfo)112 static void CreateHpaeInfo(HpaeNodeInfo &nodeInfo, HpaeSinkInfo &dummySinkInfo)
113 {
114 nodeInfo.nodeId = DEFAULT_NODEID_NUM_FIRST;
115 nodeInfo.frameLen = DEFAULT_FRAMELEN_SECOND;
116 nodeInfo.samplingRate = SAMPLE_RATE_48000;
117 nodeInfo.channels = STEREO;
118 nodeInfo.format = SAMPLE_F32LE;
119 dummySinkInfo.channels = STEREO;
120 dummySinkInfo.frameLen = DEFAULT_FRAMELEN_SECOND;
121 dummySinkInfo.format = SAMPLE_F32LE;
122 dummySinkInfo.samplingRate = SAMPLE_RATE_48000;
123 }
124
125 HWTEST_F(HpaeProcessClusterTest, testHpaeWriteDataProcessSessionTest, TestSize.Level0)
126 {
127 HpaeNodeInfo nodeInfo;
128 HpaeSinkInfo dummySinkInfo;
129 CreateHpaeInfo(nodeInfo, dummySinkInfo);
130 std::shared_ptr<HpaeSinkOutputNode> hpaeSinkOutputNode = std::make_shared<HpaeSinkOutputNode>(nodeInfo);
131 nodeInfo.sessionId = DEFAULT_SESSIONID_NUM_FIRST;
132 std::shared_ptr<HpaeSinkInputNode> hpaeSinkInputNode0 = std::make_shared<HpaeSinkInputNode>(nodeInfo);
133 nodeInfo.sessionId = DEFAULT_SESSIONID_NUM_SECOND;
134 std::shared_ptr<HpaeSinkInputNode> hpaeSinkInputNode1 = std::make_shared<HpaeSinkInputNode>(nodeInfo);
135 std::shared_ptr<HpaeProcessCluster> hpaeProcessCluster =
136 std::make_shared<HpaeProcessCluster>(nodeInfo, dummySinkInfo);
137 hpaeProcessCluster->Connect(hpaeSinkInputNode0);
138 hpaeProcessCluster->Connect(hpaeSinkInputNode1);
139 EXPECT_EQ(hpaeSinkOutputNode->GetPreOutNum(), 0);
140 EXPECT_EQ(hpaeProcessCluster->GetGainNodeCount(), DEFAULT_VALUE_TWO);
141 EXPECT_EQ(hpaeProcessCluster->GetConverterNodeCount(), DEFAULT_VALUE_TWO);
142 EXPECT_EQ(hpaeSinkOutputNode->GetPreOutNum(), 0);
143 hpaeSinkOutputNode->Connect(hpaeProcessCluster);
144 std::string deviceClass = "file_io";
145 std::string deviceNetId = "LocalDevice";
146 EXPECT_EQ(hpaeSinkOutputNode->GetPreOutNum(), 1);
147 EXPECT_EQ(hpaeSinkOutputNode->GetRenderSinkInstance(deviceClass, deviceNetId), 0);
148 EXPECT_EQ(hpaeSinkInputNode0.use_count(), static_cast<long>(DEFAULT_VALUE_TWO));
149 EXPECT_EQ(hpaeSinkInputNode1.use_count(), static_cast<long>(DEFAULT_VALUE_TWO));
150 EXPECT_EQ(hpaeProcessCluster.use_count(), 1);
151 g_testValue1 = DEFAULT_TEST_VALUE_FIRST;
152 std::shared_ptr<WriteFixedValueCb> writeFixedValueCb0 =
153 std::make_shared<WriteFixedValueCb>(SAMPLE_F32LE, g_testValue1);
154 hpaeSinkInputNode0->RegisterWriteCallback(writeFixedValueCb0);
155 g_testValue2 = DEFAULT_TEST_VALUE_SECOND;
156 std::shared_ptr<WriteFixedValueCb> writeFixedValueCb1 =
157 std::make_shared<WriteFixedValueCb>(SAMPLE_F32LE, g_testValue2);
158 hpaeSinkInputNode1->RegisterWriteCallback(writeFixedValueCb1);
159 hpaeSinkOutputNode->DoProcess();
160 TestRendererRenderFrame(hpaeSinkOutputNode->GetRenderFrameData(),
161 nodeInfo.frameLen * nodeInfo.channels * GetSizeFromFormat(nodeInfo.format));
162 hpaeSinkOutputNode->DisConnect(hpaeProcessCluster);
163 EXPECT_EQ(hpaeSinkOutputNode->GetPreOutNum(), 0);
164 EXPECT_EQ(hpaeProcessCluster.use_count(), 1);
165 hpaeProcessCluster->DisConnect(hpaeSinkInputNode0);
166 EXPECT_EQ(hpaeSinkInputNode0.use_count(), 1);
167 EXPECT_EQ(hpaeProcessCluster->GetGainNodeCount(), 1);
168 hpaeProcessCluster->DisConnect(hpaeSinkInputNode1);
169 EXPECT_EQ(hpaeSinkInputNode1.use_count(), 1);
170 EXPECT_EQ(hpaeProcessCluster->GetGainNodeCount(), 0);
171 }
172
173 HWTEST_F(HpaeProcessClusterTest, testEffectNode_001, TestSize.Level0)
174 {
175 HpaeNodeInfo nodeInfo;
176 nodeInfo.nodeId = DEFAULT_NODEID_NUM_FIRST;
177 nodeInfo.frameLen = DEFAULT_FRAMELEN_SECOND;
178 nodeInfo.sessionId = DEFAULT_SESSIONID_NUM_FIRST;
179 nodeInfo.samplingRate = SAMPLE_RATE_48000;
180 nodeInfo.channels = STEREO;
181 nodeInfo.format = SAMPLE_F32LE;
182 HpaeSinkInfo dummySinkInfo;
183
184 std::shared_ptr<HpaeProcessCluster> hpaeProcessCluster =
185 std::make_shared<HpaeProcessCluster>(nodeInfo, dummySinkInfo);
186 hpaeProcessCluster->DoProcess();
187 EXPECT_EQ(hpaeProcessCluster->AudioRendererCreate(nodeInfo), 0);
188 hpaeProcessCluster->DoProcess();
189 EXPECT_EQ(hpaeProcessCluster->AudioRendererStart(nodeInfo), 0);
190 EXPECT_EQ(hpaeProcessCluster->AudioRendererStop(nodeInfo), 0);
191 EXPECT_EQ(hpaeProcessCluster->AudioRendererRelease(nodeInfo), 0);
192
193 nodeInfo.sceneType = HPAE_SCENE_SPLIT_MEDIA;
194 hpaeProcessCluster =
195 std::make_shared<HpaeProcessCluster>(nodeInfo, dummySinkInfo);
196 EXPECT_EQ(hpaeProcessCluster->AudioRendererCreate(nodeInfo), 0);
197 EXPECT_EQ(hpaeProcessCluster->AudioRendererStart(nodeInfo), 0);
198 EXPECT_EQ(hpaeProcessCluster->AudioRendererStop(nodeInfo), 0);
199 EXPECT_EQ(hpaeProcessCluster->AudioRendererRelease(nodeInfo), 0);
200 }
201
202 HWTEST_F(HpaeProcessClusterTest, testGetNodeInputFormatInfo, TestSize.Level0)
203 {
204 // test processCluster without effectnode and loundess algorithm handle
205 HpaeNodeInfo nodeInfo;
206 nodeInfo.nodeId = DEFAULT_NODEID_NUM_FIRST;
207 nodeInfo.frameLen = DEFAULT_FRAMELEN_SECOND;
208 nodeInfo.sessionId = DEFAULT_SESSIONID_NUM_FIRST;
209 nodeInfo.samplingRate = SAMPLE_RATE_44100;
210 nodeInfo.channels = CHANNEL_6;
211 nodeInfo.channelLayout = CH_LAYOUT_5POINT1;
212 nodeInfo.format = SAMPLE_F32LE;
213 nodeInfo.sceneType = HPAE_SCENE_EFFECT_NONE;
214
215 HpaeSinkInfo dummySinkInfo;
216 dummySinkInfo.samplingRate = SAMPLE_RATE_96000;
217 dummySinkInfo.channels = STEREO;
218 dummySinkInfo.channelLayout = CH_LAYOUT_STEREO;
219
220 auto dummySinkInputNode = std::make_shared<HpaeSinkInputNode>(nodeInfo);
221 std::shared_ptr<HpaeProcessCluster> hpaeProcessCluster =
222 std::make_shared<HpaeProcessCluster>(nodeInfo, dummySinkInfo);
223
224 hpaeProcessCluster->Connect(dummySinkInputNode);
225
226 AudioBasicFormat basicFormat;
227 hpaeProcessCluster->SetLoudnessGain(DEFAULT_NODEID_NUM_FIRST, 0.0f);
228 int32_t ret = hpaeProcessCluster->GetNodeInputFormatInfo(nodeInfo.sessionId, basicFormat);
229
230 EXPECT_EQ(ret, SUCCESS);
231 EXPECT_EQ(basicFormat.audioChannelInfo.channelLayout, CH_LAYOUT_STEREO);
232 EXPECT_EQ(basicFormat.audioChannelInfo.numChannels, static_cast<uint32_t>(STEREO));
233 EXPECT_EQ(basicFormat.rate, SAMPLE_RATE_96000);
234
235 // test processCluster with effectnode and loundess algorithm handle
236 hpaeProcessCluster = nullptr;
237 nodeInfo.sceneType = HPAE_SCENE_MUSIC;
238 hpaeProcessCluster = std::make_shared<HpaeProcessCluster>(nodeInfo, dummySinkInfo);
239 hpaeProcessCluster->Connect(dummySinkInputNode);
240 EXPECT_EQ(hpaeProcessCluster->AudioRendererCreate(nodeInfo), SUCCESS);
241
242 hpaeProcessCluster->SetLoudnessGain(DEFAULT_NODEID_NUM_FIRST, LOUDNESS_GAIN);
243 ret = hpaeProcessCluster->GetNodeInputFormatInfo(nodeInfo.sessionId, basicFormat);
244 EXPECT_EQ(basicFormat.audioChannelInfo.channelLayout, CH_LAYOUT_STEREO);
245 EXPECT_EQ(basicFormat.audioChannelInfo.numChannels, static_cast<uint32_t>(STEREO));
246 EXPECT_EQ(basicFormat.rate, SAMPLE_RATE_48000);
247 }
248 } // AudioStandard
249 } // OHOS