xref: /aosp_15_r20/cts/apps/CtsVerifier/jni/megaaudio/recorder/OboeRecorder.cpp (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 #include <android/log.h>
17 
18 #include "OboeRecorder.h"
19 
20 #include "AudioSink.h"
21 
22 static const char * const TAG = "OboeRecorder(native)";
23 
24 using namespace oboe;
25 
26 constexpr int32_t kBufferSizeInBursts = 2; // Use 2 bursts as the buffer size (double buffer)
27 
OboeRecorder(AudioSink * sink,int32_t subtype)28 OboeRecorder::OboeRecorder(AudioSink* sink, int32_t subtype)
29         : Recorder(sink, subtype),
30           mInputPreset(-1)
31 {}
32 
33 //
34 // State
35 //
setupStream(int32_t channelCount,int32_t sampleRate,int32_t performanceMode,int32_t sharingMode,int32_t routeDeviceId,int32_t inputPreset)36 StreamBase::Result OboeRecorder::setupStream(int32_t channelCount, int32_t sampleRate,
37                         int32_t performanceMode, int32_t sharingMode, int32_t routeDeviceId,
38                         int32_t inputPreset)
39 {
40     //TODO much of this could be pulled up into OboeStream.
41 
42     std::lock_guard<std::mutex> lock(mStreamLock);
43 
44     oboe::Result result = oboe::Result::ErrorInternal;
45     if (mAudioStream != nullptr) {
46         __android_log_print(ANDROID_LOG_ERROR, TAG,
47                             "ERROR_INVALID_STATE - Stream Already Open");
48         return ERROR_INVALID_STATE;
49     } else {
50         mChannelCount = channelCount;
51         mSampleRate = sampleRate;
52         mRouteDeviceId = routeDeviceId;
53         mInputPreset = inputPreset;
54 
55         // Create an audio stream
56         AudioStreamBuilder builder;
57         builder.setChannelCount(mChannelCount);
58         builder.setSampleRate(mSampleRate);
59         builder.setCallback(this);
60         if (mInputPreset != DEFAULT_INPUT_NONE) {
61             builder.setInputPreset((enum InputPreset)mInputPreset);
62         }
63         builder.setPerformanceMode((PerformanceMode) performanceMode);
64         builder.setSharingMode((SharingMode) sharingMode);
65         builder.setSampleRateConversionQuality(SampleRateConversionQuality::None);
66         builder.setDirection(Direction::Input);
67 
68         if (mRouteDeviceId != -1) {
69             builder.setDeviceId(mRouteDeviceId);
70         }
71 
72         if (mSubtype == SUB_TYPE_OBOE_AAUDIO) {
73             builder.setAudioApi(AudioApi::AAudio);
74         } else if (mSubtype == SUB_TYPE_OBOE_OPENSL_ES) {
75             builder.setAudioApi(AudioApi::OpenSLES);
76         }
77 
78         result = builder.openStream(mAudioStream);
79         if (result != oboe::Result::OK){
80             __android_log_print(
81                     ANDROID_LOG_ERROR,
82                     TAG,
83                     "openStream failed. Error: %s", convertToText(result));
84         } else {
85             mBufferSizeInFrames = mAudioStream->getFramesPerBurst();
86             mAudioSink->init(mBufferSizeInFrames, mChannelCount);
87         }
88     }
89 
90     return OboeErrorToMegaAudioError(result);
91 }
92 
startStream()93 StreamBase::Result OboeRecorder::startStream() {
94     StreamBase::Result result = Recorder::startStream();
95     if (result == OK) {
96         mAudioSink->start();
97     }
98     return result;
99 }
100 
onAudioReady(oboe::AudioStream * audioStream,void * audioData,int numFrames)101 oboe::DataCallbackResult OboeRecorder::onAudioReady(
102         oboe::AudioStream *audioStream, void *audioData, int numFrames) {
103     mAudioSink->push((float*)audioData, numFrames, mChannelCount);
104     return oboe::DataCallbackResult::Continue;
105 }
106 
107 #include <jni.h>
108 
109 extern "C" {
110 JNIEXPORT jlong JNICALL
Java_org_hyphonate_megaaudio_recorder_OboeRecorder_allocNativeRecorder(JNIEnv * env,jobject thiz,jlong native_audio_sink,jint recorderSubtype)111 Java_org_hyphonate_megaaudio_recorder_OboeRecorder_allocNativeRecorder(JNIEnv *env, jobject thiz, jlong native_audio_sink, jint recorderSubtype) {
112     OboeRecorder* recorder = new OboeRecorder((AudioSink*)native_audio_sink, recorderSubtype);
113     return (jlong)recorder;
114 }
115 
116 JNIEXPORT jint JNICALL
Java_org_hyphonate_megaaudio_recorder_OboeRecorder_getBufferFrameCountN(JNIEnv * env,jobject thiz,jlong native_recorder)117 Java_org_hyphonate_megaaudio_recorder_OboeRecorder_getBufferFrameCountN(
118         JNIEnv *env, jobject thiz, jlong native_recorder) {
119     return ((OboeRecorder*)native_recorder)->getNumBufferFrames();
120 }
121 
122 JNIEXPORT void JNICALL
Java_org_hyphonate_megaaudio_recorder_OboeRecorder_setInputPresetN(JNIEnv * env,jobject thiz,jlong native_recorder,jint input_preset)123 Java_org_hyphonate_megaaudio_recorder_OboeRecorder_setInputPresetN(
124         JNIEnv *env, jobject thiz, jlong native_recorder, jint input_preset) {
125     ((OboeRecorder*)native_recorder)->setInputPreset(input_preset);
126 }
127 
128 JNIEXPORT jint JNICALL
Java_org_hyphonate_megaaudio_recorder_OboeRecorder_setupStreamN(JNIEnv * env,jobject thiz,jlong native_recorder,jint channel_count,jint sample_rate,jint performanceMode,jint sharingMode,jint route_device_id,jint input_preset)129 Java_org_hyphonate_megaaudio_recorder_OboeRecorder_setupStreamN(
130         JNIEnv *env, jobject thiz, jlong native_recorder, jint channel_count, jint sample_rate,
131         jint performanceMode, jint sharingMode, jint route_device_id, jint input_preset) {
132     return ((OboeRecorder*)native_recorder)->setupStream(
133             channel_count, sample_rate, performanceMode, sharingMode, route_device_id,
134             input_preset);
135 }
136 
137 JNIEXPORT jint JNICALL
Java_org_hyphonate_megaaudio_recorder_OboeRecorder_teardownStreamN(JNIEnv * env,jobject thiz,jlong native_recorder)138 Java_org_hyphonate_megaaudio_recorder_OboeRecorder_teardownStreamN(
139         JNIEnv *env, jobject thiz, jlong native_recorder) {
140     return ((OboeRecorder*)native_recorder)->teardownStream();
141 }
142 
143 JNIEXPORT jint JNICALL
Java_org_hyphonate_megaaudio_recorder_OboeRecorder_startStreamN(JNIEnv * env,jobject thiz,jlong native_recorder,jint recorder_subtype)144 Java_org_hyphonate_megaaudio_recorder_OboeRecorder_startStreamN(
145         JNIEnv *env, jobject thiz, jlong native_recorder, jint recorder_subtype) {
146     return ((OboeRecorder*)native_recorder)->startStream();
147 }
148 
149 JNIEXPORT jint JNICALL
Java_org_hyphonate_megaaudio_recorder_OboeRecorder_stopN(JNIEnv * env,jobject thiz,jlong native_recorder)150 Java_org_hyphonate_megaaudio_recorder_OboeRecorder_stopN(
151         JNIEnv *env, jobject thiz, jlong native_recorder) {
152     return ((OboeRecorder*)native_recorder)->stopStream();
153 }
154 
155 JNIEXPORT jboolean JNICALL
Java_org_hyphonate_megaaudio_recorder_OboeRecorder_isRecordingN(JNIEnv * env,jobject thiz,jlong native_recorder)156 Java_org_hyphonate_megaaudio_recorder_OboeRecorder_isRecordingN(
157         JNIEnv *env, jobject thiz, jlong native_recorder) {
158     OboeRecorder* nativeRecorder = ((OboeRecorder*)native_recorder);
159     return nativeRecorder->isRecording();
160 }
161 
162 JNIEXPORT jint JNICALL
Java_org_hyphonate_megaaudio_recorder_OboeRecorder_getNumBufferFramesN(JNIEnv * env,jobject thiz,jlong native_recorder)163 Java_org_hyphonate_megaaudio_recorder_OboeRecorder_getNumBufferFramesN(
164         JNIEnv *env, jobject thiz, jlong native_recorder) {
165     OboeRecorder* nativeRecorder = ((OboeRecorder*)native_recorder);
166     return nativeRecorder->getNumBufferFrames();
167 }
168 
169 extern "C"
170 JNIEXPORT jint JNICALL
Java_org_hyphonate_megaaudio_recorder_OboeRecorder_getRoutedDeviceIdN(JNIEnv * env,jobject thiz,jlong native_recorder)171 Java_org_hyphonate_megaaudio_recorder_OboeRecorder_getRoutedDeviceIdN(
172         JNIEnv *env, jobject thiz, jlong native_recorder) {
173     return ((OboeRecorder*)native_recorder)->getRoutedDeviceId();
174 }
175 
176 JNIEXPORT jint JNICALL
Java_org_hyphonate_megaaudio_recorder_OboeRecorder_getSharingModeN(JNIEnv * env,jobject thiz,jlong native_recorder)177 Java_org_hyphonate_megaaudio_recorder_OboeRecorder_getSharingModeN(
178         JNIEnv *env, jobject thiz, jlong native_recorder) {
179     return ((OboeRecorder*)native_recorder)->getSharingMode();
180 }
181 
182 JNIEXPORT jint JNICALL
Java_org_hyphonate_megaaudio_recorder_OboeRecorder_getChannelCountN(JNIEnv * env,jobject thiz,jlong native_recorder)183 Java_org_hyphonate_megaaudio_recorder_OboeRecorder_getChannelCountN(
184         JNIEnv *env, jobject thiz, jlong native_recorder) {
185     return ((OboeRecorder*)native_recorder)->getChannelCount();
186 }
187 
188 JNIEXPORT jboolean JNICALL
Java_org_hyphonate_megaaudio_recorder_OboeRecorder_isMMapN(JNIEnv * env,jobject thiz,jlong native_recorder)189 Java_org_hyphonate_megaaudio_recorder_OboeRecorder_isMMapN(
190         JNIEnv *env, jobject thiz, jlong native_recorder) {
191     return ((OboeRecorder*)native_recorder)->isMMap();
192 }
193 
Java_org_hyphonate_megaaudio_recorder_OboeRecorder_getStreamStateN(JNIEnv * env,jobject thiz,jlong native_recorder)194 JNIEXPORT jint JNICALL Java_org_hyphonate_megaaudio_recorder_OboeRecorder_getStreamStateN(
195         JNIEnv *env, jobject thiz, jlong native_recorder) {
196     return (int)((OboeRecorder*)(native_recorder))->getState();
197 }
198 
199 JNIEXPORT jint JNICALL
Java_org_hyphonate_megaaudio_recorder_OboeRecorder_getLastErrorCallbackResultN(JNIEnv * env,jobject thiz,jlong native_recorder)200 Java_org_hyphonate_megaaudio_recorder_OboeRecorder_getLastErrorCallbackResultN(
201         JNIEnv *env, jobject thiz, jlong native_recorder) {
202     return (int)((OboeRecorder*)(native_recorder))->getLastErrorCallbackResult();
203 }
204 
205 }   // extern "C"
206