1 /* 2 * Copyright 2017 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 #ifndef ANDROID_AUDIO_POWER_LOG_H 18 #define ANDROID_AUDIO_POWER_LOG_H 19 20 #ifdef __cplusplus 21 22 #include <mutex> 23 #include <vector> 24 #include <system/audio.h> 25 #include <utils/Errors.h> 26 27 namespace android { 28 29 /** 30 * PowerLogBase logs power at a given frame resolution. 31 * 32 * Generally this class is not directly accessed, rather it is embedded 33 * as a helper object in PowerLog, which uses multiple PowerLogBase objects to 34 * log at different frame resolutions. 35 * 36 * Call framesToProcess() to determine the maximum number of frames to process. 37 * Then call processEnergy() with a frame count, and the energy, and the time. 38 */ 39 class PowerLogBase { 40 public: 41 PowerLogBase(uint32_t sampleRate, 42 uint32_t channelCount, 43 audio_format_t format, 44 size_t entries, 45 size_t framesPerEntry); 46 framesToProcess(size_t frames)47 size_t framesToProcess(size_t frames) const { 48 const size_t required = mFramesPerEntry - mCurrentFrames; 49 return std::min(required, frames); 50 } 51 52 void processEnergy(size_t frames, float energy, int64_t nowNs); 53 54 std::string dumpToString(const char* prefix = "", size_t lines = 0, int64_t limitNs = 0, 55 bool logPlot = true) const; 56 57 private: 58 void flushEntry(); 59 60 const uint32_t mSampleRate; // audio data sample rate 61 const uint32_t mChannelCount; // audio data channel count 62 const audio_format_t mFormat; // audio data format 63 const size_t mFramesPerEntry; // number of audio frames per entry 64 const int64_t mEntryTimeNs; // the entry time span in ns 65 const int64_t mMaxTimeSlipNs; // maximum time incoming audio can 66 // be offset by before we flush current entry 67 68 int64_t mCurrentTime = 0; // time of first frame in buffer 69 float mCurrentEnergy = 0.f; // local energy accumulation 70 size_t mCurrentFrames = 0; // number of frames in the energy 71 size_t mIdx = 0; // next usable index in mEntries 72 size_t mConsecutiveZeroes = 1; // current run of consecutive zero entries 73 std::vector<std::pair<int64_t /* real time ns */, float /* energy */>> mEntries; 74 }; 75 76 /** 77 * PowerLog captures the audio data power (measured in dBFS) over time. 78 * 79 * For the purposes of power evaluation, the audio data is divided into "bins", 80 * and grouped by signals consisting of consecutive non-zero energy bins. 81 * The sum energy in dB of each signal is computed for comparison purposes. 82 * 83 * No distinction is made between channels in an audio frame; they are all 84 * summed together for energy purposes. 85 * 86 * The public methods are internally protected by a mutex to be thread-safe. 87 */ 88 class PowerLog { 89 public: 90 91 /** 92 * \brief Creates a PowerLog object. 93 * 94 * \param sampleRate sample rate of the audio data. 95 * \param channelCount channel count of the audio data. 96 * \param format format of the audio data. It must be allowed by 97 * audio_utils_is_compute_power_format_supported() 98 * else the constructor will abort. 99 * \param entries total number of energy entries "bins" to use. 100 * \param framesPerEntry total number of audio frames used in each entry. 101 * \param levels number of resolution levels for the log (typically 1 or 2). 102 */ 103 PowerLog(uint32_t sampleRate, 104 uint32_t channelCount, 105 audio_format_t format, 106 size_t entries, 107 size_t framesPerEntry, 108 size_t levels = 2) mChannelCount(channelCount)109 : mChannelCount(channelCount) 110 , mFormat(format) 111 , mSampleRate(sampleRate) 112 , mBase{[=]() { 113 // create a vector of PowerLogBases starting from the 114 // finest granularity to the largest granularity. 115 std::vector<std::shared_ptr<PowerLogBase>> v(levels); 116 size_t scale = 1; 117 for (size_t i = 0; i < levels; ++i) { 118 v[i] = std::make_shared<PowerLogBase>( 119 sampleRate, channelCount, format, 120 entries / levels, framesPerEntry * scale); 121 scale *= 20; // each level's entry is 20x the temporal width of the prior. 122 } 123 return v; 124 }()} {} 125 126 /** 127 * \brief Adds new audio data to the power log. 128 * 129 * \param buffer pointer to the audio data buffer. 130 * \param frames buffer size in audio frames. 131 * \param nowNs current time in nanoseconds. 132 */ 133 void log(const void *buffer, size_t frames, int64_t nowNs); 134 135 /** 136 * \brief Dumps the log to a std::string. 137 * 138 * \param lines maximum number of lines to output (0 disables). 139 * \param limitNs limit dump to data more recent than limitNs (0 disables). 140 * \param logPlot true if a log plot is generated. This will result in 141 * additional 18 lines to be output. 142 * \return the std::string for the log. 143 */ 144 std::string dumpToString(const char *prefix = "", size_t lines = 0, int64_t limitNs = 0, 145 bool logPlot = true) const; 146 147 /** 148 * \brief Dumps the log to a raw file descriptor. 149 * 150 * \param fd file descriptor to use. 151 * \param lines maximum number of lines to output (0 disables). 152 * \param limitNs limit dump to data more recent than limitNs (0 disables). 153 * \param logPlot true if a log plot is generated. This will result in 154 * additional 18 lines to be output. 155 * \return 156 * NO_ERROR on success or a negative number (-errno) on failure of write(). 157 */ 158 status_t dump(int fd, const char *prefix = "", size_t lines = 0, int64_t limitNs = 0, 159 bool logPlot = true) const; 160 161 const uint32_t mChannelCount; // audio data channel count 162 const audio_format_t mFormat; // audio data format 163 const uint32_t mSampleRate; 164 165 mutable std::mutex mMutex; // monitor mutex governs access through mBase. 166 const std::vector<std::shared_ptr<PowerLogBase>> mBase; 167 }; 168 169 } // namespace android 170 171 #endif // __cplusplus 172 173 /** \cond */ 174 __BEGIN_DECLS 175 /** \endcond */ 176 177 // C API (see C++ api above for details) 178 179 typedef struct power_log_t power_log_t; 180 181 /** 182 * \brief Creates a power log object. 183 * 184 * \param sample_rate sample rate of the audio data. 185 * \param channel_count channel count of the audio data. 186 * \param format format of the audio data. It must be allowed by 187 * audio_utils_is_compute_power_format_supported(). 188 * \param entries total number of energy entries "bins" to use. 189 * \param frames_per_entry total number of audio frames used in each entry. 190 * 191 * \return power log object or NULL on failure. 192 */ 193 power_log_t *power_log_create(uint32_t sample_rate, 194 uint32_t channel_count, audio_format_t format, size_t entries, size_t frames_per_entry); 195 196 /** 197 * \brief Adds new audio data to the power log. 198 * 199 * \param power_log object returned by create, if NULL nothing happens. 200 * \param buffer pointer to the audio data buffer. 201 * \param frames buffer size in audio frames. 202 * \param now_ns current time in nanoseconds. 203 */ 204 void power_log_log(power_log_t *power_log, const void *buffer, size_t frames, int64_t now_ns); 205 206 /** 207 * \brief Dumps the log to a raw file descriptor. 208 * 209 * A log plot is always generated, adding 18 more lines to the dump. 210 * 211 * \param power_log object returned by create, if NULL nothing happens. 212 * \param fd file descriptor to use. 213 * \param prefix displayed at start of each line. 214 * \param lines maximum number of lines to output (0 disables). 215 * \param limit_ns limit dump to data more recent than limit_ns (0 disables). 216 * \return 217 * NO_ERROR on success or a negative number (-errno) on failure of write(). 218 * if power_log is NULL, BAD_VALUE is returned. 219 */ 220 int power_log_dump( 221 power_log_t *power_log, int fd, const char *prefix, size_t lines, int64_t limit_ns); 222 223 /** 224 * \brief Destroys the power log object. 225 * 226 * \param power_log object returned by create, if NULL nothing happens. 227 */ 228 void power_log_destroy(power_log_t *power_log); 229 230 /** \cond */ 231 __END_DECLS 232 /** \endcond */ 233 234 #endif // !ANDROID_AUDIO_POWER_LOG_H 235