1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * 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, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 17 // Wrapper to the native phone test signal processing library, which 18 // exposes an interface suitable for calling via JNI. 19 20 #include <stdlib.h> 21 #include <jni.h> 22 23 #include "GenerateSinusoid.h" 24 #include "MeasureRms.h" 25 #include "GlitchTest.h" 26 #include "OverflowCheck.h" 27 #include "CompareSpectra.h" 28 #include "LinearityTest.h" 29 30 typedef short *shortPtr; 31 32 extern "C" { 33 JNIEXPORT jshortArray JNICALL 34 Java_com_android_cts_verifier_audioquality_Native_generateSinusoid( 35 JNIEnv *env, jobject obj, 36 jfloat freq, jfloat duration, 37 jfloat sampleRate, jfloat amplitude, jfloat ramp); 38 JNIEXPORT jfloatArray JNICALL 39 Java_com_android_cts_verifier_audioquality_Native_measureRms( 40 JNIEnv *env, jobject obj, 41 jshortArray jpcm, jfloat sampleRate, jfloat onsetThresh); 42 JNIEXPORT jfloatArray JNICALL 43 Java_com_android_cts_verifier_audioquality_Native_glitchTest( 44 JNIEnv *env, jobject obj, 45 jfloat sampleRate, jfloat stimFreq, jfloat onsetThresh, 46 jfloat dbSnrThresh, jshortArray jpcm); 47 JNIEXPORT jfloatArray JNICALL 48 Java_com_android_cts_verifier_audioquality_Native_overflowCheck( 49 JNIEnv *env, jobject obj, 50 jshortArray jpcm, jfloat sampleRate); 51 JNIEXPORT jfloatArray JNICALL 52 Java_com_android_cts_verifier_audioquality_Native_compareSpectra( 53 JNIEnv *env, jobject obj, 54 jshortArray jpcm, jshortArray jrefPcm, jfloat sampleRate); 55 JNIEXPORT jfloat JNICALL 56 Java_com_android_cts_verifier_audioquality_Native_linearityTest( 57 JNIEnv *env, jobject obj, 58 jobjectArray jpcms, 59 jfloat sampleRate, jfloat dbStepSize, jint referenceStim); 60 }; 61 62 /* Returns an array of sinusoidal samples. 63 If the arguments are invalid, returns an empty array. */ 64 JNIEXPORT jshortArray JNICALL 65 Java_com_android_cts_verifier_audioquality_Native_generateSinusoid( 66 JNIEnv *env, jobject obj, 67 jfloat freq, jfloat duration, 68 jfloat sampleRate, jfloat amplitude, jfloat ramp) { 69 short *wave = NULL; 70 int numSamples = 0; 71 72 generateSinusoid(freq, duration, sampleRate, amplitude, ramp, 73 &numSamples, &wave); 74 75 jshortArray ja; 76 if (!numSamples) { 77 ja = env->NewShortArray(0); 78 } else { 79 ja = env->NewShortArray(numSamples); 80 env->SetShortArrayRegion(ja, 0, numSamples, wave); 81 delete[] wave; 82 } 83 return ja; 84 } 85 86 /* Returns an array of four floats. 87 ret[0] = RMS 88 ret[1] = standard deviation of the RMS 89 ret[2] = non-silent region duration 90 ret[3] = mean value 91 */ 92 JNIEXPORT jfloatArray JNICALL 93 Java_com_android_cts_verifier_audioquality_Native_measureRms( 94 JNIEnv *env, jobject obj, 95 jshortArray jpcm, jfloat sampleRate, jfloat onsetThresh) { 96 float ret[4]; 97 ret[0] = ret[1] = ret[2] = ret[3] = -1.0; 98 int numSamples = env->GetArrayLength(jpcm); 99 short *pcm = new short[numSamples]; 100 env->GetShortArrayRegion(jpcm, 0, numSamples, pcm); 101 102 measureRms(pcm, numSamples, sampleRate, onsetThresh, ret, ret + 1, 103 ret + 3, ret + 2); 104 105 jfloatArray ja = env->NewFloatArray(4); 106 env->SetFloatArrayRegion(ja, 0, 4, ret); 107 return ja; 108 } 109 110 /* Returns an array of three floats. 111 ret[0] = #bad frames 112 ret[1] = error code 113 ret[2] = duration 114 Error code = 1 for success, 115 -1 if initialization failed, 116 -2 if insufficient samples 117 -3 if tone signal onset not found 118 -4 if tone signal end not found 119 */ 120 JNIEXPORT jfloatArray JNICALL 121 Java_com_android_cts_verifier_audioquality_Native_glitchTest( 122 JNIEnv *env, jobject obj, 123 jfloat sampleRate, jfloat stimFreq, jfloat onsetThresh, 124 jfloat dbSnrThresh, jshortArray jpcm) { 125 float ret[3]; 126 int numSamples = env->GetArrayLength(jpcm); 127 short *pcm = new short[numSamples]; 128 env->GetShortArrayRegion(jpcm, 0, numSamples, pcm); 129 130 GlitchTest gt; 131 gt.init(sampleRate, stimFreq, onsetThresh, dbSnrThresh); 132 float duration = -1.0; 133 int badFrames = -1; 134 int success = gt.checkToneSnr(pcm, numSamples, &duration, &badFrames); 135 ret[0] = badFrames; 136 ret[1] = success; 137 ret[2] = duration; 138 jfloatArray ja = env->NewFloatArray(3); 139 env->SetFloatArrayRegion(ja, 0, 3, ret); 140 return ja; 141 } 142 143 /* Returns an array of seven floats. 144 ret[0] = num deltas 145 ret[1] = error code 146 ret[2] = duration 147 ret[3] = onset 148 ret[4] = offset 149 ret[5] = max peak 150 ret[6] = min peak 151 Error code = 1 for success, -1 for failure. */ 152 JNIEXPORT jfloatArray JNICALL 153 Java_com_android_cts_verifier_audioquality_Native_overflowCheck( 154 JNIEnv *env, jobject obj, 155 jshortArray jpcm, jfloat sampleRate) { 156 float ret[7]; 157 int numSamples = env->GetArrayLength(jpcm); 158 short *pcm = new short[numSamples]; 159 env->GetShortArrayRegion(jpcm, 0, numSamples, pcm); 160 161 float duration = -1.0; 162 int numDeltas = -1, onset = -1, offset = -1; 163 int maxPeak = 0, minPeak = 0; 164 int success = overflowCheck(pcm, numSamples, sampleRate, 165 &duration, &numDeltas, &onset, &offset, &maxPeak, &minPeak); 166 ret[0] = numDeltas; 167 ret[1] = success ? 1 : -1; 168 ret[2] = duration; 169 ret[3] = onset; 170 ret[4] = offset; 171 ret[5] = maxPeak; 172 ret[6] = minPeak; 173 jfloatArray ja = env->NewFloatArray(7); 174 env->SetFloatArrayRegion(ja, 0, 7, ret); 175 return ja; 176 } 177 178 /* Returns an array of three floats. 179 ret[0] = max deviation, 180 ret[1] = error code, 181 ret[2] = rms deviation. 182 Error code = 1 for success, -1 for failure. */ 183 JNIEXPORT jfloatArray JNICALL 184 Java_com_android_cts_verifier_audioquality_Native_compareSpectra( 185 JNIEnv *env, jobject obj, 186 jshortArray jpcm, jshortArray jrefPcm, jfloat sampleRate) { 187 float ret[3]; 188 int numSamples = env->GetArrayLength(jpcm); 189 short *pcm = new short[numSamples]; 190 env->GetShortArrayRegion(jpcm, 0, numSamples, pcm); 191 int nRefSamples = env->GetArrayLength(jrefPcm); 192 short *refPcm = new short[nRefSamples]; 193 env->GetShortArrayRegion(jrefPcm, 0, nRefSamples, refPcm); 194 195 float maxDeviation = -1.0, rmsDeviation = -1.0; 196 int success = compareSpectra(pcm, numSamples, refPcm, nRefSamples, 197 sampleRate, &maxDeviation, &rmsDeviation); 198 ret[1] = success ? 1 : -1; 199 200 ret[0] = maxDeviation; 201 ret[2] = rmsDeviation; 202 jfloatArray ja = env->NewFloatArray(3); 203 env->SetFloatArrayRegion(ja, 0, 3, ret); 204 return ja; 205 } 206 207 /* Return maximum deviation from linearity in dB. 208 On failure returns: 209 -1.0 The input signals or sample counts are missing. 210 -2.0 The number of input signals is < 2. 211 -3.0 The specified sample rate is <= 4000.0 212 -4.0 The dB step size for the increase in stimulus level is <= 0.0 213 -5.0 The specified reverence stimulus number is out of range. 214 -6.0 One or more of the stimuli is too short in duration. 215 */ 216 JNIEXPORT jfloat JNICALL 217 Java_com_android_cts_verifier_audioquality_Native_linearityTest( 218 JNIEnv *env, jobject obj, 219 jobjectArray jpcms, 220 jfloat sampleRate, jfloat dbStepSize, jint referenceStim) { 221 int numSignals = env->GetArrayLength(jpcms); 222 int *sampleCounts = new int[numSignals]; 223 short **pcms = new shortPtr[numSignals]; 224 jshortArray ja; 225 for (int i = 0; i < numSignals; i++) { 226 ja = (jshortArray) env->GetObjectArrayElement(jpcms, i); 227 sampleCounts[i] = env->GetArrayLength(ja); 228 pcms[i] = new short[sampleCounts[i]]; 229 env->GetShortArrayRegion(ja, 0, sampleCounts[i], pcms[i]); 230 } 231 232 float maxDeviation = -1.0; 233 int ret = linearityTest(pcms, sampleCounts, numSignals, 234 sampleRate, dbStepSize, referenceStim, &maxDeviation); 235 delete[] sampleCounts; 236 for (int i = 0; i < numSignals; i++) { 237 delete[] pcms[i]; 238 } 239 delete[] pcms; 240 if (ret < 1) return ret; 241 242 return maxDeviation; 243 } 244