1 /*
2 * Copyright (C) 2015 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 #include <android/log.h>
18 #include "sles.h"
19 #include "jni_sles.h"
20 #include <stdio.h>
21
22
Java_org_drrickorang_loopback_NativeAudioThread_slesInit(JNIEnv * env,jobject obj __unused,jint samplingRate,jint frameCount,jint micSource,jint performanceMode,jint testType,jdouble frequency1,jobject byteBuffer,jshortArray loopbackTone,jint maxRecordedLateCallbacks,jint ignoreFirstFrames)23 JNIEXPORT jlong JNICALL Java_org_drrickorang_loopback_NativeAudioThread_slesInit
24 (JNIEnv *env, jobject obj __unused, jint samplingRate, jint frameCount, jint micSource,
25 jint performanceMode,
26 jint testType, jdouble frequency1, jobject byteBuffer, jshortArray loopbackTone,
27 jint maxRecordedLateCallbacks, jint ignoreFirstFrames) {
28
29 sles_data * pSles = NULL;
30
31 char* byteBufferPtr = (*env)->GetDirectBufferAddress(env, byteBuffer);
32 int byteBufferLength = (*env)->GetDirectBufferCapacity(env, byteBuffer);
33
34 short* loopbackToneArray = (*env)->GetShortArrayElements(env, loopbackTone, 0);
35
36 if (slesInit(&pSles, samplingRate, frameCount, micSource,
37 performanceMode,
38 testType, frequency1, byteBufferPtr, byteBufferLength,
39 loopbackToneArray, maxRecordedLateCallbacks, ignoreFirstFrames) != SLES_FAIL) {
40 return (long) pSles;
41 }
42
43 // FIXME This should be stored as a (long) field in the object,
44 // so that incorrect Java code could not synthesize a bad sles pointer.
45 return 0;
46 }
47
48
Java_org_drrickorang_loopback_NativeAudioThread_slesProcessNext(JNIEnv * env __unused,jobject obj __unused,jlong sles,jdoubleArray samplesArray,jlong offset)49 JNIEXPORT jint JNICALL Java_org_drrickorang_loopback_NativeAudioThread_slesProcessNext
50 (JNIEnv *env __unused, jobject obj __unused, jlong sles, jdoubleArray samplesArray, jlong offset) {
51 sles_data * pSles = (sles_data*) (size_t) sles;
52
53 long maxSamples = (*env)->GetArrayLength(env, samplesArray);
54 double *pSamples = (*env)->GetDoubleArrayElements(env, samplesArray, 0);
55
56 long availableSamples = maxSamples-offset;
57 double *pCurrentSample = pSamples+offset;
58
59 SLES_PRINTF("jni slesProcessNext pSles:%p, currentSample %p, availableSamples %ld ",
60 pSles, pCurrentSample, availableSamples);
61
62 int samplesRead = slesProcessNext(pSles, pCurrentSample, availableSamples);
63 return samplesRead;
64 }
65
66
Java_org_drrickorang_loopback_NativeAudioThread_slesDestroy(JNIEnv * env __unused,jobject obj __unused,jlong sles)67 JNIEXPORT jint JNICALL Java_org_drrickorang_loopback_NativeAudioThread_slesDestroy
68 (JNIEnv *env __unused, jobject obj __unused, jlong sles) {
69 sles_data * pSles = (sles_data*) (size_t) sles;
70 int status = slesDestroy(&pSles);
71 return status;
72 }
73
74
75 JNIEXPORT jintArray JNICALL
Java_org_drrickorang_loopback_NativeAudioThread_slesGetRecorderBufferPeriod(JNIEnv * env,jobject obj __unused,jlong sles)76 Java_org_drrickorang_loopback_NativeAudioThread_slesGetRecorderBufferPeriod
77 (JNIEnv *env, jobject obj __unused, jlong sles) {
78 sles_data * pSles = (sles_data*) (size_t) sles;
79 int* recorderBufferPeriod = slesGetRecorderBufferPeriod(pSles);
80
81 // get the length = RANGE
82 jintArray result = (*env)->NewIntArray(env, RANGE);
83 (*env)->SetIntArrayRegion(env, result, 0, RANGE, recorderBufferPeriod);
84
85 return result;
86 }
87
88
89 JNIEXPORT jint JNICALL
Java_org_drrickorang_loopback_NativeAudioThread_slesGetRecorderMaxBufferPeriod(JNIEnv * env __unused,jobject obj __unused,jlong sles)90 Java_org_drrickorang_loopback_NativeAudioThread_slesGetRecorderMaxBufferPeriod
91 (JNIEnv *env __unused, jobject obj __unused, jlong sles) {
92 sles_data * pSles = (sles_data*) (size_t) sles;
93 int recorderMaxBufferPeriod = slesGetRecorderMaxBufferPeriod(pSles);
94
95 return recorderMaxBufferPeriod;
96 }
97
98
99 JNIEXPORT jdouble JNICALL
Java_org_drrickorang_loopback_NativeAudioThread_slesGetRecorderVarianceBufferPeriod(JNIEnv * env __unused,jobject obj __unused,jlong sles)100 Java_org_drrickorang_loopback_NativeAudioThread_slesGetRecorderVarianceBufferPeriod
101 (JNIEnv *env __unused, jobject obj __unused, jlong sles) {
102 sles_data *pSles = (sles_data *) (size_t) sles;
103 int64_t result = slesGetRecorderVarianceBufferPeriod(pSles);
104 // variance has units ns^2 so we have to square the conversion factor
105 double scaled = (double) result / ((double) NANOS_PER_MILLI * (double) NANOS_PER_MILLI);
106 return scaled;
107 }
108
109
110 JNIEXPORT jintArray
Java_org_drrickorang_loopback_NativeAudioThread_slesGetPlayerBufferPeriod(JNIEnv * env __unused,jobject obj __unused,jlong sles)111 JNICALL Java_org_drrickorang_loopback_NativeAudioThread_slesGetPlayerBufferPeriod
112 (JNIEnv *env __unused, jobject obj __unused, jlong sles) {
113 sles_data * pSles = (sles_data*) (size_t) sles;
114 int* playerBufferPeriod = slesGetPlayerBufferPeriod(pSles);
115
116 jintArray result = (*env)->NewIntArray(env, RANGE);
117 (*env)->SetIntArrayRegion(env, result, 0, RANGE, playerBufferPeriod);
118
119 return result;
120 }
121
122
123 JNIEXPORT jint JNICALL
Java_org_drrickorang_loopback_NativeAudioThread_slesGetPlayerMaxBufferPeriod(JNIEnv * env __unused,jobject obj __unused,jlong sles)124 Java_org_drrickorang_loopback_NativeAudioThread_slesGetPlayerMaxBufferPeriod
125 (JNIEnv *env __unused, jobject obj __unused, jlong sles) {
126 sles_data * pSles = (sles_data*) (size_t) sles;
127 int playerMaxBufferPeriod = slesGetPlayerMaxBufferPeriod(pSles);
128
129 return playerMaxBufferPeriod;
130 }
131
132
133 JNIEXPORT jdouble JNICALL
Java_org_drrickorang_loopback_NativeAudioThread_slesGetPlayerVarianceBufferPeriod(JNIEnv * env __unused,jobject obj __unused,jlong sles)134 Java_org_drrickorang_loopback_NativeAudioThread_slesGetPlayerVarianceBufferPeriod
135 (JNIEnv *env __unused, jobject obj __unused, jlong sles) {
136 sles_data *pSles = (sles_data *) (size_t) sles;
137 int64_t result = slesGetPlayerVarianceBufferPeriod(pSles);
138 // variance has units ns^2 so we have to square the conversion factor
139 double scaled = (double) result / ((double) NANOS_PER_MILLI * (double) NANOS_PER_MILLI);
140 return scaled;
141 }
142
143
getCallbackTimes(JNIEnv * env,callbackTimeStamps * callbacks,short expectedBufferPeriod)144 jobject getCallbackTimes(JNIEnv *env, callbackTimeStamps *callbacks, short expectedBufferPeriod){
145 jintArray timeStamps = (*env)->NewIntArray(env, callbacks->index);
146 (*env)->SetIntArrayRegion(env, timeStamps, 0, callbacks->index, callbacks->timeStampsMs);
147
148 jshortArray callbackLengths = (*env)->NewShortArray(env, callbacks->index);
149 (*env)->SetShortArrayRegion(env, callbackLengths, 0, callbacks->index,
150 callbacks->callbackDurations);
151
152 jclass cls = (*env)->FindClass(env, "org/drrickorang/loopback/BufferCallbackTimes");
153 jmethodID methodID = (*env)->GetMethodID(env, cls, "<init>", "([I[SZS)V");
154 jobject callbackTimes=(*env)->NewObject(env,cls, methodID, timeStamps, callbackLengths,
155 callbacks->exceededCapacity, expectedBufferPeriod);
156 return callbackTimes;
157 }
158
159 JNIEXPORT jobject
Java_org_drrickorang_loopback_NativeAudioThread_slesGetPlayerCallbackTimeStamps(JNIEnv * env,jobject obj __unused,jlong sles)160 JNICALL Java_org_drrickorang_loopback_NativeAudioThread_slesGetPlayerCallbackTimeStamps
161 (JNIEnv *env, jobject obj __unused, jlong sles) {
162 sles_data * pSles = (sles_data*) (size_t) sles;
163 return getCallbackTimes(env, &(pSles->playerTimeStamps), pSles->expectedBufferPeriod);
164 }
165
166 JNIEXPORT jobject
Java_org_drrickorang_loopback_NativeAudioThread_slesGetRecorderCallbackTimeStamps(JNIEnv * env,jobject obj __unused,jlong sles)167 JNICALL Java_org_drrickorang_loopback_NativeAudioThread_slesGetRecorderCallbackTimeStamps
168 (JNIEnv *env, jobject obj __unused, jlong sles) {
169 sles_data * pSles = (sles_data*) (size_t) sles;
170 return getCallbackTimes(env, &(pSles->recorderTimeStamps), pSles->expectedBufferPeriod);
171 }
172
173 JNIEXPORT jint
Java_org_drrickorang_loopback_NativeAudioThread_slesGetCaptureRank(JNIEnv * env __unused,jobject obj __unused,jlong sles)174 JNICALL Java_org_drrickorang_loopback_NativeAudioThread_slesGetCaptureRank
175 (JNIEnv *env __unused, jobject obj __unused, jlong sles) {
176 sles_data * pSles = (sles_data*) (size_t) sles;
177 return slesGetCaptureRank(pSles);
178 }
179