1*b7c941bbSAndroid Build Coastguard Worker /* 2*b7c941bbSAndroid Build Coastguard Worker * Copyright 2020 The Android Open Source Project 3*b7c941bbSAndroid Build Coastguard Worker * 4*b7c941bbSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*b7c941bbSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*b7c941bbSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*b7c941bbSAndroid Build Coastguard Worker * 8*b7c941bbSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*b7c941bbSAndroid Build Coastguard Worker * 10*b7c941bbSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*b7c941bbSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*b7c941bbSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*b7c941bbSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*b7c941bbSAndroid Build Coastguard Worker * limitations under the License. 15*b7c941bbSAndroid Build Coastguard Worker */ 16*b7c941bbSAndroid Build Coastguard Worker 17*b7c941bbSAndroid Build Coastguard Worker #ifndef CTS_NATIVE_AUDIO_ANALYZER_H 18*b7c941bbSAndroid Build Coastguard Worker #define CTS_NATIVE_AUDIO_ANALYZER_H 19*b7c941bbSAndroid Build Coastguard Worker 20*b7c941bbSAndroid Build Coastguard Worker #define LOG_TAG "NativeAudioAnalyzer" 21*b7c941bbSAndroid Build Coastguard Worker #include <android/log.h> 22*b7c941bbSAndroid Build Coastguard Worker 23*b7c941bbSAndroid Build Coastguard Worker #ifndef MODULE_NAME 24*b7c941bbSAndroid Build Coastguard Worker #define MODULE_NAME "NativeAudioAnalyzer" 25*b7c941bbSAndroid Build Coastguard Worker #endif 26*b7c941bbSAndroid Build Coastguard Worker 27*b7c941bbSAndroid Build Coastguard Worker #define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, __VA_ARGS__) 28*b7c941bbSAndroid Build Coastguard Worker #define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, MODULE_NAME, __VA_ARGS__) 29*b7c941bbSAndroid Build Coastguard Worker #define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, MODULE_NAME, __VA_ARGS__) 30*b7c941bbSAndroid Build Coastguard Worker #define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, MODULE_NAME, __VA_ARGS__) 31*b7c941bbSAndroid Build Coastguard Worker #define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, __VA_ARGS__) 32*b7c941bbSAndroid Build Coastguard Worker #define ALOGF(...) __android_log_print(ANDROID_LOG_FATAL, MODULE_NAME, __VA_ARGS__) 33*b7c941bbSAndroid Build Coastguard Worker 34*b7c941bbSAndroid Build Coastguard Worker #include <aaudio/AAudio.h> 35*b7c941bbSAndroid Build Coastguard Worker 36*b7c941bbSAndroid Build Coastguard Worker #include "analyzer/LatencyAnalyzer.h" 37*b7c941bbSAndroid Build Coastguard Worker 38*b7c941bbSAndroid Build Coastguard Worker class NativeAudioAnalyzer { 39*b7c941bbSAndroid Build Coastguard Worker public: 40*b7c941bbSAndroid Build Coastguard Worker 41*b7c941bbSAndroid Build Coastguard Worker /** 42*b7c941bbSAndroid Build Coastguard Worker * Open the audio input and output streams. 43*b7c941bbSAndroid Build Coastguard Worker * @return AAUDIO_OK or negative error 44*b7c941bbSAndroid Build Coastguard Worker */ 45*b7c941bbSAndroid Build Coastguard Worker aaudio_result_t openAudio(int inputDeviceId, int outputDeviceId); 46*b7c941bbSAndroid Build Coastguard Worker 47*b7c941bbSAndroid Build Coastguard Worker /** 48*b7c941bbSAndroid Build Coastguard Worker * Start the audio input and output streams. 49*b7c941bbSAndroid Build Coastguard Worker * @return AAUDIO_OK or negative error 50*b7c941bbSAndroid Build Coastguard Worker */ 51*b7c941bbSAndroid Build Coastguard Worker aaudio_result_t startAudio(); 52*b7c941bbSAndroid Build Coastguard Worker 53*b7c941bbSAndroid Build Coastguard Worker /** 54*b7c941bbSAndroid Build Coastguard Worker * Stop the audio input and output streams. 55*b7c941bbSAndroid Build Coastguard Worker * @return AAUDIO_OK or negative error 56*b7c941bbSAndroid Build Coastguard Worker */ 57*b7c941bbSAndroid Build Coastguard Worker aaudio_result_t stopAudio(); 58*b7c941bbSAndroid Build Coastguard Worker 59*b7c941bbSAndroid Build Coastguard Worker /** 60*b7c941bbSAndroid Build Coastguard Worker * Close the audio input and output streams. 61*b7c941bbSAndroid Build Coastguard Worker * @return AAUDIO_OK or negative error 62*b7c941bbSAndroid Build Coastguard Worker */ 63*b7c941bbSAndroid Build Coastguard Worker aaudio_result_t closeAudio(); 64*b7c941bbSAndroid Build Coastguard Worker 65*b7c941bbSAndroid Build Coastguard Worker /** 66*b7c941bbSAndroid Build Coastguard Worker * @return true if enough audio input has been recorded 67*b7c941bbSAndroid Build Coastguard Worker */ 68*b7c941bbSAndroid Build Coastguard Worker bool isRecordingComplete(); 69*b7c941bbSAndroid Build Coastguard Worker 70*b7c941bbSAndroid Build Coastguard Worker /** 71*b7c941bbSAndroid Build Coastguard Worker * Analyze the input and measure the latency between output and input. 72*b7c941bbSAndroid Build Coastguard Worker * @return AAUDIO_OK or negative error 73*b7c941bbSAndroid Build Coastguard Worker */ 74*b7c941bbSAndroid Build Coastguard Worker int analyze(); 75*b7c941bbSAndroid Build Coastguard Worker 76*b7c941bbSAndroid Build Coastguard Worker /** 77*b7c941bbSAndroid Build Coastguard Worker * @return the measured latency in milliseconds 78*b7c941bbSAndroid Build Coastguard Worker */ 79*b7c941bbSAndroid Build Coastguard Worker double getLatencyMillis(); 80*b7c941bbSAndroid Build Coastguard Worker 81*b7c941bbSAndroid Build Coastguard Worker /** 82*b7c941bbSAndroid Build Coastguard Worker * @return the sample rate (in Hz) used for the measurement signal 83*b7c941bbSAndroid Build Coastguard Worker */ 84*b7c941bbSAndroid Build Coastguard Worker int getSampleRate(); 85*b7c941bbSAndroid Build Coastguard Worker 86*b7c941bbSAndroid Build Coastguard Worker /** 87*b7c941bbSAndroid Build Coastguard Worker * The confidence is based on a normalized correlation. 88*b7c941bbSAndroid Build Coastguard Worker * It ranges from 0.0 to 1.0. Higher is better. 89*b7c941bbSAndroid Build Coastguard Worker * 90*b7c941bbSAndroid Build Coastguard Worker * @return the confidence in the latency result 91*b7c941bbSAndroid Build Coastguard Worker */ 92*b7c941bbSAndroid Build Coastguard Worker double getConfidence(); 93*b7c941bbSAndroid Build Coastguard Worker 94*b7c941bbSAndroid Build Coastguard Worker // These are the same as in NativeAnalyzerThread.java and need to stay in sync. 95*b7c941bbSAndroid Build Coastguard Worker static const uint32_t NUM_STREAM_TYPES = 2; 96*b7c941bbSAndroid Build Coastguard Worker static const uint32_t STREAM_INPUT = 0; 97*b7c941bbSAndroid Build Coastguard Worker static const uint32_t STREAM_OUTPUT = 1; 98*b7c941bbSAndroid Build Coastguard Worker 99*b7c941bbSAndroid Build Coastguard Worker /** 100*b7c941bbSAndroid Build Coastguard Worker * Returns true if the hardware supports 24 bit audio. 101*b7c941bbSAndroid Build Coastguard Worker */ 102*b7c941bbSAndroid Build Coastguard Worker bool has24BitHardwareSupport(); 103*b7c941bbSAndroid Build Coastguard Worker 104*b7c941bbSAndroid Build Coastguard Worker /** 105*b7c941bbSAndroid Build Coastguard Worker * Gets the hardware format. 106*b7c941bbSAndroid Build Coastguard Worker */ 107*b7c941bbSAndroid Build Coastguard Worker int getHardwareFormat(); 108*b7c941bbSAndroid Build Coastguard Worker 109*b7c941bbSAndroid Build Coastguard Worker /** 110*b7c941bbSAndroid Build Coastguard Worker * @param streamId One of STREAM_INPUT or STREAM_OUTPUT 111*b7c941bbSAndroid Build Coastguard Worker * @return true if the specified stream was opened in low-latency mode. 112*b7c941bbSAndroid Build Coastguard Worker */ isLowLatencyStream(int streamId)113*b7c941bbSAndroid Build Coastguard Worker bool isLowLatencyStream(int streamId) { 114*b7c941bbSAndroid Build Coastguard Worker if (streamId != STREAM_OUTPUT && streamId != STREAM_INPUT) { 115*b7c941bbSAndroid Build Coastguard Worker return -1; 116*b7c941bbSAndroid Build Coastguard Worker } 117*b7c941bbSAndroid Build Coastguard Worker return mIsLowLatencyStream[streamId]; 118*b7c941bbSAndroid Build Coastguard Worker } 119*b7c941bbSAndroid Build Coastguard Worker 120*b7c941bbSAndroid Build Coastguard Worker /** 121*b7c941bbSAndroid Build Coastguard Worker * @param streamId One of STREAM_INPUT or STREAM_OUTPUT 122*b7c941bbSAndroid Build Coastguard Worker * @return The burst size in frames of the specified stream. 123*b7c941bbSAndroid Build Coastguard Worker */ getFramesPerBurst(int streamId)124*b7c941bbSAndroid Build Coastguard Worker int32_t getFramesPerBurst(int streamId) { 125*b7c941bbSAndroid Build Coastguard Worker if (streamId != STREAM_OUTPUT && streamId != STREAM_INPUT) { 126*b7c941bbSAndroid Build Coastguard Worker return -1; 127*b7c941bbSAndroid Build Coastguard Worker } 128*b7c941bbSAndroid Build Coastguard Worker return mBurstFrames[streamId]; 129*b7c941bbSAndroid Build Coastguard Worker } 130*b7c941bbSAndroid Build Coastguard Worker 131*b7c941bbSAndroid Build Coastguard Worker /** 132*b7c941bbSAndroid Build Coastguard Worker * @param streamId One of STREAM_INPUT or STREAM_OUTPUT 133*b7c941bbSAndroid Build Coastguard Worker * @return The capacity in frames of the specified stream. 134*b7c941bbSAndroid Build Coastguard Worker */ getCapacityFrames(int streamId)135*b7c941bbSAndroid Build Coastguard Worker int32_t getCapacityFrames(int streamId) { 136*b7c941bbSAndroid Build Coastguard Worker if (streamId != STREAM_OUTPUT && streamId != STREAM_INPUT) { 137*b7c941bbSAndroid Build Coastguard Worker return -1; 138*b7c941bbSAndroid Build Coastguard Worker } 139*b7c941bbSAndroid Build Coastguard Worker return mCapacityFrames[streamId]; 140*b7c941bbSAndroid Build Coastguard Worker } 141*b7c941bbSAndroid Build Coastguard Worker 142*b7c941bbSAndroid Build Coastguard Worker /** 143*b7c941bbSAndroid Build Coastguard Worker * @param streamId One of STREAM_INPUT or STREAM_OUTPUT 144*b7c941bbSAndroid Build Coastguard Worker * @return true if the specified stream was opened as a MMAP stream. 145*b7c941bbSAndroid Build Coastguard Worker */ isMMapStream(int streamId)146*b7c941bbSAndroid Build Coastguard Worker bool isMMapStream(int streamId) { 147*b7c941bbSAndroid Build Coastguard Worker if (streamId != STREAM_OUTPUT && streamId != STREAM_INPUT) { 148*b7c941bbSAndroid Build Coastguard Worker return -1; 149*b7c941bbSAndroid Build Coastguard Worker } 150*b7c941bbSAndroid Build Coastguard Worker return mIsMMap[streamId]; 151*b7c941bbSAndroid Build Coastguard Worker } 152*b7c941bbSAndroid Build Coastguard Worker getError()153*b7c941bbSAndroid Build Coastguard Worker aaudio_result_t getError() { 154*b7c941bbSAndroid Build Coastguard Worker return mInputError ? mInputError : mOutputError; 155*b7c941bbSAndroid Build Coastguard Worker } 156*b7c941bbSAndroid Build Coastguard Worker 157*b7c941bbSAndroid Build Coastguard Worker double measureTimestampLatencyMillis(); 158*b7c941bbSAndroid Build Coastguard Worker 159*b7c941bbSAndroid Build Coastguard Worker AAudioStream *mInputStream = nullptr; 160*b7c941bbSAndroid Build Coastguard Worker AAudioStream *mOutputStream = nullptr; 161*b7c941bbSAndroid Build Coastguard Worker aaudio_format_t mActualInputFormat = AAUDIO_FORMAT_INVALID; 162*b7c941bbSAndroid Build Coastguard Worker int16_t *mInputShortData = nullptr; 163*b7c941bbSAndroid Build Coastguard Worker float *mInputFloatData = nullptr; 164*b7c941bbSAndroid Build Coastguard Worker 165*b7c941bbSAndroid Build Coastguard Worker int32_t mOutputSampleRate = 0; 166*b7c941bbSAndroid Build Coastguard Worker 167*b7c941bbSAndroid Build Coastguard Worker aaudio_result_t mInputError = AAUDIO_OK; 168*b7c941bbSAndroid Build Coastguard Worker aaudio_result_t mOutputError = AAUDIO_OK; 169*b7c941bbSAndroid Build Coastguard Worker 170*b7c941bbSAndroid Build Coastguard Worker aaudio_data_callback_result_t dataCallbackProc( 171*b7c941bbSAndroid Build Coastguard Worker void *audioData, 172*b7c941bbSAndroid Build Coastguard Worker int32_t numFrames); 173*b7c941bbSAndroid Build Coastguard Worker 174*b7c941bbSAndroid Build Coastguard Worker private: 175*b7c941bbSAndroid Build Coastguard Worker 176*b7c941bbSAndroid Build Coastguard Worker int32_t readFormattedData(int32_t numFrames); 177*b7c941bbSAndroid Build Coastguard Worker 178*b7c941bbSAndroid Build Coastguard Worker bool has24BitSupport(aaudio_format_t format); 179*b7c941bbSAndroid Build Coastguard Worker 180*b7c941bbSAndroid Build Coastguard Worker WhiteNoiseLatencyAnalyzer mWhiteNoiseLatencyAnalyzer; 181*b7c941bbSAndroid Build Coastguard Worker LoopbackProcessor *mLoopbackProcessor; 182*b7c941bbSAndroid Build Coastguard Worker 183*b7c941bbSAndroid Build Coastguard Worker int32_t mInputFramesMaximum = 0; 184*b7c941bbSAndroid Build Coastguard Worker int32_t mActualInputChannelCount = 0; 185*b7c941bbSAndroid Build Coastguard Worker int32_t mActualOutputChannelCount = 0; 186*b7c941bbSAndroid Build Coastguard Worker int32_t mNumCallbacksToDrain = kNumCallbacksToDrain; 187*b7c941bbSAndroid Build Coastguard Worker int32_t mNumCallbacksToNotRead = kNumCallbacksToNotRead; 188*b7c941bbSAndroid Build Coastguard Worker int32_t mNumCallbacksToDiscard = kNumCallbacksToDiscard; 189*b7c941bbSAndroid Build Coastguard Worker int32_t mMinNumFrames = INT32_MAX; 190*b7c941bbSAndroid Build Coastguard Worker int32_t mMaxNumFrames = 0; 191*b7c941bbSAndroid Build Coastguard Worker int32_t mInsufficientReadCount = 0; 192*b7c941bbSAndroid Build Coastguard Worker int32_t mInsufficientReadFrames = 0; 193*b7c941bbSAndroid Build Coastguard Worker int32_t mFramesReadTotal = 0; 194*b7c941bbSAndroid Build Coastguard Worker int32_t mFramesWrittenTotal = 0; 195*b7c941bbSAndroid Build Coastguard Worker bool mIsDone = false; 196*b7c941bbSAndroid Build Coastguard Worker bool mHas24BitHardwareSupport = false; 197*b7c941bbSAndroid Build Coastguard Worker int32_t mHardwareFormat = 0; 198*b7c941bbSAndroid Build Coastguard Worker 199*b7c941bbSAndroid Build Coastguard Worker int32_t mBurstFrames[NUM_STREAM_TYPES] = {-1, -1}; 200*b7c941bbSAndroid Build Coastguard Worker int32_t mCapacityFrames[NUM_STREAM_TYPES] = {-1, -1}; 201*b7c941bbSAndroid Build Coastguard Worker bool mIsLowLatencyStream[NUM_STREAM_TYPES] = {false, false}; 202*b7c941bbSAndroid Build Coastguard Worker bool mIsMMap[NUM_STREAM_TYPES] = {false, false}; 203*b7c941bbSAndroid Build Coastguard Worker 204*b7c941bbSAndroid Build Coastguard Worker int32_t mOutputDeviceId = 0; 205*b7c941bbSAndroid Build Coastguard Worker int32_t mInputDeviceId = 0; 206*b7c941bbSAndroid Build Coastguard Worker 207*b7c941bbSAndroid Build Coastguard Worker std::atomic<bool> mWriteReadDeltaValid{false}; 208*b7c941bbSAndroid Build Coastguard Worker std::atomic<int64_t> mWriteReadDelta{0}; 209*b7c941bbSAndroid Build Coastguard Worker 210*b7c941bbSAndroid Build Coastguard Worker static constexpr int kLogPeriodMillis = 1000; 211*b7c941bbSAndroid Build Coastguard Worker static constexpr int kNumInputChannels = 1; 212*b7c941bbSAndroid Build Coastguard Worker static constexpr int kNumCallbacksToDrain = 20; 213*b7c941bbSAndroid Build Coastguard Worker static constexpr int kNumCallbacksToNotRead = 0; // let input fill back up 214*b7c941bbSAndroid Build Coastguard Worker static constexpr int kNumCallbacksToDiscard = 20; 215*b7c941bbSAndroid Build Coastguard Worker static constexpr int kDefaultHangTimeMillis = 50; 216*b7c941bbSAndroid Build Coastguard Worker static constexpr int kMaxGlitchEventsToSave = 32; 217*b7c941bbSAndroid Build Coastguard Worker static constexpr int kDefaultOutputSizeBursts = 2; 218*b7c941bbSAndroid Build Coastguard Worker }; 219*b7c941bbSAndroid Build Coastguard Worker 220*b7c941bbSAndroid Build Coastguard Worker #endif // CTS_NATIVE_AUDIO_ANALYZER_H 221