1 /*
2  * Copyright 2020 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 CTS_NATIVE_AUDIO_ANALYZER_H
18 #define CTS_NATIVE_AUDIO_ANALYZER_H
19 
20 #define LOG_TAG "NativeAudioAnalyzer"
21 #include <android/log.h>
22 
23 #ifndef MODULE_NAME
24 #define MODULE_NAME  "NativeAudioAnalyzer"
25 #endif
26 
27 #define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, __VA_ARGS__)
28 #define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, MODULE_NAME, __VA_ARGS__)
29 #define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, MODULE_NAME, __VA_ARGS__)
30 #define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, MODULE_NAME, __VA_ARGS__)
31 #define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, __VA_ARGS__)
32 #define ALOGF(...) __android_log_print(ANDROID_LOG_FATAL, MODULE_NAME, __VA_ARGS__)
33 
34 #include <aaudio/AAudio.h>
35 
36 #include "analyzer/GlitchAnalyzer.h"
37 #include "analyzer/LatencyAnalyzer.h"
38 
39 class NativeAudioAnalyzer {
40 public:
41 
42     /**
43      * Open the audio input and output streams.
44      * @return AAUDIO_OK or negative error
45      */
46     aaudio_result_t openAudio();
47 
48     /**
49      * Start the audio input and output streams.
50      * @return AAUDIO_OK or negative error
51      */
52     aaudio_result_t startAudio();
53 
54     /**
55      * Stop the audio input and output streams.
56      * @return AAUDIO_OK or negative error
57      */
58     aaudio_result_t stopAudio();
59 
60     /**
61      * Close the audio input and output streams.
62      * @return AAUDIO_OK or negative error
63      */
64     aaudio_result_t closeAudio();
65 
66     /**
67      * @return true if enough audio input has been recorded
68      */
69     bool isRecordingComplete();
70 
71     /**
72      * Analyze the input and measure the latency between output and input.
73      * @return AAUDIO_OK or negative error
74      */
75     int analyze();
76 
77     /**
78      * @return the measured latency in milliseconds
79      */
80     double getLatencyMillis();
81 
82     /**
83      * @return the sample rate (in Hz) used for the measurement signal
84      */
85     int getSampleRate();
86 
87     /**
88      * The confidence is based on a normalized correlation.
89      * It ranges from 0.0 to 1.0. Higher is better.
90      *
91      * @return the confidence in the latency result
92      */
93     double getConfidence();
94 
95     /**
96      * Returns true if the stream was successfully opened in low-latency mode.
97      */
98     bool isLowLatencyStream();
99 
getError()100     aaudio_result_t getError() {
101         return mInputError ? mInputError : mOutputError;
102     }
103 
104     AAudioStream      *mInputStream = nullptr;
105     AAudioStream      *mOutputStream = nullptr;
106     aaudio_format_t    mActualInputFormat = AAUDIO_FORMAT_INVALID;
107     int16_t           *mInputShortData = nullptr;
108     float             *mInputFloatData = nullptr;
109     int32_t            mOutputSampleRate = 0;
110 
111     aaudio_result_t    mInputError = AAUDIO_OK;
112     aaudio_result_t    mOutputError = AAUDIO_OK;
113 
114 aaudio_data_callback_result_t dataCallbackProc(
115         void *audioData,
116         int32_t numFrames);
117 
118 private:
119 
120     int32_t readFormattedData(int32_t numFrames);
121 
122     GlitchAnalyzer       mSineAnalyzer;
123     PulseLatencyAnalyzer mPulseLatencyAnalyzer;
124     LoopbackProcessor   *mLoopbackProcessor;
125 
126     int32_t            mInputFramesMaximum = 0;
127     int32_t            mActualInputChannelCount = 0;
128     int32_t            mActualOutputChannelCount = 0;
129     int32_t            mNumCallbacksToDrain = kNumCallbacksToDrain;
130     int32_t            mNumCallbacksToNotRead = kNumCallbacksToNotRead;
131     int32_t            mNumCallbacksToDiscard = kNumCallbacksToDiscard;
132     int32_t            mMinNumFrames = INT32_MAX;
133     int32_t            mMaxNumFrames = 0;
134     int32_t            mInsufficientReadCount = 0;
135     int32_t            mInsufficientReadFrames = 0;
136     int32_t            mFramesReadTotal = 0;
137     int32_t            mFramesWrittenTotal = 0;
138     bool               mIsDone = false;
139     bool               mIsLowLatencyStream = false;
140 
141     static constexpr int kLogPeriodMillis         = 1000;
142     static constexpr int kNumInputChannels        = 1;
143     static constexpr int kNumCallbacksToDrain     = 20;
144     static constexpr int kNumCallbacksToNotRead   = 0; // let input fill back up
145     static constexpr int kNumCallbacksToDiscard   = 20;
146     static constexpr int kDefaultHangTimeMillis   = 50;
147     static constexpr int kMaxGlitchEventsToSave   = 32;
148     static constexpr int kDefaultOutputSizeBursts = 2;
149 };
150 
151 #endif // CTS_NATIVE_AUDIO_ANALYZER_H
152