Home | History | Annotate | Download | only in audioquality
      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