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 #ifndef PEAK_FINDER_H 17 #define PEAK_FINDER_H 18 19 #include <vector> 20 21 namespace OHOS { 22 namespace Sensors { 23 /** 24 * @brief Three points on the left, middle, and right of a mountainPosition peak, aka low + high + low. 25 */ 26 struct MountainPosition { 27 /** Index of the first low point on the left */ 28 std::vector<int32_t> firstPos; 29 /** Index of the middle highest point on the peak */ 30 std::vector<int32_t> peakPos; 31 /** Index of the last low point on the right */ 32 std::vector<int32_t> lastPos; 33 }; 34 35 /** Points on both sides of the mountainPosition peak */ 36 struct BothSidesOfPeak { 37 /** Index of the left low postion */ 38 int32_t leftPos { 0 }; 39 /** Index of the right low postion */ 40 int32_t rightPos { 0 }; 41 }; 42 43 /** The position and value of points on the envelope appear in pairs */ 44 struct ValleyPoint { 45 std::vector<int32_t> pos; 46 std::vector<double> values; 47 }; 48 49 /** 50 * @brief Peak information. 51 */ 52 struct PeaksInfo { 53 /** amplitude envelope */ 54 std::vector<double> ampPeakEnvelope; 55 /** All peak point IDs */ 56 std::vector<int32_t> ampPeakAllIdx; 57 /** Peak IDs, after filtered. */ 58 std::vector<int32_t> ampPeakIdxs; 59 /** Filtered, corresponding time for each peak point */ 60 std::vector<double> ampPeakTimes; 61 }; 62 63 /** 64 * @brief Continuous merging of several long events. Continuous merging of several short events. 65 */ 66 struct EnvelopeSegmentInfo { 67 /** The starting and ending points of a paragraph. the endpoint is the starting point of the next paragraph */ 68 std::vector<int32_t> demarcPos; 69 /** True, all events within this segment are long events, otherwise they are all short events */ 70 std::vector<bool> continuousEventFlag; 71 }; 72 73 /** Outline Description of Peak Detection */ 74 struct IsolatedEnvelopeInfo { 75 /** Whether the envelope contains long events */ 76 bool isHaveContinuousEvent { false }; 77 /** Number of points for the longest continuous signal */ 78 int32_t longestSampleCount { 0 }; 79 /** The flag of peak is a transient event. */ 80 std::vector<bool> transientEventFlags; 81 MountainPosition mountainPosition; 82 }; 83 84 /** 85 * @brief Estimation of the downward trend from the peak to the lowest point on the right. 86 */ 87 struct DownwardTrendInfo { 88 /** Is it a rapidly decaying peak. */ 89 bool isRapidlyDecay { false }; 90 /** 100 point descent height */ 91 double dropHeight { 0.0 }; 92 /** The proportion of descent interval in a rms-hop length. */ 93 double ducyCycle { 0.0 }; 94 95 DownwardTrendInfo() = default; DownwardTrendInfoDownwardTrendInfo96 DownwardTrendInfo(bool isDecay, double drop, double cycle) 97 { 98 isRapidlyDecay = isDecay; 99 dropHeight = drop; 100 ducyCycle = cycle; 101 } 102 }; 103 104 class PeakFinder { 105 public: 106 /** 107 * @brief Calculate peak value by difference, method: low+high+low 108 * 1. When equal to 0, all peak points are selected 109 * 2. Like heartbeat. wav, the secondary peak point is not from the lowest point and must be removed 110 * 111 * @param envelope Envelope curve of the peak point to be searched. 112 * @param peakThreshold If the peak drop is less than 'peakThreshold', 113 * it is considered not the peak. Value range 0~1.0. 114 * @return Return the index of peaks. 115 */ 116 std::vector<int32_t> DetectPeak(const std::vector<double> &envelope, double peakThreshold); 117 118 /** 119 * @brief Get the Transient By Amplitude object 120 * Find all isolated short events through the original amplitude 121 * @param data Audio time series. 122 * @param isolatedEnvelopeInfo A series of parameters for independent envelopes. 123 * 124 * @return Returns <b>0</b> if the operation is successful; returns a negative value otherwise. 125 */ 126 int32_t ObtainTransientByAmplitude(const std::vector<double> &data, IsolatedEnvelopeInfo &isolatedEnvelopeInfo); 127 128 /** 129 * @brief Get the Voice Segment Flag 130 * Must first call 'ObtainTransientByAmplitude' 131 * 132 * @return Return the Voice Segment Flags. 133 */ 134 std::vector<bool> GetVoiceSegmentFlag() const; 135 136 private: 137 bool GetDeleteFlagOfPeak(const std::vector<double> &envelope, int32_t peakIndex, int32_t valleyIndex, 138 const std::vector<double> &valleysValue, const MountainPosition &mountainPosition); 139 std::vector<double> ExtractValues(const std::vector<double> &envelope, const std::vector<int32_t> &idxs); 140 std::vector<bool> GetVoiceFlag(const std::vector<double> &data, 141 const std::vector<int32_t> &peaks, double lowerAmp); 142 void GetEachIndependentEnvelope(const std::vector<double> &data, const std::vector<int32_t> &peaks, 143 double lowerAmp, MountainPosition &mountainPosition); 144 bool FindPeakBoundary(const std::vector<double> &data, int32_t peakPlace, double threshold, 145 BothSidesOfPeak &bothSides); 146 std::vector<int32_t> PeakFilterMinRange(const std::vector<double> &data, 147 std::vector<int32_t> &peaks, int32_t minSampleCount); 148 std::vector<int32_t> FilterLowPeak(const std::vector<double> &envelope, 149 const std::vector<int32_t> &peaks, double removeRatio); 150 std::vector<bool> SplitVoiceSlienceRange(int32_t dataSize, const std::vector<int32_t> &envelopeStart, 151 const std::vector<int32_t> &envelopeLast); 152 std::vector<int32_t> FilterSecondaryPeak(const std::vector<double> &envelope, 153 const std::vector<int32_t> &peaks, double lowerAmp); 154 int32_t DeletePeaks(const std::vector<double> &envelope, int32_t startPos, int32_t endPos, 155 MountainPosition &mountainPosition, int32_t &index); 156 int32_t DetectValley(const std::vector<double> &envelope, int32_t startPos, int32_t endPos, 157 const MountainPosition &mountainPosition, ValleyPoint &valleyPoint); 158 159 double GetLowestPeakValue(const std::vector<double> &envelope, const std::vector<int32_t> &peaks); 160 int32_t GetPeakEnvelope(const std::vector<double> &data, int32_t samplingRate, int32_t hopLength, 161 PeaksInfo &peakDetection); 162 int32_t EstimateDownwardTrend(const std::vector<double> &data, const std::vector<int32_t> &peaksPoint, 163 const std::vector<int32_t> &lastPeaksPoint, std::vector<DownwardTrendInfo> &downwardTrends); 164 165 /** 166 * @brief Merge continuous long envelopes and continuous pure instantaneous event intervals to avoid low energy 167 * long event outputs. 168 * 169 * between two short events, such as CoinDrop.wav. 170 * Pre processing before peak point co envelope refinement 171 * a0[0],a2[0],a0[1],a2[1]... May be discontinuous 172 * Output list_I is continuous 173 * 174 * @param dataSize Length of envelope points 175 * @param firstPos Start positions. 176 * @param lastPos Last positions. 177 * @param envelopeList Output continuous Long or Short Envelope Results. 178 */ 179 void SplitLongShortEnvelope(int32_t dataSize, const std::vector<int32_t> &firstPos, 180 const std::vector<int32_t> &lastPos, EnvelopeSegmentInfo &envelopeList); 181 int32_t GetIsolatedEnvelope(const std::vector<double> &data, const std::vector<int32_t> &peaks, 182 double lowerAmp, IsolatedEnvelopeInfo &isolatedEnvelopeInfo); 183 // Descending energy 184 // 1.Energy occupation ratio(area occupation ratio) 185 // 2.Lowering energy difference 186 // Returns < b>0 < / b > if the operation is successful; returns a negative value otherwise. 187 int32_t EstimateDesentEnergy(const std::vector<double> &data, double &dropHeight, double &dutyCycle); 188 189 private: 190 std::vector<bool> voiceSegmentFlag_; 191 int32_t hopLength_ { 1024 }; 192 }; 193 } // namespace Sensors 194 } // namespace OHOS 195 #endif // PEAK_FINDER_H