1 /* 2 * Copyright 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <android-base/thread_annotations.h> 20 #include <audio_utils/MelProcessor.h> 21 #include <map> 22 #include <mutex> 23 24 namespace android::audio_utils { 25 26 struct MelRecord { 27 /** The port ID of the audio device where the MEL value was recorded. */ 28 audio_port_handle_t portId; 29 /** 30 * Array of continuously recorded MEL values >= RS1 (1 per second). First 31 * value in the array was recorded at time: timestamp. 32 */ 33 std::vector<float> mels; 34 /** Corresponds to the time when the first MEL entry in MelRecord was recorded. */ 35 int64_t timestamp; 36 MelRecordMelRecord37 MelRecord(audio_port_handle_t portId, 38 std::vector<float> mels, 39 int64_t timestamp) 40 : portId(portId), mels(std::move(mels)), timestamp(timestamp) {} 41 overlapsEndMelRecord42 inline bool overlapsEnd(const MelRecord& record) const { 43 return timestamp + static_cast<int64_t>(mels.size()) > record.timestamp; 44 } 45 }; 46 47 struct CsdRecord { 48 /** Corresponds to the time when the CSD value is calculated from. */ 49 const int64_t timestamp; 50 /** Corresponds to the duration that leads to the CSD value. */ 51 const size_t duration; 52 /** The actual contribution to the CSD computation normalized: 1.f is 100%CSD. */ 53 const float value; 54 /** The average MEL value that lead to this CSD value. */ 55 const float averageMel; 56 CsdRecordCsdRecord57 CsdRecord(int64_t timestamp, 58 size_t duration, 59 float value, 60 float averageMel) 61 : timestamp(timestamp), 62 duration(duration), 63 value(value), 64 averageMel(averageMel) {}; 65 }; 66 67 /** 68 * Class used to aggregate MEL values from different streams that play sounds 69 * simultaneously. 70 * 71 * The public methods are internally protected by a mutex to be thread-safe. 72 */ 73 class MelAggregator : public RefBase { 74 public: 75 MelAggregator(int64_t csdWindowSeconds)76 explicit MelAggregator(int64_t csdWindowSeconds) 77 : mCsdWindowSeconds(csdWindowSeconds) {} 78 79 /** 80 * \returns the size of the stored CSD values. 81 */ 82 size_t getCsdRecordsSize() const; 83 84 /** 85 * \brief Iterate over the CsdRecords and applies function f. 86 * 87 * \param f function to apply on the iterated CsdRecord's sorted by timestamp 88 */ 89 void foreachCsd(const std::function<void(const CsdRecord&)>& f) const; 90 91 /** Returns the current CSD computed with a rolling window of mCsdWindowSeconds. */ 92 float getCsd(); 93 94 /** 95 * \returns the size of the stored MEL records. 96 */ 97 size_t getCachedMelRecordsSize() const; 98 99 /** 100 * \brief Iterate over the MelRecords and applies function f. 101 * 102 * \param f function to apply on the iterated MelRecord's sorted by timestamp 103 */ 104 void foreachCachedMel(const std::function<void(const MelRecord&)>& f) const; 105 106 /** 107 * New value are stored and MEL values that correspond to the same timestamp 108 * will be aggregated. 109 * 110 * \returns a vector containing all the new CsdRecord's that were added to 111 * the current CSD value. Vector could be empty in case no new records 112 * contributed to CSD. 113 */ 114 std::vector<CsdRecord> aggregateAndAddNewMelRecord(const MelRecord& record); 115 116 /** 117 * Reset the aggregator values. Discards all the previous cached values and 118 * uses the passed records for the new callbacks. 119 **/ 120 void reset(float newCsd, const std::vector<CsdRecord>& newRecords); 121 private: 122 /** Locked aggregateAndAddNewMelRecord method. */ 123 std::vector<CsdRecord> aggregateAndAddNewMelRecord_l(const MelRecord& record) REQUIRES(mLock); 124 125 void removeOldCsdRecords_l(std::vector<CsdRecord>& removeRecords) REQUIRES(mLock); 126 127 std::vector<CsdRecord> updateCsdRecords_l() REQUIRES(mLock); 128 129 int64_t csdTimeIntervalStored_l() REQUIRES(mLock); 130 131 std::map<int64_t, CsdRecord>::iterator addNewestCsdRecord_l(int64_t timestamp, 132 int64_t duration, 133 float csdRecord, 134 float averageMel) REQUIRES(mLock); 135 136 const int64_t mCsdWindowSeconds; 137 138 mutable std::mutex mLock; 139 140 std::map<int64_t, MelRecord> mMelRecords GUARDED_BY(mLock); 141 std::map<int64_t, CsdRecord> mCsdRecords GUARDED_BY(mLock); 142 143 /** Current CSD value in mMelRecords. */ 144 float mCurrentMelRecordsCsd GUARDED_BY(mLock) = 0.f; 145 146 /** CSD value containing sum of all CSD values stored. */ 147 float mCurrentCsd GUARDED_BY(mLock) = 0.f; 148 }; 149 150 } // naemspace android::audio_utils 151