--- /dev/null
+/*
+ * Copyright (C) 2010 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.
+ */
+
+// Wrapper to the native phone test signal processing library, which
+// exposes an interface suitable for calling via JNI.
+
+#include <stdlib.h>
+#include <jni.h>
+
+#include "GenerateSinusoid.h"
+#include "MeasureRms.h"
+#include "GlitchTest.h"
+#include "OverflowCheck.h"
+#include "CompareSpectra.h"
+#include "LinearityTest.h"
+
+typedef short *shortPtr;
+
+extern "C" {
+ JNIEXPORT jshortArray JNICALL
+ Java_com_android_cts_verifier_audioquality_Native_generateSinusoid(
+ JNIEnv *env, jobject obj,
+ jfloat freq, jfloat duration,
+ jfloat sampleRate, jfloat amplitude, jfloat ramp);
+ JNIEXPORT jfloatArray JNICALL
+ Java_com_android_cts_verifier_audioquality_Native_measureRms(
+ JNIEnv *env, jobject obj,
+ jshortArray jpcm, jfloat sampleRate, jfloat onsetThresh);
+ JNIEXPORT jfloatArray JNICALL
+ Java_com_android_cts_verifier_audioquality_Native_glitchTest(
+ JNIEnv *env, jobject obj,
+ jfloat sampleRate, jfloat stimFreq, jfloat onsetThresh,
+ jfloat dbSnrThresh, jshortArray jpcm);
+ JNIEXPORT jfloatArray JNICALL
+ Java_com_android_cts_verifier_audioquality_Native_overflowCheck(
+ JNIEnv *env, jobject obj,
+ jshortArray jpcm, jfloat sampleRate);
+ JNIEXPORT jfloatArray JNICALL
+ Java_com_android_cts_verifier_audioquality_Native_compareSpectra(
+ JNIEnv *env, jobject obj,
+ jshortArray jpcm, jshortArray jrefPcm, jfloat sampleRate);
+ JNIEXPORT jfloat JNICALL
+ Java_com_android_cts_verifier_audioquality_Native_linearityTest(
+ JNIEnv *env, jobject obj,
+ jobjectArray jpcms,
+ jfloat sampleRate, jfloat dbStepSize, jint referenceStim);
+};
+
+/* Returns an array of sinusoidal samples.
+ If the arguments are invalid, returns an empty array. */
+JNIEXPORT jshortArray JNICALL
+ Java_com_android_cts_verifier_audioquality_Native_generateSinusoid(
+ JNIEnv *env, jobject obj,
+ jfloat freq, jfloat duration,
+ jfloat sampleRate, jfloat amplitude, jfloat ramp) {
+ short *wave = NULL;
+ int numSamples = 0;
+
+ generateSinusoid(freq, duration, sampleRate, amplitude, ramp,
+ &numSamples, &wave);
+
+ jshortArray ja;
+ if (!numSamples) {
+ ja = env->NewShortArray(0);
+ } else {
+ ja = env->NewShortArray(numSamples);
+ env->SetShortArrayRegion(ja, 0, numSamples, wave);
+ delete[] wave;
+ }
+ return ja;
+}
+
+/* Returns an array of four floats.
+ ret[0] = RMS
+ ret[1] = standard deviation of the RMS
+ ret[2] = non-silent region duration
+ ret[3] = mean value
+*/
+JNIEXPORT jfloatArray JNICALL
+ Java_com_android_cts_verifier_audioquality_Native_measureRms(
+ JNIEnv *env, jobject obj,
+ jshortArray jpcm, jfloat sampleRate, jfloat onsetThresh) {
+ float ret[4];
+ ret[0] = ret[1] = ret[2] = ret[3] = -1.0;
+ int numSamples = env->GetArrayLength(jpcm);
+ short *pcm = new short[numSamples];
+ env->GetShortArrayRegion(jpcm, 0, numSamples, pcm);
+
+ measureRms(pcm, numSamples, sampleRate, onsetThresh, ret, ret + 1,
+ ret + 3, ret + 2);
+
+ jfloatArray ja = env->NewFloatArray(4);
+ env->SetFloatArrayRegion(ja, 0, 4, ret);
+ return ja;
+}
+
+/* Returns an array of three floats.
+ ret[0] = #bad frames
+ ret[1] = error code
+ ret[2] = duration
+ Error code = 1 for success,
+ -1 if initialization failed,
+ -2 if insufficient samples
+ -3 if tone signal onset not found
+ -4 if tone signal end not found
+*/
+JNIEXPORT jfloatArray JNICALL
+ Java_com_android_cts_verifier_audioquality_Native_glitchTest(
+ JNIEnv *env, jobject obj,
+ jfloat sampleRate, jfloat stimFreq, jfloat onsetThresh,
+ jfloat dbSnrThresh, jshortArray jpcm) {
+ float ret[3];
+ int numSamples = env->GetArrayLength(jpcm);
+ short *pcm = new short[numSamples];
+ env->GetShortArrayRegion(jpcm, 0, numSamples, pcm);
+
+ GlitchTest gt;
+ gt.init(sampleRate, stimFreq, onsetThresh, dbSnrThresh);
+ float duration = -1.0;
+ int badFrames = -1;
+ int success = gt.checkToneSnr(pcm, numSamples, &duration, &badFrames);
+ ret[0] = badFrames;
+ ret[1] = success;
+ ret[2] = duration;
+ jfloatArray ja = env->NewFloatArray(3);
+ env->SetFloatArrayRegion(ja, 0, 3, ret);
+ return ja;
+}
+
+/* Returns an array of seven floats.
+ ret[0] = num deltas
+ ret[1] = error code
+ ret[2] = duration
+ ret[3] = onset
+ ret[4] = offset
+ ret[5] = max peak
+ ret[6] = min peak
+ Error code = 1 for success, -1 for failure. */
+JNIEXPORT jfloatArray JNICALL
+ Java_com_android_cts_verifier_audioquality_Native_overflowCheck(
+ JNIEnv *env, jobject obj,
+ jshortArray jpcm, jfloat sampleRate) {
+ float ret[7];
+ int numSamples = env->GetArrayLength(jpcm);
+ short *pcm = new short[numSamples];
+ env->GetShortArrayRegion(jpcm, 0, numSamples, pcm);
+
+ float duration = -1.0;
+ int numDeltas = -1, onset = -1, offset = -1;
+ int maxPeak = 0, minPeak = 0;
+ int success = overflowCheck(pcm, numSamples, sampleRate,
+ &duration, &numDeltas, &onset, &offset, &maxPeak, &minPeak);
+ ret[0] = numDeltas;
+ ret[1] = success ? 1 : -1;
+ ret[2] = duration;
+ ret[3] = onset;
+ ret[4] = offset;
+ ret[5] = maxPeak;
+ ret[6] = minPeak;
+ jfloatArray ja = env->NewFloatArray(7);
+ env->SetFloatArrayRegion(ja, 0, 7, ret);
+ return ja;
+}
+
+/* Returns an array of three floats.
+ ret[0] = max deviation,
+ ret[1] = error code,
+ ret[2] = rms deviation.
+ Error code = 1 for success, -1 for failure. */
+JNIEXPORT jfloatArray JNICALL
+ Java_com_android_cts_verifier_audioquality_Native_compareSpectra(
+ JNIEnv *env, jobject obj,
+ jshortArray jpcm, jshortArray jrefPcm, jfloat sampleRate) {
+ float ret[3];
+ int numSamples = env->GetArrayLength(jpcm);
+ short *pcm = new short[numSamples];
+ env->GetShortArrayRegion(jpcm, 0, numSamples, pcm);
+ int nRefSamples = env->GetArrayLength(jrefPcm);
+ short *refPcm = new short[nRefSamples];
+ env->GetShortArrayRegion(jrefPcm, 0, nRefSamples, refPcm);
+
+ float maxDeviation = -1.0, rmsDeviation = -1.0;
+ int success = compareSpectra(pcm, numSamples, refPcm, nRefSamples,
+ sampleRate, &maxDeviation, &rmsDeviation);
+ ret[1] = success ? 1 : -1;
+
+ ret[0] = maxDeviation;
+ ret[2] = rmsDeviation;
+ jfloatArray ja = env->NewFloatArray(3);
+ env->SetFloatArrayRegion(ja, 0, 3, ret);
+ return ja;
+}
+
+/* Return maximum deviation from linearity in dB.
+ On failure returns:
+ -1.0 The input signals or sample counts are missing.
+ -2.0 The number of input signals is < 2.
+ -3.0 The specified sample rate is <= 4000.0
+ -4.0 The dB step size for the increase in stimulus level is <= 0.0
+ -5.0 The specified reverence stimulus number is out of range.
+ -6.0 One or more of the stimuli is too short in duration.
+*/
+JNIEXPORT jfloat JNICALL
+ Java_com_android_cts_verifier_audioquality_Native_linearityTest(
+ JNIEnv *env, jobject obj,
+ jobjectArray jpcms,
+ jfloat sampleRate, jfloat dbStepSize, jint referenceStim) {
+ int numSignals = env->GetArrayLength(jpcms);
+ int *sampleCounts = new int[numSignals];
+ short **pcms = new shortPtr[numSignals];
+ jshortArray ja;
+ for (int i = 0; i < numSignals; i++) {
+ ja = (jshortArray) env->GetObjectArrayElement(jpcms, i);
+ sampleCounts[i] = env->GetArrayLength(ja);
+ pcms[i] = new short[sampleCounts[i]];
+ env->GetShortArrayRegion(ja, 0, sampleCounts[i], pcms[i]);
+ }
+
+ float maxDeviation = -1.0;
+ int ret = linearityTest(pcms, sampleCounts, numSignals,
+ sampleRate, dbStepSize, referenceStim, &maxDeviation);
+ delete[] sampleCounts;
+ for (int i = 0; i < numSignals; i++) {
+ delete[] pcms[i];
+ }
+ delete[] pcms;
+ if (ret < 1) return ret;
+
+ return maxDeviation;
+}