• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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