| /* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <android/log.h> |
| #include "sles.h" |
| #include "jni_sles.h" |
| #include <stdio.h> |
| |
| |
| JNIEXPORT jlong JNICALL 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) { |
| |
| sles_data * pSles = NULL; |
| |
| char* byteBufferPtr = (*env)->GetDirectBufferAddress(env, byteBuffer); |
| int byteBufferLength = (*env)->GetDirectBufferCapacity(env, byteBuffer); |
| |
| short* loopbackToneArray = (*env)->GetShortArrayElements(env, loopbackTone, 0); |
| |
| if (slesInit(&pSles, samplingRate, frameCount, micSource, |
| performanceMode, |
| testType, frequency1, byteBufferPtr, byteBufferLength, |
| loopbackToneArray, maxRecordedLateCallbacks, ignoreFirstFrames) != SLES_FAIL) { |
| return (long) pSles; |
| } |
| |
| // FIXME This should be stored as a (long) field in the object, |
| // so that incorrect Java code could not synthesize a bad sles pointer. |
| return 0; |
| } |
| |
| |
| JNIEXPORT jint JNICALL Java_org_drrickorang_loopback_NativeAudioThread_slesProcessNext |
| (JNIEnv *env __unused, jobject obj __unused, jlong sles, jdoubleArray samplesArray, jlong offset) { |
| sles_data * pSles = (sles_data*) (size_t) sles; |
| |
| long maxSamples = (*env)->GetArrayLength(env, samplesArray); |
| double *pSamples = (*env)->GetDoubleArrayElements(env, samplesArray, 0); |
| |
| long availableSamples = maxSamples-offset; |
| double *pCurrentSample = pSamples+offset; |
| |
| SLES_PRINTF("jni slesProcessNext pSles:%p, currentSample %p, availableSamples %ld ", |
| pSles, pCurrentSample, availableSamples); |
| |
| int samplesRead = slesProcessNext(pSles, pCurrentSample, availableSamples); |
| return samplesRead; |
| } |
| |
| |
| JNIEXPORT jint JNICALL Java_org_drrickorang_loopback_NativeAudioThread_slesDestroy |
| (JNIEnv *env __unused, jobject obj __unused, jlong sles) { |
| sles_data * pSles = (sles_data*) (size_t) sles; |
| int status = slesDestroy(&pSles); |
| return status; |
| } |
| |
| |
| JNIEXPORT jintArray JNICALL |
| Java_org_drrickorang_loopback_NativeAudioThread_slesGetRecorderBufferPeriod |
| (JNIEnv *env, jobject obj __unused, jlong sles) { |
| sles_data * pSles = (sles_data*) (size_t) sles; |
| int* recorderBufferPeriod = slesGetRecorderBufferPeriod(pSles); |
| |
| // get the length = RANGE |
| jintArray result = (*env)->NewIntArray(env, RANGE); |
| (*env)->SetIntArrayRegion(env, result, 0, RANGE, recorderBufferPeriod); |
| |
| return result; |
| } |
| |
| |
| JNIEXPORT jint JNICALL |
| Java_org_drrickorang_loopback_NativeAudioThread_slesGetRecorderMaxBufferPeriod |
| (JNIEnv *env __unused, jobject obj __unused, jlong sles) { |
| sles_data * pSles = (sles_data*) (size_t) sles; |
| int recorderMaxBufferPeriod = slesGetRecorderMaxBufferPeriod(pSles); |
| |
| return recorderMaxBufferPeriod; |
| } |
| |
| |
| JNIEXPORT jdouble JNICALL |
| Java_org_drrickorang_loopback_NativeAudioThread_slesGetRecorderVarianceBufferPeriod |
| (JNIEnv *env __unused, jobject obj __unused, jlong sles) { |
| sles_data *pSles = (sles_data *) (size_t) sles; |
| int64_t result = slesGetRecorderVarianceBufferPeriod(pSles); |
| // variance has units ns^2 so we have to square the conversion factor |
| double scaled = (double) result / ((double) NANOS_PER_MILLI * (double) NANOS_PER_MILLI); |
| return scaled; |
| } |
| |
| |
| JNIEXPORT jintArray |
| JNICALL Java_org_drrickorang_loopback_NativeAudioThread_slesGetPlayerBufferPeriod |
| (JNIEnv *env __unused, jobject obj __unused, jlong sles) { |
| sles_data * pSles = (sles_data*) (size_t) sles; |
| int* playerBufferPeriod = slesGetPlayerBufferPeriod(pSles); |
| |
| jintArray result = (*env)->NewIntArray(env, RANGE); |
| (*env)->SetIntArrayRegion(env, result, 0, RANGE, playerBufferPeriod); |
| |
| return result; |
| } |
| |
| |
| JNIEXPORT jint JNICALL |
| Java_org_drrickorang_loopback_NativeAudioThread_slesGetPlayerMaxBufferPeriod |
| (JNIEnv *env __unused, jobject obj __unused, jlong sles) { |
| sles_data * pSles = (sles_data*) (size_t) sles; |
| int playerMaxBufferPeriod = slesGetPlayerMaxBufferPeriod(pSles); |
| |
| return playerMaxBufferPeriod; |
| } |
| |
| |
| JNIEXPORT jdouble JNICALL |
| Java_org_drrickorang_loopback_NativeAudioThread_slesGetPlayerVarianceBufferPeriod |
| (JNIEnv *env __unused, jobject obj __unused, jlong sles) { |
| sles_data *pSles = (sles_data *) (size_t) sles; |
| int64_t result = slesGetPlayerVarianceBufferPeriod(pSles); |
| // variance has units ns^2 so we have to square the conversion factor |
| double scaled = (double) result / ((double) NANOS_PER_MILLI * (double) NANOS_PER_MILLI); |
| return scaled; |
| } |
| |
| |
| jobject getCallbackTimes(JNIEnv *env, callbackTimeStamps *callbacks, short expectedBufferPeriod){ |
| jintArray timeStamps = (*env)->NewIntArray(env, callbacks->index); |
| (*env)->SetIntArrayRegion(env, timeStamps, 0, callbacks->index, callbacks->timeStampsMs); |
| |
| jshortArray callbackLengths = (*env)->NewShortArray(env, callbacks->index); |
| (*env)->SetShortArrayRegion(env, callbackLengths, 0, callbacks->index, |
| callbacks->callbackDurations); |
| |
| jclass cls = (*env)->FindClass(env, "org/drrickorang/loopback/BufferCallbackTimes"); |
| jmethodID methodID = (*env)->GetMethodID(env, cls, "<init>", "([I[SZS)V"); |
| jobject callbackTimes=(*env)->NewObject(env,cls, methodID, timeStamps, callbackLengths, |
| callbacks->exceededCapacity, expectedBufferPeriod); |
| return callbackTimes; |
| } |
| |
| JNIEXPORT jobject |
| JNICALL Java_org_drrickorang_loopback_NativeAudioThread_slesGetPlayerCallbackTimeStamps |
| (JNIEnv *env, jobject obj __unused, jlong sles) { |
| sles_data * pSles = (sles_data*) (size_t) sles; |
| return getCallbackTimes(env, &(pSles->playerTimeStamps), pSles->expectedBufferPeriod); |
| } |
| |
| JNIEXPORT jobject |
| JNICALL Java_org_drrickorang_loopback_NativeAudioThread_slesGetRecorderCallbackTimeStamps |
| (JNIEnv *env, jobject obj __unused, jlong sles) { |
| sles_data * pSles = (sles_data*) (size_t) sles; |
| return getCallbackTimes(env, &(pSles->recorderTimeStamps), pSles->expectedBufferPeriod); |
| } |
| |
| JNIEXPORT jint |
| JNICALL Java_org_drrickorang_loopback_NativeAudioThread_slesGetCaptureRank |
| (JNIEnv *env __unused, jobject obj __unused, jlong sles) { |
| sles_data * pSles = (sles_data*) (size_t) sles; |
| return slesGetCaptureRank(pSles); |
| } |