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> &amplitudePeakPos,
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 &amplitudePeakIdx,
779     double &amplitudePeakTime)
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> &times, 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> &times, 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