xref: /aosp_15_r20/cts/apps/CtsVerifier/jni/audio_loopback/NativeAudioAnalyzer.h (revision b7c941bb3fa97aba169d73cee0bed2de8ac964bf)
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