1 /*
2 * Copyright (c) 2023 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 "intensity_processor.h"
17
18 #include "audio_utils.h"
19 #include "sensor_log.h"
20 #include "sensors_errors.h"
21
22 #undef LOG_TAG
23 #define LOG_TAG "IntensityProcessor"
24
25 namespace OHOS {
26 namespace Sensors {
27 namespace {
28 constexpr double VOLUME_DB_COEF { 10.0 };
29 } // namespace
30
GetRMS(const std::vector<double> & data,int32_t hopLength,bool centerFlag)31 std::vector<double> IntensityProcessor::GetRMS(const std::vector<double> &data, int32_t hopLength, bool centerFlag)
32 {
33 CALL_LOG_ENTER;
34 std::vector<double> rmseEnvelop;
35 if ((data.empty()) || (hopLength < 1)) {
36 SEN_HILOGE("data is empty or hopLength is less than 1");
37 return rmseEnvelop;
38 }
39 std::vector<double> paddingData;
40 if (centerFlag) {
41 AudioUtils audioUtil;
42 paddingData = audioUtil.PadData(data, hopLength);
43 } else {
44 paddingData = data;
45 }
46 size_t paddingDataSize = paddingData.size();
47 size_t frmN = paddingDataSize / static_cast<size_t>(hopLength);
48 for (size_t i = 0; i < frmN; ++i) {
49 double accum = 0.0;
50 int32_t index = i * hopLength;
51 for (int32_t j = 0; j < hopLength; ++j, ++index) {
52 accum += pow(paddingData[index], 2);
53 }
54 rmseEnvelop.push_back(sqrt(accum / hopLength));
55 }
56 return rmseEnvelop;
57 }
58
EnergyEnvelop(const std::vector<double> & data,int32_t nFft,int32_t hopLength)59 std::vector<double> IntensityProcessor::EnergyEnvelop(const std::vector<double> &data, int32_t nFft, int32_t hopLength)
60 {
61 std::vector<double> dataAbsPower;
62 size_t dataSize = data.size();
63 for (size_t i = 0; i < dataSize; ++i) {
64 dataAbsPower.push_back(data[i] * data[i]);
65 }
66 std::vector<double> oneFrmData;
67 std::vector<double> blockAmplitudeSum;
68 auto it = dataAbsPower.begin();
69 for (size_t i = 0; (i + nFft) < dataSize;) {
70 oneFrmData.assign(it + i, it + i + nFft);
71 double accum = accumulate(begin(oneFrmData), end(oneFrmData), 0);
72 blockAmplitudeSum.emplace_back(accum);
73 i += hopLength;
74 }
75 return blockAmplitudeSum;
76 }
77
RmseNormalize(const std::vector<double> & rmseEnvelope,double lowerDelta,std::vector<double> & rmseBand,std::vector<int32_t> & rmseNorm)78 int32_t IntensityProcessor::RmseNormalize(const std::vector<double> &rmseEnvelope, double lowerDelta,
79 std::vector<double> &rmseBand, std::vector<int32_t> &rmseNorm)
80 {
81 CALL_LOG_ENTER;
82 if (rmseEnvelope.empty()) {
83 SEN_HILOGE("rmseEnvelope is empty");
84 return Sensors::ERROR;
85 }
86 // Set low energy to 0.
87 rmseBand = rmseEnvelope;
88 for (size_t i = 0; i < rmseBand.size(); ++i) {
89 if (rmseBand[i] < lowerDelta) {
90 rmseBand[i] = 0;
91 }
92 }
93 rmseNorm = OHOS::Sensors::NormalizePercentage(rmseBand);
94 if (rmseNorm.empty()) {
95 SEN_HILOGE("rmseNorm is empty");
96 return Sensors::ERROR;
97 }
98 return Sensors::SUCCESS;
99 }
100
VolumeInLinary(const std::vector<double> & data,int32_t hopLength)101 std::vector<double> IntensityProcessor::VolumeInLinary(const std::vector<double> &data, int32_t hopLength)
102 {
103 CALL_LOG_ENTER;
104 std::vector<double> dataAbsPower;
105 size_t dataSize = data.size();
106 for (size_t i = 0; i < dataSize; ++i) {
107 dataAbsPower.push_back(abs(data[i]));
108 }
109 std::vector<double> oneFrmData;
110 std::vector<double> blockAmplitudeSum;
111 auto it = dataAbsPower.begin();
112 for (size_t i = 0; (i + hopLength) < dataSize;) {
113 oneFrmData.assign(it + i, it + i + hopLength);
114 double accum = accumulate(oneFrmData.begin(), oneFrmData.end(), 0);
115 blockAmplitudeSum.push_back(accum);
116 i += hopLength;
117 }
118 return blockAmplitudeSum;
119 }
120
VolumeInDB(const std::vector<double> & data,int32_t hopLength)121 std::vector<double> IntensityProcessor::VolumeInDB(const std::vector<double> &data, int32_t hopLength)
122 {
123 CALL_LOG_ENTER;
124 std::vector<double> blockSum = EnergyEnvelop(data, hopLength, hopLength);
125 std::vector<double> db(blockSum.size(), 0.0);
126 for (size_t i = 0; i < blockSum.size(); ++i) {
127 db[i] = VOLUME_DB_COEF * log(blockSum[i]);
128 if (IsLessNotEqual(db[i], 0.0)) {
129 db[i] = 0.0;
130 }
131 }
132 return db;
133 }
134 } // namespace Sensors
135 } // namespace OHOS