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 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 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 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 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 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 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 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 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 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 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 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 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 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