/* * Copyright 2020 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. */ #ifndef CTS_NATIVE_AUDIO_ANALYZER_H #define CTS_NATIVE_AUDIO_ANALYZER_H #define LOG_TAG "NativeAudioAnalyzer" #include #ifndef MODULE_NAME #define MODULE_NAME "NativeAudioAnalyzer" #endif #define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, __VA_ARGS__) #define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, MODULE_NAME, __VA_ARGS__) #define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, MODULE_NAME, __VA_ARGS__) #define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, MODULE_NAME, __VA_ARGS__) #define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, __VA_ARGS__) #define ALOGF(...) __android_log_print(ANDROID_LOG_FATAL, MODULE_NAME, __VA_ARGS__) #include #include "analyzer/LatencyAnalyzer.h" class NativeAudioAnalyzer { public: /** * Open the audio input and output streams. * @return AAUDIO_OK or negative error */ aaudio_result_t openAudio(int inputDeviceId, int outputDeviceId); /** * Start the audio input and output streams. * @return AAUDIO_OK or negative error */ aaudio_result_t startAudio(); /** * Stop the audio input and output streams. * @return AAUDIO_OK or negative error */ aaudio_result_t stopAudio(); /** * Close the audio input and output streams. * @return AAUDIO_OK or negative error */ aaudio_result_t closeAudio(); /** * @return true if enough audio input has been recorded */ bool isRecordingComplete(); /** * Analyze the input and measure the latency between output and input. * @return AAUDIO_OK or negative error */ int analyze(); /** * @return the measured latency in milliseconds */ double getLatencyMillis(); /** * @return the sample rate (in Hz) used for the measurement signal */ int getSampleRate(); /** * The confidence is based on a normalized correlation. * It ranges from 0.0 to 1.0. Higher is better. * * @return the confidence in the latency result */ double getConfidence(); // These are the same as in NativeAnalyzerThread.java and need to stay in sync. static const uint32_t NUM_STREAM_TYPES = 2; static const uint32_t STREAM_INPUT = 0; static const uint32_t STREAM_OUTPUT = 1; /** * Returns true if the hardware supports 24 bit audio. */ bool has24BitHardwareSupport(); /** * Gets the hardware format. */ int getHardwareFormat(); /** * @param streamId One of STREAM_INPUT or STREAM_OUTPUT * @return true if the specified stream was opened in low-latency mode. */ bool isLowLatencyStream(int streamId) { if (streamId != STREAM_OUTPUT && streamId != STREAM_INPUT) { return -1; } return mIsLowLatencyStream[streamId]; } /** * @param streamId One of STREAM_INPUT or STREAM_OUTPUT * @return The burst size in frames of the specified stream. */ int32_t getFramesPerBurst(int streamId) { if (streamId != STREAM_OUTPUT && streamId != STREAM_INPUT) { return -1; } return mBurstFrames[streamId]; } /** * @param streamId One of STREAM_INPUT or STREAM_OUTPUT * @return The capacity in frames of the specified stream. */ int32_t getCapacityFrames(int streamId) { if (streamId != STREAM_OUTPUT && streamId != STREAM_INPUT) { return -1; } return mCapacityFrames[streamId]; } /** * @param streamId One of STREAM_INPUT or STREAM_OUTPUT * @return true if the specified stream was opened as a MMAP stream. */ bool isMMapStream(int streamId) { if (streamId != STREAM_OUTPUT && streamId != STREAM_INPUT) { return -1; } return mIsMMap[streamId]; } aaudio_result_t getError() { return mInputError ? mInputError : mOutputError; } double measureTimestampLatencyMillis(); AAudioStream *mInputStream = nullptr; AAudioStream *mOutputStream = nullptr; aaudio_format_t mActualInputFormat = AAUDIO_FORMAT_INVALID; int16_t *mInputShortData = nullptr; float *mInputFloatData = nullptr; int32_t mOutputSampleRate = 0; aaudio_result_t mInputError = AAUDIO_OK; aaudio_result_t mOutputError = AAUDIO_OK; aaudio_data_callback_result_t dataCallbackProc( void *audioData, int32_t numFrames); private: int32_t readFormattedData(int32_t numFrames); bool has24BitSupport(aaudio_format_t format); WhiteNoiseLatencyAnalyzer mWhiteNoiseLatencyAnalyzer; LoopbackProcessor *mLoopbackProcessor; int32_t mInputFramesMaximum = 0; int32_t mActualInputChannelCount = 0; int32_t mActualOutputChannelCount = 0; int32_t mNumCallbacksToDrain = kNumCallbacksToDrain; int32_t mNumCallbacksToNotRead = kNumCallbacksToNotRead; int32_t mNumCallbacksToDiscard = kNumCallbacksToDiscard; int32_t mMinNumFrames = INT32_MAX; int32_t mMaxNumFrames = 0; int32_t mInsufficientReadCount = 0; int32_t mInsufficientReadFrames = 0; int32_t mFramesReadTotal = 0; int32_t mFramesWrittenTotal = 0; bool mIsDone = false; bool mHas24BitHardwareSupport = false; int32_t mHardwareFormat = 0; int32_t mBurstFrames[NUM_STREAM_TYPES] = {-1, -1}; int32_t mCapacityFrames[NUM_STREAM_TYPES] = {-1, -1}; bool mIsLowLatencyStream[NUM_STREAM_TYPES] = {false, false}; bool mIsMMap[NUM_STREAM_TYPES] = {false, false}; int32_t mOutputDeviceId = 0; int32_t mInputDeviceId = 0; std::atomic mWriteReadDeltaValid{false}; std::atomic mWriteReadDelta{0}; static constexpr int kLogPeriodMillis = 1000; static constexpr int kNumInputChannels = 1; static constexpr int kNumCallbacksToDrain = 20; static constexpr int kNumCallbacksToNotRead = 0; // let input fill back up static constexpr int kNumCallbacksToDiscard = 20; static constexpr int kDefaultHangTimeMillis = 50; static constexpr int kMaxGlitchEventsToSave = 32; static constexpr int kDefaultOutputSizeBursts = 2; }; #endif // CTS_NATIVE_AUDIO_ANALYZER_H