xref: /aosp_15_r20/cts/apps/CtsVerifier/jni/audio_loopback/NativeAudioAnalyzer.h (revision b7c941bb3fa97aba169d73cee0bed2de8ac964bf)
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/LatencyAnalyzer.h"
37 
38 class NativeAudioAnalyzer {
39 public:
40 
41     /**
42      * Open the audio input and output streams.
43      * @return AAUDIO_OK or negative error
44      */
45     aaudio_result_t openAudio(int inputDeviceId, int outputDeviceId);
46 
47     /**
48      * Start the audio input and output streams.
49      * @return AAUDIO_OK or negative error
50      */
51     aaudio_result_t startAudio();
52 
53     /**
54      * Stop the audio input and output streams.
55      * @return AAUDIO_OK or negative error
56      */
57     aaudio_result_t stopAudio();
58 
59     /**
60      * Close the audio input and output streams.
61      * @return AAUDIO_OK or negative error
62      */
63     aaudio_result_t closeAudio();
64 
65     /**
66      * @return true if enough audio input has been recorded
67      */
68     bool isRecordingComplete();
69 
70     /**
71      * Analyze the input and measure the latency between output and input.
72      * @return AAUDIO_OK or negative error
73      */
74     int analyze();
75 
76     /**
77      * @return the measured latency in milliseconds
78      */
79     double getLatencyMillis();
80 
81     /**
82      * @return the sample rate (in Hz) used for the measurement signal
83      */
84     int getSampleRate();
85 
86     /**
87      * The confidence is based on a normalized correlation.
88      * It ranges from 0.0 to 1.0. Higher is better.
89      *
90      * @return the confidence in the latency result
91      */
92     double getConfidence();
93 
94     // These are the same as in NativeAnalyzerThread.java and need to stay in sync.
95     static const uint32_t NUM_STREAM_TYPES = 2;
96     static const uint32_t STREAM_INPUT = 0;
97     static const uint32_t STREAM_OUTPUT = 1;
98 
99     /**
100      * Returns true if the hardware supports 24 bit audio.
101      */
102     bool has24BitHardwareSupport();
103 
104     /**
105      * Gets the hardware format.
106      */
107     int getHardwareFormat();
108 
109     /**
110      * @param streamId One of STREAM_INPUT or STREAM_OUTPUT
111      * @return true if the specified stream was opened in low-latency mode.
112      */
isLowLatencyStream(int streamId)113     bool isLowLatencyStream(int streamId) {
114         if (streamId != STREAM_OUTPUT && streamId != STREAM_INPUT) {
115             return -1;
116         }
117         return mIsLowLatencyStream[streamId];
118     }
119 
120     /**
121      * @param streamId One of STREAM_INPUT or STREAM_OUTPUT
122      * @return The burst size in frames of the specified stream.
123      */
getFramesPerBurst(int streamId)124     int32_t getFramesPerBurst(int streamId) {
125         if (streamId != STREAM_OUTPUT && streamId != STREAM_INPUT) {
126             return -1;
127         }
128         return mBurstFrames[streamId];
129     }
130 
131     /**
132      * @param streamId One of STREAM_INPUT or STREAM_OUTPUT
133      * @return The capacity in frames of the specified stream.
134      */
getCapacityFrames(int streamId)135     int32_t getCapacityFrames(int streamId) {
136         if (streamId != STREAM_OUTPUT && streamId != STREAM_INPUT) {
137             return -1;
138         }
139         return mCapacityFrames[streamId];
140     }
141 
142     /**
143      * @param streamId One of STREAM_INPUT or STREAM_OUTPUT
144      * @return true if the specified stream was opened as a MMAP stream.
145      */
isMMapStream(int streamId)146     bool isMMapStream(int streamId) {
147         if (streamId != STREAM_OUTPUT && streamId != STREAM_INPUT) {
148             return -1;
149         }
150         return mIsMMap[streamId];
151     }
152 
getError()153     aaudio_result_t getError() {
154         return mInputError ? mInputError : mOutputError;
155     }
156 
157     double measureTimestampLatencyMillis();
158 
159     AAudioStream      *mInputStream = nullptr;
160     AAudioStream      *mOutputStream = nullptr;
161     aaudio_format_t    mActualInputFormat = AAUDIO_FORMAT_INVALID;
162     int16_t           *mInputShortData = nullptr;
163     float             *mInputFloatData = nullptr;
164 
165     int32_t            mOutputSampleRate = 0;
166 
167     aaudio_result_t    mInputError = AAUDIO_OK;
168     aaudio_result_t    mOutputError = AAUDIO_OK;
169 
170 aaudio_data_callback_result_t dataCallbackProc(
171         void *audioData,
172         int32_t numFrames);
173 
174 private:
175 
176     int32_t readFormattedData(int32_t numFrames);
177 
178     bool has24BitSupport(aaudio_format_t format);
179 
180     WhiteNoiseLatencyAnalyzer mWhiteNoiseLatencyAnalyzer;
181     LoopbackProcessor   *mLoopbackProcessor;
182 
183     int32_t            mInputFramesMaximum = 0;
184     int32_t            mActualInputChannelCount = 0;
185     int32_t            mActualOutputChannelCount = 0;
186     int32_t            mNumCallbacksToDrain = kNumCallbacksToDrain;
187     int32_t            mNumCallbacksToNotRead = kNumCallbacksToNotRead;
188     int32_t            mNumCallbacksToDiscard = kNumCallbacksToDiscard;
189     int32_t            mMinNumFrames = INT32_MAX;
190     int32_t            mMaxNumFrames = 0;
191     int32_t            mInsufficientReadCount = 0;
192     int32_t            mInsufficientReadFrames = 0;
193     int32_t            mFramesReadTotal = 0;
194     int32_t            mFramesWrittenTotal = 0;
195     bool               mIsDone = false;
196     bool               mHas24BitHardwareSupport = false;
197     int32_t            mHardwareFormat = 0;
198 
199     int32_t            mBurstFrames[NUM_STREAM_TYPES] = {-1, -1};
200     int32_t            mCapacityFrames[NUM_STREAM_TYPES] = {-1, -1};
201     bool               mIsLowLatencyStream[NUM_STREAM_TYPES] = {false, false};
202     bool               mIsMMap[NUM_STREAM_TYPES] = {false, false};
203 
204     int32_t            mOutputDeviceId = 0;
205     int32_t            mInputDeviceId = 0;
206 
207     std::atomic<bool> mWriteReadDeltaValid{false};
208     std::atomic<int64_t> mWriteReadDelta{0};
209 
210     static constexpr int kLogPeriodMillis         = 1000;
211     static constexpr int kNumInputChannels        = 1;
212     static constexpr int kNumCallbacksToDrain     = 20;
213     static constexpr int kNumCallbacksToNotRead   = 0; // let input fill back up
214     static constexpr int kNumCallbacksToDiscard   = 20;
215     static constexpr int kDefaultHangTimeMillis   = 50;
216     static constexpr int kMaxGlitchEventsToSave   = 32;
217     static constexpr int kDefaultOutputSizeBursts = 2;
218 };
219 
220 #endif // CTS_NATIVE_AUDIO_ANALYZER_H
221