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 <algorithm>
17 #include <numeric>
18
19 #include "generate_vibration_json_file.h"
20 #include "sensor_log.h"
21 #include "sensors_errors.h"
22 #include "vibration_convert_core.h"
23
24 #undef LOG_TAG
25 #define LOG_TAG "VibrationConvertCore"
26
27 namespace OHOS {
28 namespace Sensors {
29 namespace {
30 constexpr double AMP_INVALIDE_DELTA { 0.001 };
31 constexpr int32_t FRAGMENT_MIN_LEN { 32 };
32 constexpr double COEF { 0.01 };
33 constexpr double RMS_INVALIDE_DELTA { 0.04 };
34 // A transient event is distributed within three 1024 (46ms) windows
35 constexpr int32_t ONSET_ONE_WIN { 3072 };
36 // A transient event rising range
37 constexpr double ONSET_SPLIT_RATIO { 0.33334 };
38 constexpr double LOWER_AMP { 0.03 };
39 constexpr double FRAME_DURATION { 0.046 };
40 constexpr double TRANSIENT_DURATION_DEFAULT { 0.03 };
41 constexpr double CONTINOUS_MIN_DURATION { 0.01 };
42 constexpr int32_t FRAME_LEN { 2048 };
43 constexpr int32_t SILENCE_COUNT_MIN { 32 };
44 constexpr int32_t CONTINUOUS_EVENT_LOW_DELTA_MULTIPLES { 5 };
45 constexpr int32_t ONE_TRANSIENT_DURATION_MS { 30 };
46 constexpr int32_t ONSET_MINSKIP_MAX { 5 };
47 constexpr int32_t ONSET_MINSKIP_MIN { 1 };
48 constexpr double TRANSIENT_UNZERO_DENSITY_MIN { 0.3 };
49 constexpr double DB_ZOOM_COEF { 3.846 }; // 100 / 26
50 constexpr int32_t TRANSIENT_EVENT_INTENSITY_MIN { 30 };
51 constexpr int32_t TRANSIENT_EVENT_FREQUENCY_MIN { 80 };
52 constexpr double RMSEMAX_THRESHOLD_HIGH { 0.4 };
53 constexpr double RMSEMAX_THRESHIOLD_MID { 0.2 };
54 constexpr double RMSE_LOWDELTA_RATIO_HIGH { 0.1 };
55 constexpr double RMSE_LOWDELTA_RATIO_MID { 0.05 };
56 constexpr double RMSE_LOWDELTA_RATIO_LOW { 0.03 };
57 constexpr double RMSE_LOWDELTA_RATIO_STEP { 0.01 };
58 constexpr int32_t RMSE_LOWDELTA_ITERATION_TIMES { 8 };
59 constexpr double SLOP_DELTA_MIN { 0.1745329251 }; // PI / 18
60 constexpr int32_t RESAMPLE_MULTIPLE { 4 };
61 constexpr size_t LOCAL_ENVELOPE_MAX_LEN { 16 };
62 constexpr size_t MIN_SKIP { 3 };
63 constexpr double AMPLITUDE_DB_MAX { 1.0 };
64 constexpr int32_t ADSR_BOUNDARY_STATUS_NONE { 0 };
65 constexpr int32_t ADSR_BOUNDARY_STATUS_ONE { 1 };
66 constexpr int32_t ADSR_BOUNDARY_STATUS_BOTH { 2 };
67 } // namespace
68
GetAudioData()69 int32_t VibrationConvertCore::GetAudioData()
70 {
71 std::vector<double> data = PreprocessAudioData();
72 int32_t onsetHopLength = WINDOW_LENGTH;
73 double rmsILowerDelta = 0.0;
74 if (PreprocessParameter(data, onsetHopLength, rmsILowerDelta) != Sensors::SUCCESS) {
75 SEN_HILOGE("PreprocessParameter failed");
76 return Sensors::ERROR;
77 }
78 std::vector<UnionTransientEvent> unionTransientEvents;
79 if (ConvertTransientEvent(data, onsetHopLength, unionTransientEvents) != Sensors::SUCCESS) {
80 SEN_HILOGE("ConvertTransientEvent failed");
81 return Sensors::ERROR;
82 }
83 std::vector<IntensityData> intensityData;
84 // Processing intensity data, output parameters:intensityData
85 if (DetectRmsIntensity(data, rmsILowerDelta, intensityData) != Sensors::SUCCESS) {
86 SEN_HILOGE("DetectRmsIntensity failed");
87 return Sensors::ERROR;
88 }
89 // Frequency detection
90 std::vector<int32_t> rmseIntensityNorm;
91 for (size_t i = 0; i < intensityData.size(); i++) {
92 rmseIntensityNorm.push_back(intensityData[i].rmseIntensityNorm);
93 }
94 std::vector<int32_t> freqNorm = DetectFrequency(data, rmseIntensityNorm);
95 if (freqNorm.empty()) {
96 SEN_HILOGE("DetectFrequency failed");
97 return Sensors::ERROR;
98 }
99 std::vector<int32_t> transientIndexes;
100 std::vector<double> transientEventTime;
101 // Output all Transient events, output parameters: transientIndex transientEventTime
102 OutputTransientEvents(unionTransientEvents, intensityData, freqNorm, transientIndexes, transientEventTime);
103 if (continuousEventExistFlag_) {
104 std::vector<bool> transientEventFlags;
105 for (size_t i = 0; i < unionTransientEvents.size(); i++) {
106 transientEventFlags.push_back(unionTransientEvents[i].transientEventFlag);
107 }
108 OutputAllContinuousEvent(intensityData, transientIndexes, freqNorm, transientEventFlags);
109 }
110 return Sensors::SUCCESS;
111 }
112
ConvertAudioToHaptic(const AudioSetting & audioSetting,const std::vector<double> & audioData,std::vector<HapticEvent> & hapticEvents)113 int32_t VibrationConvertCore::ConvertAudioToHaptic(const AudioSetting &audioSetting,
114 const std::vector<double> &audioData, std::vector<HapticEvent> &hapticEvents)
115 {
116 if (audioData.empty()) {
117 SEN_HILOGE("audioData is empty");
118 return Sensors::ERROR;
119 }
120 audioSetting_ = audioSetting;
121 if (ResampleAudioData(audioData) != Sensors::SUCCESS) {
122 SEN_HILOGE("ResampleAudioData failed");
123 return Sensors::ERROR;
124 }
125 if (GetAudioData() != Sensors::SUCCESS) {
126 SEN_HILOGE("GetAudioData failed");
127 return Sensors::ERROR;
128 }
129 StoreHapticEvent();
130 hapticEvents = hapticEvents_;
131 GenerateVibrationJsonFile jsonFile;
132 jsonFile.GenerateJsonFile(hapticEvents_);
133 return Sensors::SUCCESS;
134 }
135
ResampleAudioData(const std::vector<double> & srcData)136 int32_t VibrationConvertCore::ResampleAudioData(const std::vector<double> &srcData)
137 {
138 if (srcData.empty()) {
139 SEN_HILOGE("srcData is empty");
140 return Sensors::ERROR;
141 }
142 size_t originDataSize = srcData.size();
143 srcAudioData_.clear();
144 for (size_t i = 0; i < (originDataSize - 1); i += RESAMPLE_MULTIPLE) {
145 srcAudioData_.push_back(srcData[i]);
146 srcAudioData_.push_back(srcData[i + 1]);
147 }
148 return Sensors::SUCCESS;
149 }
150
PreprocessAudioData()151 std::vector<double> VibrationConvertCore::PreprocessAudioData()
152 {
153 CALL_LOG_ENTER;
154 if (srcAudioData_.empty()) {
155 SEN_HILOGE("invalid parameter");
156 return {};
157 }
158 std::vector<double> absData = srcAudioData_;
159 std::vector<double> dstData = srcAudioData_;
160 int32_t silence = 0;
161 int32_t preClearEnd = 0;
162 int32_t absDataSize = static_cast<int32_t>(absData.size());
163 for (int32_t i = 0; i < absDataSize; ++i) {
164 absData[i] = std::fabs(absData[i]);
165 if (absData[i] < AMP_INVALIDE_DELTA) {
166 ++silence;
167 continue;
168 }
169 if (silence <= SILENCE_COUNT_MIN) {
170 silence = 0;
171 continue;
172 }
173 int32_t curClearBegin = i - silence;
174 for (int32_t j = curClearBegin; j < i; ++j) {
175 dstData[j] = 0;
176 }
177 if (((curClearBegin - preClearEnd) < FRAGMENT_MIN_LEN) && (curClearBegin > preClearEnd)) {
178 for (int32_t j = preClearEnd; j < curClearBegin; ++j) {
179 dstData[j] = 0;
180 }
181 preClearEnd = i;
182 }
183 silence = 0;
184 }
185 if (silence != 0) {
186 int32_t curClearBegin = absDataSize - silence;
187 for (int32_t i = curClearBegin; i < absDataSize; ++i) {
188 dstData[i] = 0;
189 }
190 if (((curClearBegin - preClearEnd) < FRAGMENT_MIN_LEN) && (curClearBegin > preClearEnd)) {
191 for (int32_t i = preClearEnd; i < curClearBegin; ++i) {
192 dstData[i] = 0;
193 }
194 }
195 }
196 return dstData;
197 }
198
PreprocessParameter(const std::vector<double> & data,int32_t & onsetHopLength,double & lowerDelta)199 int32_t VibrationConvertCore::PreprocessParameter(const std::vector<double> &data, int32_t &onsetHopLength,
200 double &lowerDelta)
201 {
202 CALL_LOG_ENTER;
203 if (data.empty()) {
204 SEN_HILOGE("data is empty");
205 return Sensors::ERROR;
206 }
207 std::vector<double> rmse = intensityProcessor_.GetRMS(data, ENERGY_HOP_LEN, systemPara_.centerPaddingFlag);
208 OnsetInfo onsetInfo;
209 if (onset_.CheckOnset(data, NFFT, onsetHopLength, onsetInfo) != Sensors::SUCCESS) {
210 SEN_HILOGE("CheckOnset Failed");
211 return Sensors::ERROR;
212 }
213 std::vector<int32_t> newDrwIdx = MapOnsetHop(onsetInfo.idx, onsetHopLength);
214 lowerDelta = CalcRmsLowerData(data.size(), rmse, newDrwIdx);
215 double rmseMax = *std::max_element(rmse.begin(), rmse.end());
216 size_t newDrwIdxLen = newDrwIdx.size();
217 bool continuousEventFlag = false;
218 int32_t newOnsetHopLen = onsetHopLength;
219 // Amplitude density is used to classify audio files, determine whether there are long events in the audio file,
220 // and adjust the onset detection window
221 if (CalcOnsetHopLength(data, rmseMax, newDrwIdxLen, continuousEventFlag, newOnsetHopLen) != Sensors::SUCCESS) {
222 SEN_HILOGE("CalcOnsetHopLength failed");
223 return Sensors::ERROR;
224 }
225 continuousEventExistFlag_ = continuousEventFlag;
226 onsetHopLength = newOnsetHopLen;
227 return Sensors::SUCCESS;
228 }
229
MapOnsetHop(const std::vector<int32_t> & drwIdx,int32_t onsetHopLength)230 std::vector<int32_t> VibrationConvertCore::MapOnsetHop(const std::vector<int32_t> &drwIdx, int32_t onsetHopLength)
231 {
232 if (onsetHopLength == 0) {
233 SEN_HILOGE("onsetHopLength is equal to 0");
234 return {};
235 }
236 std::vector<int32_t> newIdx;
237 int32_t coef = static_cast<int32_t>(round(static_cast<double>(ENERGY_HOP_LEN) / onsetHopLength));
238 if (coef == 0) {
239 SEN_HILOGE("coef is equal to 0");
240 return {};
241 }
242 for (auto idx : drwIdx) {
243 newIdx.push_back(static_cast<int32_t>(round(static_cast<double>(idx) / coef)));
244 }
245 return newIdx;
246 }
247
GetRmseLowerDelta(double lowerDelta,const std::vector<double> & rmse,double & deltaByTime)248 bool VibrationConvertCore::GetRmseLowerDelta(double lowerDelta, const std::vector<double> &rmse, double &deltaByTime)
249 {
250 int32_t rmseSize = static_cast<int32_t>(rmse.size());
251 double rmseMax = *std::max_element(rmse.begin(), rmse.end());
252 double rmseMin = *std::min_element(rmse.begin(), rmse.end());
253 double rmseRange = rmseMax - rmseMin;
254 int32_t i = 0;
255 deltaByTime = lowerDelta;
256 for (i = 0; i < rmseSize; ++i) {
257 if (rmse[i] > lowerDelta) {
258 break;
259 }
260 }
261 double rmsTimePerFrame = static_cast<double>(ENERGY_HOP_LEN) / SAMPLE_RATE;
262 int32_t j = rmseSize - 1;
263 for (; j >= 0 ; j = (j - 1)) {
264 if (rmse[j] > lowerDelta) {
265 break;
266 }
267 }
268 if ((j - i) <= 0) {
269 return false;
270 }
271 double totalDuration = (j - i) * rmsTimePerFrame;
272 if (IsLessNotEqual(totalDuration, 1.0)) { // 1s
273 deltaByTime = rmseRange * RMSE_LOWDELTA_RATIO_LOW + rmseMin;
274 return true;
275 }
276 return false;
277 }
278
CalcRmsLowerData(size_t dataSize,const std::vector<double> & rmse,const std::vector<int32_t> & newDrwIdx)279 double VibrationConvertCore::CalcRmsLowerData(size_t dataSize, const std::vector<double> &rmse,
280 const std::vector<int32_t> &newDrwIdx)
281 {
282 double soundSizeDelta = 0.0;
283 double rmseMax = *std::max_element(rmse.begin(), rmse.end());
284 double rmseMin = *std::min_element(rmse.begin(), rmse.end());
285 double rmseRange = rmseMax - rmseMin;
286 if (rmseMax > RMSEMAX_THRESHOLD_HIGH) {
287 soundSizeDelta = rmseRange * RMSE_LOWDELTA_RATIO_HIGH + rmseMin;
288 } else if (rmseMax > RMSEMAX_THRESHIOLD_MID) {
289 soundSizeDelta = rmseRange * RMSE_LOWDELTA_RATIO_MID + rmseMin;
290 } else {
291 soundSizeDelta = rmseRange * RMSE_LOWDELTA_RATIO_LOW + rmseMin;
292 }
293 double lowerDelta = 0.0;
294 if (newDrwIdx.size() > 0) {
295 for (int32_t i = 0; i < RMSE_LOWDELTA_ITERATION_TIMES; i++) {
296 int32_t j = newDrwIdx[0];
297 lowerDelta = rmseRange * (RMSE_LOWDELTA_RATIO_HIGH - i * RMSE_LOWDELTA_RATIO_STEP) + rmseMin;
298 if ((rmse[j] > lowerDelta) || (rmse[j + 1] > lowerDelta)) {
299 break;
300 }
301 }
302 }
303 double audioDurationDelta = soundSizeDelta;
304 double audioDuration = static_cast<double>(dataSize) / SAMPLE_RATE;
305 if (IsLessOrEqual(audioDuration, 1.0)) {
306 audioDurationDelta = rmseRange * RMSE_LOWDELTA_RATIO_LOW + rmseMin;
307 return audioDurationDelta;
308 }
309 double soundDurationDelta = soundSizeDelta;
310 bool findFlag = GetRmseLowerDelta(soundSizeDelta, rmse, soundDurationDelta);
311 if (findFlag) {
312 return soundDurationDelta;
313 }
314 if (soundSizeDelta < lowerDelta) {
315 return soundSizeDelta;
316 }
317 return lowerDelta;
318 }
319
CalcOnsetHopLength(const std::vector<double> & data,double rmseMax,size_t newDrwIdxLen,bool & continuousEventFlag,int32_t & newOnsetHopLen)320 int32_t VibrationConvertCore::CalcOnsetHopLength(const std::vector<double> &data, double rmseMax,
321 size_t newDrwIdxLen, bool &continuousEventFlag, int32_t &newOnsetHopLen)
322 {
323 if (data.empty()) {
324 SEN_HILOGE("invalid parameter");
325 return Sensors::ERROR;
326 }
327 int32_t longestCount = 0;
328 double unzeroDensity = 0.0;
329 bool continuousEventExistFlag = false;
330 int32_t ret = IsIncludeContinuoustEvent(data, longestCount, unzeroDensity, continuousEventExistFlag);
331 if (ret != Sensors::SUCCESS) {
332 SEN_HILOGE("IsIncludeContinuoustEvent failed");
333 return ret;
334 }
335 if ((!continuousEventExistFlag) && (longestCount > ENERGY_HOP_LEN)) {
336 if (rmseMax > (CONTINUOUS_EVENT_LOW_DELTA_MULTIPLES * RMS_INVALIDE_DELTA)) {
337 continuousEventExistFlag = true;
338 }
339 }
340 if ((!continuousEventExistFlag) || (newDrwIdxLen < 2)) {
341 newOnsetHopLen = static_cast<int32_t>(round(ENERGY_HOP_LEN * INTERSITY_BOUNDARY_POINT));
342 }
343 continuousEventFlag = continuousEventExistFlag;
344 return Sensors::SUCCESS;
345 }
346
GetLocalEnvelope(const std::vector<double> & data)347 std::vector<double> VibrationConvertCore::GetLocalEnvelope(const std::vector<double> &data)
348 {
349 if (data.empty()) {
350 SEN_HILOGE("invalid parameter");
351 return {};
352 }
353 std::vector<double> envelope = data;
354 for (auto &elem : envelope) {
355 elem = std::fabs(elem);
356 }
357 double threshold = COEF * (*std::max_element(envelope.begin(), envelope.end()));
358 for (auto &elem : envelope) {
359 if (elem < threshold) {
360 elem = 0;
361 }
362 }
363 size_t dataSize = envelope.size();
364 for (size_t i = 0; i < dataSize; ++i) {
365 if ((i + LOCAL_ENVELOPE_MAX_LEN) > dataSize) {
366 break;
367 }
368 std::vector<double> segmentEnvelope;
369 for (size_t j = i; j < (i + LOCAL_ENVELOPE_MAX_LEN); ++j) {
370 segmentEnvelope.push_back(envelope[j]);
371 }
372 envelope[i] = *std::max_element(segmentEnvelope.begin(), segmentEnvelope.end());
373 }
374 return envelope;
375 }
376
IsIncludeContinuoustEvent(const std::vector<double> & data,int32_t & longestCount,double & unzeroDensity,bool & isIncludeContinuoustEvent)377 int32_t VibrationConvertCore::IsIncludeContinuoustEvent(const std::vector<double> &data,
378 int32_t &longestCount, double &unzeroDensity, bool &isIncludeContinuoustEvent)
379 {
380 // envelope must be a non-negative number.
381 std::vector<double> envelope = GetLocalEnvelope(data);
382 if (envelope.empty()) {
383 SEN_HILOGE("GetLocalEnvelope failed");
384 return Sensors::ERROR;
385 }
386 size_t envelopeSize = envelope.size();
387 size_t j = 0;
388 size_t k = 0;
389 int32_t atLeastCnt = 2 * ENERGY_HOP_LEN;
390 int32_t adsrCompleteStatus = ADSR_BOUNDARY_STATUS_NONE;
391 std::vector<int32_t> countList;
392 for (size_t i = 0; i < envelopeSize; ++i) {
393 if ((envelope[i] >= EPS_MIN) && (adsrCompleteStatus == ADSR_BOUNDARY_STATUS_NONE)) {
394 j = i;
395 adsrCompleteStatus = ADSR_BOUNDARY_STATUS_ONE;
396 }
397 if ((envelope[i] < EPS_MIN) && (adsrCompleteStatus == ADSR_BOUNDARY_STATUS_ONE)) {
398 k = i;
399 adsrCompleteStatus = ADSR_BOUNDARY_STATUS_BOTH;
400 }
401 if (adsrCompleteStatus == ADSR_BOUNDARY_STATUS_BOTH) {
402 adsrCompleteStatus = ADSR_BOUNDARY_STATUS_NONE;
403 countList.push_back(k - j);
404 if ((k - j) > atLeastCnt) {
405 isIncludeContinuoustEvent = true;
406 break;
407 }
408 }
409 }
410 if (countList.empty()) {
411 SEN_HILOGI("countList is empty");
412 longestCount = 0;
413 unzeroDensity = 0;
414 return Sensors::SUCCESS;
415 }
416 longestCount = *std::max_element(countList.begin(), countList.end());
417 unzeroDensity = static_cast<double>(accumulate(countList.begin(), countList.end(), 0)) / envelopeSize;
418 return Sensors::SUCCESS;
419 }
420
StoreHapticEvent()421 void VibrationConvertCore::StoreHapticEvent()
422 {
423 CALL_LOG_ENTER;
424 bool blockStoreFlag = systemPara_.blockStoreFlag;
425 if (blockStoreFlag) {
426 StoreEventBlock();
427 } else {
428 StoreEventSequence();
429 }
430 }
431
StoreEventSequence()432 void VibrationConvertCore::StoreEventSequence()
433 {
434 HapticEvent eventData;
435 if (continuousEvents_.empty()) {
436 for (size_t i = 0; i < transientEvents_.size(); ++i) {
437 eventData.vibrateTag = EVENT_TAG_TRANSIENT;
438 eventData.startTime = static_cast<int32_t>(round(transientEvents_[i].time * SAMPLE_IN_MS));
439 eventData.duration = ONE_TRANSIENT_DURATION_MS;
440 eventData.intensity = transientEvents_[i].intensity;
441 eventData.frequency = transientEvents_[i].frequency;
442 hapticEvents_.push_back(eventData);
443 }
444 return;
445 }
446 double preTime = -1.0; // invalid time.
447 for (size_t i = 0; i < continuousEvents_.size(); ++i) {
448 for (size_t j = 0; j < transientEvents_.size(); ++j) {
449 int32_t seStartTime = static_cast<int32_t>(round(transientEvents_[j].time * SAMPLE_IN_MS));
450 int32_t leStartTime = static_cast<int32_t>(round(continuousEvents_[i].time * SAMPLE_IN_MS));
451 if ((seStartTime > static_cast<int32_t>(round(preTime * SAMPLE_IN_MS))) && (seStartTime < leStartTime)) {
452 eventData.vibrateTag = EVENT_TAG_TRANSIENT;
453 eventData.startTime = static_cast<int32_t>(round(transientEvents_[j].time * SAMPLE_IN_MS));
454 eventData.duration = ONE_TRANSIENT_DURATION_MS;
455 eventData.intensity = transientEvents_[j].intensity;
456 eventData.frequency = transientEvents_[j].frequency;
457 hapticEvents_.push_back(eventData);
458 }
459 }
460 eventData.vibrateTag = EVENT_TAG_CONTINUOUS;
461 eventData.startTime = static_cast<int32_t>(round(continuousEvents_[i].time * SAMPLE_IN_MS));
462 eventData.duration = static_cast<int32_t>(round(continuousEvents_[i].duration * SAMPLE_IN_MS));
463 eventData.intensity = continuousEvents_[i].intensity;
464 eventData.frequency = continuousEvents_[i].frequency;
465 hapticEvents_.push_back(eventData);
466 preTime = continuousEvents_[i].time;
467 }
468 }
469
StoreEventBlock()470 void VibrationConvertCore::StoreEventBlock()
471 {
472 if (continuousEvents_.empty()) {
473 SEN_HILOGW("continuousEvents_ is empty");
474 return;
475 }
476 HapticEvent eventData;
477 ContinuousEvent continuousEvent = *(continuousEvents_.end() - 1);
478 for (size_t i = 0; i < transientEvents_.size(); ++i) {
479 if (transientEvents_[i].time > continuousEvent.time) {
480 break;
481 }
482 eventData.vibrateTag = EVENT_TAG_TRANSIENT;
483 eventData.startTime = static_cast<int32_t>(round(transientEvents_[i].time * SAMPLE_IN_MS));
484 eventData.duration = ONE_TRANSIENT_DURATION_MS;
485 eventData.intensity = transientEvents_[i].intensity;
486 eventData.frequency = transientEvents_[i].frequency;
487 hapticEvents_.push_back(eventData);
488 }
489 for (size_t i = 0; i < continuousEvents_.size(); ++i) {
490 eventData.vibrateTag = EVENT_TAG_CONTINUOUS;
491 eventData.startTime = static_cast<int32_t>(round(continuousEvents_[i].time * SAMPLE_IN_MS));
492 eventData.duration = static_cast<int32_t>(round(continuousEvents_[i].duration * SAMPLE_IN_MS));
493 eventData.intensity = continuousEvents_[i].intensity;
494 eventData.frequency = continuousEvents_[i].frequency;
495 hapticEvents_.push_back(eventData);
496 }
497 }
498
EmplaceOnsetTime(bool flag,int32_t idx,double time,std::vector<UnionTransientEvent> & unionTransientEvents)499 void VibrationConvertCore::EmplaceOnsetTime(bool flag, int32_t idx, double time,
500 std::vector<UnionTransientEvent> &unionTransientEvents)
501 {
502 if (unionTransientEvents.empty()) {
503 SEN_HILOGE("unionTransientEvents is empty");
504 return;
505 }
506 if (idx < unionTransientEvents[0].onsetIdx) {
507 UnionTransientEvent unionSeData(idx, time, flag);
508 unionTransientEvents.emplace(unionTransientEvents.begin(), unionSeData);
509 }
510 if (idx > unionTransientEvents[unionTransientEvents.size() - 1].onsetIdx) {
511 UnionTransientEvent unionSeData(idx, time, flag);
512 unionTransientEvents.push_back(unionSeData);
513 }
514 for (size_t j = 0; j < (unionTransientEvents.size() - 1); ++j) {
515 if ((idx > unionTransientEvents[j].onsetIdx) && (idx < unionTransientEvents[j + 1].onsetIdx)) {
516 size_t index = j + 1;
517 UnionTransientEvent unionSeData(idx, time, flag);
518 unionTransientEvents.emplace(unionTransientEvents.begin() + index, unionSeData);
519 break;
520 }
521 }
522 }
523
ConvertTransientEvent(const std::vector<double> & data,int32_t onsetHopLength,std::vector<UnionTransientEvent> & unionTransientEvents)524 int32_t VibrationConvertCore::ConvertTransientEvent(const std::vector<double> &data, int32_t onsetHopLength,
525 std::vector<UnionTransientEvent> &unionTransientEvents)
526 {
527 CALL_LOG_ENTER;
528 if (data.empty()) {
529 SEN_HILOGE("data is empty");
530 return Sensors::ERROR;
531 }
532 // Using System Methods to Detect Onset
533 std::vector<UnionTransientEvent> unionTransientValues = DetectOnset(data, onsetHopLength);
534 // Is the onset just a transient event
535 std::vector<int32_t> onsetIdxs;
536 for (size_t i = 0; i < unionTransientValues.size(); i++) {
537 onsetIdxs.push_back(unionTransientValues[i].onsetIdx);
538 }
539 std::vector<bool> transientEventFlags = IsTransientEvent(data, onsetIdxs);
540 for (size_t i = 0; i < unionTransientValues.size(); i++) {
541 unionTransientValues[i].transientEventFlag = transientEventFlags[i];
542 }
543 IsolatedEnvelopeInfo isolatedEnvelopeInfo;
544 int32_t ret = peakFinder_.ObtainTransientByAmplitude(data, isolatedEnvelopeInfo);
545 if (ret != Sensors::SUCCESS) {
546 SEN_HILOGE("ObtainTransientByAmplitude failed");
547 return ret;
548 }
549 if (!isolatedEnvelopeInfo.isHaveContinuousEvent) {
550 unionTransientValues.clear();
551 TranslateAnchorPoint(isolatedEnvelopeInfo.mountainPosition.peakPos, unionTransientValues);
552 for (size_t i = 0; i < unionTransientValues.size(); ++i) {
553 unionTransientValues[i].transientEventFlag = isolatedEnvelopeInfo.transientEventFlags[i];
554 }
555 } else {
556 size_t size = isolatedEnvelopeInfo.mountainPosition.peakPos.size();
557 for (size_t i = 0; i < size; ++i) {
558 if (!isolatedEnvelopeInfo.transientEventFlags[i]) {
559 continue;
560 }
561 bool flag = isolatedEnvelopeInfo.transientEventFlags[i];
562 int32_t idx = 0;
563 double time = 0.0;
564 TranslateAnchorPoint(isolatedEnvelopeInfo.mountainPosition.peakPos[i], idx, time);
565 size_t findIndex = -1;
566 for (size_t j = 0; j < unionTransientValues.size(); j++) {
567 if (unionTransientValues[j].onsetIdx == idx) {
568 findIndex = j;
569 break;
570 }
571 }
572 if (findIndex != -1) {
573 unionTransientValues[findIndex].onsetTime = time;
574 unionTransientValues[findIndex].transientEventFlag = flag;
575 } else {
576 EmplaceOnsetTime(flag, idx, time, unionTransientValues);
577 }
578 }
579 }
580 unionTransientEvents = unionTransientValues;
581 return Sensors::SUCCESS;
582 }
583
DetectOnset(const std::vector<double> & data,int32_t onsetHopLength)584 std::vector<UnionTransientEvent> VibrationConvertCore::DetectOnset(const std::vector<double> &data,
585 int32_t onsetHopLength)
586 {
587 OnsetInfo onsetInfo;
588 if (onset_.CheckOnset(data, NFFT, onsetHopLength, onsetInfo) != Sensors::SUCCESS) {
589 SEN_HILOGE("CheckOnset Failed");
590 return {};
591 }
592 onsetInfo.idx = MapOnsetHop(onsetInfo.idx, onsetHopLength);
593 std::vector<int32_t> newIdx;
594 std::vector<double> newTime;
595 UniqueIdx(onsetInfo.idx, onsetInfo.time, newIdx, newTime);
596 int32_t minSkip = ONSET_MINSKIP_MAX;
597 if (newIdx.size() > 1) {
598 std::vector<int32_t> idxDiff;
599 for (size_t i = 1; i < newIdx.size(); ++i) {
600 idxDiff.push_back(newIdx[i] - newIdx[i - 1]);
601 }
602 minSkip = *std::min_element(idxDiff.begin(), idxDiff.end());
603 }
604 if (minSkip < ONSET_MINSKIP_MIN) {
605 SEN_HILOGE("minSkip is less than 1");
606 return {};
607 }
608 bool onsetBacktrackFlag = systemPara_.onsetBacktrackFlag;
609 if (onsetBacktrackFlag) {
610 minSkip = ONSET_MINSKIP_MIN;
611 } else {
612 if (minSkip > ONSET_MINSKIP_MAX) {
613 minSkip = ONSET_MINSKIP_MAX;
614 }
615 }
616 std::vector<UnionTransientEvent> unionTransientEvents;
617 for (size_t i = 0; i < newIdx.size(); ++i) {
618 unionTransientEvents.push_back(UnionTransientEvent(newIdx[i], newTime[i]));
619 }
620 onsetMinSkip_ = minSkip;
621 return unionTransientEvents;
622 }
623
GetTransientEventFlag(const std::vector<double> & data,int32_t onsetIdx)624 bool VibrationConvertCore::GetTransientEventFlag(const std::vector<double> &data, int32_t onsetIdx)
625 {
626 if (data.empty()) {
627 SEN_HILOGE("data is empty");
628 return false;
629 }
630 int32_t partLen = ONSET_ONE_WIN;
631 int32_t partCount = static_cast<int32_t>(round(partLen * ONSET_SPLIT_RATIO));
632 int32_t partNumber = partLen - partCount;
633 int32_t beginIdx = onsetIdx * ENERGY_HOP_LEN - partCount;
634 int32_t endIdx = onsetIdx * ENERGY_HOP_LEN + partNumber;
635 if (beginIdx < 0) {
636 beginIdx = 0;
637 }
638 int32_t dataSize = static_cast<int32_t>(data.size());
639 if (endIdx >= dataSize) {
640 endIdx = dataSize - 1;
641 }
642 std::vector<double> localData;
643 for (int32_t i = beginIdx; i <= endIdx; ++i) {
644 localData.push_back(data[i]);
645 }
646 double unzeroDensity = 0.0;
647 int32_t unzeroCount = 0;
648 // Output parameter: unzeroCnt unzeroDensity
649 GetUnzeroCount(localData, unzeroCount, unzeroDensity);
650 return IsTransientEventFlag(unzeroCount, unzeroDensity);
651 }
652
GetTransientEventFlags(const std::vector<double> & data,const std::vector<int32_t> & onsetIdxs)653 std::vector<bool> VibrationConvertCore::GetTransientEventFlags(const std::vector<double> &data,
654 const std::vector<int32_t> &onsetIdxs)
655 {
656 if (data.empty() || (onsetIdxs.size() <= 1)) {
657 SEN_HILOGE("Invalid parameter");
658 return {};
659 }
660 int32_t partLen = 0;
661 std::vector<bool> transientEventFlags;
662 size_t onsetIdxsSize = onsetIdxs.size();
663 for (size_t i = 0; i < onsetIdxsSize; ++i) {
664 if (i == (onsetIdxsSize - 1)) {
665 partLen = (onsetIdxs[i] - onsetIdxs[i - 1]) * ENERGY_HOP_LEN;
666 } else {
667 partLen = (onsetIdxs[i + 1] - onsetIdxs[i]) * ENERGY_HOP_LEN;
668 }
669 if (partLen == 0) {
670 SEN_HILOGE("partLen is equal to 0");
671 return {};
672 }
673 int32_t partCount = static_cast<int32_t>(round(partLen * ONSET_SPLIT_RATIO));
674 int32_t partNumber = partLen - partCount;
675 int32_t beginIdx = onsetIdxs[i] * ENERGY_HOP_LEN - partCount;
676 int32_t endIdx = onsetIdxs[i] * ENERGY_HOP_LEN + partNumber;
677 if (beginIdx < 0) {
678 beginIdx = 0;
679 }
680 if ((i != 0) && (beginIdx < onsetIdxs[i - 1] * ENERGY_HOP_LEN)) {
681 beginIdx = onsetIdxs[i - 1] * ENERGY_HOP_LEN;
682 }
683 int32_t dataSize = static_cast<int32_t>(data.size());
684 if (endIdx >= dataSize) {
685 endIdx = dataSize - 1;
686 }
687 std::vector<double> localData;
688 for (int32_t j = beginIdx; j <= endIdx; ++j) {
689 localData.push_back(data[i]);
690 }
691 double unzeroDensity = 0.0;
692 int32_t unzeroCount = 0;
693 GetUnzeroCount(localData, unzeroCount, unzeroDensity);
694 transientEventFlags.push_back(IsTransientEventFlag(unzeroCount, unzeroDensity));
695 }
696 return transientEventFlags;
697 }
698
IsTransientEvent(const std::vector<double> & data,const std::vector<int32_t> & onsetIdxs)699 std::vector<bool> VibrationConvertCore::IsTransientEvent(const std::vector<double> &data,
700 const std::vector<int32_t> &onsetIdxs)
701 {
702 if (data.empty() || onsetIdxs.empty()) {
703 SEN_HILOGE("data or onsetIdxs is empty");
704 return {};
705 }
706 std::vector<bool> transientEventFlags;
707 if (onsetIdxs.size() == 1) {
708 bool transientEventFlag = GetTransientEventFlag(data, onsetIdxs[0]);
709 transientEventFlags.push_back(transientEventFlag);
710 } else {
711 transientEventFlags = GetTransientEventFlags(data, onsetIdxs);
712 }
713 return transientEventFlags;
714 }
715
GetUnzeroCount(const std::vector<double> & localData,int32_t & unzeroCount,double & unzeroDensity)716 void VibrationConvertCore::GetUnzeroCount(const std::vector<double> &localData,
717 int32_t &unzeroCount, double &unzeroDensity)
718 {
719 if (localData.empty()) {
720 unzeroCount = 0;
721 unzeroDensity = 0;
722 SEN_HILOGE("localData is empty");
723 return;
724 }
725 std::vector<double> envelope = localData;
726 for (auto &elem : envelope) {
727 elem = std::fabs(elem);
728 if (elem < LOWER_AMP) {
729 elem = 0;
730 }
731 }
732 size_t envelopeSize = envelope.size();
733 for (size_t i = 0; i < envelopeSize; ++i) {
734 if ((i + LOCAL_ENVELOPE_MAX_LEN) >= envelopeSize) {
735 break;
736 }
737 std::vector<double> segmentEnvelope;
738 for (size_t j = i; j < (i + LOCAL_ENVELOPE_MAX_LEN); ++j) {
739 segmentEnvelope.push_back(envelope[j]);
740 }
741 envelope[i] = *std::max_element(segmentEnvelope.begin(), segmentEnvelope.end());
742 }
743 for (auto elem : envelope) {
744 if (elem > 0) {
745 ++unzeroCount;
746 }
747 }
748 unzeroDensity = static_cast<double>(unzeroCount) / envelopeSize;
749 }
750
IsTransientEventFlag(int32_t unzeroCount,double unzeroDensity)751 bool VibrationConvertCore::IsTransientEventFlag(int32_t unzeroCount, double unzeroDensity)
752 {
753 double duration = static_cast<double>(unzeroCount) / SAMPLE_RATE;
754 if (IsLessNotEqual(duration, FRAME_DURATION) || IsLessNotEqual(unzeroDensity, TRANSIENT_UNZERO_DENSITY_MIN)) {
755 return true;
756 }
757 return false;
758 }
759
TranslateAnchorPoint(const std::vector<int32_t> & amplitudePeakPos,std::vector<UnionTransientEvent> & unionTransientEvents)760 void VibrationConvertCore::TranslateAnchorPoint(const std::vector<int32_t> &litudePeakPos,
761 std::vector<UnionTransientEvent> &unionTransientEvents)
762 {
763 bool useAbsTimeFlag = systemPara_.useAbsTimeFlag;
764 if (useAbsTimeFlag) {
765 for (auto pos : amplitudePeakPos) {
766 unionTransientEvents.emplace_back(
767 UnionTransientEvent(static_cast<int32_t>(round(1.0 * pos / ENERGY_HOP_LEN)), 1.0 * pos / SAMPLE_RATE));
768 }
769 } else {
770 double rmsTimePerFrame = static_cast<double>(ENERGY_HOP_LEN) / SAMPLE_RATE;
771 for (auto pos : amplitudePeakPos) {
772 int32_t idx = static_cast<int32_t>(round(1.0 * pos / ENERGY_HOP_LEN));
773 unionTransientEvents.emplace_back(UnionTransientEvent(idx, idx * rmsTimePerFrame));
774 }
775 }
776 }
777
TranslateAnchorPoint(int32_t amplitudePeakPos,int32_t & amplitudePeakIdx,double & amplitudePeakTime)778 void VibrationConvertCore::TranslateAnchorPoint(int32_t amplitudePeakPos, int32_t &litudePeakIdx,
779 double &litudePeakTime)
780 {
781 bool useAbsTimeFlag = systemPara_.useAbsTimeFlag;
782 amplitudePeakIdx = static_cast<int32_t>(round(1.0 * amplitudePeakPos / ENERGY_HOP_LEN));
783 if (useAbsTimeFlag) {
784 amplitudePeakTime = static_cast<double>(amplitudePeakPos) / SAMPLE_RATE;
785 } else {
786 double rmsTimePerFrame = static_cast<double>(ENERGY_HOP_LEN) / SAMPLE_RATE;
787 amplitudePeakTime = amplitudePeakIdx * rmsTimePerFrame;
788 }
789 }
790
DetectFrequency(const std::vector<double> & data,const std::vector<int32_t> & rmseIntensityNorm)791 std::vector<int32_t> VibrationConvertCore::DetectFrequency(const std::vector<double> &data,
792 const std::vector<int32_t> &rmseIntensityNorm)
793 {
794 CALL_LOG_ENTER;
795 std::vector<double> zcr = frequencyEstimation_.GetZeroCrossingRate(data, FRAME_LEN, ENERGY_HOP_LEN);
796 for (auto &elem : zcr) {
797 elem = elem * SAMPLE_RATE * F_HALF;
798 }
799 std::vector<bool> voiceSegmentFlag = peakFinder_.GetVoiceSegmentFlag();
800 std::vector<int32_t> freqNorm;
801 frequencyEstimation_.FreqPostProcess(zcr, voiceSegmentFlag, rmseIntensityNorm, freqNorm);
802 return freqNorm;
803 }
804
DetectRmsIntensity(const std::vector<double> & data,double rmsILowerDelta,std::vector<IntensityData> & intensityData)805 int32_t VibrationConvertCore::DetectRmsIntensity(const std::vector<double> &data, double rmsILowerDelta,
806 std::vector<IntensityData> &intensityData)
807 {
808 CALL_LOG_ENTER;
809 std::vector<double> rmse = intensityProcessor_.GetRMS(data, ENERGY_HOP_LEN, systemPara_.centerPaddingFlag);
810 if (rmse.empty()) {
811 SEN_HILOGE("rmse is empty");
812 return Sensors::ERROR;
813 }
814 std::vector<double> rmseTime;
815 double rmsTimePerFrame = static_cast<double>(ENERGY_HOP_LEN) / SAMPLE_RATE;
816 for (auto elem : rmse) {
817 rmseTime.push_back(elem * rmsTimePerFrame);
818 }
819 std::vector<double> rmseBand;
820 std::vector<int32_t> rmseNorm;
821 if (intensityProcessor_.RmseNormalize(rmse, rmsILowerDelta, rmseBand, rmseNorm) != Sensors::SUCCESS) {
822 SEN_HILOGE("RmseNormalize failed");
823 return Sensors::ERROR;
824 }
825 std::vector<double> rmseTimeNorm = StartTimeNormalize(rmse.size());
826 std::vector<double> ampLin = intensityProcessor_.VolumeInLinary(data, ENERGY_HOP_LEN);
827 std::vector<double> ampDb = intensityProcessor_.VolumeInDB(data, ENERGY_HOP_LEN);
828 double ampDbMax = *std::max_element(ampDb.begin(), ampDb.end());
829 bool intensityUseLinearFlag = systemPara_.intensityUseLinearFlag;
830 if (!intensityUseLinearFlag && (ampDbMax > AMPLITUDE_DB_MAX)) {
831 for (size_t i = 0; i < ampDb.size(); ++i) {
832 rmseNorm[i] = ampDb[i] * DB_ZOOM_COEF;
833 }
834 }
835 for (size_t i = 0; i < rmse.size(); i++) {
836 intensityData.push_back(IntensityData(rmse[i], rmseTime[i], rmseBand[i], rmseNorm[i], rmseTimeNorm[i]));
837 }
838 return Sensors::SUCCESS;
839 }
840
StartTimeNormalize(int32_t rmseLen)841 std::vector<double> VibrationConvertCore::StartTimeNormalize(int32_t rmseLen)
842 {
843 CALL_LOG_ENTER;
844 std::vector<double> rmseTimeNorm;
845 double startTime = 0.0;
846 for (int32_t i = 0; i < rmseLen; ++i) {
847 rmseTimeNorm.push_back(startTime);
848 startTime += FRAME_DURATION;
849 }
850 return rmseTimeNorm;
851 }
852
OutputTransientEvents(const std::vector<UnionTransientEvent> & unionTransientEvents,const std::vector<IntensityData> & intensityData,const std::vector<int32_t> & freqNorm,std::vector<int32_t> & transientIndex,std::vector<double> & transientEventTime)853 void VibrationConvertCore::OutputTransientEvents(const std::vector<UnionTransientEvent> &unionTransientEvents,
854 const std::vector<IntensityData> &intensityData, const std::vector<int32_t> &freqNorm,
855 std::vector<int32_t> &transientIndex, std::vector<double> &transientEventTime)
856 {
857 CALL_LOG_ENTER;
858 bool onsetBacktrackFlag = systemPara_.onsetBacktrackFlag;
859 if (!continuousEventExistFlag_) {
860 std::vector<double> onsetTimes;
861 for (size_t i = 0; i < unionTransientEvents.size(); i++) {
862 onsetTimes.push_back(unionTransientEvents[i].onsetTime);
863 }
864 OutputTransientEventsByInsertTime(onsetTimes, intensityData, freqNorm, transientIndex, transientEventTime);
865 return;
866 }
867 if (onsetBacktrackFlag) {
868 OutputTransientEventsAlign(unionTransientEvents, intensityData, freqNorm, transientIndex, transientEventTime);
869 } else {
870 OutputTransientEventsDirect(unionTransientEvents, intensityData, freqNorm, transientIndex, transientEventTime);
871 }
872 }
873
OutputTransientEventsByInsertTime(const std::vector<double> & onsetTimes,const std::vector<IntensityData> & intensityData,const std::vector<int32_t> & freqNorm,std::vector<int32_t> & transientIndex,std::vector<double> & transientEventTime)874 void VibrationConvertCore::OutputTransientEventsByInsertTime(const std::vector<double> &onsetTimes,
875 const std::vector<IntensityData> &intensityData, const std::vector<int32_t> &freqNorm,
876 std::vector<int32_t> &transientIndex, std::vector<double> &transientEventTime)
877 {
878 double rmsTimePerFrame = static_cast<double>(ENERGY_HOP_LEN) / SAMPLE_RATE;
879 for (size_t i = 0; i < onsetTimes.size(); ++i) {
880 bool flag = false;
881 size_t j = 0;
882 while (j < intensityData.size()) {
883 if ((onsetTimes[i] >= intensityData[j].rmseTimeNorm) &&
884 (onsetTimes[i] < (intensityData[j].rmseTimeNorm + rmsTimePerFrame))) {
885 flag = true;
886 break;
887 }
888 ++j;
889 }
890 if (flag) {
891 auto it = std::find(transientIndex.begin(), transientIndex.end(), j);
892 if (it == transientIndex.end()) {
893 size_t endIndex = std::min(j + MIN_SKIP, intensityData.size() - 1);
894 // get max index.
895 size_t maxIndex = j;
896 double maxRmseEnvelope = intensityData[j].rmseEnvelope;
897 for (size_t k = (j + 1); k < endIndex; k++) {
898 if (intensityData[k].rmseEnvelope > maxRmseEnvelope) {
899 maxRmseEnvelope = intensityData[k].rmseEnvelope;
900 maxIndex = k;
901 }
902 }
903 double onsetTimeNorm = static_cast<double>(round(SAMPLE_IN_MS * onsetTimes[i]) / SAMPLE_IN_MS);
904 transientEventTime.push_back(onsetTimeNorm);
905 transientIndex.push_back(j);
906 AddTransientEventData(TransientEvent(onsetTimeNorm, intensityData[maxIndex].rmseIntensityNorm,
907 freqNorm[maxIndex]));
908 }
909 }
910 }
911 }
912
AddTransientEventData(TransientEvent transientEvent)913 void VibrationConvertCore::AddTransientEventData(TransientEvent transientEvent)
914 {
915 if (transientEvent.intensity < TRANSIENT_EVENT_INTENSITY_MIN) {
916 transientEvent.intensity = TRANSIENT_EVENT_INTENSITY_MIN;
917 }
918 if (transientEvent.frequency < TRANSIENT_EVENT_FREQUENCY_MIN) {
919 transientEvent.frequency = TRANSIENT_EVENT_FREQUENCY_MIN;
920 }
921 transientEvents_.push_back(transientEvent);
922 }
923
GetIdex(const UnionTransientEvent & unionTransientEvent,const std::vector<IntensityData> & intensityData)924 void VibrationConvertCore::GetIdex(const UnionTransientEvent &unionTransientEvent,
925 const std::vector<IntensityData> &intensityData)
926 {
927 // get max index.
928 size_t beginIndex = unionTransientEvent.onsetIdx;
929 size_t endIndex = beginIndex + onsetMinSkip_;
930 size_t maxIndex = beginIndex;
931 double maxRmseEnvelope = intensityData[beginIndex].rmseEnvelope;
932 for (size_t k = (beginIndex + 1); k < endIndex; k++) {
933 if (intensityData[k].rmseEnvelope > maxRmseEnvelope) {
934 maxRmseEnvelope = intensityData[k].rmseEnvelope;
935 maxIndex = k;
936 }
937 }
938 int32_t fromIndex = unionTransientEvent.onsetIdx - onsetMinSkip_;
939 if (fromIndex < 0) {
940 fromIndex = 0;
941 }
942 // get min index.
943 beginIndex = fromIndex;
944 endIndex = unionTransientEvent.onsetIdx + 1;
945 size_t minIndex = beginIndex;
946 double minRmseEnvelope = intensityData[beginIndex].rmseEnvelope;
947 for (size_t k = (beginIndex + 1); k < endIndex; k++) {
948 if (intensityData[k].rmseEnvelope < minRmseEnvelope) {
949 minRmseEnvelope = intensityData[k].rmseEnvelope;
950 minIndex = k;
951 }
952 }
953 if (minIndex == (unionTransientEvent.onsetIdx + 1)) {
954 minIndex = unionTransientEvent.onsetIdx;
955 }
956 }
957
OutputTransientEventsAlign(const std::vector<UnionTransientEvent> & unionTransientEvents,const std::vector<IntensityData> & intensityData,const std::vector<int32_t> & freqNorm,std::vector<int32_t> & transientIndex,std::vector<double> & transientEventTime)958 void VibrationConvertCore::OutputTransientEventsAlign(const std::vector<UnionTransientEvent> &unionTransientEvents,
959 const std::vector<IntensityData> &intensityData, const std::vector<int32_t> &freqNorm,
960 std::vector<int32_t> &transientIndex, std::vector<double> &transientEventTime)
961 {
962 size_t size = unionTransientEvents.size();
963 for (size_t i = 1; i < size; ++i) {
964 if ((unionTransientEvents[i].onsetIdx != 0) &&
965 (unionTransientEvents[i - 1].onsetIdx == (unionTransientEvents[i].onsetIdx - 1))) {
966 auto it = find(transientIndex.begin(), transientIndex.end(), unionTransientEvents[i].onsetIdx);
967 if (it == transientIndex.end()) {
968 int32_t index = unionTransientEvents[i].onsetIdx;
969 transientEventTime.push_back(intensityData[index].rmseTimeNorm);
970 transientIndex.push_back(index);
971 AddTransientEventData(TransientEvent(intensityData[index].rmseTimeNorm,
972 intensityData[index].rmseIntensityNorm, freqNorm[index]));
973 continue;
974 }
975 }
976 GetIdex(unionTransientEvents[i], intensityData);
977 auto it = find(transientIndex.begin(), transientIndex.end(), minIndex);
978 if (it == transientIndex.end()) {
979 transientEventTime.push_back(intensityData[minIndex].rmseTimeNorm);
980 transientIndex.push_back(minIndex);
981 AddTransientEventData(TransientEvent(intensityData[minIndex].rmseTimeNorm,
982 intensityData[maxIndex].rmseIntensityNorm, freqNorm[maxIndex]));
983 }
984 }
985 }
986
OutputTransientEventsDirect(const std::vector<UnionTransientEvent> & unionTransientEvents,const std::vector<IntensityData> & intensityData,const std::vector<int32_t> & freqNorm,std::vector<int32_t> & transientIndex,std::vector<double> & transientEventTime)987 void VibrationConvertCore::OutputTransientEventsDirect(const std::vector<UnionTransientEvent> &unionTransientEvents,
988 const std::vector<IntensityData> &intensityData, const std::vector<int32_t> &freqNorm,
989 std::vector<int32_t> &transientIndex, std::vector<double> &transientEventTime)
990 {
991 size_t size = unionTransientEvents.size();
992 for (size_t i = 0; i < size; ++i) {
993 auto it = find(transientIndex.begin(), transientIndex.end(), unionTransientEvents[i].onsetIdx);
994 if (it == transientIndex.end()) {
995 int32_t index = unionTransientEvents[i].onsetIdx;
996 transientEventTime.push_back(intensityData[index].rmseTimeNorm);
997 transientIndex.push_back(index);
998 AddTransientEventData(TransientEvent(intensityData[index].rmseTimeNorm,
999 intensityData[index].rmseIntensityNorm, freqNorm[index]));
1000 }
1001 }
1002 }
1003
OutputAllContinuousEvent(const std::vector<IntensityData> & intensityData,const std::vector<int32_t> transientIndex,const std::vector<int32_t> & freqNorm,const std::vector<bool> & transientEventFlags)1004 void VibrationConvertCore::OutputAllContinuousEvent(const std::vector<IntensityData> &intensityData,
1005 const std::vector<int32_t> transientIndex, const std::vector<int32_t> &freqNorm,
1006 const std::vector<bool> &transientEventFlags)
1007 {
1008 CALL_LOG_ENTER;
1009 if (!systemPara_.splitSegmentFlag) {
1010 OutputAllContinuousEventByUnseg(intensityData, transientIndex, freqNorm, transientEventFlags);
1011 }
1012 }
1013
OutputAllContinuousEventByUnseg(const std::vector<IntensityData> & intensityData,const std::vector<int32_t> transientIndex,const std::vector<int32_t> & freqNorm,const std::vector<bool> & transientEventFlags)1014 void VibrationConvertCore::OutputAllContinuousEventByUnseg(const std::vector<IntensityData> &intensityData,
1015 const std::vector<int32_t> transientIndex, const std::vector<int32_t> &freqNorm,
1016 const std::vector<bool> &transientEventFlags)
1017 {
1018 std::vector<double> rmseTimeNorm;
1019 for (size_t i = 0; i < intensityData.size(); i++) {
1020 rmseTimeNorm.push_back(intensityData[i].rmseTimeNorm);
1021 }
1022 std::vector<double> times;
1023 std::vector<double> durations;
1024 FillDefaultContinuousEvents(rmseTimeNorm, times, durations);
1025 int32_t ret = InsertTransientEvent(rmseTimeNorm, transientIndex, transientEventFlags,
1026 times, durations);
1027 if (ret != Sensors::SUCCESS) {
1028 SEN_HILOGE("InsertTransientEvent failed");
1029 return;
1030 }
1031 std::vector<ContinuousEvent> continuousEvents;
1032 for (size_t i = 0; i < times.size(); i++) {
1033 continuousEvents.push_back(ContinuousEvent(times[i], durations[i],
1034 intensityData[i].rmseIntensityNorm, freqNorm[i]));
1035 }
1036 MergeContinuousEvents(continuousEvents);
1037 }
1038
FillDefaultContinuousEvents(const std::vector<double> & rmseTimeNorm,std::vector<double> & times,std::vector<double> & durations)1039 void VibrationConvertCore::FillDefaultContinuousEvents(const std::vector<double> &rmseTimeNorm,
1040 std::vector<double> ×, std::vector<double> &durations)
1041 {
1042 double value = 0.0;
1043 for (size_t i = 0; i < rmseTimeNorm.size(); ++i) {
1044 times.push_back(value);
1045 durations.push_back(FRAME_DURATION);
1046 value += FRAME_DURATION;
1047 }
1048 }
1049
InsertTransientEvent(const std::vector<double> & rmseTimeNorm,const std::vector<int32_t> & transientIndex,const std::vector<bool> & transientEventFlags,std::vector<double> & times,std::vector<double> & durations)1050 int32_t VibrationConvertCore::InsertTransientEvent(const std::vector<double> &rmseTimeNorm,
1051 const std::vector<int32_t> &transientIndex, const std::vector<bool> &transientEventFlags,
1052 std::vector<double> ×, std::vector<double> &durations)
1053 {
1054 if ((times.empty()) || (transientIndex.size() != transientEventFlags.size())) {
1055 SEN_HILOGE("times is empty");
1056 return Sensors::ERROR;
1057 }
1058 for (size_t i = 0; i < (times.size() - 1); ++i) {
1059 auto it = find(transientIndex.begin(), transientIndex.end(), i);
1060 if (it == transientIndex.end()) {
1061 continue;
1062 }
1063 int32_t index = it - transientIndex.begin();
1064
1065 double preDuration = 0.0;
1066 if (i > 0) {
1067 preDuration = durations[i - 1];
1068 }
1069 double transientTime = transientEvents_[index].time;
1070 double preInterDuration = transientTime - rmseTimeNorm[i];
1071 double postInterDuration = (rmseTimeNorm[i] + FRAME_DURATION) - (transientTime + TRANSIENT_DURATION_DEFAULT);
1072 if (IsGreatOrEqual(preInterDuration, CONTINOUS_MIN_DURATION)) {
1073 times[i] = rmseTimeNorm[i];
1074 durations[i] = preInterDuration;
1075 if (IsLessNotEqual(postInterDuration, CONTINOUS_MIN_DURATION)) {
1076 times[i + 1] = transientTime + TRANSIENT_DURATION_DEFAULT;
1077 durations[i + 1] = postInterDuration + durations[i + 1];
1078 }
1079 } else {
1080 if (i > 0) {
1081 durations[i - 1] = preDuration + preInterDuration;
1082 }
1083 if (IsLessNotEqual(postInterDuration, CONTINOUS_MIN_DURATION)) {
1084 times[i] = transientTime + TRANSIENT_DURATION_DEFAULT;
1085 durations[i] = 0;
1086 times[i + 1] = transientTime + TRANSIENT_DURATION_DEFAULT;
1087 durations[i + 1] = postInterDuration + durations[i + 1];
1088 } else {
1089 times[i] = transientTime + TRANSIENT_DURATION_DEFAULT;
1090 durations[i] = postInterDuration;
1091 }
1092 }
1093 if (transientEventFlags[index]) {
1094 durations[i] = 0;
1095 }
1096 }
1097 return Sensors::SUCCESS;
1098 }
1099
CombinateContinuousEvents(const std::vector<ContinuousEvent> & continuousEvents,int32_t startIdx,int32_t endIdx)1100 void VibrationConvertCore::CombinateContinuousEvents(const std::vector<ContinuousEvent> &continuousEvents,
1101 int32_t startIdx, int32_t endIdx)
1102 {
1103 int32_t begIdx = startIdx;
1104 int32_t mergeCnt = 0;
1105 int32_t endIndex = 0;
1106 bool intensityCmbFlag = systemPara_.intensityCmbFlag;
1107 int32_t intensityCombinateDelta = 5;
1108 bool monotonicityCmbFlag = systemPara_.monotonicityCmbFlag;
1109 bool slopCmbFlag = systemPara_.slopCmbFlag;
1110 double slopDelta = SLOP_DELTA_MIN;
1111 double durationSum = 0.0;
1112 for (int32_t k = startIdx; k < endIdx; ++k) {
1113 if (mergeCnt == 0) {
1114 endIndex = begIdx;
1115 }
1116 if (intensityCmbFlag && (begIdx != (endIdx - 1))) {
1117 int32_t intensityDiff = std::abs(continuousEvents[endIndex].intensity -
1118 continuousEvents[begIdx + 1].intensity);
1119 int32_t frequencyDiff = std::abs(continuousEvents[endIndex].frequency -
1120 continuousEvents[begIdx + 1].frequency);
1121 if ((intensityDiff < intensityCombinateDelta) && (frequencyDiff < intensityCombinateDelta)) {
1122 ++mergeCnt;
1123 ++begIdx;
1124 continue;
1125 }
1126 }
1127 if (monotonicityCmbFlag && ((begIdx != 0) && (begIdx != (k - 1)))) {
1128 double slope1 = (continuousEvents[begIdx].intensity - continuousEvents[begIdx - 1].intensity);
1129 double slope2 = (continuousEvents[begIdx].intensity - continuousEvents[begIdx - 1].intensity);
1130 if ((slope1 * slope2) > 0) {
1131 ++mergeCnt;
1132 ++begIdx;
1133 continue;
1134 }
1135 }
1136 if (slopCmbFlag && ((begIdx != 0) && (begIdx != (k - 1)))) {
1137 double slope1 = (continuousEvents[begIdx].intensity - continuousEvents[begIdx - 1].intensity) /
1138 FRAME_DURATION;
1139 double slope2 = (continuousEvents[begIdx].intensity - continuousEvents[begIdx - 1].intensity) /
1140 FRAME_DURATION;
1141 if (((slope1 * slope2) > 0) && (std::abs(slope2 - slope1) < slopDelta)) {
1142 ++mergeCnt;
1143 ++begIdx;
1144 continue;
1145 }
1146 }
1147 if (endIndex != (begIdx - mergeCnt)) {
1148 SEN_HILOGW("endIndex is out of range");
1149 return;
1150 }
1151 endIndex = begIdx - mergeCnt;
1152 durationSum = 0;
1153 for (size_t i = endIndex; i < (begIdx + 1); ++i) {
1154 durationSum += continuousEvents[i].duration;
1155 }
1156 AddContinuousEventData(ContinuousEvent(continuousEvents[endIndex].time, durationSum,
1157 continuousEvents[endIndex].intensity, continuousEvents[endIndex].frequency));
1158 mergeCnt = 0;
1159 ++begIdx;
1160 }
1161 }
1162
MergeContinuousEvents(const std::vector<ContinuousEvent> & interContinuousEvents)1163 void VibrationConvertCore::MergeContinuousEvents(const std::vector<ContinuousEvent> &interContinuousEvents)
1164 {
1165 if (interContinuousEvents.empty()) {
1166 SEN_HILOGE("interContinuousEvents is empty");
1167 return;
1168 }
1169 size_t interTimeSize = interContinuousEvents.size();
1170 size_t j = 0;
1171 for (size_t i = 0; i < interTimeSize; ++i) {
1172 if (i < j) {
1173 continue;
1174 }
1175 if ((interContinuousEvents[i].intensity == 0) || (interContinuousEvents[i].duration < EPS_MIN)) {
1176 continue;
1177 }
1178 double durationSum = 0.0;
1179 for (; j < (interTimeSize - 1); ++j) {
1180 durationSum += interContinuousEvents[j].duration;
1181 if ((interContinuousEvents[j].intensity != 0) &&
1182 ((interContinuousEvents[j].time + durationSum) == interContinuousEvents[j + 1].time)) {
1183 continue;
1184 }
1185 if (j == i) {
1186 AddContinuousEventData(ContinuousEvent(interContinuousEvents[i].time,
1187 interContinuousEvents[i].duration, interContinuousEvents[i].intensity,
1188 interContinuousEvents[i].frequency));
1189 break;
1190 }
1191 CombinateContinuousEvents(interContinuousEvents, i, j);
1192 }
1193 }
1194 }
1195
AddContinuousEventData(const ContinuousEvent & continuousEvent)1196 void VibrationConvertCore::AddContinuousEventData(const ContinuousEvent &continuousEvent)
1197 {
1198 continuousEvents_.push_back(continuousEvent);
1199 }
1200 } // namespace Sensors
1201 } // namespace OHOS
1202