blob: cf262bb09acac629b89bd8d2c1578511f7cdd463 [file] [log] [blame]
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <android-base/thread_annotations.h>
#include <audio_utils/MelProcessor.h>
#include <map>
#include <mutex>
namespace android::audio_utils {
struct MelRecord {
/** The port ID of the audio device where the MEL value was recorded. */
audio_port_handle_t portId;
/**
* Array of continuously recorded MEL values >= RS1 (1 per second). First
* value in the array was recorded at time: timestamp.
*/
std::vector<float> mels;
/** Corresponds to the time when the first MEL entry in MelRecord was recorded. */
int64_t timestamp;
MelRecord(audio_port_handle_t portId,
std::vector<float> mels,
int64_t timestamp)
: portId(portId), mels(std::move(mels)), timestamp(timestamp) {}
inline bool overlapsEnd(const MelRecord& record) const {
return timestamp + static_cast<int64_t>(mels.size()) > record.timestamp;
}
};
struct CsdRecord {
/** Corresponds to the time when the CSD value is calculated from. */
const int64_t timestamp;
/** Corresponds to the duration that leads to the CSD value. */
const size_t duration;
/** The actual contribution to the CSD computation normalized: 1.f is 100%CSD. */
const float value;
/** The average MEL value that lead to this CSD value. */
const float averageMel;
CsdRecord(int64_t timestamp,
size_t duration,
float value,
float averageMel)
: timestamp(timestamp),
duration(duration),
value(value),
averageMel(averageMel) {};
};
/**
* Class used to aggregate MEL values from different streams that play sounds
* simultaneously.
*
* The public methods are internally protected by a mutex to be thread-safe.
*/
class MelAggregator : public RefBase {
public:
explicit MelAggregator(int64_t csdWindowSeconds)
: mCsdWindowSeconds(csdWindowSeconds) {}
/**
* \returns the size of the stored CSD values.
*/
size_t getCsdRecordsSize() const;
/**
* \brief Iterate over the CsdRecords and applies function f.
*
* \param f function to apply on the iterated CsdRecord's sorted by timestamp
*/
void foreachCsd(const std::function<void(const CsdRecord&)>& f) const;
/** Returns the current CSD computed with a rolling window of mCsdWindowSeconds. */
float getCsd();
/**
* \returns the size of the stored MEL records.
*/
size_t getCachedMelRecordsSize() const;
/**
* \brief Iterate over the MelRecords and applies function f.
*
* \param f function to apply on the iterated MelRecord's sorted by timestamp
*/
void foreachCachedMel(const std::function<void(const MelRecord&)>& f) const;
/**
* New value are stored and MEL values that correspond to the same timestamp
* will be aggregated.
*
* \returns a vector containing all the new CsdRecord's that were added to
* the current CSD value. Vector could be empty in case no new records
* contributed to CSD.
*/
std::vector<CsdRecord> aggregateAndAddNewMelRecord(const MelRecord& record);
/**
* Reset the aggregator values. Discards all the previous cached values and
* uses the passed records for the new callbacks.
**/
void reset(float newCsd, const std::vector<CsdRecord>& newRecords);
private:
/** Locked aggregateAndAddNewMelRecord method. */
std::vector<CsdRecord> aggregateAndAddNewMelRecord_l(const MelRecord& record) REQUIRES(mLock);
void removeOldCsdRecords_l(std::vector<CsdRecord>& removeRecords) REQUIRES(mLock);
std::vector<CsdRecord> updateCsdRecords_l() REQUIRES(mLock);
int64_t csdTimeIntervalStored_l() REQUIRES(mLock);
std::map<int64_t, CsdRecord>::iterator addNewestCsdRecord_l(int64_t timestamp,
int64_t duration,
float csdRecord,
float averageMel) REQUIRES(mLock);
const int64_t mCsdWindowSeconds;
mutable std::mutex mLock;
std::map<int64_t, MelRecord> mMelRecords GUARDED_BY(mLock);
std::map<int64_t, CsdRecord> mCsdRecords GUARDED_BY(mLock);
/** Current CSD value in mMelRecords. */
float mCurrentMelRecordsCsd GUARDED_BY(mLock) = 0.f;
/** CSD value containing sum of all CSD values stored. */
float mCurrentCsd GUARDED_BY(mLock) = 0.f;
};
} // naemspace android::audio_utils