Remove Audio Quality Verifier
Bug 6265552
The test is being rewritten to be more stable.
Change-Id: I5729b167a3dcb92936ba8146019a9f52d77e7f21
diff --git a/apps/CtsVerifier/Android.mk b/apps/CtsVerifier/Android.mk
index 54fc522..aa3f117 100644
--- a/apps/CtsVerifier/Android.mk
+++ b/apps/CtsVerifier/Android.mk
@@ -25,7 +25,7 @@
LOCAL_PACKAGE_NAME := CtsVerifier
-LOCAL_JNI_SHARED_LIBRARIES := libctsverifier_jni libaudioquality libcameraanalyzer
+LOCAL_JNI_SHARED_LIBRARIES := libctsverifier_jni libcameraanalyzer
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index d9afe8d..f643eb7 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -282,24 +282,6 @@
<meta-data android:name="test_required_features" android:value="android.hardware.sensor.gyroscope" />
</activity>
- <activity android:name=".audioquality.AudioQualityVerifierActivity"
- android:label="@string/aq_verifier">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
- <meta-data android:name="test_category" android:value="@string/test_category_audio" />
- <meta-data android:name="test_required_features" android:value="android.hardware.microphone" />
- </activity>
-
- <activity android:name=".audioquality.CalibrateVolumeActivity"
- android:label="@string/aq_calibrate_volume_name" />
-
- <activity android:name=".audioquality.ViewResultsActivity"
- android:label="@string/aq_view_results_name" />
-
- <service android:name=".audioquality.ExperimentService" />
-
<activity android:name=".camera.analyzer.CameraAnalyzerActivity"
android:label="@string/camera_analyzer"
android:screenOrientation="landscape">
diff --git a/apps/CtsVerifier/assets/audioquality/pink_10000_3s b/apps/CtsVerifier/assets/audioquality/pink_10000_3s
deleted file mode 100644
index e248a50..0000000
--- a/apps/CtsVerifier/assets/audioquality/pink_10000_3s
+++ /dev/null
Binary files differ
diff --git a/apps/CtsVerifier/assets/audioquality/pink_5000_1s b/apps/CtsVerifier/assets/audioquality/pink_5000_1s
deleted file mode 100644
index 6d88505..0000000
--- a/apps/CtsVerifier/assets/audioquality/pink_5000_1s
+++ /dev/null
Binary files differ
diff --git a/apps/CtsVerifier/assets/audioquality/pink_5000_2s b/apps/CtsVerifier/assets/audioquality/pink_5000_2s
deleted file mode 100644
index 4acb0ca..0000000
--- a/apps/CtsVerifier/assets/audioquality/pink_5000_2s
+++ /dev/null
Binary files differ
diff --git a/apps/CtsVerifier/assets/audioquality/stim_dt_1 b/apps/CtsVerifier/assets/audioquality/stim_dt_1
deleted file mode 100644
index 65830bd..0000000
--- a/apps/CtsVerifier/assets/audioquality/stim_dt_1
+++ /dev/null
Binary files differ
diff --git a/apps/CtsVerifier/assets/audioquality/stim_dt_2 b/apps/CtsVerifier/assets/audioquality/stim_dt_2
deleted file mode 100644
index c61e7c8..0000000
--- a/apps/CtsVerifier/assets/audioquality/stim_dt_2
+++ /dev/null
Binary files differ
diff --git a/apps/CtsVerifier/assets/audioquality/stim_dt_3 b/apps/CtsVerifier/assets/audioquality/stim_dt_3
deleted file mode 100644
index be5f755..0000000
--- a/apps/CtsVerifier/assets/audioquality/stim_dt_3
+++ /dev/null
Binary files differ
diff --git a/apps/CtsVerifier/assets/audioquality/stim_dt_31 b/apps/CtsVerifier/assets/audioquality/stim_dt_31
deleted file mode 100644
index 8ff5b20..0000000
--- a/apps/CtsVerifier/assets/audioquality/stim_dt_31
+++ /dev/null
Binary files differ
diff --git a/apps/CtsVerifier/assets/audioquality/stim_dt_4 b/apps/CtsVerifier/assets/audioquality/stim_dt_4
deleted file mode 100644
index a9c0497..0000000
--- a/apps/CtsVerifier/assets/audioquality/stim_dt_4
+++ /dev/null
Binary files differ
diff --git a/apps/CtsVerifier/assets/audioquality/stim_dt_5 b/apps/CtsVerifier/assets/audioquality/stim_dt_5
deleted file mode 100644
index 73c2777..0000000
--- a/apps/CtsVerifier/assets/audioquality/stim_dt_5
+++ /dev/null
Binary files differ
diff --git a/apps/CtsVerifier/assets/audioquality/stim_dt_6 b/apps/CtsVerifier/assets/audioquality/stim_dt_6
deleted file mode 100644
index 381c79a..0000000
--- a/apps/CtsVerifier/assets/audioquality/stim_dt_6
+++ /dev/null
Binary files differ
diff --git a/apps/CtsVerifier/assets/audioquality/stim_dt_66 b/apps/CtsVerifier/assets/audioquality/stim_dt_66
deleted file mode 100644
index 84964ec..0000000
--- a/apps/CtsVerifier/assets/audioquality/stim_dt_66
+++ /dev/null
Binary files differ
diff --git a/apps/CtsVerifier/assets/audioquality/stim_dt_7 b/apps/CtsVerifier/assets/audioquality/stim_dt_7
deleted file mode 100644
index c304764..0000000
--- a/apps/CtsVerifier/assets/audioquality/stim_dt_7
+++ /dev/null
Binary files differ
diff --git a/apps/CtsVerifier/assets/audioquality/stim_dt_8 b/apps/CtsVerifier/assets/audioquality/stim_dt_8
deleted file mode 100644
index 7479f34..0000000
--- a/apps/CtsVerifier/assets/audioquality/stim_dt_8
+++ /dev/null
Binary files differ
diff --git a/apps/CtsVerifier/assets/audioquality/stim_dt_9 b/apps/CtsVerifier/assets/audioquality/stim_dt_9
deleted file mode 100644
index 02f5276..0000000
--- a/apps/CtsVerifier/assets/audioquality/stim_dt_9
+++ /dev/null
Binary files differ
diff --git a/apps/CtsVerifier/assets/audioquality/tone_250 b/apps/CtsVerifier/assets/audioquality/tone_250
deleted file mode 100644
index ed411f5..0000000
--- a/apps/CtsVerifier/assets/audioquality/tone_250
+++ /dev/null
Binary files differ
diff --git a/apps/CtsVerifier/jni/audioquality/Android.mk b/apps/CtsVerifier/jni/audioquality/Android.mk
deleted file mode 100644
index 787128a..0000000
--- a/apps/CtsVerifier/jni/audioquality/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-# 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.
-#
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_CPP_EXTENSION := .cpp
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils
-
-LOCAL_MODULE := libaudioquality
-LOCAL_SRC_FILES := Fft.cpp Window.cpp GlitchTest.cpp MeasureRms.cpp \
- OverflowCheck.cpp LinearityTest.cpp CompareSpectra.cpp \
- GenerateSinusoid.cpp Wrapper.cpp LinearityTestRms.cpp
-
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/apps/CtsVerifier/jni/audioquality/CompareSpectra.cpp b/apps/CtsVerifier/jni/audioquality/CompareSpectra.cpp
deleted file mode 100644
index 262a400..0000000
--- a/apps/CtsVerifier/jni/audioquality/CompareSpectra.cpp
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * 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.
- */
-
-// An amplitude-normalized spectrum comparison method.
-
-#include "Fft.h"
-#include "Window.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-
-/* Find the endpoints of the signal stored in data such that the rms of
- the found segment exceeds signalOnRms. data is of length n. The
- RMS calculations used to find the endpoints use a window of length
- step and advance step samples. The approximate, conservative
- endpoint sample indices are returned in start and end. */
-static void findEndpoints(short* data, int n, int step, float signalOnRms,
- int* start, int* end) {
- int size = step;
- *start = *end = 0;
- int last_frame = n - size;
- for (int frame = 0; frame < last_frame; frame += step) {
- double sum = 0.0;
- for (int i=0; i < size; ++i) {
- float val = data[i + frame];
- sum += (val * val);
- }
- float rms = sqrt(sum / size);
- if (! *start) {
- if (rms >= signalOnRms) {
- *start = frame + size;
- }
- continue;
- } else {
- if (rms < signalOnRms) {
- *end = frame - size;
- // fprintf(stderr, "n:%d onset:%d offset:%d\n", n, *start, *end);
- return;
- }
- }
- }
- // Handle the case where the signal does not drop below threshold
- // after onset.
- if ((*start > 0) && (! *end)) {
- *end = n - size - 1;
- }
-}
-
-// Sum the magnitude squared spectra.
-static void accumulateMagnitude(float* im, float* re, int size, double* mag) {
- for (int i = 0; i < size; ++i) {
- mag[i] += ((re[i] * re[i]) + (im[i] * im[i]));
- }
-}
-
-/* Return a pointer to 1+(fftSize/2) spectrum magnitude values
- averaged over all of the numSamples in pcm. It is the
- responsibility of the caller to free this magnitude array. Return
- NULL on failure. Use 50% overlap on the spectra. An FFT of
- fftSize points is used to compute the spectra, The overall signal
- rms over all frequencies between lowestBin and highestBin is
- returned as a scalar in rms. */
-double* getAverageSpectrum(short* pcm, int numSamples, int fftSize,
- int lowestBin, int highestBin, float* rms) {
- if (numSamples < fftSize) return NULL;
- int numFrames = 1 + ((2 * (numSamples - fftSize)) / fftSize);
- int numMag = 1 + (fftSize / 2);
- float* re = new float[fftSize];
- float* im = new float[fftSize];
- double* mag = new double[numMag];
- for (int i = 0; i < numMag; ++i) {
- mag[i] = 0.0;
- }
- Window wind(fftSize);
- Fft ft;
- int pow2 = ft.fftPow2FromWindowSize(fftSize);
- ft.fftInit(pow2);
- int input_p = 0;
- for (int i = 0; i < numFrames; ++i) {
- wind.window(pcm + input_p, re, 0.0);
- for (int j = 0; j < fftSize; ++j) {
- im[j] = 0.0;
- }
- ft.fft(re,im);
- accumulateMagnitude(im, re, numMag, mag);
- input_p += fftSize / 2;
- }
- double averageEnergy = 0.0; // per frame average energy
- for (int i = 0; i < numMag; ++i) {
- double e = mag[i]/numFrames;
- if ((i >= lowestBin) && (i <= highestBin))
- averageEnergy += e;
- mag[i] = sqrt(e);
- }
- *rms = sqrt(averageEnergy / (highestBin - lowestBin + 1));
- delete [] re;
- delete [] im;
- return mag;
-}
-
-/* Compare the average magnitude spectra of the signals in pcm and
- refPcm, which are of length numSamples and numRefSamples,
- respectively; both sampled at sample_rate. The maximum deviation
- between average spectra, expressed in dB, is returned in
- maxDeviation, and the rms of all dB variations is returned in
- rmsDeviation. Note that a lower limit is set on the frequencies that
- are compared so as to ignore irrelevant DC and rumble components. If
- the measurement fails for some reason, return 0; else return 1, for
- success. Causes for failure include the amplitude of one or both of
- the signals being too low, or the duration of the signals being too
- short.
-
- Note that the expected signal collection scenario is that the phone
- would be stimulated with a broadband signal as in a recognition
- attempt, so that there will be some "silence" regions at the start and
- end of the pcm signals. The preferred stimulus would be pink noise,
- but any broadband signal should work. */
-int compareSpectra(short* pcm, int numSamples, short* refPcm,
- int numRefSamples, float sample_rate,
- float* maxDeviation, float* rmsDeviation) {
- int fftSize = 512; // must be a power of 2
- float lowestFreq = 100.0; // don't count DC, room rumble, etc.
- float highestFreq = 3500.0; // ignore most effects of sloppy anti alias filters.
- int lowestBin = int(0.5 + (lowestFreq * fftSize / sample_rate));
- int highestBin = int(0.5 + (highestFreq * fftSize / sample_rate));
- float signalOnRms = 1000.0; // endpointer RMS on/off threshold
- int endpointStepSize = int(0.5 + (sample_rate * 0.02)); // 20ms setp
- float rms1 = 0.0;
- float rms2 = 0.0;
- int onset = 0;
- int offset = 0;
- findEndpoints(refPcm, numRefSamples, endpointStepSize, signalOnRms,
- &onset, &offset);
- double* spect1 = getAverageSpectrum(refPcm + onset, offset - onset,
- fftSize, lowestBin, highestBin, &rms1);
- findEndpoints(pcm, numSamples, endpointStepSize, signalOnRms,
- &onset, &offset);
- double* spect2 = getAverageSpectrum(pcm + onset, offset - onset,
- fftSize, lowestBin, highestBin, &rms2);
- int magSize = 1 + (fftSize/2);
- if ((rms1 <= 0.0) || (rms2 <= 0.0))
- return 0; // failure because one or both signals are too short or
- // too low in amplitude.
- float rmsNorm = rms2 / rms1; // compensate for overall gain differences
- // fprintf(stderr, "Level normalization: %f dB\n", 20.0 * log10(rmsNorm));
- *maxDeviation = 0.0;
- float sumDevSquared = 0.0;
- for (int i = lowestBin; i <= highestBin; ++i) {
- double val = 1.0;
- if ((spect1[i] > 0.0) && (spect2[i] > 0.0)) {
- val = 20.0 * log10(rmsNorm * spect1[i] / spect2[i]);
- }
- sumDevSquared += val * val;
- if (fabs(val) > fabs(*maxDeviation)) {
- *maxDeviation = val;
- }
- // fprintf(stderr, "%d %f\n", i, val);
- }
- *rmsDeviation = sqrt(sumDevSquared / (highestBin - lowestBin + 1));
- delete [] spect1;
- delete [] spect2;
- return 1; // success
-}
-
-
diff --git a/apps/CtsVerifier/jni/audioquality/CompareSpectra.h b/apps/CtsVerifier/jni/audioquality/CompareSpectra.h
deleted file mode 100644
index 8b473e1..0000000
--- a/apps/CtsVerifier/jni/audioquality/CompareSpectra.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef COMPARE_SPECTRA_H
-#define COMPARE_SPECTRA_H
-
-/* Compare the average magnitude spectra of the signals in pcm and
- refPcm, which are of length numSamples and nRefSamples,
- respectively; both sampled at sample_rate. The maximum deviation
- between average spectra, expressed in dB, is returned in
- maxDeviation, and the rms of all dB variations is returned in
- rmsDeviation. Note that a lower limit is set on the frequencies that
- are compared so as to ignore irrelevant DC and rumble components. If
- the measurement fails for some reason, return 0; else return 1, for
- success. Causes for failure include the amplitude of one or both of
- the signals being too low, or the duration of the signals being too
- short.
-
- Note that the expected signal collection scenario is that the phone
- would be stimulated with a broadband signal as in a recognition
- attempt, so that there will be some "silence" regions at the start and
- end of the pcm signals. The preferred stimulus would be pink noise,
- but any broadband signal should work. */
-
-int compareSpectra(short* pcm, int numSamples, short* refPcm,
- int nRefSamples, float sampleRate,
- float* maxDeviation, float* rmsDeviation);
-
-#endif // COMPARE_SPECTRA_H
diff --git a/apps/CtsVerifier/jni/audioquality/Fft.cpp b/apps/CtsVerifier/jni/audioquality/Fft.cpp
deleted file mode 100644
index 867bc86..0000000
--- a/apps/CtsVerifier/jni/audioquality/Fft.cpp
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * 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.
- */
-
-#include "Fft.h"
-
-#include <stdlib.h>
-#include <math.h>
-
-Fft::Fft(void) : mCosine(0), mSine(0), mFftSize(0), mFftTableSize(0) { }
-
-Fft::~Fft(void) {
- fftCleanup();
-}
-
-/* Construct a FFT table suitable to perform a DFT of size 2^power. */
-void Fft::fftInit(int power) {
- fftCleanup();
- fftMakeTable(power);
-}
-
-void Fft::fftCleanup() {
- delete [] mSine;
- delete [] mCosine;
- mSine = NULL;
- mCosine = NULL;
- mFftTableSize = 0;
- mFftSize = 0;
-}
-
-/* z <- (10 * log10(x^2 + y^2)) for n elements */
-int Fft::fftLogMag(float *x, float *y, float *z, int n) {
- float *xp, *yp, *zp, t1, t2, ssq;
-
- if(x && y && z && n) {
- for(xp=x+n, yp=y+n, zp=z+n; zp > z;) {
- t1 = *--xp;
- t2 = *--yp;
- ssq = (t1*t1)+(t2*t2);
- *--zp = (ssq > 0.0)? 10.0 * log10((double)ssq) : -200.0;
- }
- return 1; //true
- } else {
- return 0; // false/fail
- }
-}
-
-int Fft::fftMakeTable(int pow2) {
- int lmx, lm;
- float *c, *s;
- double scl, arg;
-
- mFftSize = 1 << pow2;
- mFftTableSize = lmx = mFftSize/2;
- mSine = new float[lmx];
- mCosine = new float[lmx];
- scl = (M_PI*2.0)/mFftSize;
- for (s=mSine, c=mCosine, lm=0; lm<lmx; lm++ ) {
- arg = scl * lm;
- *s++ = sin(arg);
- *c++ = cos(arg);
- }
- mBase = (mFftTableSize * 2)/mFftSize;
- mPower2 = pow2;
- return(mFftTableSize);
-}
-
-
-/* Compute the discrete Fourier transform of the 2**l complex sequence
- * in x (real) and y (imaginary). The DFT is computed in place and the
- * Fourier coefficients are returned in x and y.
- */
-void Fft::fft( float *x, float *y ) {
- float c, s, t1, t2;
- int j1, j2, li, lix, i;
- int lmx, lo, lixnp, lm, j, nv2, k=mBase, im, jm, l = mPower2;
-
- for (lmx=mFftSize, lo=0; lo < l; lo++, k *= 2) {
- lix = lmx;
- lmx /= 2;
- lixnp = mFftSize - lix;
- for (i=0, lm=0; lm<lmx; lm++, i += k ) {
- c = mCosine[i];
- s = mSine[i];
- for ( li = lixnp+lm, j1 = lm, j2 = lm+lmx; j1<=li;
- j1+=lix, j2+=lix ) {
- t1 = x[j1] - x[j2];
- t2 = y[j1] - y[j2];
- x[j1] += x[j2];
- y[j1] += y[j2];
- x[j2] = (c * t1) + (s * t2);
- y[j2] = (c * t2) - (s * t1);
- }
- }
- }
-
- /* Now perform the bit reversal. */
- j = 1;
- nv2 = mFftSize/2;
- for ( i=1; i < mFftSize; i++ ) {
- if ( j < i ) {
- jm = j-1;
- im = i-1;
- t1 = x[jm];
- t2 = y[jm];
- x[jm] = x[im];
- y[jm] = y[im];
- x[im] = t1;
- y[im] = t2;
- }
- k = nv2;
- while ( j > k ) {
- j -= k;
- k /= 2;
- }
- j += k;
- }
-}
-
-/* Compute the discrete inverse Fourier transform of the 2**l complex
- * sequence in x (real) and y (imaginary). The DFT is computed in
- * place and the Fourier coefficients are returned in x and y. Note
- * that this DOES NOT scale the result by the inverse FFT size.
- */
-void Fft::ifft(float *x, float *y ) {
- float c, s, t1, t2;
- int j1, j2, li, lix, i;
- int lmx, lo, lixnp, lm, j, nv2, k=mBase, im, jm, l = mPower2;
-
- for (lmx=mFftSize, lo=0; lo < l; lo++, k *= 2) {
- lix = lmx;
- lmx /= 2;
- lixnp = mFftSize - lix;
- for (i=0, lm=0; lm<lmx; lm++, i += k ) {
- c = mCosine[i];
- s = - mSine[i];
- for ( li = lixnp+lm, j1 = lm, j2 = lm+lmx; j1<=li;
- j1+=lix, j2+=lix ) {
- t1 = x[j1] - x[j2];
- t2 = y[j1] - y[j2];
- x[j1] += x[j2];
- y[j1] += y[j2];
- x[j2] = (c * t1) + (s * t2);
- y[j2] = (c * t2) - (s * t1);
- }
- }
- }
-
- /* Now perform the bit reversal. */
- j = 1;
- nv2 = mFftSize/2;
- for ( i=1; i < mFftSize; i++ ) {
- if ( j < i ) {
- jm = j-1;
- im = i-1;
- t1 = x[jm];
- t2 = y[jm];
- x[jm] = x[im];
- y[jm] = y[im];
- x[im] = t1;
- y[im] = t2;
- }
- k = nv2;
- while ( j > k ) {
- j -= k;
- k /= 2;
- }
- j += k;
- }
-}
-
-int Fft::fftGetSize(void) { return mFftSize; }
-
-int Fft::fftGetPower2(void) { return mPower2; }
diff --git a/apps/CtsVerifier/jni/audioquality/Fft.h b/apps/CtsVerifier/jni/audioquality/Fft.h
deleted file mode 100644
index 6a21d9a..0000000
--- a/apps/CtsVerifier/jni/audioquality/Fft.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef LEGACY_TALKIN_FFT_H
-#define LEGACY_TALKIN_FFT_H
-
-class Fft {
-public:
- Fft(void);
-
- virtual ~Fft(void);
-
- // Prepare for radix-2 FFT's of size (1<<pow2)
- void fftInit(int pow2);
-
- // Forward fft. Real time-domain components in x, imaginary in y
- void fft(float *x, float *y);
-
- // Inverse fft. Real frequency-domain components in x, imaginary in y
- void ifft(float *x, float *y);
-
- // Compute the dB-scaled log-magnitude spectrum from the real spectal
- // amplitude values in 'x', and imaginary values in 'y'. Return the
- // magnitude spectrum in z. Compute 'n' components.
- int fftLogMag(float *x, float *y, float *z, int n);
-
- int fftGetSize();
-
- int fftGetPower2();
-
- // Return the power of 2 required to contain at least size samples.
- static int fftPow2FromWindowSize(int size) {
- int pow2 = 1;
- while ((1 << pow2) < size)
- pow2++;
- return pow2;
- }
-
-private:
- // Free up memory and reset the static globals.
- void fftCleanup();
-
- // Create the sine/cosine basis tables and return the size of the FFT
- // corresponding to pow2.
- int fftMakeTable(int pow2);
-
- float* mSine;
- float* mCosine;
- int mFftTableSize;
- int mFftSize;
- int mPower2;
- int mBase;
-};
-
-#endif // LEGACY_TALKIN_FFT_H
diff --git a/apps/CtsVerifier/jni/audioquality/GenerateSinusoid.cpp b/apps/CtsVerifier/jni/audioquality/GenerateSinusoid.cpp
deleted file mode 100644
index 1823d58..0000000
--- a/apps/CtsVerifier/jni/audioquality/GenerateSinusoid.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.
- */
-
-// Generate a sinusoidal signal with optional onset and offset ramps.
-
-#include <stdlib.h>
-#include <math.h>
-
-static inline short clipAndRound(float val) {
- if (val > 32767.0)
- return 32767;
- if (val < -32768.0)
- return -32768;
- if (val >= 0.0)
- return static_cast<short>(0.5 + val);
- return static_cast<short>(val - 0.5);
-}
-
-/* Return a sinusoid of frequency freq Hz and amplitude ampl in output
- of length numOutput. If ramp > 0.0, taper the ends of the signal
- with a half-raised-cosine function. It is up to the caller to
- delete[] output. If this call fails due to unreasonable arguments,
- numOutput will be zero, and output will be NULL. Note that the
- duration of the up/down ramps will be within the specified
- duration. Note that if amplitude is specified outside of the
- numerical range of int16, the signal will be clipped at +- 32767. */
-void generateSinusoid(float freq, float duration, float sampleRate,
- float amplitude, float ramp,
- int* numOutput, short** output) {
- // Sanity check
- if ((duration < (2.0 * ramp)) || ((freq * 2.0) > sampleRate) || (ramp < 0.0)) {
- *output = NULL;
- *numOutput = 0;
- return;
- }
- int numSamples = int(0.5 + (sampleRate * duration));
- double arg = M_PI * 2.0 * freq / sampleRate;
- short* wave = new short[numSamples];
- int numRamp = int(0.5 + (sampleRate * ramp));
- for (int i = 0; i < numSamples; ++i) {
- float val = amplitude * sin(arg * i);
- if (numRamp > 0) {
- if (i < numRamp) {
- float gain = (0.5 - (0.5 * cos((0.5 + i) * M_PI / numRamp)));
- val *= gain;
- } else {
- if (i > (numSamples - numRamp - 1)) {
- float gain = (0.5 - (0.5 * cos((0.5 + (numSamples - i - 1))
- * M_PI / numRamp)));
- val *= gain;
- }
- }
- }
- wave[i] = clipAndRound(val);
- }
- *numOutput = numSamples;
- *output = wave;
-}
diff --git a/apps/CtsVerifier/jni/audioquality/GenerateSinusoid.h b/apps/CtsVerifier/jni/audioquality/GenerateSinusoid.h
deleted file mode 100644
index eeedca6..0000000
--- a/apps/CtsVerifier/jni/audioquality/GenerateSinusoid.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef GENERATE_SINUSOID_H
-#define GENERATE_SINUSOID_H
-
-/* Return a sinusoid of frequency freq Hz and amplitude ampl in output
- of length numOutput. If ramp > 0.0, taper the ends of the signal
- with a half-raised-cosine function. It is up to the caller to
- delete[] output. If this call fails due to unreasonable arguments,
- numOutput will be zero, and output will be NULL. Note that the
- duration of the up/down ramps will be within the specified
- duration. Note that if amplitude is specified outside of the
- numerical range of int16, the signal will be clipped at +- 32767. */
-void generateSinusoid(float freq, float duration, float sampleRate,
- float amplitude, float ramp,
- int* numOutput, short** output);
-
-#endif // GENERATE_SINUSOID_H
-
diff --git a/apps/CtsVerifier/jni/audioquality/GlitchTest.cpp b/apps/CtsVerifier/jni/audioquality/GlitchTest.cpp
deleted file mode 100644
index 2605f77..0000000
--- a/apps/CtsVerifier/jni/audioquality/GlitchTest.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * 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.
- */
-
-#include "GlitchTest.h"
-#include "Window.h"
-#include "Fft.h"
-
-#include <math.h>
-
-GlitchTest::GlitchTest(void) : mRe(0), mIm(0), mFt(0), mWind(0) {}
-
-void GlitchTest::init(float sampleRate, float stimFreq, float onsetThresh,
- float dbSnrThresh) {
- cleanup(); // in case Init gets called multiple times.
- // Analysis parameters
- float windowDur = 0.025; // Duration of the analysis window in seconds.
- float frameInterval = 0.01; // Interval in seconds between frame onsets
- float lowestFreq = 200.0; // Lowest frequency to include in
- // background noise power integration.
- mSampleRate = sampleRate;
- mOnsetThresh = onsetThresh;
- mDbSnrThresh = dbSnrThresh;
- mFrameStep = (int)(0.5 + (mSampleRate * frameInterval));
- mWindowSize = (int)(0.5 + (mSampleRate * windowDur));
- mWind = new Window(mWindowSize);
- mFt = new Fft;
- mFt->fftInit(mFt->fftPow2FromWindowSize(mWindowSize));
- mFftSize = mFt->fftGetSize();
- mRe = new float[mFftSize];
- mIm = new float[mFftSize];
- float freqInterval = mSampleRate / mFftSize;
- // We can exclude low frequencies from consideration, since the
- // phone may have DC offset in the A/D, and there may be rumble in
- // the testing room.
- mLowestSpectrumBin = (int)(0.5 + (lowestFreq / freqInterval));
- // These are the bin indices within which most of the energy due to
- // the (windowed) tone should be found.
- mLowToneBin = (int)(0.5 + (stimFreq / freqInterval)) - 2;
- mHighToneBin = (int)(0.5 + (stimFreq / freqInterval)) + 2;
- if (mLowestSpectrumBin >= mLowToneBin) {
- mLowestSpectrumBin = mHighToneBin + 1;
- }
-}
-
-int GlitchTest::checkToneSnr(short* pcm, int numSamples, float* duration,
- int* numBadFrames) {
- *numBadFrames = 0;
- *duration = 0.0;
- if (!(mRe && mIm)) {
- return -1; // not initialized.
- }
- int n_frames = 1 + ((numSamples - mWindowSize) / mFrameStep);
- if (n_frames < 4) { // pathologically short input signal
- return -2;
- }
- *numBadFrames = 0;
- int onset = -1;
- int offset = -1;
- for (int frame = 0; frame < n_frames; ++frame) {
- int numSpectra = 0;
- mWind->window(pcm + frame*mFrameStep, mRe, 0.0);
- realMagSqSpectrum(mRe, mWindowSize, mRe, &numSpectra);
- int maxLoc = 0;
- float maxValue = 0.0;
- findPeak(mRe, mLowestSpectrumBin, numSpectra, &maxLoc, &maxValue);
- // possible states: (1) before tone onset; (2) within tone
- // region; (3) after tone offset.
- if ((onset < 0) && (offset < 0)) { // (1)
- if ((maxLoc >= mLowToneBin) && (maxLoc <= mHighToneBin)
- && (maxValue > mOnsetThresh)) {
- onset = frame;
- }
- continue;
- }
- if ((onset >= 0) && (offset < 0)) { // (2)
- if (frame > (onset + 2)) { // let the framer get completely
- // into the tonal signal
- double sumNoise = 1.0; // init. to small non-zero vals to
- // avoid log or divz problems
- double sumSignal = 1.0;
- float snr = 0.0;
- if (maxValue < mOnsetThresh) {
- offset = frame;
- *duration = mFrameStep * (offset - onset) / mSampleRate;
- if (*numBadFrames >= 1) {
- (*numBadFrames) -= 1; // account for expected glitch at
- // signal offset
- }
- continue;
- }
- for (int i = mLowestSpectrumBin; i < mLowToneBin; ++i) {
- sumNoise += mRe[i]; // note that mRe contains the magnitude
- // squared spectrum.
- }
- for (int i = mLowToneBin; i <= mHighToneBin; ++i)
- sumSignal += mRe[i];
- for (int i = mHighToneBin + 1; i < numSpectra; ++i) {
- sumNoise += mRe[i]; // Note: mRe has the mag squared spectrum.
- }
- snr = 10.0 * log10(sumSignal / sumNoise);
- if (snr < mDbSnrThresh)
- (*numBadFrames) += 1;
- }
- continue;
- }
- if ((onset >= 0) && (offset > 0)) { // (3)
- if ((maxLoc >= mLowToneBin) && (maxLoc <= mHighToneBin) &&
- (maxValue > mOnsetThresh)) { // tone should not pop up again!
- (*numBadFrames) += 1;
- }
- continue;
- }
- }
- if ((onset >= 0) && (offset > 0))
- return 1; // Success.
- if (onset < 0) {
- return -3; // Signal onset not found.
- }
- return -4; // Signal offset not found.
-}
-
-void GlitchTest::cleanup(void) {
- delete [] mRe;
- delete [] mIm;
- delete mFt;
- delete mWind;
- mRe = 0;
- mIm = 0;
- mWind = 0;
- mFt = 0;
-}
-
-int GlitchTest::realMagSqSpectrum(float* data, int numInput,
- float* output, int* numOutput) {
- *numOutput = 0;
- if ((numInput <= 0) || (numInput > mFftSize))
- return 0;
- int i = 0;
- for (i = 0; i < numInput; ++i) {
- mRe[i] = data[i];
- mIm[i] = 0.0;
- }
- for ( ; i < mFftSize; ++i) {
- mRe[i] = 0.0;
- mIm[i] = 0.0;
- }
- mFt->fft(mRe, mIm);
- *numOutput = 1 + (mFftSize / 2);
- for (i = 0; i < *numOutput; ++i) {
- output[i] = (mRe[i] * mRe[i]) + (mIm[i] * mIm[i]);
- }
- return 1;
-}
-
-void GlitchTest::findPeak(float* data, int startSearch, int endSearch,
- int* maxLoc, float* maxValue) {
- float amax = data[startSearch];
- int loc = startSearch;
- for (int i = startSearch + 1; i < endSearch; ++i) {
- if (data[i] > amax) {
- amax = data[i];
- loc = i;
- }
- }
- *maxLoc = loc;
- *maxValue = 10.0 * log10(amax / mWindowSize);
-}
-
diff --git a/apps/CtsVerifier/jni/audioquality/GlitchTest.h b/apps/CtsVerifier/jni/audioquality/GlitchTest.h
deleted file mode 100644
index de96e6e..0000000
--- a/apps/CtsVerifier/jni/audioquality/GlitchTest.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef GLITCH_TEST_H
-#define GLITCH_TEST_H
-
-class Fft;
-class Window;
-
-class GlitchTest {
-public:
- GlitchTest(void);
-
- virtual ~GlitchTest(void) {
- cleanup();
- }
-
- /* Set up the instance to operate on input test signals sampled at
- sample_rate that contain a stimulis tone of stim_freq frequency.
- The signal will be considered on during the interval it exceeds
- onset_thresh (dB re 1.0). Any frames containing a tone that have
- a signal energy to out-of-band energy ratio less than
- db_snr_thresh are counted as bad frames. Init must be called
- before CheckToneSnr. */
- void init(float sample_rate, float stim_freq, float onset_thresh,
- float db_snr_thresh);
-
- /* Analyze the n_samples of the lin16 signal in pcm. This signal is
- assumed sampled at sample_rate, and to contain a sinusoid with
- center frequency stim_freq, embedded somewhere in time, with
- "silence" intervals before and after. The contiguous duration of
- the tone that exceeds onset_thresh (in dB re 1.0) is returned as
- seconds in duration. The number of frames for which the ratio of
- the energy at the tone frequency to the energy in the rest of the
- spectrum is less than db_snr_thresh is returned in n_bad_frames.
- If the test succeed, the method returns 1, else it returns a
- negative number that reflects the cause of failure as follows:
- -1 The instance is not initialized.
- -2 There are not enough samples to do a reasonable check.
- -3 The tone signal onset was not found.
- -4 The tone signal end was not found. */
- int checkToneSnr(short* pcm, int n_samples, float* duration,
- int* n_bad_frames);
-
-private:
- // Free memory, etc.
- void cleanup(void);
-
- /* Do a real FFT on the n_input samples in data, and return n_output
- power spectral density points in output. The output points include
- DC through the Nyquist frequency (i.e. 1 + fft_size/2). output
- must be large enough to accommodate this size. If n_input==0 or
- n_input > fft_size, return 0; else return 1. */
- int realMagSqSpectrum(float* data, int n_input,
- float* output, int* n_output);
-
- /* Find the largest value in data starting at start_search and ending
- at end_search-1. The values in data are assumed to be magnitude
- squared values from a spectrum computation based on window_size
- sample points. Return the index where the largest value was found,
- and return the dB (re 1.0) equivalent of the highest magnitude. */
- void findPeak(float* data, int start_search, int end_search,
- int* max_loc, float* max_value);
-
- // Real and Imaginary analysis arrays.
- float* mRe;
- float* mIm;
- // Fourier transform and window.
- Fft* mFt;
- Window* mWind;
- // Derived parameters and other variables.
- float mSampleRate;
- int mFrameStep;
- int mWindowSize;
- int mFftSize;
- float mOnsetThresh;
- float mDbSnrThresh;
- int mLowestSpectrumBin;
- int mLowToneBin;
- int mHighToneBin;
-};
-
-#endif // GLITCH_TEST_H
diff --git a/apps/CtsVerifier/jni/audioquality/LinearityTest.cpp b/apps/CtsVerifier/jni/audioquality/LinearityTest.cpp
deleted file mode 100644
index 2df7603..0000000
--- a/apps/CtsVerifier/jni/audioquality/LinearityTest.cpp
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * 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.
- */
-
-/* This test accepts a collection of N speech waveforms collected as
- part of N recognition attempts. The waveforms are ordered by
- increasing presentation level. The test determines the extent to
- which the peak amplitudes in the waveforms track the change in
- presentation level. Failure to track the presentation level within
- some reasonable margin is an indication of clipping or of automatic
- gain control in the signal path.
-
- The speech stimuli that are used for this test should simply be
- replications of exactly the same speech signal presented at
- different levels. It is expected that all recognition attempts on
- this signal result in correct recognition. A warning, but not a
- hard failure, should be issued if any of the attempts fail. The
- hard failure criterion for this test should be only based on the
- amplitude linearity tracking. */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-
-/* Keep a record of the top N absolute values found using a slow
- bubble-sort. This is OK, since the use of this program is not time
- critical, and N is usually small. Note that the argument n = N-1. */
-static void bubbleUp(int* store, int n, short val) {
- if (val < store[n])
- return;
- for (int i = 0; i <= n; ++i) {
- if (val >= store[i]) {
- for (int j = n; j > i ; j--)
- store[j] = store[j-1];
- store[i] = val;
- return;
- }
- }
-}
-
-/* Make two measurements on the signal of length numSamples sampled at
- sampleRate in pcm: the RMS of the highest amplitude 30ms segment
- (returned in peakRms), and the RMS of the top 50 peak absolute
- values found (returned in peakAverage). If the signal is too
- short to make reasonable measurements, the function returns 0, else
- it returns 1. */
-static int peakLevels(short* pcm, int numSamples, float sampleRate,
- float* peakAverage, float* peakRms) {
- float rmsFrameSize = 0.03;
- float rmsFrameStep = 0.01;
- int frameStep = int(0.5 + (sampleRate * rmsFrameStep));
- int frameSize = int(0.5 + (sampleRate * rmsFrameSize));
- int numFrames = 1 + ((numSamples - frameSize) / frameStep);
-
- if (numFrames < 10) {
- return 0; // failure for too short signal
- }
-
- // Peak RMS calculation
- double maxEnergy = 0.0;
- for (int frame = 0; frame < numFrames; ++frame) {
- double energy = 0.0;
- int limit = (frame * frameStep) + frameSize;
- for (int i = frame * frameStep; i < limit; ++i) {
- double s = pcm[i];
- energy += s * s;
- }
- if (energy > maxEnergy) {
- maxEnergy = energy;
- }
- }
- *peakRms = sqrt(maxEnergy / frameSize);
-
- // Find the absolute highest topN peaks in the signal and compute
- // the RMS of their values.
- int topN = 50; // The number of highest peaks over which to average.
- int topM = topN - 1;
- int* maxVal = new int[topN];
- for (int i = 0; i < topN; ++i) {
- maxVal[i] = 0;
- }
- for (int i = 0; i < numSamples; ++i) {
- if (pcm[i] >= 0) {
- bubbleUp(maxVal, topM, pcm[i]);
- } else {
- bubbleUp(maxVal, topM, -pcm[i]);
- }
- }
- float sum = 0.0;
- // The RMS is taken bacause we want the values of the highest peaks
- // to dominate.
- for (int i = 0; i < topN; ++i) {
- float fval = maxVal[i];
- sum += (fval * fval);
- }
- delete [] maxVal;
- *peakAverage = sqrt(sum/topN);
- return 1; // success
-}
-
-/* There are numSignals int16 signals in pcms. sampleCounts is an
- integer array of length numSignals containing their respective
- lengths in samples. They are all sampled at sampleRate. The pcms
- are ordered by increasing stimulus level. The level steps between
- successive stimuli were of size dbStepSize dB. The signal with
- index referenceStim (0 <= referenceStim < numSignals) should be in
- an amplitude range that is reasonably certain to be linear (e.g. at
- normal speaking levels). The maximum deviation in linearity found
- (in dB) is returned in maxDeviation. The function returns 1 if
- the measurements could be made, or a negative number that
- indicates the error, as follows:
- -1 The input signals or sample counts are missing.
- -2 The number of input signals is < 2.
- -3 The specified sample rate is <= 4000.0
- -4 The dB step size for the increase in stimulus level is <= 0.0
- -5 The specified reverence stimulus number is out of range.
- -6 One or more of the stimuli is too short in duration. */
-int linearityTest(short** pcms, int* sampleCounts, int numSignals,
- float sampleRate, float dbStepSize, int referenceStim,
- float* maxDeviation) {
- if (!(pcms && sampleCounts)) {
- return -1; // Input signals or sample counts are missing
- }
- if (numSignals < 2) {
- return -2; // the number of input signals must be >= 2;
- }
- if (sampleRate <= 4000.0) {
- return -3; // The sample rate must be > 4000 Hz.
- }
- if (dbStepSize <= 0.0) {
- return -4; // The dB step size must be > 0.0
- }
- if (!((referenceStim >= 0) && (referenceStim < numSignals))) {
- return -5; // (0 <= referenceStim < numSignals) must be true
- }
- float* peakAverage = new float[numSignals];
- float* peakRms = new float[numSignals];
- for (int sig = 0; sig < numSignals; ++sig) {
- if (!peakLevels(pcms[sig], sampleCounts[sig],
- sampleRate, peakAverage + sig, peakRms + sig)) {
- delete []peakAverage;
- delete []peakRms;
- return -6; // failure because a signal is too short.
- }
- }
- float peakAverageRef = peakAverage[referenceStim];
- float peakRmsRef = peakRms[referenceStim];
- float maxDev = 0.0;
- for (int i = 0; i < numSignals; ++i) {
- float dbAverage = 20.0 * log10(peakAverage[i]/peakAverageRef);
- float dbRms = 20.0 * log10(peakRms[i]/peakRmsRef);
- float reference = dbStepSize * (i - referenceStim);
- float average_level = 0.5 * (dbAverage + dbRms);
- float dev = fabs(average_level - reference);
- // fprintf(stderr,"dbAverage:%f dbRms:%f reference:%f dev:%f\n",
- // dbAverage, dbRms, reference, dev);
- if (dev > maxDev)
- maxDev = dev;
- }
- *maxDeviation = maxDev;
- delete []peakAverage;
- delete []peakRms;
- return 1;
-}
diff --git a/apps/CtsVerifier/jni/audioquality/LinearityTest.h b/apps/CtsVerifier/jni/audioquality/LinearityTest.h
deleted file mode 100644
index 1aac4b6..0000000
--- a/apps/CtsVerifier/jni/audioquality/LinearityTest.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef LINEARITY_TEST_H
-#define LINEARITY_TEST_H
-
-/* error codes returned */
-// The input signals or sample counts are missing.
-const int ERROR_INPUT_SIGNAL_MISSING = -1;
-// The number of input signals is < 2.
-const int ERROR_INPUT_SIGNAL_NUMBERS = -2;
-// The specified sample rate is <= 4000.0
-const int ERROR_SAMPLE_RATE_TOO_LOW = -3;
-// The dB step size for the increase in stimulus level is <= 0.0
-const int ERROR_NEGATIVE_STEP_SIZE = -4;
-// The specified reference stimulus number is out of range.
-const int ERROR_STIMULUS_NUMBER = -5;
-// One or more of the stimuli is too short in duration.
-const int ERROR_STIMULI_TOO_SHORT = -6;
-// cannot find linear fitting for the given data
-const int ERROR_LINEAR_FITTING = -7;
-
-/* There are numSignals int16 signals in pcms. sampleCounts is an
- integer array of length numSignals containing their respective
- lengths in samples. They are all sampled at sampleRate. The pcms
- are ordered by increasing stimulus level. The level steps between
- successive stimuli were of size dbStepSize dB. The signal with
- index referenceStim (0 <= referenceStim < numSignals) should be in
- an amplitude range that is reasonably certain to be linear (e.g. at
- normal speaking levels). The maximum deviation in linearity found
- (in dB) is returned in maxDeviation. The function returns 1 if
- the measurements could be made, or a negative number that
- indicates the error, as defined above. */
-int linearityTest(short** pcms, int* sampleCounts, int numSignals,
- float sampleRate, float dbStepSize,
- int referenceStim, float* maxDeviation);
-
-/* a version using RMS of the whole signal and linear fitting */
-int linearityTestRms(short** pcms, int* sampleCounts, int numSignals,
- float sampleRate, float dbStepSize,
- float* maxDeviation);
-
-
-#endif /* LINEARITY_TEST_H */
diff --git a/apps/CtsVerifier/jni/audioquality/LinearityTestRms.cpp b/apps/CtsVerifier/jni/audioquality/LinearityTestRms.cpp
deleted file mode 100644
index d83b056..0000000
--- a/apps/CtsVerifier/jni/audioquality/LinearityTestRms.cpp
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-/* This test accepts a collection of N speech waveforms collected as
- part of N recognition attempts. The waveforms are ordered by
- increasing presentation level. The test determines the extent to
- which the peak amplitudes in the waveforms track the change in
- presentation level. Failure to track the presentation level within
- some reasonable margin is an indication of clipping or of automatic
- gain control in the signal path.
-
- RMS of each level is used as a parameter for deciding lienairy.
- For each level, RMS is calculated, and a line fitting into RMS vs level
- will be calculated. Then for each level, residual error of measurement
- vs line fitting will be calculated, and the residual error is normalized
- with each measurement. The test failes if residual error is bigger than
- 2dB.
-
- This test will be robust to background noise as long as it is persistent.
- But background noise which appears shortly with enough strength can
- mess up the result.
-*/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include <cutils/log.h>
-#include "LinearityTest.h"
-
-#define LOG_TAG "LinearityTestRms"
-
-// vectorDot, vectorNorm, and solveLeastSquares
-// copied from frameworks/base/libs/ui/Input.cpp
-
-static inline float vectorDot(const float* a, const float* b, uint32_t m) {
- float r = 0;
- while (m--) {
- r += *(a++) * *(b++);
- }
- return r;
-}
-
-static inline float vectorNorm(const float* a, uint32_t m) {
- float r = 0;
- while (m--) {
- float t = *(a++);
- r += t * t;
- }
- return sqrtf(r);
-}
-
-/**
- * Solves a linear least squares problem to obtain a N degree polynomial that fits
- * the specified input data as nearly as possible.
- *
- * Returns true if a solution is found, false otherwise.
- *
- * The input consists of two vectors of data points X and Y with indices 0..m-1.
- * The output is a vector B with indices 0..n-1 that describes a polynomial
- * that fits the data, such the sum of abs(Y[i] - (B[0] + B[1] X[i] + B[2] X[i]^2 ... B[n] X[i]^n))
- * for all i between 0 and m-1 is minimized.
- *
- * That is to say, the function that generated the input data can be approximated
- * by y(x) ~= B[0] + B[1] x + B[2] x^2 + ... + B[n] x^n.
- *
- * The coefficient of determination (R^2) is also returned to describe the goodness
- * of fit of the model for the given data. It is a value between 0 and 1, where 1
- * indicates perfect correspondence.
- *
- * This function first expands the X vector to a m by n matrix A such that
- * A[i][0] = 1, A[i][1] = X[i], A[i][2] = X[i]^2, ..., A[i][n] = X[i]^n.
- *
- * Then it calculates the QR decomposition of A yielding an m by m orthonormal matrix Q
- * and an m by n upper triangular matrix R. Because R is upper triangular (lower
- * part is all zeroes), we can simplify the decomposition into an m by n matrix
- * Q1 and a n by n matrix R1 such that A = Q1 R1.
- *
- * Finally we solve the system of linear equations given by R1 B = (Qtranspose Y)
- * to find B.
- *
- * For efficiency, we lay out A and Q column-wise in memory because we frequently
- * operate on the column vectors. Conversely, we lay out R row-wise.
- *
- * http://en.wikipedia.org/wiki/Numerical_methods_for_linear_least_squares
- * http://en.wikipedia.org/wiki/Gram-Schmidt
- */
-static bool solveLeastSquares(const float* x, const float* y, uint32_t m, uint32_t n,
- float* outB, float* outDet) {
-#if DEBUG_LEAST_SQUARES
- LOGD("solveLeastSquares: m=%d, n=%d, x=%s, y=%s", int(m), int(n),
- vectorToString(x, m).string(), vectorToString(y, m).string());
-#endif
-
- // Expand the X vector to a matrix A.
- float a[n][m]; // column-major order
- for (uint32_t h = 0; h < m; h++) {
- a[0][h] = 1;
- for (uint32_t i = 1; i < n; i++) {
- a[i][h] = a[i - 1][h] * x[h];
- }
- }
-#if DEBUG_LEAST_SQUARES
- LOGD(" - a=%s", matrixToString(&a[0][0], m, n, false /*rowMajor*/).string());
-#endif
-
- // Apply the Gram-Schmidt process to A to obtain its QR decomposition.
- float q[n][m]; // orthonormal basis, column-major order
- float r[n][n]; // upper triangular matrix, row-major order
- for (uint32_t j = 0; j < n; j++) {
- for (uint32_t h = 0; h < m; h++) {
- q[j][h] = a[j][h];
- }
- for (uint32_t i = 0; i < j; i++) {
- float dot = vectorDot(&q[j][0], &q[i][0], m);
- for (uint32_t h = 0; h < m; h++) {
- q[j][h] -= dot * q[i][h];
- }
- }
-
- float norm = vectorNorm(&q[j][0], m);
- if (norm < 0.000001f) {
- // vectors are linearly dependent or zero so no solution
-#if DEBUG_LEAST_SQUARES
- LOGD(" - no solution, norm=%f", norm);
-#endif
- return false;
- }
-
- float invNorm = 1.0f / norm;
- for (uint32_t h = 0; h < m; h++) {
- q[j][h] *= invNorm;
- }
- for (uint32_t i = 0; i < n; i++) {
- r[j][i] = i < j ? 0 : vectorDot(&q[j][0], &a[i][0], m);
- }
- }
-#if DEBUG_LEAST_SQUARES
- LOGD(" - q=%s", matrixToString(&q[0][0], m, n, false /*rowMajor*/).string());
- LOGD(" - r=%s", matrixToString(&r[0][0], n, n, true /*rowMajor*/).string());
-
- // calculate QR, if we factored A correctly then QR should equal A
- float qr[n][m];
- for (uint32_t h = 0; h < m; h++) {
- for (uint32_t i = 0; i < n; i++) {
- qr[i][h] = 0;
- for (uint32_t j = 0; j < n; j++) {
- qr[i][h] += q[j][h] * r[j][i];
- }
- }
- }
- LOGD(" - qr=%s", matrixToString(&qr[0][0], m, n, false /*rowMajor*/).string());
-#endif
-
- // Solve R B = Qt Y to find B. This is easy because R is upper triangular.
- // We just work from bottom-right to top-left calculating B's coefficients.
- for (uint32_t i = n; i-- != 0; ) {
- outB[i] = vectorDot(&q[i][0], y, m);
- for (uint32_t j = n - 1; j > i; j--) {
- outB[i] -= r[i][j] * outB[j];
- }
- outB[i] /= r[i][i];
- }
-#if DEBUG_LEAST_SQUARES
- LOGD(" - b=%s", vectorToString(outB, n).string());
-#endif
-
- // Calculate the coefficient of determination as 1 - (SSerr / SStot) where
- // SSerr is the residual sum of squares (squared variance of the error),
- // and SStot is the total sum of squares (squared variance of the data).
- float ymean = 0;
- for (uint32_t h = 0; h < m; h++) {
- ymean += y[h];
- }
- ymean /= m;
-
- float sserr = 0;
- float sstot = 0;
- for (uint32_t h = 0; h < m; h++) {
- float err = y[h] - outB[0];
- float term = 1;
- for (uint32_t i = 1; i < n; i++) {
- term *= x[h];
- err -= term * outB[i];
- }
- sserr += err * err;
- float var = y[h] - ymean;
- sstot += var * var;
- }
- *outDet = sstot > 0.000001f ? 1.0f - (sserr / sstot) : 1;
-#if DEBUG_LEAST_SQUARES
- LOGD(" - sserr=%f", sserr);
- LOGD(" - sstot=%f", sstot);
- LOGD(" - det=%f", *outDet);
-#endif
- return true;
-}
-
-/* calculate RMS of given sample with numSamples of length */
-float calcRms(short* pcm, int numSamples)
-{
- float energy = 0.0f;
- for(int i = 0; i < numSamples; i++) {
- float sample = (float)pcm[i];
- energy += (sample * sample);
- }
- return sqrtf(energy);
-}
-
-/* There are numSignals int16 signals in pcms. sampleCounts is an
- integer array of length numSignals containing their respective
- lengths in samples. They are all sampled at sampleRate. The pcms
- are ordered by increasing stimulus level. The level steps between
- successive stimuli were of size dbStepSize dB.
- The maximum deviation in linearity found
- (in dB) is returned in maxDeviation. The function returns 1 if
- the measurements could be made, or a negative number that
- indicates the error, as defined in LinearityTest.h */
-int linearityTestRms(short** pcms, int* sampleCounts, int numSignals,
- float sampleRate, float dbStepSize,
- float* maxDeviation) {
- if (!(pcms && sampleCounts)) {
- return ERROR_INPUT_SIGNAL_MISSING;
- }
- if (numSignals < 2) {
- return ERROR_INPUT_SIGNAL_NUMBERS;
- }
- if (sampleRate <= 4000.0) {
- return ERROR_SAMPLE_RATE_TOO_LOW;
- }
- if (dbStepSize <= 0.0) {
- return ERROR_NEGATIVE_STEP_SIZE;
- }
-
- float* levels = new float[numSignals];
- levels[0] = 1.0f;
- float stepInMag = powf(10.0f, dbStepSize/20.0f);
- for(int i = 1; i < numSignals; i++) {
- levels[i] = levels[i - 1] * stepInMag;
- }
-
- float* rmsValues = new float[numSignals];
- for (int i = 0; i < numSignals; i++) {
- rmsValues[i] = calcRms(pcms[i], sampleCounts[i]);
- }
- const int NO_COEFFS = 2; // only line fitting
- float coeffs[NO_COEFFS];
- float outDet;
- if(!solveLeastSquares(levels, rmsValues, numSignals, NO_COEFFS,
- coeffs, &outDet)) {
- ALOGI(" solveLeastSquares fails with det %f", outDet);
- return ERROR_LINEAR_FITTING;
- }
- ALOGI(" coeffs offset %f linear %f", coeffs[0], coeffs[1]);
- float maxDev = 0.0f;
- for(int i = 0; i < numSignals; i++) {
- float residue = coeffs[0] + coeffs[1] * levels[i] - rmsValues[i];
- // to make devInDb positive, add measured value itself
- // then normalize
- float devInDb = 20.0f * log10f((fabs(residue) + rmsValues[i])
- / rmsValues[i]);
- ALOGI(" %d-th residue %f dB", i, devInDb);
- if (devInDb > maxDev) {
- maxDev = devInDb;
- }
- }
- *maxDeviation = maxDev;
-
- delete[] levels;
- delete[] rmsValues;
-
- return 1;
-}
diff --git a/apps/CtsVerifier/jni/audioquality/MeasureRms.cpp b/apps/CtsVerifier/jni/audioquality/MeasureRms.cpp
deleted file mode 100644
index 640b191..0000000
--- a/apps/CtsVerifier/jni/audioquality/MeasureRms.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * 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.
- */
-
-#include <math.h>
-
-/* Return the median of the n values in "values".
- Uses a stupid bubble sort, but is only called once on small array. */
-float getMedian(float* values, int n) {
- if (n <= 0)
- return 0.0;
- if (n == 1)
- return values[0];
- if (n == 2)
- return 0.5 * (values[0] + values[1]);
- for (int i = 1; i < n; ++i)
- for (int j = i; j < n; ++j) {
- if (values[j] < values[i-1]) {
- float tmp = values[i-1];
- values[i-1] = values[j];
- values[j] = tmp;
- }
- }
- int ind = int(0.5 + (0.5 * n)) - 1;
- return values[ind];
-}
-
-float computeAndRemoveMean(short* pcm, int numSamples) {
- float sum = 0.0;
-
- for (int i = 0; i < numSamples; ++i)
- sum += pcm[i];
- short mean;
- if (sum >= 0.0)
- mean = (short)(0.5 + (sum / numSamples));
- else
- mean = (short)((sum / numSamples) - 0.5);
- for (int i = 0; i < numSamples; ++i)
- pcm[i] -= mean;
- return sum / numSamples;
-}
-
-void measureRms(short* pcm, int numSamples, float sampleRate, float onsetThresh,
- float* rms, float* stdRms, float* mean, float* duration) {
- *rms = 0.0;
- *stdRms = 0.0;
- *duration = 0.0;
- float frameDur = 0.025; // Both the duration and interval of the
- // analysis frames.
- float calInterval = 0.250; // initial part of signal used to
- // establish background level (seconds).
- double sumFrameRms = 1.0;
- float sumSampleSquares = 0.0;
- double sumFrameSquares = 1.0; // init. to small number to avoid
- // log and divz problems.
- int frameSize = (int)(0.5 + (sampleRate * frameDur));
- int numFrames = numSamples / frameSize;
- int numCalFrames = int(0.5 + (calInterval / frameDur));
- if (numCalFrames < 1)
- numCalFrames = 1;
- int frame = 0;
-
- *mean = computeAndRemoveMean(pcm, numSamples);
-
- if (onsetThresh < 0.0) { // Handle the case where we want to
- // simply measure the RMS of the entire
- // input sequence.
- for (frame = 0; frame < numFrames; ++frame) {
- short* p_data = pcm + (frame * frameSize);
- int i;
- for (i = 0, sumSampleSquares = 0.0; i < frameSize; ++i) {
- float samp = p_data[i];
- sumSampleSquares += samp * samp;
- }
- sumSampleSquares /= frameSize;
- sumFrameSquares += sumSampleSquares;
- double localRms = sqrt(sumSampleSquares);
- sumFrameRms += localRms;
- }
- *rms = sumFrameRms / numFrames;
- *stdRms = sqrt((sumFrameSquares / numFrames) - (*rms * *rms));
- *duration = frameSize * numFrames / sampleRate;
- return;
- }
-
- /* This handles the case where we look for a target signal against a
- background, and expect the signal to start some time after the
- beginning, and to finish some time before the end of the input
- samples. */
- if (numFrames < (3 * numCalFrames)) {
- return;
- }
- float* calValues = new float[numCalFrames];
- float calMedian = 0.0;
- int onset = -1;
- int offset = -1;
-
- for (frame = 0; frame < numFrames; ++frame) {
- short* p_data = pcm + (frame * frameSize);
- int i;
- for (i = 0, sumSampleSquares = 1.0; i < frameSize; ++i) {
- float samp = p_data[i];
- sumSampleSquares += samp * samp;
- }
- sumSampleSquares /= frameSize;
- /* We handle three states: (1) before the onset of the signal; (2)
- within the signal; (3) following the signal. The signal is
- assumed to be at least onsetThresh dB above the background
- noise, and that at least one frame of silence/background
- precedes the onset of the signal. */
- if (onset < 0) { // (1)
- sumFrameSquares += sumSampleSquares;
- if (frame < numCalFrames ) {
- calValues[frame] = sumSampleSquares;
- continue;
- }
- if (frame == numCalFrames) {
- calMedian = getMedian(calValues, numCalFrames);
- if (calMedian < 10.0)
- calMedian = 10.0; // avoid divz, etc.
- }
- float ratio = 10.0 * log10(sumSampleSquares / calMedian);
- if (ratio > onsetThresh) {
- onset = frame;
- sumFrameSquares = 1.0;
- sumFrameRms = 1.0;
- }
- continue;
- }
- if ((onset > 0) && (offset < 0)) { // (2)
- int sig_frame = frame - onset;
- if (sig_frame < numCalFrames) {
- calValues[sig_frame] = sumSampleSquares;
- } else {
- if (sig_frame == numCalFrames) {
- calMedian = getMedian(calValues, numCalFrames);
- if (calMedian < 10.0)
- calMedian = 10.0; // avoid divz, etc.
- }
- float ratio = 10.0 * log10(sumSampleSquares / calMedian);
- int denFrames = frame - onset - 1;
- if (ratio < (-onsetThresh)) { // found signal end
- *rms = sumFrameRms / denFrames;
- *stdRms = sqrt((sumFrameSquares / denFrames) - (*rms * *rms));
- *duration = frameSize * (frame - onset) / sampleRate;
- offset = frame;
- continue;
- }
- }
- sumFrameSquares += sumSampleSquares;
- double localRms = sqrt(sumSampleSquares);
- sumFrameRms += localRms;
- continue;
- }
- if (offset > 0) { // (3)
- /* If we have found the real signal end, the level should stay
- low till data end. If not, flag this anomaly by increasing the
- reported duration. */
- float localRms = 1.0 + sqrt(sumSampleSquares);
- float localSnr = 20.0 * log10(*rms / localRms);
- if (localSnr < onsetThresh)
- *duration = frameSize * (frame - onset) / sampleRate;
- continue;
- }
- }
- delete [] calValues;
-}
-
diff --git a/apps/CtsVerifier/jni/audioquality/MeasureRms.h b/apps/CtsVerifier/jni/audioquality/MeasureRms.h
deleted file mode 100644
index 78b43ae..0000000
--- a/apps/CtsVerifier/jni/audioquality/MeasureRms.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef MEASURE_RMS_H
-#define MEASURE_RMS_H
-
-/* Measure the rms of the non-silence segment of the signal in pcm, which
- is of numSamples length, and sampled at sampleRate. pcm is assumed to
- consist of silence - signal - silence, as might be logged during a
- speech recognition attempt. The stimulus signal in this case should
- be approximately a 3-second burst of pink noise presented at a level
- comparable to normal speaking level. The RMS is measured using 25ms
- duration non-overlapping windows. These are averaged over the whole
- non-silence part of pcm, and the result is returned in rms. The
- standard deviation of this measurement over all frames is returned in
- stdRms, and the estimated duration of the non-silence region, in
- seconds, is returned in duration. The target signal is taken to be
- that segment that is onsetThresh dB above the background, and is
- expected to be continuous, once the onset has been found. If
- onsetThresh < 0.0, simply make the measurememt over the entire pcm
- signal. In both cases, the mean of the entire signal is returned in
- mean. */
-void measureRms(short* pcm, int numSamples, float sampleRate,
- float onsetThresh, float* rms, float* stdRms,
- float* mean, float* duration);
-
-
-#endif /* MEASURE_RMS_H */
diff --git a/apps/CtsVerifier/jni/audioquality/OverflowCheck.cpp b/apps/CtsVerifier/jni/audioquality/OverflowCheck.cpp
deleted file mode 100644
index 20e9285..0000000
--- a/apps/CtsVerifier/jni/audioquality/OverflowCheck.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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.
- */
-
-/* This assumes an input signal that has at least a few hundred
- milliseconds of high-amplitude sinusoidal signal. The signal is
- expected to be a relatively low-frequency sinusoid (200-400 Hz).
- If the signal is linearly reproduced or clipped, There will be no
- large step changes in value from one sample to the next. On the
- other hand, if the signal contains numerical overflow
- (wrap-around), very large excursions will be produced.
-
- This program first searches for the high-amplitude recorded
- segment, then examines just that part of the signal for "large
- excursions", and returns the results of the search as four
- integers:
-
- n_wraps signal_size sine_start sine_end
-
- where n_wraps is the number of anomolous value jumps found,
- signal_size is the number of lin16 samples found in the file,
- sine_start and sine_end are the limits of the region searched for
- anomolous jumps. */
-
-#include <stdlib.h>
-#include <math.h>
-
-// MAX_ALLOWED_STEP is the largest sample-to-sample change that will
-// be considered "normal" for 250 Hz signals sampled at 8kHz. This is
-// calibrated by the largest sample-to-sample change that is naturally
-// present in a 250 Hz sine wave with amplitude of 40000 (which is
-// actually 7804).
-#define MAX_ALLOWED_STEP 16000
-
-// This is the RMS value that is expected to be exceded by a sinusoid
-// with a peak amplitude of 32767 (actually 23169).
-#define SIGNAL_ON_RMS 12000.0
-
-static void findEndpoints(short* data, int n, int step, int* start, int* end) {
- int size = step;
- *start = *end = 0;
- int last_frame = n - size;
- for (int frame = 0; frame < last_frame; frame += step) {
- double sum = 0.0;
- for (int i=0; i < size; ++i) {
- float val = data[i + frame];
- sum += (val * val);
- }
- float rms = sqrt(sum / size);
- if (! *start) {
- if (rms >= SIGNAL_ON_RMS) {
- *start = frame + size;
- }
- continue;
- } else {
- if (rms < SIGNAL_ON_RMS) {
- *end = frame - size;
- return;
- }
- }
- }
- if ((*start > 0) && (! *end)) {
- *end = n - size - 1;
- }
-}
-
-static void checkExcursions(short* data, int start, int end, int* numJumps,
- int* maxPeak, int* minPeak) {
- *numJumps = 0;
- int endm = end - 1;
- if ((endm - start) < 3) {
- *numJumps = -1;
- return;
- }
- *maxPeak = *minPeak = data[start];
- for (int i = start; i < endm; ++i) {
- int v1 = data[i];
- int v2 = data[i+1];
- if (v1 > *maxPeak)
- *maxPeak = v1;
- if (v1 < *minPeak)
- *minPeak = v1;
- int diff = v2 - v1;
- if (diff < 0)
- diff = -diff;
- if (diff > MAX_ALLOWED_STEP)
- (*numJumps) += 1;
- }
- return;
-}
-
-int overflowCheck(short* pcm, int numSamples, float sampleRate,
- float* duration, int* numDeltas, int* onset, int* offset,
- int* maxPeak, int* minPeak) {
- float windSize = 0.020;
- int minBuff = int(2.0 * sampleRate); // must have 2 sec of data at least.
-
- if(pcm && (numSamples >= minBuff)) {
- int step = int(0.5 + (windSize * sampleRate));
- *onset = 0;
- *offset = 0;
-
- findEndpoints(pcm, numSamples, step, onset, offset);
- *numDeltas = -1;
- checkExcursions(pcm, *onset, *offset, numDeltas, maxPeak, minPeak);
- *duration = (*offset - *onset) / sampleRate;
- return 1; // true/success
- }
- return 0; // failure
-}
diff --git a/apps/CtsVerifier/jni/audioquality/OverflowCheck.h b/apps/CtsVerifier/jni/audioquality/OverflowCheck.h
deleted file mode 100644
index ea6d780..0000000
--- a/apps/CtsVerifier/jni/audioquality/OverflowCheck.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef OVERFLOW_CHECK_H
-#define OVERFLOW_CHECK_H
-
-/* This is a clipping/overflow check. This is designed to look for a
- ~3-second duration ~250 Hz pure tone at a level sufficient to cause
- about 20% clipping. It examines the recorded waveform for possible
- overflow/wraparound. The input signal of numSamples total sampled at
- sampleRate is in pcm. The expected signal contains silence - tone -
- silence. The approximate duration in seconds of the tone found is
- returned in duration. The number of unexpectedly-large jumps within
- the tone is returned in numDeltas. The approximate sample numbers of
- the tone endpoints are returned in onset and offset. The maximum
- and minimum found in the signal located between onset and offset are
- returned in maxPeak and minPeak, respectively. The function
- return is 1 if the operation was sucessful, 0 on failure. */
-int overflowCheck(short* pcm, int numSamples, float sampleRate,
- float* duration, int* numDeltas, int* onset, int* offset,
- int* maxPeak, int* minPeak);
-
-#endif // OVERFLOW_CHECK_H
diff --git a/apps/CtsVerifier/jni/audioquality/Window.cpp b/apps/CtsVerifier/jni/audioquality/Window.cpp
deleted file mode 100644
index 8e89ed4..0000000
--- a/apps/CtsVerifier/jni/audioquality/Window.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.
- */
-
-#include "Window.h"
-
-#include <stdlib.h>
-#include <math.h>
-
-void Window::windowCreate(int size) {
- if (mWindowWeights && (mWindowSize < size)) {
- delete [] mWindowWeights;
- mWindowWeights = NULL;
- mWindowSize = 0;
- }
- if (!mWindowWeights) {
- mWindowWeights = new float[size];
- }
- if (mWindowSize != size) {
- double arg = M_PI * 2.0 / size;
- mWindowSize = size;
- for (int i = 0; i < size; ++i) {
- mWindowWeights[i] = 0.5 - (0.5 * cos((i + 0.5) * arg));
- }
- }
-}
-
-void Window::windowCleanup() {
- mWindowSize = 0;
- delete [] mWindowWeights;
- mWindowWeights = NULL;
-}
-
-/* Multiply the signal in data by the window weights. Place the
- resulting mWindowSize floating-point values in output. If preemp
- is != 0.0, apply a 1st-order preemphasis filter, and assume that
- there are mWindowSize+1 samples available in data. */
-void Window::window(short* data, float* output, float preemp) {
- if (preemp == 0.0) {
- for (int i = 0; i < mWindowSize; ++i)
- output[i] = data[i] * mWindowWeights[i];
- } else {
- for (int i = 0; i < mWindowSize; ++i)
- output[i] = (data[i+1] - (preemp * data[i])) * mWindowWeights[i];
- }
-}
-
diff --git a/apps/CtsVerifier/jni/audioquality/Window.h b/apps/CtsVerifier/jni/audioquality/Window.h
deleted file mode 100644
index 08298354..0000000
--- a/apps/CtsVerifier/jni/audioquality/Window.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef WINDOW_INTERFACE_H
-#define WINDOW_INTERFACE_H
-
-class Window {
-public:
- Window(int size) : mWindowWeights(0), mWindowSize(0) {
- windowCreate(size);
- }
-
- Window() : mWindowWeights(0), mWindowSize(0) {
- }
-
- virtual ~Window(void) {
- windowCleanup();
- }
-
- /* Create a Hann window of length size. This allocates memory that
- should be freed using window_cleanup(). */
- void windowCreate(int size);
-
- /* Free up memory and reset size to 0. */
- void windowCleanup(void);
-
-
- /* Multiply the signal in data by the window weights. Place the
- resulting window_size floating-point values in output. If preemp
- is != 0.0, apply a 1st-order preemphasis filter, and assume that
- there are window_size+1 samples available in data. */
- void window(short* data, float* output, float preemp);
-
- int getWindowSize() { return mWindowSize; }
-
- float* getWindowWeights() { return mWindowWeights; }
-
-private:
- float* mWindowWeights;
- int mWindowSize;
-
-};
-
-#endif /* WINDOW_INTERFACE_H */
diff --git a/apps/CtsVerifier/jni/audioquality/Wrapper.cpp b/apps/CtsVerifier/jni/audioquality/Wrapper.cpp
deleted file mode 100644
index 438f0d89..0000000
--- a/apps/CtsVerifier/jni/audioquality/Wrapper.cpp
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * 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);
-
- JNIEXPORT jfloat JNICALL
- Java_com_android_cts_verifier_audioquality_Native_linearityTestRms(
- JNIEnv *env, jobject obj,
- jobjectArray jpcms,
- jfloat sampleRate, jfloat dbStepSize);
-};
-
-/* 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;
-}
-
-
-/* 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
- -6.0 One or more of the stimuli is too short in duration.
-*/
-JNIEXPORT jfloat JNICALL
- Java_com_android_cts_verifier_audioquality_Native_linearityTestRms(
- JNIEnv *env, jobject obj,
- jobjectArray jpcms,
- jfloat sampleRate, jfloat dbStepSize) {
- 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 = linearityTestRms(pcms, sampleCounts, numSignals,
- sampleRate, dbStepSize, &maxDeviation);
- delete[] sampleCounts;
- for (int i = 0; i < numSignals; i++) {
- delete[] pcms[i];
- }
- delete[] pcms;
- if (ret < 1) return ret;
-
- return maxDeviation;
-}
diff --git a/apps/CtsVerifier/res/layout/aq_row.xml b/apps/CtsVerifier/res/layout/aq_row.xml
deleted file mode 100644
index 5db33f3..0000000
--- a/apps/CtsVerifier/res/layout/aq_row.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="horizontal"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:background="#FF000000"
- >
- <TextView
- android:id="@+id/testName"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="22px"
- android:textColor="#FFFFFF"
- android:layout_margin="10px"
- />
- <TextView
- android:id="@+id/testScore"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:gravity="right"
- android:textSize="22px"
- android:textColor="#FFFFFF"
- android:layout_margin="10px"
- />
-</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/aq_sound_level_meter.xml b/apps/CtsVerifier/res/layout/aq_sound_level_meter.xml
deleted file mode 100644
index c3cc8f9..0000000
--- a/apps/CtsVerifier/res/layout/aq_sound_level_meter.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:gravity="center_horizontal"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:background="#FF000000"
- >
- <TextView
- android:id="@+id/label"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="20px"
- android:gravity="center_horizontal"
- android:textSize="18px"
- android:textColor="#FFFFFF"
- android:text="@string/aq_calibrate_volume_instructions"
- />
- <ProgressBar
- android:id="@+id/slider"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:max="2000"
- android:progress="1000"
- style="?android:attr/progressBarStyleHorizontal"
- android:padding="10px"
- />
- <TextView
- android:id="@+id/status"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:gravity="center_horizontal"
- android:textSize="18px"
- android:textColor="#FFFFFF"
- />
- <Button
- android:id="@+id/doneButton"
- android:text="@string/aq_done"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="20px"
- />
-</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/aq_verifier_activity.xml b/apps/CtsVerifier/res/layout/aq_verifier_activity.xml
deleted file mode 100644
index 3961e92..0000000
--- a/apps/CtsVerifier/res/layout/aq_verifier_activity.xml
+++ /dev/null
@@ -1,85 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:gravity="center_horizontal"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:background="#FF000000"
- >
- <FrameLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1.0"
- >
- <ListView
- android:id="@+id/list"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- />
- <ProgressBar
- android:id="@+id/progress"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:indeterminate="true"
- android:layout_gravity="center"
- android:visibility="invisible"
- />
- </FrameLayout>
-
- <LinearLayout
- android:gravity="center_horizontal"
- android:orientation="horizontal"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="10px"
- android:layout_marginBottom="10px"
- >
- <Button
- android:id="@+id/calibrateButton"
- android:text="@string/aq_calibrate"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
- <Button
- android:id="@+id/runAllButton"
- android:text="@string/aq_run_all"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
- <Button
- android:id="@+id/stopButton"
- android:text="@string/aq_stop"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
- <Button
- android:id="@+id/viewResultsButton"
- android:text="@string/aq_view_results"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
- <Button
- android:id="@+id/clearButton"
- android:text="@string/aq_clear"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
- </LinearLayout>
-
- <include layout="@layout/pass_fail_buttons" />
-
-</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/aq_view_results.xml b/apps/CtsVerifier/res/layout/aq_view_results.xml
deleted file mode 100644
index b8f020d0..0000000
--- a/apps/CtsVerifier/res/layout/aq_view_results.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:gravity="center_horizontal"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:background="#FF000000"
- >
- <ScrollView
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1.0"
- >
- <TextView
- android:id="@+id/textView"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:textSize="18px"
- android:textColor="#FFFFFF"
- />
- </ScrollView>
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="10px"
- android:layout_marginBottom="10px"
- >
- <Button
- android:id="@+id/dismissButton"
- android:text="@string/aq_dismiss"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
- <Button
- android:id="@+id/sendResultsButton"
- android:text="@string/aq_email_results"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
- </LinearLayout>
-</LinearLayout>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 0b449a5..b70d148 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -278,98 +278,6 @@
<string name="congratulations">Congratulations!</string>
<string name="no_suid_files">No unauthorized suid files detected!</string>
- <!-- Strings for Audio Quality Verifier -->
-
- <!-- Title for Audio Quality Verifier activity -->
- <string name="aq_verifier">Audio Quality Verifier</string>
- <string name="aq_verifier_info">
- 1. Click \"Calibrate\". Position the phone in front of the center of
- the speaker cone with the microphone facing the speaker,
- and adjust the volume of the speaker until the status message
- indicates it is correct.
- \n\n2. Click on any test in the list to run it, or \"Run All\" to run
- each test in sequence.
- \n\nIf the sound level check fails, go back to the calibration step before
- running any other test.
- \n\n3. Click \"Results\" to view the outcomes. A correctly functioning
- device should pass all tests.
- \n\n4. Click \"Send by email\" from the results page to send the
- results to an e-mail address of your choice. The recordings
- made are also attached as raw 16 bit, 16 kHz audio files to
- help you diagnose any failed tests.
- </string>
-
- <!-- Button labels for VerifierActivity -->
- <string name="aq_calibrate">Calibrate</string>
- <string name="aq_run_all">Run All</string>
- <string name="aq_stop">Stop</string>
- <string name="aq_view_results">Results</string>
- <string name="aq_email_results">Send by email</string>
- <string name="aq_clear">Clear</string>
-
- <!-- Title for ViewResultsActivity -->
- <string name="aq_view_results_name">Audio Quality Results</string>
- <!-- Button label for ViewResultsActivity -->
- <string name="aq_dismiss">Dismiss</string>
- <!-- E-mail subject line for test results -->
- <string name="aq_subject">Android Audio Quality Verifier Test Results</string>
-
- <!-- Title for CalibrateVolumeActivity -->
- <string name="aq_calibrate_volume_name">Calibrate Volume</string>
- <!-- Instructions for calibrating the volume -->
- <string name="aq_calibrate_volume_instructions">Adjust volume to the central point</string>
- <!-- Button label for CalibrateVolumeActivity -->
- <string name="aq_done">Done</string>
- <!-- Status values for CalibrateVolumeActivity -->
- <string name="aq_status_unknown">Status: unknown</string>
- <string name="aq_status_low">Volume too low</string>
- <string name="aq_status_high">Volume too high</string>
- <string name="aq_status_ok">Volume OK</string>
-
- <!-- Experiment names -->
- <string name="aq_default_exp">Unnamed experiment</string>
- <string name="aq_sound_level_exp">Sound level check</string>
- <string name="aq_spectrum_shape_exp">Spectrum shape test</string>
- <string name="aq_glitch_exp">Glitch test</string>
- <string name="aq_linearity_exp">Gain linearity test</string>
- <string name="aq_overflow_exp">Overflow check</string>
- <string name="aq_bias_exp">Bias measurement</string>
- <string name="aq_cold_latency">Cold recording latency</string>
- <string name="aq_warm_latency">Warm recording latency</string>
-
- <!-- Experiment outcomes -->
- <string name="aq_fail">Fail</string>
- <string name="aq_pass">Pass</string>
- <string name="aq_complete">Complete</string>
-
- <!-- Experiment reports -->
- <string name="aq_loopback_report">Experiment ran successfully.</string>
- <string name="aq_bias_report">Mean = %1$.3g, tolerance = +/- %2$.0f\nRMS = %3$.0f, duration = %4$.1fs</string>
- <string name="aq_overflow_report_error">Overflow check unsuccessful</string>
- <string name="aq_overflow_report_short">Insufficient tone detected.\nExpected %1$.1fs tone; observed %2$.1fs</string>
- <string name="aq_overflow_report_fail">"Overflow check failed due to discontinuities.\nObserved %1$d bad frames\nTone duration %2$.1fs\nMin peak = %3$.0f, max = %4$.0f</string>
- <string name="aq_overflow_report_pass">"Observed %1$d bad frames\nTone duration %2$.1fs\nMin peak = %3$.0f, max = %4$.0f</string>
- <string name="aq_linearity_report_error">Experiment failed, error code %1$g</string>
- <string name="aq_linearity_report_normal">Deviation from linearity = %1$.3g dB\nMax allowed = %2$.1f dB</string>
- <string name="aq_glitch_report_error">Error performing Glitch test.</string>
- <string name="aq_glitch_report_exact">%1$d glitches detected; expected %2$d, duration %3$.1fs</string>
- <string name="aq_glitch_report_range">%1$d glitches detected; expected %2$d-%3$d, duration %4$.1fs</string>
- <string name="aq_level_report">RMS = %1$.0f, target = %2$.0f\nTolerance = %3$.1f%%\nDuration = %4$.1fs</string>
- <string name="aq_spectrum_report_error">Cannot perform test.\nCheck volume is sufficiently high?</string>
- <string name="aq_spectrum_report_normal">RMS deviation = %1$.2f\nMax allowed deviation = %2$.1f</string>
-
- <string name="aq_cold_latency_report">Latency = %1$dms, maximum allowed = %2$dms</string>
- <string name="aq_warm_latency_report_error">RMS = %1$.0f, target = %2$.0f</string>
- <string name="aq_warm_latency_report_normal">Latency = %1$dms</string>
-
- <!-- General experiment messages -->
- <string name="aq_audiorecord_buffer_size_error">Error getting minimum AudioRecord buffer size: %1$d</string>
- <string name="aq_audiotrack_buffer_size_error">Error getting minimum AudioTrack buffer size: %1$d</string>
- <string name="aq_init_audiorecord_error">Error initializing AudioRecord instance</string>
- <string name="aq_init_audiotrack_error">Error initializing AudioTrack instance</string>
- <string name="aq_recording_error">Error reading data from AudioRecord instance</string>
- <string name="aq_exception_error">Exception thrown during test: %1$s</string>
-
<!-- Strings for Camera Analyzer -->
<string name="camera_analyzer">Camera Analyzer</string>
<string name="ca_find_checkerboard_label">Find color checker</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/AudioAssets.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/AudioAssets.java
deleted file mode 100644
index 7b7d427..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/AudioAssets.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.verifier.audioquality;
-
-import android.content.Context;
-import android.content.res.AssetManager;
-import android.util.Log;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-public class AudioAssets {
-
- private static final String TAG = "AudioQualityVerifier";
-
- private static final String STIM_BASENAME = "audioquality/stim_dt_";
-
- public static byte[] getStim(Context context, int which) {
- return readAsset(context, STIM_BASENAME + which);
- }
-
- public static byte[] getPinkNoise(Context context, int ampl, int duration) {
- return readAsset(context, "audioquality/pink_" + ampl + "_" + duration + "s");
- }
-
- private static byte[] readAsset(Context context, String filename) {
- AssetManager assetManager = context.getAssets();
- InputStream ais;
- try {
- ais = assetManager.open(filename);
- } catch (IOException e) {
- Log.e(TAG, "Cannot load asset " + filename, e);
- return null;
- }
- byte[] buffer = Utils.readFile(ais);
- return buffer;
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/AudioQualityVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/AudioQualityVerifierActivity.java
deleted file mode 100644
index af389a6..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/AudioQualityVerifierActivity.java
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.verifier.audioquality;
-
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.graphics.Color;
-import android.graphics.Typeface;
-import android.media.AudioFormat;
-import android.media.AudioManager;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.Button;
-import android.widget.ListView;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-import android.widget.AdapterView.OnItemClickListener;
-
-import java.util.ArrayList;
-
-/**
- * Main UI for the Android Audio Quality Verifier.
- */
-public class AudioQualityVerifierActivity extends PassFailButtons.Activity
- implements View.OnClickListener, OnItemClickListener {
- public static final String TAG = "AudioQualityVerifier";
-
- public static final int SAMPLE_RATE = 16000;
- public static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
- public static final int BYTES_PER_SAMPLE = 2;
- public static final int PLAYBACK_STREAM = AudioManager.STREAM_MUSIC;
-
- // Intent Extra definitions, which must match those in
- // com.google.android.voicesearch.speechservice.RecognitionController
- public static final String EXTRA_RAW_AUDIO =
- "android.speech.extras.RAW_AUDIO";
-
- // Communication with ExperimentService
- public static final String ACTION_EXP_STARTED =
- "com.android.cts.verifier.audioquality.EXP_STARTED";
- public static final String ACTION_EXP_FINISHED =
- "com.android.cts.verifier.audioquality.EXP_FINISHED";
- public static final String EXTRA_ABORTED =
- "com.android.cts.verifier.audioquality.ABORTED";
- public static final String EXTRA_EXP_ID =
- "com.android.cts.verifier.audioquality.EXP_ID";
- public static final String EXTRA_RUN_ALL =
- "com.android.cts.verifier.audioquality.RUN_ALL";
-
- // Communication with ViewResultsActivity
- public static final String EXTRA_RESULTS =
- "com.android.cts.verifier.audioquality.RESULTS";
-
- private Button mCalibrateButton;
- private Button mRunAllButton;
- private Button mStopButton;
- private Button mViewResultsButton;
- private Button mClearButton;
-
- private ListView mList;
- private TwoColumnAdapter mAdapter;
-
- private ProgressBar mProgress;
-
- private ArrayList<Experiment> mExperiments;
-
- private boolean mRunningExperiment;
-
- private BroadcastReceiver mReceiver;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.aq_verifier_activity);
- setPassFailButtonClickListeners();
- setInfoResources(R.string.aq_verifier, R.string.aq_verifier_info, -1);
-
- mCalibrateButton = (Button) findViewById(R.id.calibrateButton);
- mRunAllButton = (Button) findViewById(R.id.runAllButton);
- mStopButton = (Button) findViewById(R.id.stopButton);
- mViewResultsButton = (Button) findViewById(R.id.viewResultsButton);
- mClearButton = (Button) findViewById(R.id.clearButton);
-
- mCalibrateButton.setOnClickListener(this);
- mRunAllButton.setOnClickListener(this);
- mStopButton.setOnClickListener(this);
- mViewResultsButton.setOnClickListener(this);
- mClearButton.setOnClickListener(this);
-
- mStopButton.setEnabled(false);
-
- mProgress = (ProgressBar) findViewById(R.id.progress);
-
- mList = (ListView) findViewById(R.id.list);
- mAdapter = new TwoColumnAdapter(this);
-
- mExperiments = VerifierExperiments.getExperiments(this);
-
- mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- experimentReplied(intent);
- }
- };
- IntentFilter filter = new IntentFilter();
- filter.addAction(ACTION_EXP_STARTED);
- filter.addAction(ACTION_EXP_FINISHED);
- registerReceiver(mReceiver, filter);
-
- fillAdapter();
- mList.setAdapter(mAdapter);
- mList.setOnItemClickListener(this);
- adjustVolume();
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mAdapter.notifyDataSetChanged(); // Update List UI
- setVolumeControlStream(AudioManager.STREAM_MUSIC);
- adjustVolume();
- }
-
- private void adjustVolume() {
- AudioManager mgr = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
- mgr.setStreamMute(PLAYBACK_STREAM, false);
- int volume = mgr.getStreamVolume(PLAYBACK_STREAM);
- int max = mgr.getStreamMaxVolume(PLAYBACK_STREAM);
- int target = (max * 2) / 3;
- Log.i(TAG, "Volume " + volume + ", max " + max);
- if (volume != target) {
- mgr.setStreamVolume(PLAYBACK_STREAM, target, AudioManager.FLAG_SHOW_UI);
- }
- }
-
- // Called when an experiment has completed
- private void experimentReplied(Intent intent) {
- String action = intent.getAction();
- if (ACTION_EXP_STARTED.equals(action)) {
- mStopButton.setEnabled(true);
- mRunAllButton.setEnabled(false);
- } else if (ACTION_EXP_FINISHED.equals(action)) {
- boolean mRunAll = intent.getBooleanExtra(EXTRA_RUN_ALL, false);
- boolean aborted = intent.getBooleanExtra(EXTRA_ABORTED, true);
- int expID = intent.getIntExtra(EXTRA_EXP_ID, -1);
- if (mRunAll && !aborted) {
- while (expID < mExperiments.size() - 1) {
- if (runExperiment(++expID, true)) {
- // OK, experiment is running
- mAdapter.notifyDataSetChanged();
- return;
- }
- // Otherwise, loop back and try the next experiment
- }
- }
- mStopButton.setEnabled(false);
- mRunAllButton.setEnabled(true);
- mRunningExperiment = false;
- mProgress.setVisibility(ProgressBar.INVISIBLE);
- }
- mAdapter.notifyDataSetChanged();
- }
-
- // Implements AdapterView.OnItemClickListener
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- if (mRunningExperiment) return;
- adjustVolume();
- runExperiment(position, false);
- }
-
- // Begin an experiment. Returns false if the experiment is not enabled.
- private boolean runExperiment(int which, boolean all) {
- Experiment exp = mExperiments.get(which);
- if (!exp.isEnabled()) return false;
- Intent intent = new Intent(this, ExperimentService.class);
- intent.putExtra(EXTRA_EXP_ID, which);
- intent.putExtra(EXTRA_RUN_ALL, all);
- startService(intent);
- mRunningExperiment = true;
- mAdapter.notifyDataSetChanged();
- mProgress.setVisibility(ProgressBar.VISIBLE);
- return true;
- }
-
- // Implements View.OnClickListener:
- public void onClick(View v) {
- adjustVolume();
- if (v == mCalibrateButton) {
- Intent intent = new Intent(this, CalibrateVolumeActivity.class);
- startActivity(intent);
- } else if (v == mRunAllButton) {
- if (mRunningExperiment) return;
- int expID = -1;
- while (expID < mExperiments.size() - 1) {
- if (runExperiment(++expID, true)) break;
- }
- } else if (v == mStopButton) {
- Intent intent = new Intent(this, ExperimentService.class);
- stopService(intent);
- } else if (v == mViewResultsButton) {
- Intent intent = new Intent(this, ViewResultsActivity.class);
- intent.putExtra(EXTRA_RESULTS, genReport());
- startActivity(intent);
- } else if (v == mClearButton) {
- clear();
- }
- }
-
- private void fillAdapter() {
- mAdapter.clear();
- for (Experiment exp : mExperiments) {
- mAdapter.add(exp.getName());
- }
- }
-
- class TwoColumnAdapter extends ArrayAdapter<String> {
- TwoColumnAdapter(Context context) {
- super(context, R.layout.aq_row);
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- LayoutInflater inflater = getLayoutInflater();
- View row = inflater.inflate(R.layout.aq_row, parent, false);
- TextView nameField = (TextView) row.findViewById(R.id.testName);
- TextView scoreField = (TextView) row.findViewById(R.id.testScore);
- Experiment exp = mExperiments.get(position);
- nameField.setText(exp.getName());
- scoreField.setText(exp.getScore());
- if (exp.isRunning()) {
- Typeface tf = nameField.getTypeface();
- nameField.setTypeface(tf, 1);
- }
- if (!exp.isEnabled()) {
- nameField.setTextColor(Color.GRAY);
- }
- return row;
- }
- }
-
- private String genReport() {
- StringBuilder sb = new StringBuilder();
- for (Experiment exp : mExperiments) {
- exp.getReport(sb);
- }
- return sb.toString();
- }
-
- private void clear() {
- if (mRunningExperiment) {
- Intent intent = new Intent(this, ExperimentService.class);
- stopService(intent);
- }
- for (Experiment exp : mExperiments) {
- exp.reset();
- }
- mAdapter.notifyDataSetChanged();
- }
-
- @Override
- public String getTestDetails() {
- return genReport();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- unregisterReceiver(mReceiver);
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/BackgroundAudio.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/BackgroundAudio.java
deleted file mode 100644
index e55f9b7..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/BackgroundAudio.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.verifier.audioquality;
-
-import android.media.AudioFormat;
-import android.media.AudioTrack;
-import android.util.Log;
-
-/**
- * Continuously play background noise in a loop, until halt() is called.
- * Used to simulate noisy environments, and for sound level calibration.
- */
-public class BackgroundAudio extends Thread {
- public static final String TAG = "AudioQualityVerifier";
-
- private static final int BUFFER_TIME = 100; // Time in ms to buffer for
-
- private boolean mProceed;
- private AudioTrack mAudioTrack;
- private byte[] mData;
- private int mPos;
- private int mBufferSize;
-
- public void halt() {
- mProceed = false;
- }
-
- public BackgroundAudio(byte[] data) {
- mProceed = true;
- mData = data;
- mPos = 0;
-
- // Calculate suitable buffer size:
- final int minBufferSize = (BUFFER_TIME * AudioQualityVerifierActivity.SAMPLE_RATE
- * AudioQualityVerifierActivity.BYTES_PER_SAMPLE) / 1000;
- final int minHardwareBufferSize =
- AudioTrack.getMinBufferSize(AudioQualityVerifierActivity.SAMPLE_RATE,
- AudioFormat.CHANNEL_OUT_MONO, AudioQualityVerifierActivity.AUDIO_FORMAT);
- mBufferSize = Utils.getAudioTrackBufferSize(minBufferSize);
- Log.i(TAG, "minBufferSize = " + minBufferSize + ", minHWSize = " + minHardwareBufferSize
- + ", bufferSize = " + mBufferSize);
-
- // Start playback:
- Log.i(TAG, "Looping " + data.length + " bytes of audio, buffer size " + mBufferSize);
- mAudioTrack = new AudioTrack(AudioQualityVerifierActivity.PLAYBACK_STREAM,
- AudioQualityVerifierActivity.SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO,
- AudioQualityVerifierActivity.AUDIO_FORMAT, mBufferSize, AudioTrack.MODE_STREAM);
- if (mAudioTrack.getState() == AudioTrack.STATE_INITIALIZED) {
- writeAudio();
- start(); // Begin background thread to push audio data
- mAudioTrack.play();
- } else {
- Log.e(TAG, "Error initializing audio track.");
- }
- }
-
- @Override
- public void run() {
- while (true) {
- if (!mProceed) {
- mAudioTrack.stop();
- return; // End thread
- }
- writeAudio();
- }
- }
-
- private void writeAudio() {
- int len = mData.length;
- int count;
- int maxBytes = Math.min(mBufferSize, len - mPos);
-
- count = mAudioTrack.write(mData, mPos, maxBytes);
- if (count < 0) {
- Log.e(TAG, "Error writing looped audio data");
- halt();
- return;
- }
- mPos += count;
- if (mPos == len) {
- mPos = 0; // Wraparound
- }
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/CalibrateVolumeActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/CalibrateVolumeActivity.java
deleted file mode 100644
index 98e8cd1..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/CalibrateVolumeActivity.java
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.verifier.audioquality;
-
-import com.android.cts.verifier.R;
-
-import android.app.Activity;
-import android.media.AudioFormat;
-import android.media.AudioRecord;
-import android.media.MediaRecorder;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.util.Log;
-import android.view.View;
-import android.widget.Button;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-
-/**
- * Play a continuous sound and allow the user to monitor the sound level
- * at the mic in real time, relative to the range the phone can detect.
- * This is not an absolute sound level meter, but lets the speaker volume
- * and position be adjusted so that the clipping point is known.
- */
-public class CalibrateVolumeActivity extends Activity implements View.OnClickListener {
- public static final String TAG = "AudioQualityVerifier";
-
- public static final int OUTPUT_AMPL = 5000;
- public static final float TARGET_RMS = 5000.0f;
- public static final float TARGET_AMPL = (float) (TARGET_RMS * Math.sqrt(2.0));
- private static final float FREQ = 625.0f;
-
- private static final float TOLERANCE = 1.03f;
-
- private static final int DEBOUNCE_TIME = 500; // Minimum time in ms between status text changes
- public static final boolean USE_PINK = false;
-
- private ProgressBar mSlider;
- private Button mDoneButton;
- private TextView mStatus;
- private BackgroundAudio mBackgroundAudio;
- private Monitor mMonitor;
- private Handler mHandler;
-
- private Native mNative;
-
- enum Status { LOW, OK, HIGH, UNDEFINED }
- private static int[] mStatusText = {
- R.string.aq_status_low, R.string.aq_status_ok, R.string.aq_status_high };
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.aq_sound_level_meter);
-
- mSlider = (ProgressBar) findViewById(R.id.slider);
- mStatus = (TextView) findViewById(R.id.status);
- mStatus.setText(R.string.aq_status_unknown);
-
- mDoneButton = (Button) findViewById(R.id.doneButton);
- mDoneButton.setOnClickListener(this);
-
- mNative = Native.getInstance();
- mHandler = new UpdateHandler();
- }
-
- // Implements View.OnClickListener
- public void onClick(View v) {
- if (v == mDoneButton) {
- finish();
- }
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- final int DURATION = 1;
- final float RAMP = 0.0f;
- byte[] noise;
- if (USE_PINK) {
- noise = Utils.getPinkNoise(this, OUTPUT_AMPL, DURATION);
- } else {
- short[] sinusoid = mNative.generateSinusoid(FREQ, DURATION,
- AudioQualityVerifierActivity.SAMPLE_RATE, OUTPUT_AMPL, RAMP);
- noise = Utils.shortToByteArray(sinusoid);
- }
- float[] results = mNative.measureRms(Utils.byteToShortArray(noise),
- AudioQualityVerifierActivity.SAMPLE_RATE, -1.0f);
- float rms = results[Native.MEASURE_RMS_RMS];
- Log.i(TAG, "Stimulus amplitude " + OUTPUT_AMPL + ", RMS " + rms);
- mBackgroundAudio = new BackgroundAudio(noise);
- mMonitor = new Monitor();
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- mBackgroundAudio.halt();
- mMonitor.halt();
- }
-
- private class UpdateHandler extends Handler {
- private Status mState = Status.UNDEFINED;
- private long mTimestamp = 0; // Time of last status change in ms
-
- @Override
- public void handleMessage(Message msg) {
- int rms = msg.arg1;
- int max = mSlider.getMax();
- int progress = (max / 2 * rms) / Math.round(TARGET_RMS);
- if (progress > max) progress = max;
- mSlider.setProgress(progress);
-
- Status state;
- if (rms * TOLERANCE < TARGET_RMS) state = Status.LOW;
- else if (rms > TARGET_RMS * TOLERANCE) state = Status.HIGH;
- else state = Status.OK;
- if (state != mState) {
- long timestamp = System.currentTimeMillis();
- if (timestamp - mTimestamp > DEBOUNCE_TIME) {
- mStatus.setText(mStatusText[state.ordinal()]);
- mState = state;
- mTimestamp = timestamp;
- }
- }
- }
- }
-
- class Monitor extends Thread {
- private static final int BUFFER_TIME = 100; // Min time in ms to buffer for
- private static final int READ_TIME = 25; // Max length of time in ms to read in one chunk
- private static final boolean DEBUG = false;
-
- private AudioRecord mRecord;
- private int mSamplesToRead;
- private byte[] mBuffer;
- private boolean mProceed;
-
- Monitor() {
- mProceed = true;
-
- mSamplesToRead = (READ_TIME * AudioQualityVerifierActivity.SAMPLE_RATE) / 1000;
- mBuffer = new byte[mSamplesToRead * AudioQualityVerifierActivity.BYTES_PER_SAMPLE];
-
- final int minBufferSize = (BUFFER_TIME * AudioQualityVerifierActivity.SAMPLE_RATE *
- AudioQualityVerifierActivity.BYTES_PER_SAMPLE) / 1000;
- final int bufferSize = Utils.getAudioRecordBufferSize(minBufferSize);
-
- mRecord = new AudioRecord(MediaRecorder.AudioSource.VOICE_RECOGNITION,
- AudioQualityVerifierActivity.SAMPLE_RATE, AudioFormat.CHANNEL_IN_MONO,
- AudioQualityVerifierActivity.AUDIO_FORMAT, bufferSize);
- if (mRecord.getState() != AudioRecord.STATE_INITIALIZED) {
- Log.e(TAG, "Couldn't open audio for recording");
- return;
- }
- mRecord.startRecording();
- if (mRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
- Log.e(TAG, "Couldn't record");
- return;
- }
-
- start(); // Begin background thread
- }
-
- public void halt() {
- mProceed = false;
- }
-
- @Override
- public void run() {
- int maxBytes = mSamplesToRead * AudioQualityVerifierActivity.BYTES_PER_SAMPLE;
- int bytes;
- while (true) {
- if (!mProceed) {
- mRecord.stop();
- mRecord.release();
- return; // End thread
- }
- bytes = mRecord.read(mBuffer, 0, maxBytes);
- if (bytes < 0) {
- if (bytes == AudioRecord.ERROR_INVALID_OPERATION) {
- Log.e(TAG, "Recording object not initalized");
- } else if (bytes == AudioRecord.ERROR_BAD_VALUE) {
- Log.e(TAG, "Invalid recording parameters");
- } else {
- Log.e(TAG, "Error during recording");
- }
- return;
- }
- if (bytes >= 2) {
- // Note: this won't work well if bytes is small (we should check)
- short[] samples = Utils.byteToShortArray(mBuffer, 0, bytes);
- float[] results = mNative.measureRms(samples,
- AudioQualityVerifierActivity.SAMPLE_RATE, -1.0f);
- float rms = results[Native.MEASURE_RMS_RMS];
- float duration = results[Native.MEASURE_RMS_DURATION];
- float mean = results[Native.MEASURE_RMS_MEAN];
- if (DEBUG) {
- // Confirm the RMS calculation
- float verifyRms = 0.0f;
- for (short x : samples) {
- verifyRms += x * x;
- }
- verifyRms /= samples.length;
- Log.i(TAG, "RMS: " + rms + ", bytes: " + bytes
- + ", duration: " + duration + ", mean: " + mean
- + ", manual RMS: " + Math.sqrt(verifyRms));
- }
- Message msg = mHandler.obtainMessage();
- msg.arg1 = Math.round(rms);
- mHandler.sendMessage(msg);
- }
- }
- }
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/Experiment.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/Experiment.java
deleted file mode 100644
index bd5f186..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/Experiment.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.verifier.audioquality;
-
-import java.util.ArrayList;
-import java.util.List;
-import com.android.cts.verifier.R;
-
-import android.content.Context;
-import android.util.Log;
-
-/**
- * The base class for all audio experiments.
- */
-public class Experiment implements Runnable {
- private static final String TAG = "AudioQualityVerifier";
-
- private static final int DEFAULT_TIMEOUT = 5; // In seconds
-
- private String mName;
- private String mScore;
- private String mReport;
- private List<String> mAudioFileNames;
-
- enum Status { NotStarted, Running, Stopped, Completed }
- private Status mStatus;
- private boolean mEnabled;
-
- protected Native mNative;
- protected Context mContext;
- protected Terminator mTerminator;
-
- public Experiment(boolean enable) {
- mEnabled = enable;
- mNative = Native.getInstance();
- reset();
- }
-
- public void init(Context context) {
- mName = lookupName(context);
- }
-
- protected String lookupName(Context context) {
- return context.getString(R.string.aq_default_exp);
- }
-
- protected String getString(int resId) {
- return mContext.getString(resId);
- }
-
- public boolean isEnabled() {
- return mEnabled;
- }
-
- public void reset() {
- mStatus = Status.NotStarted;
- mScore = "";
- mReport = "";
- mAudioFileNames = new ArrayList<String>();
- }
-
- public void start() {
- mStatus = Status.Running;
- }
-
- protected void setScore(String score) {
- mScore = score;
- }
-
- protected void setReport(String report) {
- mReport = report;
- }
-
- // Implements Runnable
- public void run() {}
-
- public void run(Context context, Terminator t) {
- mContext = context;
- mTerminator = t;
- Thread thread = new Thread(this);
- thread.start();
- }
-
- public void setRecording(byte[] data) {
- setRecording(data, -1);
- }
-
- public void setRecording(byte[] data, int num) {
- // Save captured data to file
- String filename = Utils.getExternalDir(mContext, this) + "/"
- + Utils.cleanString(getName())
- + (num == -1 ? "" : "_" + String.valueOf(num)) + ".raw";
- Log.i(TAG, "Saving recorded data to " + filename);
- Utils.saveFile(filename, data);
- mAudioFileNames.add(filename);
- }
-
- public List<String> getAudioFileNames() {
- return mAudioFileNames;
- }
-
- // Timeout in seconds
- public int getTimeout() {
- return DEFAULT_TIMEOUT;
- }
-
- public void cancel() {
- mStatus = Status.Stopped;
- }
-
- public void stop() {
- mStatus = Status.Completed;
- }
-
- public boolean isRunning() {
- return mStatus == Status.Running;
- }
-
- public String getName() {
- return mName;
- }
-
- public String getScore() {
- switch (mStatus) {
- case NotStarted:
- return "-";
- case Running:
- return "...";
- case Stopped:
- return "-";
- case Completed:
- return mScore;
- }
- return "";
- }
-
- public void getReport(StringBuilder sb) {
- sb.append(getName());
- sb.append(": ");
- sb.append(getScore());
- sb.append("\n");
- sb.append(mReport);
- sb.append("\n\n");
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/ExperimentService.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/ExperimentService.java
deleted file mode 100644
index 95fd3b5..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/ExperimentService.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.verifier.audioquality;
-
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.PowerManager;
-import android.util.Log;
-
-import java.util.ArrayList;
-
-/**
- * Launch an experiment.
- *
- * Experiments are decoupled from the UI both so that they can run on a
- * background thread without freezing the UI, and to support experiments
- * which take over the screen from the UI (such as invoking Voice Search).
- */
-public class ExperimentService extends Service implements Terminator {
- private static final String TAG = "AudioQualityVerifier";
- private static int BACKGROUND_LOAD = 0;
-
- private ArrayList<Experiment> mExperiments;
- private Experiment mExp;
-
- private TimeoutHandler mHandler = null;
- private PowerManager.WakeLock mWakeLock = null;
-
- private boolean mRunAll;
- private int mExpID;
-
- private boolean mActive;
- private LoadGenerator[] mLoadGenerator = null;
-
- @Override
- public IBinder onBind(Intent intent) {
- return null;
- }
-
- @Override
- public void onCreate() {
- mExperiments = VerifierExperiments.getExperiments(this);
- }
-
- @Override
- public void onDestroy() {
- Log.i(TAG, "Service destroyed");
- terminate(true);
- }
-
- /**
- * Implements Terminator, to clean up when the experiment indicates it
- * has completed.
- */
- public void terminate(boolean aborted) {
- if (mLoadGenerator != null) {
- for (LoadGenerator generator : mLoadGenerator) {
- generator.halt();
- }
- mLoadGenerator = null;
- }
- if (!mActive) return;
- mActive = false;
- if (mHandler != null) mHandler.clear();
- if (aborted) {
- mExp.cancel();
- } else {
- mExp.stop();
- }
- Intent intent = new Intent(AudioQualityVerifierActivity.ACTION_EXP_FINISHED);
- intent.putExtra(AudioQualityVerifierActivity.EXTRA_EXP_ID, mExpID);
- intent.putExtra(AudioQualityVerifierActivity.EXTRA_RUN_ALL, mRunAll);
- intent.putExtra(AudioQualityVerifierActivity.EXTRA_ABORTED, aborted);
- sendBroadcast(intent);
- if (mWakeLock != null) {
- mWakeLock.release();
- mWakeLock = null;
- }
- }
-
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- mActive = true;
-
- // Obtain wakelock
- PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
- mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, TAG);
- mWakeLock.acquire();
-
- if (BACKGROUND_LOAD > 0) {
- mLoadGenerator = new LoadGenerator[BACKGROUND_LOAD];
- for (int i = 0; i < BACKGROUND_LOAD; i++) {
- mLoadGenerator[i] = new LoadGenerator();
- }
- }
-
- mExpID = intent.getIntExtra(AudioQualityVerifierActivity.EXTRA_EXP_ID, -1);
- if (mExpID == -1) {
- Log.e(TAG, "Invalid test ID");
- System.exit(0);
- }
- mRunAll = intent.getBooleanExtra(AudioQualityVerifierActivity.EXTRA_RUN_ALL, false);
- mExp = mExperiments.get(mExpID);
- mExp.start();
-
- // Inform the VerifierActivity Activity that we have started:
- Intent feedback = new Intent(AudioQualityVerifierActivity.ACTION_EXP_STARTED);
- feedback.putExtra(AudioQualityVerifierActivity.EXTRA_EXP_ID, mExpID);
- sendBroadcast(feedback);
-
- mHandler = new TimeoutHandler();
- mHandler.delay(mExp.getTimeout());
- mExp.run(this, this);
-
- return START_NOT_STICKY;
- }
-
- class TimeoutHandler extends Handler {
- @Override
- public void handleMessage(Message msg) {
- terminate(true);
- stopSelf();
- }
-
- public void delay(int secs) {
- removeMessages(0);
- sendMessageDelayed(obtainMessage(0), secs * 1000);
- }
-
- public void clear() {
- removeMessages(0);
- }
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/LoadGenerator.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/LoadGenerator.java
deleted file mode 100644
index f19359c..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/LoadGenerator.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.verifier.audioquality;
-
-/**
- * Simulate a simple load on the CPU, to determine the effect on recording.
- * A better approach would be to generate network activity, to
- * trigger interrupts as well.
- */
-public class LoadGenerator extends Thread {
- private boolean mProceed;
-
- public LoadGenerator() {
- mProceed = true;
- start(); // Begin thread
- }
-
- public void halt() {
- mProceed = false;
- }
-
- @Override
- public void run() {
- long counter = 0;
- while (mProceed) {
- counter++; // Busy loop
- }
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/Native.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/Native.java
deleted file mode 100644
index cdb3e25..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/Native.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.verifier.audioquality;
-
-/**
- * Interface to native (C++) DSP code.
- */
-public class Native {
- public native short[] generateSinusoid(float freq, float duration,
- float sampleRate, float amplitude, float ramp);
- public native float[] measureRms(short[] pcm, float sampleRate,
- float onsetThresh);
- public native float[] glitchTest(float sampleRate, float stimFreq,
- float onsetThresh, float dbSnrThresh, short[] pcm);
- public native float[] overflowCheck(short[] pcm, float sampleRate);
- public native float[] compareSpectra(short[] pcm, short[] refPcm,
- float sampleRate);
- public native float linearityTest(short[][] pcms,
- float sampleRate, float dbStepSize, int referenceStim);
- public native float linearityTestRms(short[][] pcms,
- float sampleRate, float dbStepSize);
-
- // The following indexes must match those in wrapper.cc
- public static final int MEASURE_RMS_RMS = 0;
- public static final int MEASURE_RMS_STD_DEV = 1;
- public static final int MEASURE_RMS_DURATION = 2;
- public static final int MEASURE_RMS_MEAN = 3;
-
- public static final int OVERFLOW_DELTAS = 0;
- public static final int OVERFLOW_ERROR = 1;
- public static final int OVERFLOW_DURATION = 2;
- public static final int OVERFLOW_ONSET = 3;
- public static final int OVERFLOW_OFFSET = 4;
- public static final int OVERFLOW_MAX = 5;
- public static final int OVERFLOW_MIN = 6;
-
- public static final int GLITCH_COUNT = 0;
- public static final int GLITCH_ERROR = 1;
- public static final int GLITCH_DURATION = 2;
-
- public static final int SPECTRUM_MAX_DEVIATION = 0;
- public static final int SPECTRUM_ERROR = 1;
- public static final int SPECTRUM_RMS_DEVIATION = 2;
-
- private static Native mInstance = null;
-
- static {
- System.loadLibrary("audioquality");
- }
-
- private Native() {}
-
- public static Native getInstance() {
- if (mInstance == null) {
- mInstance = new Native();
- }
- return mInstance;
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/README.txt b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/README.txt
deleted file mode 100644
index 3f9a59c..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/README.txt
+++ /dev/null
@@ -1,96 +0,0 @@
-Android Audio Quality Verifier App
-==================================
-
-This app runs a set of audio quality tests on an Android device,
-to verify the end-end sound recording path.
-
-If any of these tests fail, the device is probably unsuitable
-for demanding audio tasks such as speech recognition.
-If all the tests pass, the device audio is of a good standard.
-Note that not all possible audio defects can be detected by this
-test suite, so passing does not guarantee ideal audio quality.
-
-Hardware setup
---------------
-
-The required physical set-up consists of a powered speaker,
-connected to the Android's headphone output by a standard
-audio cable.
-
-For loudspeakers which come in pairs, you only need to use
-one speaker (typically the powered or master speaker); you
-can leave the second speaker disconnected.
-If the speakers are stereo within a single unit (sometimes
-with speakers facing in opposite directions), place the phone
-in front of either of them.
-Speakers with multiple drivers per channel (e.g. a tweeter
-and a woofer) are not suitable.
-
-The phone should be placed in front of the centre of the
-speaker cone. The distance from the speaker will be adjusted
-during calibration; typically you could expect it to be around
-3cm or so.
-Use a supporting platform such as a stack of books to raise
-the phone to the correct height to line up with the speaker.
-
-Bluetooth connection is possible but cable connection is
-usually preferable.
-
-Recommended loudspeakers
-------------------------
-
-Using suitable loudspeakers ensures that test failures highlight
-problems with the Android device under test, and not limitations
-of the loudspeakers. The following loudspeakers work well for this
-purpose:
-
-1. Yamaha NX-B02
-
-Use on AC power, not batteries.
-This speaker works well with Bluetooth as well as a wired connection.
-Note that it's not uncommon for the devices to exhibit different
-bugs under Bluetooth.
-
-2. Cakewalk MA-7A (Edirol / Roland)
-
-The "Bass Enhancer" feature MUST be switched off.
-Note that it turns itself on again every time the speakers are
-powered on, so it is easy to forget to switch it off!
-
-Software setup
---------------
-
-1. Build the application's apk.
-2. Install the apk using adb.
-3. Run the app.
-4. Click "Calibrate". Position the phone as described in
- Hardware setup above, with the microphone facing the speaker,
- and adjust the volume of the speaker until the status message
- indicates it is correct.
-5. Click on any test in the list to run it, or "Run All" to run
- each test in sequence.
-6. Click "Results" to view the outcomes. A correctly functioning
- device should pass all tests.
-7. Click "Send by email" from the results page to send the
- results to an e-mail address of your choice. The recordings
- made are also attached as raw 16 bit, 16 kHz audio files to
- help you diagnose any failed tests.
-
-Q&A
----
-
-Q. What if the sound level check fails?
-A. Go back to the calibration step before running any other test.
- Make sure the device has not been moved.
- We also recommend that once the setup is calibrated there are no
- moving objects or people near the device under test, since these
- will change the acoustic properties of the environment from the
- calibrated state.
-
-Q. Some of the tests sound very loud. Is this normal?
-A. The clipping test will generally be very loud indeed;
- the others should be at a moderate volume.
-
-Q. What sort of room should the tests be performed in?
-A. Any, as long as the background noise levels are kept low, to
- avoid interference with the test recordings.
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/Terminator.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/Terminator.java
deleted file mode 100644
index b0edc90..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/Terminator.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.verifier.audioquality;
-
-/**
- * Interface passed to each Experiment.
- */
-public interface Terminator {
- /**
- * Indicate that the experiment has finished.
- *
- * @param aborted is true if the experiment terminated abnormally.
- */
- public void terminate(boolean aborted);
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/Utils.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/Utils.java
deleted file mode 100644
index f2019c2..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/Utils.java
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.verifier.audioquality;
-
-import android.content.Context;
-import android.media.AudioFormat;
-import android.media.AudioRecord;
-import android.media.AudioTrack;
-import android.os.Environment;
-import android.util.Log;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * File and data utilities for the Audio Verifier.
- */
-public class Utils {
- public static final String TAG = "AudioQualityVerifier";
- public static final ByteOrder BYTE_ORDER = ByteOrder.LITTLE_ENDIAN;
-
- /**
- * @param minBufferSize requested
- * @return the buffer size or a negative {@link AudioTrack} ERROR value
- */
- public static int getAudioTrackBufferSize(int minBufferSize) {
- int minHardwareBufferSize = AudioTrack.getMinBufferSize(
- AudioQualityVerifierActivity.SAMPLE_RATE,
- AudioFormat.CHANNEL_OUT_MONO,
- AudioQualityVerifierActivity.AUDIO_FORMAT);
- if (minHardwareBufferSize < 0) {
- return minHardwareBufferSize;
- } else {
- return Math.max(minHardwareBufferSize, minBufferSize);
- }
- }
-
- /**
- * @param minBufferSize requested
- * @return the buffer size or a negative {@link AudioRecord} ERROR value
- */
- public static int getAudioRecordBufferSize(int minBufferSize) {
- int minHardwareBufferSize = AudioRecord.getMinBufferSize(
- AudioQualityVerifierActivity.SAMPLE_RATE,
- AudioFormat.CHANNEL_IN_MONO,
- AudioQualityVerifierActivity.AUDIO_FORMAT);
- if (minHardwareBufferSize < 0) {
- return minHardwareBufferSize;
- } else {
- return Math.max(minHardwareBufferSize, minBufferSize);
- }
- }
-
- /**
- * Time delay.
- *
- * @param ms time in milliseconds to pause for
- */
- public static void delay(int ms) {
- try {
- Thread.sleep(ms);
- } catch (InterruptedException e) {}
- }
-
- public static String getExternalDir(Context context, Object exp) {
- checkExternalStorageAvailable();
- // API level 8:
- // return context.getExternalFilesDir(null).getAbsolutePath();
- // API level < 8:
- String dir = Environment.getExternalStorageDirectory().getAbsolutePath();
- dir += "/Android/data/" + exp.getClass().getPackage().getName() + "/files";
- checkMakeDir(dir);
- return dir;
- }
-
- private static void checkExternalStorageAvailable() {
- String state = Environment.getExternalStorageState();
- if (!Environment.MEDIA_MOUNTED.equals(state)) {
- // TODO: Raise a Toast and supply internal storage instead
- }
- }
-
- private static void checkMakeDir(String dir) {
- File f = new File(dir);
- if (!f.exists()) {
- f.mkdirs();
- }
- }
-
- /**
- * Convert a string (e.g. the name of an experiment) to something more suitable
- * for use as a filename.
- *
- * @param s the string to be cleaned
- * @return a string which is similar (not necessarily unique) and safe for filename use
- */
- public static String cleanString(String s) {
- StringBuilder sb = new StringBuilder();
- for (char c : s.toCharArray()) {
- if (Character.isWhitespace(c)) sb.append('_');
- else if (Character.isLetterOrDigit(c)) sb.append(c);
- }
- return sb.toString();
- }
-
- /**
- * Convert a sub-array from bytes to shorts.
- *
- * @param data array of bytes to be converted
- * @param start first index to convert (should be even)
- * @param len number of bytes to convert (should be even)
- * @return an array of half the length, containing shorts
- */
- public static short[] byteToShortArray(byte[] data, int start, int len) {
- short[] samples = new short[len / 2];
- ByteBuffer bb = ByteBuffer.wrap(data, start, len);
- bb.order(BYTE_ORDER);
- for (int i = 0; i < len / 2; i++) {
- samples[i] = bb.getShort();
- }
- return samples;
- }
-
- /**
- * Convert a byte array to an array of shorts (suitable for the phone test
- * native library's audio sample data).
- *
- * @param data array of bytes to be converted
- * @return an array of half the length, containing shorts
- */
- public static short[] byteToShortArray(byte[] data) {
- int len = data.length / 2;
- short[] samples = new short[len];
- ByteBuffer bb = ByteBuffer.wrap(data);
- bb.order(BYTE_ORDER);
- for (int i = 0; i < len; i++) {
- samples[i] = bb.getShort();
- }
- return samples;
- }
-
- /**
- * Convert a short array (as returned by the phone test native library)
- * to an array of bytes.
- *
- * @param samples array of shorts to be converted
- * @return an array of twice the length, broken out into bytes
- */
- public static byte[] shortToByteArray(short[] samples) {
- int len = samples.length;
- byte[] data = new byte[len * 2];
- ByteBuffer bb = ByteBuffer.wrap(data);
- bb.order(BYTE_ORDER);
- for (int i = 0; i < len; i++) {
- bb.putShort(samples[i]);
- }
- return data;
- }
-
- /**
- * Scale the amplitude of an array of samples.
- *
- * @param samples to be scaled
- * @param db decibels to scale up by (may be negative)
- * @return the scaled samples
- */
- public static short[] scale(short[] samples, float db) {
- short[] scaled = new short[samples.length];
- // Convert decibels to a linear ratio:
- double ratio = Math.pow(10.0, db / 20.0);
- for (int i = 0; i < samples.length; i++) {
- scaled[i] = (short) (samples[i] * ratio);
- }
- return scaled;
- }
-
- /**
- * Read an entire file into memory.
- *
- * @param filename to be opened
- * @return the file data, or null in case of error
- */
- private static byte[] readFile(String filename) {
- FileInputStream fis;
- try {
- fis = new FileInputStream(filename);
- } catch (FileNotFoundException e1) {
- return null;
- }
-
- File file = new File(filename);
- int len = (int) file.length();
- byte[] data = new byte[len];
-
- int pos = 0;
- int bytes = 0;
- int count;
- while (pos < len) {
- try {
- count = fis.read(data, pos, len - pos);
- } catch (IOException e) {
- return null;
- }
- if (count < 1) return null;
- pos += count;
- }
-
- try {
- fis.close();
- } catch (IOException e) {}
- return data;
- }
-
- /**
- * Read an entire file from an InputStream.
- * Useful as AssetManager returns these.
- *
- * @param stream to read file contents from
- * @return file data
- */
- public static byte[] readFile(InputStream stream) {
- final int CHUNK_SIZE = 10000;
- ByteArrayBuilder bab = new ByteArrayBuilder();
- byte[] buf = new byte[CHUNK_SIZE];
- int count;
- while (true) {
- try {
- count = stream.read(buf, 0, CHUNK_SIZE);
- } catch (IOException e) {
- return null;
- }
- if (count == -1) break; // EOF
- bab.append(buf, count);
- }
- return bab.toByteArray();
- }
-
- /**
- * Save binary (audio) data to a file.
- *
- * @param filename to be written
- * @param data contents
- */
- public static void saveFile(String filename, byte[] data) {
- try {
- FileOutputStream fos = new FileOutputStream(filename);
- fos.write(data);
- fos.close();
- } catch (IOException e) {
- Log.e(TAG, "Error writing to file " + filename, e);
- }
- }
-
- /**
- * Push an entire array of audio data to an AudioTrack.
- *
- * @param at destination
- * @param data to be written
- * @return true if successful, or false on error
- */
- public static boolean writeAudio(AudioTrack at, byte[] data) {
- int pos = 0;
- int len = data.length;
- int count;
-
- while (pos < len) {
- count = at.write(data, pos, len - pos);
- if (count < 0) return false;
- pos += count;
- }
- at.flush();
- return true;
- }
-
- /**
- * Determine the number of audio samples in a file
- *
- * @param filename file containing audio data
- * @return number of samples in file, or 0 if file does not exist
- */
- public static int duration(String filename) {
- File file = new File(filename);
- int len = (int) file.length();
- return len / AudioQualityVerifierActivity.BYTES_PER_SAMPLE;
- }
-
- /**
- * Determine the number of audio samples in a stimulus asset
- *
- * @param context to look up stimulus
- * @param stimNum index number of this stimulus
- * @return number of samples in stimulus
- */
- public static int duration(Context context, int stimNum) {
- byte[] data = AudioAssets.getStim(context, stimNum);
- return data.length / AudioQualityVerifierActivity.BYTES_PER_SAMPLE;
- }
-
- public static AudioTrack playRawFile(String filename) {
- byte[] data = readFile(filename);
- if (data == null) {
- Log.e(TAG, "Cannot read " + filename);
- return null;
- }
- return playRaw(data);
- }
-
- public static AudioTrack playStim(Context context, int stimNum) {
- return Utils.playRaw(getStim(context, stimNum));
- }
-
- public static byte[] getStim(Context context, int stimNum) {
- return AudioAssets.getStim(context, stimNum);
- }
-
- public static byte[] getPinkNoise(Context context, int ampl, int duration) {
- return AudioAssets.getPinkNoise(context, ampl, duration);
- }
-
- public static AudioTrack playRaw(byte[] data) {
- Log.i(TAG, "Playing " + data.length + " bytes of pre-recorded audio");
- AudioTrack at = new AudioTrack(AudioQualityVerifierActivity.PLAYBACK_STREAM, AudioQualityVerifierActivity.SAMPLE_RATE,
- AudioFormat.CHANNEL_OUT_MONO, AudioQualityVerifierActivity.AUDIO_FORMAT,
- data.length, AudioTrack.MODE_STREAM);
- writeAudio(at, data);
- at.play();
-
- return at;
- }
-
- /**
- * The equivalent of a simplified StringBuilder, but for bytes.
- */
- public static class ByteArrayBuilder {
- private byte[] buf;
- private int capacity, size;
-
- public ByteArrayBuilder() {
- capacity = 100;
- size = 0;
- buf = new byte[capacity];
- }
-
- public void append(byte[] b, int nBytes) {
- if (nBytes < 1) return;
- if (size + nBytes > capacity) expandCapacity(size + nBytes);
- System.arraycopy(b, 0, buf, size, nBytes);
- size += nBytes;
- }
-
- public byte[] toByteArray() {
- byte[] result = new byte[size];
- System.arraycopy(buf, 0, result, 0, size);
- return result;
- }
-
- private void expandCapacity(int min) {
- capacity *= 2;
- if (capacity < min) capacity = min;
- byte[] expanded = new byte[capacity];
- System.arraycopy(buf, 0, expanded, 0, size);
- buf = expanded;
- }
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/VerifierExperiments.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/VerifierExperiments.java
deleted file mode 100644
index 044bde9..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/VerifierExperiments.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.verifier.audioquality;
-
-import com.android.cts.verifier.audioquality.experiments.BiasExperiment;
-import com.android.cts.verifier.audioquality.experiments.ColdLatencyExperiment;
-import com.android.cts.verifier.audioquality.experiments.OverflowExperiment;
-import com.android.cts.verifier.audioquality.experiments.GainLinearityExperiment;
-import com.android.cts.verifier.audioquality.experiments.GlitchExperiment;
-import com.android.cts.verifier.audioquality.experiments.SoundLevelExperiment;
-import com.android.cts.verifier.audioquality.experiments.SpectrumShapeExperiment;
-import com.android.cts.verifier.audioquality.experiments.WarmLatencyExperiment;
-
-import android.content.Context;
-
-import java.util.ArrayList;
-
-/**
- * Data shared between the VerifierActivity and ExperimentService
- */
-public class VerifierExperiments {
-
- private static ArrayList<Experiment> mExperiments = null;
-
- private VerifierExperiments() {
- }
-
- public static ArrayList<Experiment> getExperiments(Context context) {
- if (mExperiments == null) {
- mExperiments = new ArrayList<Experiment>();
- mExperiments.add(new SoundLevelExperiment());
- mExperiments.add(new BiasExperiment());
- mExperiments.add(new OverflowExperiment());
- mExperiments.add(new GainLinearityExperiment());
- mExperiments.add(new SpectrumShapeExperiment());
- mExperiments.add(new GlitchExperiment(0));
- mExperiments.add(new GlitchExperiment(7));
- mExperiments.add(new ColdLatencyExperiment());
- mExperiments.add(new WarmLatencyExperiment());
- for (Experiment exp : mExperiments) {
- exp.init(context);
- }
- }
- return mExperiments;
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/ViewResultsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/ViewResultsActivity.java
deleted file mode 100644
index 6563335..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/ViewResultsActivity.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.verifier.audioquality;
-
-import com.android.cts.verifier.R;
-
-import android.app.Activity;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.view.View;
-import android.widget.Button;
-import android.widget.TextView;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * This Activity allows the user to examine the results of the
- * experiments which have been run so far.
- */
-public class ViewResultsActivity extends Activity implements View.OnClickListener {
- private TextView mTextView;
- private Button mDismissButton;
- private Button mSendResultsButton;
- private String mResults;
-
- private ArrayList<Experiment> mExperiments;
-
- // The package of the Gmail application
- private static final String GMAIL_PACKAGE = "com.google.android.gm";
-
- // The Gmail compose activity name
- private static final String GMAIL_ACTIVITY = GMAIL_PACKAGE
- + ".ComposeActivityGmail";
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.aq_view_results);
-
- mDismissButton = (Button) findViewById(R.id.dismissButton);
- mDismissButton.setOnClickListener(this);
-
- mSendResultsButton = (Button) findViewById(R.id.sendResultsButton);
- mSendResultsButton.setOnClickListener(this);
-
- mTextView = (TextView) findViewById(R.id.textView);
-
- Intent intent = getIntent();
- mResults = intent.getStringExtra(AudioQualityVerifierActivity.EXTRA_RESULTS);
- mTextView.setText(mResults);
-
- mExperiments = VerifierExperiments.getExperiments(this);
- }
-
- private void sendResults() {
- Intent intent = new Intent();
- intent.setAction(Intent.ACTION_SEND_MULTIPLE);
- intent.setComponent(new ComponentName(GMAIL_PACKAGE, GMAIL_ACTIVITY));
- intent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.aq_subject));
- intent.putExtra(Intent.EXTRA_TEXT, mResults);
-
- ArrayList<Parcelable> attachments = new ArrayList<Parcelable>();
- for (Experiment exp : mExperiments) {
- List<String> filenames = exp.getAudioFileNames();
- for (String filename : filenames) {
- attachments.add(Uri.fromFile(new File(filename)));
- }
- }
- intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, attachments);
-
- startActivity(intent);
- }
-
- // Implements View.OnClickListener
- public void onClick(View v) {
- if (v == mDismissButton) {
- finish();
- } else if (v == mSendResultsButton) {
- sendResults();
- }
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/BiasExperiment.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/BiasExperiment.java
deleted file mode 100644
index bb6f8bf..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/BiasExperiment.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.verifier.audioquality.experiments;
-
-import com.android.cts.verifier.R;
-import com.android.cts.verifier.audioquality.AudioQualityVerifierActivity;
-import com.android.cts.verifier.audioquality.Native;
-import com.android.cts.verifier.audioquality.Utils;
-
-import android.content.Context;
-
-/**
- * Experiment to look for excessive DC bias in the recordings.
- * It calculates the mean of the observed samples.
- */
-public class BiasExperiment extends LoopbackExperiment {
- private static final float ONSET_THRESH = 10.0f;
- private static final float TOLERANCE = 200.0f;
-
- public BiasExperiment() {
- super(true);
- }
-
- @Override
- protected String lookupName(Context context) {
- return context.getString(R.string.aq_bias_exp);
- }
-
- @Override
- protected void compare(byte[] stim, byte[] record) {
- short[] pcm = Utils.byteToShortArray(record);
- float[] results = mNative.measureRms(pcm, AudioQualityVerifierActivity.SAMPLE_RATE, ONSET_THRESH);
- float rms = results[Native.MEASURE_RMS_RMS];
- float duration = results[Native.MEASURE_RMS_DURATION];
- float mean = results[Native.MEASURE_RMS_MEAN];
- if (mean < -TOLERANCE || mean > TOLERANCE) {
- setScore(getString(R.string.aq_fail));
- } else {
- setScore(getString(R.string.aq_pass));
- }
- setReport(String.format(getString(R.string.aq_bias_report),
- mean, TOLERANCE, rms, duration));
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/ColdLatencyExperiment.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/ColdLatencyExperiment.java
deleted file mode 100644
index 648e6cb..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/ColdLatencyExperiment.java
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-package com.android.cts.verifier.audioquality.experiments;
-
-import com.android.cts.verifier.R;
-import com.android.cts.verifier.audioquality.AudioQualityVerifierActivity;
-import com.android.cts.verifier.audioquality.Experiment;
-import com.android.cts.verifier.audioquality.Utils;
-
-import android.content.Context;
-import android.media.AudioFormat;
-import android.media.AudioRecord;
-import android.media.MediaRecorder.AudioSource;
-
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-/**
- * {@link Experiment} that measures how long it takes for an initialized
- * {@link AudioRecord} object to enter the recording state.
- */
-public class ColdLatencyExperiment extends Experiment {
-
- /**
- * Rough latency amounts observed:
- *
- * N1 2.3.4: 350 ms
- * NS 2.3.4: 250 ms
- * Xoom 3.1: 100 ms
- */
- private static final int MAXIMUM_LATENCY_ALLOWED_MS = 500;
-
- /** Enough time to say a short phrase usually entered as a voice command. */
- private static final int BUFFER_TIME_MS = 25 * 1000;
-
- /** Milliseconds to pause while repeatedly checking the recording state. */
- private static final int DELAY_MS = 10;
-
- /** Milliseconds to record before turning off the recording. */
- private static final int RECORDING_DELAY_MS = 3000;
-
- /** Milliseconds to pause before checking the latency after making a sound. */
- private static final int LATENCY_CHECK_DELAY_MS = 5000;
-
- private static final int TEST_TIMEOUT_SECONDS = 10;
-
- public ColdLatencyExperiment() {
- super(true);
- }
-
- @Override
- protected String lookupName(Context context) {
- return context.getString(R.string.aq_cold_latency);
- }
-
- @Override
- public void run() {
- ExecutorService executor = Executors.newCachedThreadPool();
- RecordingTask recordingTask = new RecordingTask(RECORDING_DELAY_MS);
-
- try {
- // 1. Start recording for a couple seconds.
- Future<Long> recordingFuture = executor.submit(recordingTask);
- long recordTime = recordingFuture.get(RECORDING_DELAY_MS * 2, TimeUnit.MILLISECONDS);
- if (recordTime < 0) {
- setScore(getString(R.string.aq_fail));
- return;
- }
-
- // 2. Wait a bit for the audio hardware to shut down.
- long startTime = System.currentTimeMillis();
- while (System.currentTimeMillis() - startTime < LATENCY_CHECK_DELAY_MS) {
- Utils.delay(DELAY_MS);
- }
-
- // 3. Now measure the latency by starting up the hardware again.
- long latency = getLatency();
- if (latency < 0) {
- setScore(getString(R.string.aq_fail));
- } else {
- setScore(latency < MAXIMUM_LATENCY_ALLOWED_MS
- ? getString(R.string.aq_pass)
- : getString(R.string.aq_fail));
- setReport(String.format(getString(R.string.aq_cold_latency_report), latency,
- MAXIMUM_LATENCY_ALLOWED_MS));
- }
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- setScore(getString(R.string.aq_fail));
- } catch (ExecutionException e) {
- setScore(getString(R.string.aq_fail));
- } catch (TimeoutException e) {
- setScore(getString(R.string.aq_fail));
- } finally {
- recordingTask.stopRecording();
- executor.shutdown();
- mTerminator.terminate(false);
- }
- }
-
- @Override
- public int getTimeout() {
- return TEST_TIMEOUT_SECONDS;
- }
-
- /** Task that records for a given length of time. */
- private class RecordingTask implements Callable<Long> {
-
- private static final int READ_TIME = 25;
-
- private final long mRecordMs;
-
- private final int mSamplesToRead;
-
- private final byte[] mBuffer;
-
- private boolean mKeepRecording = true;
-
- public RecordingTask(long recordMs) {
- this.mRecordMs = recordMs;
- this.mSamplesToRead = (READ_TIME * AudioQualityVerifierActivity.SAMPLE_RATE) / 1000;
- this.mBuffer = new byte[mSamplesToRead * AudioQualityVerifierActivity.BYTES_PER_SAMPLE];
- }
-
- public Long call() throws Exception {
- int minBufferSize = BUFFER_TIME_MS / 1000
- * AudioQualityVerifierActivity.SAMPLE_RATE
- * AudioQualityVerifierActivity.BYTES_PER_SAMPLE;
- int bufferSize = Utils.getAudioRecordBufferSize(minBufferSize);
- if (bufferSize < 0) {
- setReport(getString(R.string.aq_audiorecord_buffer_size_error));
- return -1L;
- }
-
- AudioRecord record = null;
- try {
- record = new AudioRecord(AudioSource.VOICE_RECOGNITION,
- AudioQualityVerifierActivity.SAMPLE_RATE,
- AudioFormat.CHANNEL_IN_MONO,
- AudioQualityVerifierActivity.AUDIO_FORMAT,
- bufferSize);
-
- if (record.getRecordingState() != AudioRecord.STATE_INITIALIZED) {
- setReport(getString(R.string.aq_init_audiorecord_error));
- return -2L;
- }
-
- record.startRecording();
- while (record.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
- // Wait until we can start recording...
- Utils.delay(DELAY_MS);
- }
-
- long startTime = System.currentTimeMillis();
- int maxBytes = mSamplesToRead * AudioQualityVerifierActivity.BYTES_PER_SAMPLE;
- while (true) {
- synchronized (this) {
- if (!mKeepRecording) {
- break;
- }
- }
- int numBytesRead = record.read(mBuffer, 0, maxBytes);
- if (numBytesRead < 0) {
- setReport(getString(R.string.aq_recording_error));
- return -3L;
- } else if (System.currentTimeMillis() - startTime >= mRecordMs) {
- return System.currentTimeMillis() - startTime;
- }
- }
-
- return -4L;
- } finally {
- if (record != null) {
- if (record.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING) {
- record.stop();
- }
- record.release();
- record = null;
- }
- }
- }
-
- public void stopRecording() {
- synchronized (this) {
- mKeepRecording = false;
- }
- }
- }
-
- /**
- * @return latency between starting to record and entering the record state or
- * -1 if an error occurred
- */
- private long getLatency() {
- int minBufferSize = BUFFER_TIME_MS / 1000
- * AudioQualityVerifierActivity.SAMPLE_RATE
- * AudioQualityVerifierActivity.BYTES_PER_SAMPLE;
- int bufferSize = Utils.getAudioRecordBufferSize(minBufferSize);
- if (bufferSize < 0) {
- setReport(String.format(getString(R.string.aq_audiorecord_buffer_size_error),
- bufferSize));
- return -1;
- }
-
- AudioRecord record = null;
- try {
- record = new AudioRecord(AudioSource.VOICE_RECOGNITION,
- AudioQualityVerifierActivity.SAMPLE_RATE, AudioFormat.CHANNEL_IN_MONO,
- AudioQualityVerifierActivity.AUDIO_FORMAT, bufferSize);
-
- if (record.getRecordingState() != AudioRecord.STATE_INITIALIZED) {
- setReport(getString(R.string.aq_init_audiorecord_error));
- return -1;
- }
-
- long startTime = System.currentTimeMillis();
- record.startRecording();
- while (record.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
- Utils.delay(DELAY_MS);
- }
- long endTime = System.currentTimeMillis();
-
- return endTime - startTime;
- } finally {
- if (record != null) {
- if (record.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING) {
- record.stop();
- }
- record.release();
- record = null;
- }
- }
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/GainLinearityExperiment.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/GainLinearityExperiment.java
deleted file mode 100644
index 225df1a..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/GainLinearityExperiment.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.verifier.audioquality.experiments;
-
-import com.android.cts.verifier.R;
-import com.android.cts.verifier.audioquality.AudioQualityVerifierActivity;
-import com.android.cts.verifier.audioquality.Utils;
-
-import android.content.Context;
-
-/**
- * Experiment to test the linearity of the microphone gain response.
- *
- * This plays a sequence of identical stimuli at increasing volumes and then
- * analyzes the set of recordings.
- */
-public class GainLinearityExperiment extends SequenceExperiment {
- private static final int LEVELS = 4;
- private static final float DB_STEP_SIZE = 10.0f;
- private static final float TOLERANCE = 2.0f; // Maximum allowed deviation from linearity in dB
- private static final int STIM_NUM = 31;
-
- private short[] mReference = null;
-
- public GainLinearityExperiment() {
- super(true);
- }
-
- @Override
- protected String lookupName(Context context) {
- return context.getString(R.string.aq_linearity_exp);
- }
-
- @Override
- protected int getTrials() {
- return LEVELS;
- }
-
- @Override
- protected byte[] getStim(Context context, int trial) {
- float db = (trial - (LEVELS - 1)) * DB_STEP_SIZE;
- if (mReference == null) {
- mReference = Utils.byteToShortArray(Utils.getStim(context, STIM_NUM));
- }
- short[] samples = Utils.scale(mReference, db);
- return Utils.shortToByteArray(samples);
- }
-
- @Override
- protected void compare(byte[][] stim, byte[][] record) {
- short[][] pcms = new short[LEVELS][];
- for (int i = 0; i < LEVELS; i++) {
- pcms[i] = Utils.byteToShortArray(record[i]);
- }
- float deviation = mNative.linearityTestRms(pcms, AudioQualityVerifierActivity.SAMPLE_RATE,
- DB_STEP_SIZE);
- if (deviation < 0.0f) {
- setScore(getString(R.string.aq_fail));
- setReport(String.format(getString(R.string.aq_linearity_report_error), deviation));
- } else if (deviation > TOLERANCE) {
- setScore(getString(R.string.aq_fail));
- setReport(String.format(getString(R.string.aq_linearity_report_normal),
- deviation, TOLERANCE));
- } else {
- setScore(getString(R.string.aq_pass));
- setReport(String.format(getString(R.string.aq_linearity_report_normal),
- deviation, TOLERANCE));
- }
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/GlitchExperiment.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/GlitchExperiment.java
deleted file mode 100644
index 143c4a0..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/GlitchExperiment.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.verifier.audioquality.experiments;
-
-import com.android.cts.verifier.R;
-import com.android.cts.verifier.audioquality.AudioQualityVerifierActivity;
-import com.android.cts.verifier.audioquality.Native;
-import com.android.cts.verifier.audioquality.Utils;
-
-import android.content.Context;
-
-import java.util.Random;
-
-/**
- * Experiment to detect glitches or dropouts in the signal.
- * A number of artificial glitches can be optionally introduced.
- */
-public class GlitchExperiment extends LoopbackExperiment {
- private static final float FREQ = 625.0f;
- private static final float AMPL = 10000.0f;
- private static final float ONSET_THRESH = 80.0f;
- private static final float SNR_THRESH = 20.0f;
- private static final float RAMP = 0.01f;
- private static final float DURATION = 3.0f;
-
- private int mArtificialGlitches;
-
- public GlitchExperiment(int artificialGlitches) {
- super(true);
- mArtificialGlitches = artificialGlitches;
- }
-
- @Override
- protected String lookupName(Context context) {
- String s = context.getString(R.string.aq_glitch_exp);
- if (mArtificialGlitches > 0) {
- s += " (" + mArtificialGlitches + ")";
- }
- return s;
- }
-
- @Override
- protected byte[] getStim(Context context) {
- short[] sinusoid = mNative.generateSinusoid(FREQ, DURATION,
- AudioQualityVerifierActivity.SAMPLE_RATE, AMPL, RAMP);
- addGlitches(sinusoid);
- return Utils.shortToByteArray(sinusoid);
- }
-
- private void addGlitches(short[] samples) {
- Random random = new Random();
- for (int i = 0; i < mArtificialGlitches; i++) {
- samples[random.nextInt(samples.length)] = 0;
- }
- }
-
- @Override
- protected void compare(byte[] stim, byte[] record) {
- int targetMin = mArtificialGlitches > 0 ? 1 : 0;
- int targetMax = mArtificialGlitches;
- short[] pcm = Utils.byteToShortArray(record);
- float[] ret = mNative.glitchTest(AudioQualityVerifierActivity.SAMPLE_RATE, FREQ,
- ONSET_THRESH, SNR_THRESH, pcm);
- int glitches = Math.round(ret[Native.GLITCH_COUNT]);
- float error = ret[Native.GLITCH_ERROR];
- float duration = ret[Native.GLITCH_DURATION];
- if (error < 0.0f) {
- setScore(getString(R.string.aq_fail));
- setReport(getString(R.string.aq_glitch_report_error));
- } else {
- if (glitches > targetMax || glitches < targetMin) {
- setScore(getString(R.string.aq_fail));
- } else {
- setScore(getString(R.string.aq_pass));
- }
- if (targetMin == targetMax) {
- setReport(String.format(getString(R.string.aq_glitch_report_exact),
- glitches, targetMax, duration));
- } else {
- setReport(String.format(getString(R.string.aq_glitch_report_range),
- glitches, targetMin, targetMax, duration));
- }
- }
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/LoopbackExperiment.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/LoopbackExperiment.java
deleted file mode 100644
index 0817860..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/LoopbackExperiment.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.verifier.audioquality.experiments;
-
-import com.android.cts.verifier.R;
-import com.android.cts.verifier.audioquality.AudioQualityVerifierActivity;
-import com.android.cts.verifier.audioquality.Experiment;
-import com.android.cts.verifier.audioquality.Utils;
-
-import android.content.Context;
-import android.media.AudioFormat;
-import android.media.AudioRecord;
-import android.media.AudioTrack;
-import android.media.MediaRecorder;
-import android.util.Log;
-
-/**
- * LoopbackExperiment represents a general class of experiments, all of which
- * comprise playing an audio stimulus of some kind, whilst simultaneously
- * recording from the microphone. The recording is then analyzed to determine
- * the test results (score and report).
- */
-public class LoopbackExperiment extends Experiment {
- private static final String TAG = "LoopbackExperiment";
-
- protected static final int TIMEOUT = 10;
-
- // Amount of silence in ms before and after playback
- protected static final int END_DELAY_MS = 500;
-
- private Recorder mRecorder = null;
-
- public LoopbackExperiment(boolean enable) {
- super(enable);
- }
-
- protected byte[] getStim(Context context) {
- int stimNum = 2;
- byte[] data = Utils.getStim(context, stimNum);
- return data;
- }
-
- @Override
- public void run() {
- byte[] playbackData = getStim(mContext);
- byte[] recordedData = loopback(playbackData);
-
- compare(playbackData, recordedData);
- setRecording(recordedData);
- mTerminator.terminate(false);
- }
-
- protected byte[] loopback(byte[] playbackData) {
- int samples = playbackData.length / 2;
- int duration = (samples * 1000) / AudioQualityVerifierActivity.SAMPLE_RATE; // In ms
- int padSamples = (END_DELAY_MS * AudioQualityVerifierActivity.SAMPLE_RATE) / 1000;
- int totalSamples = samples + 2 * padSamples;
- byte[] recordedData = new byte[totalSamples * 2];
-
- mRecorder = new Recorder(recordedData, totalSamples);
- mRecorder.start();
- Utils.delay(END_DELAY_MS);
-
- AudioTrack track = Utils.playRaw(playbackData);
-
- int timeout = duration + 2 * END_DELAY_MS;
- try {
- mRecorder.join(timeout);
- } catch (InterruptedException e) {}
-
- track.stop();
- track.release();
- return recordedData;
- }
-
- protected void compare(byte[] stim, byte[] record) {
- setScore(getString(R.string.aq_complete));
- setReport(getString(R.string.aq_loopback_report));
- }
-
- private void halt() {
- if (mRecorder != null) {
- mRecorder.halt();
- }
- }
-
- @Override
- public void cancel() {
- super.cancel();
- halt();
- }
-
- @Override
- public void stop() {
- super.stop();
- halt();
- }
-
- @Override
- public int getTimeout() {
- return TIMEOUT;
- }
-
- /* Class which records audio in a background thread, to fill the supplied buffer. */
- class Recorder extends Thread {
- private AudioRecord mRecord;
- private int mSamples;
- private byte[] mBuffer;
- private boolean mProceed;
-
- Recorder(byte[] buffer, int samples) {
- mBuffer = buffer;
- mSamples = samples;
- mProceed = true;
- }
-
- public void halt() {
- mProceed = false;
- }
-
- @Override
- public void run() {
- final int minBufferSize = AudioQualityVerifierActivity.SAMPLE_RATE
- * AudioQualityVerifierActivity.BYTES_PER_SAMPLE;
- final int bufferSize = Utils.getAudioRecordBufferSize(minBufferSize);
-
- mRecord = new AudioRecord(MediaRecorder.AudioSource.VOICE_RECOGNITION,
- AudioQualityVerifierActivity.SAMPLE_RATE, AudioFormat.CHANNEL_IN_MONO,
- AudioQualityVerifierActivity.AUDIO_FORMAT, bufferSize);
- if (mRecord.getState() != AudioRecord.STATE_INITIALIZED) {
- Log.e(TAG, "Couldn't open audio for recording");
- return;
- }
- mRecord.startRecording();
- if (mRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
- Log.e(TAG, "Couldn't record");
- return;
- }
-
- captureLoop();
-
- mRecord.stop();
- mRecord.release();
- mRecord = null;
- }
-
- private void captureLoop() {
- int totalBytes = mSamples * AudioQualityVerifierActivity.BYTES_PER_SAMPLE;
- Log.i(TAG, "Recording " + totalBytes + " bytes");
- int position = 0;
- int bytes;
- while (position < totalBytes && mProceed) {
- bytes = mRecord.read(mBuffer, position, totalBytes - position);
- if (bytes < 0) {
- if (bytes == AudioRecord.ERROR_INVALID_OPERATION) {
- Log.e(TAG, "Recording object not initalized");
- } else if (bytes == AudioRecord.ERROR_BAD_VALUE) {
- Log.e(TAG, "Invalid recording parameters");
- } else {
- Log.e(TAG, "Error during recording");
- }
- return;
- }
- position += bytes;
- }
- }
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/OverflowExperiment.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/OverflowExperiment.java
deleted file mode 100644
index 71deac8..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/OverflowExperiment.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.verifier.audioquality.experiments;
-
-import com.android.cts.verifier.R;
-import com.android.cts.verifier.audioquality.AudioQualityVerifierActivity;
-import com.android.cts.verifier.audioquality.CalibrateVolumeActivity;
-import com.android.cts.verifier.audioquality.Native;
-import com.android.cts.verifier.audioquality.Utils;
-
-import android.content.Context;
-
-/**
- * Experiment to test the clipping behaviour of the microphone.
- *
- * The stimulus is sinusoidal, and calculated to cause clipping for
- * part of the waveform. The experiment looks for strange clipping behaviour
- * by checking if the signal has any discontinuities (which might indicate
- * wraparound, for example).
- */
-public class OverflowExperiment extends LoopbackExperiment {
- private static final float FREQ = 250.0f;
- private static final float AMPL = 32768.0f * 1.1f * CalibrateVolumeActivity.OUTPUT_AMPL
- / CalibrateVolumeActivity.TARGET_AMPL;
- private static final float DURATION = 3.0f; // Duration of tone in seconds
- private static final float MIN_DURATION = DURATION * 0.9f;
- private static final float RAMP = 0.01f;
-
- public OverflowExperiment() {
- super(true);
- }
-
- @Override
- protected String lookupName(Context context) {
- return context.getString(R.string.aq_overflow_exp);
- }
-
- @Override
- protected byte[] getStim(Context context) {
- short[] sinusoid = mNative.generateSinusoid(FREQ, DURATION,
- AudioQualityVerifierActivity.SAMPLE_RATE, AMPL, RAMP);
- return Utils.shortToByteArray(sinusoid);
- }
-
- @Override
- protected void compare(byte[] stim, byte[] record) {
- short[] pcm = Utils.byteToShortArray(record);
- float[] ret = mNative.overflowCheck(pcm, AudioQualityVerifierActivity.SAMPLE_RATE);
- int numDeltas = Math.round(ret[0]);
- float error = ret[Native.OVERFLOW_ERROR];
- float duration = ret[Native.OVERFLOW_DURATION];
- float minPeak = ret[Native.OVERFLOW_MIN];
- float maxPeak = ret[Native.OVERFLOW_MAX];
-
- if (error < 0.0f) {
- setScore(getString(R.string.aq_fail));
- setReport(getString(R.string.aq_overflow_report_error));
- } else if (duration < MIN_DURATION) {
- setScore(getString(R.string.aq_fail));
- setReport(String.format(getString(R.string.aq_overflow_report_short),
- DURATION, duration));
- } else if (numDeltas > 0) {
- setScore(getString(R.string.aq_fail));
- setReport(String.format(getString(R.string.aq_overflow_report_fail),
- numDeltas, duration, minPeak, maxPeak));
- } else {
- setScore(getString(R.string.aq_pass));
- setReport(String.format(getString(R.string.aq_overflow_report_pass),
- numDeltas, duration, minPeak, maxPeak));
- }
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/SequenceExperiment.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/SequenceExperiment.java
deleted file mode 100644
index 0a3846c..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/SequenceExperiment.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.verifier.audioquality.experiments;
-
-import com.android.cts.verifier.R;
-import com.android.cts.verifier.audioquality.Utils;
-
-import android.content.Context;
-
-/**
- * An extension to LoopbackExperiment, in which the "playback and record"
- * cycle is repeated several times. A family of stimuli is defined, and
- * the experiment outcome may depend on the whole sequence of recordings.
- */
-public class SequenceExperiment extends LoopbackExperiment {
- public SequenceExperiment(boolean enable) {
- super(enable);
- }
-
- protected int getTrials() {
- return 1;
- }
-
- protected byte[] getStim(Context context, int trial) {
- int stimNum = 2;
- byte[] data = Utils.getStim(context, stimNum);
- return data;
- }
-
- protected void compare(byte[][] stim, byte[][] record) {
- setScore(getString(R.string.aq_complete));
- setReport(getString(R.string.aq_loopback_report));
- }
-
- @Override
- public void run() {
- int n = getTrials();
- byte[][] playbackData = new byte[n][];
- byte[][] recordedData = new byte[n][];
- for (int trial = 0; trial < n; trial++) {
- playbackData[trial] = getStim(mContext, trial);
- recordedData[trial] = loopback(playbackData[trial]);
- setRecording(recordedData[trial], trial);
- }
- compare(playbackData, recordedData);
- mTerminator.terminate(false);
- }
-
- @Override
- public int getTimeout() {
- return TIMEOUT * getTrials();
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/SoundLevelExperiment.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/SoundLevelExperiment.java
deleted file mode 100644
index 4435f31..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/SoundLevelExperiment.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.verifier.audioquality.experiments;
-
-import com.android.cts.verifier.R;
-import com.android.cts.verifier.audioquality.AudioQualityVerifierActivity;
-import com.android.cts.verifier.audioquality.CalibrateVolumeActivity;
-import com.android.cts.verifier.audioquality.Native;
-import com.android.cts.verifier.audioquality.Utils;
-
-import android.content.Context;
-
-/**
- * Experiment to verify that the sound level has been correctly set.
- *
- * This experiment should be run first; if it fails the others may
- * fail also.
- */
-public class SoundLevelExperiment extends LoopbackExperiment {
- private static final float ONSET_THRESH = 10.0f;
- private static final int DURATION = 2;
- private static final float TOLERANCE = 1.05f;
- private static final float FREQ = 625.0f;
- private static final float RAMP = 0.0f;
-
- public SoundLevelExperiment() {
- super(true);
- }
-
- @Override
- protected String lookupName(Context context) {
- return context.getString(R.string.aq_sound_level_exp);
- }
-
- @Override
- protected byte[] getStim(Context context) {
- if (CalibrateVolumeActivity.USE_PINK) {
- return Utils.getPinkNoise(context, CalibrateVolumeActivity.OUTPUT_AMPL, DURATION);
- } else {
- short[] sinusoid = mNative.generateSinusoid(FREQ, DURATION,
- AudioQualityVerifierActivity.SAMPLE_RATE, CalibrateVolumeActivity.OUTPUT_AMPL, RAMP);
- return Utils.shortToByteArray(sinusoid);
- }
- }
-
- @Override
- protected void compare(byte[] stim, byte[] record) {
- short[] pcm = Utils.byteToShortArray(record);
- float[] results = mNative.measureRms(pcm, AudioQualityVerifierActivity.SAMPLE_RATE, ONSET_THRESH);
- float rms = results[Native.MEASURE_RMS_RMS];
- float duration = results[Native.MEASURE_RMS_DURATION];
- String delta;
- if (rms * TOLERANCE < CalibrateVolumeActivity.TARGET_RMS) {
- setScore(getString(R.string.aq_fail));
- delta = getString(R.string.aq_status_low);
- } else if (rms > CalibrateVolumeActivity.TARGET_RMS * TOLERANCE) {
- setScore(getString(R.string.aq_fail));
- delta = getString(R.string.aq_status_high);
- } else {
- setScore(getString(R.string.aq_pass));
- delta = getString(R.string.aq_status_ok);
- }
- setReport(delta + ".\n" + String.format(getString(R.string.aq_level_report),
- rms, CalibrateVolumeActivity.TARGET_RMS,
- 100.0f * (TOLERANCE - 1.0f), duration));
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/SpectrumShapeExperiment.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/SpectrumShapeExperiment.java
deleted file mode 100644
index df7919e..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/SpectrumShapeExperiment.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.cts.verifier.audioquality.experiments;
-
-import com.android.cts.verifier.R;
-import com.android.cts.verifier.audioquality.AudioQualityVerifierActivity;
-import com.android.cts.verifier.audioquality.Native;
-import com.android.cts.verifier.audioquality.Utils;
-
-import android.content.Context;
-
-/**
- * Experiment to check that the frequency profile of the recorded signal
- * does not differ too much from the stimulus.
- */
-public class SpectrumShapeExperiment extends LoopbackExperiment {
- private static final float MAX_RMS_DEVIATION = 7.0f;
- private static final int AMPL = 10000;
- private static final int DURATION = 3;
-
- public SpectrumShapeExperiment() {
- super(false); // disable temporarily
- }
-
- @Override
- protected String lookupName(Context context) {
- return context.getString(R.string.aq_spectrum_shape_exp);
- }
-
- @Override
- protected byte[] getStim(Context context) {
- return Utils.getPinkNoise(context, AMPL, DURATION);
- }
-
- @Override
- protected void compare(byte[] stim, byte[] record) {
- short[] pcm = Utils.byteToShortArray(record);
- short[] refPcm = Utils.byteToShortArray(stim);
- float[] ret = mNative.compareSpectra(pcm, refPcm, AudioQualityVerifierActivity.SAMPLE_RATE);
- float maxDeviation = ret[Native.SPECTRUM_MAX_DEVIATION];
- float error = ret[Native.SPECTRUM_ERROR];
- float rmsDeviation = ret[Native.SPECTRUM_RMS_DEVIATION];
- if (error < 0.0f) {
- setScore(getString(R.string.aq_fail));
- setReport(getString(R.string.aq_spectrum_report_error));
- } else if (rmsDeviation > MAX_RMS_DEVIATION) {
- setScore(getString(R.string.aq_fail));
- setReport(String.format(getString(R.string.aq_spectrum_report_normal),
- rmsDeviation, MAX_RMS_DEVIATION));
- } else {
- setScore(getString(R.string.aq_pass));
- setReport(String.format(getString(R.string.aq_spectrum_report_normal),
- rmsDeviation, MAX_RMS_DEVIATION));
- }
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/WarmLatencyExperiment.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/WarmLatencyExperiment.java
deleted file mode 100644
index 88aaf8c..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/WarmLatencyExperiment.java
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-package com.android.cts.verifier.audioquality.experiments;
-
-import com.android.cts.verifier.R;
-import com.android.cts.verifier.audioquality.AudioQualityVerifierActivity;
-import com.android.cts.verifier.audioquality.Experiment;
-import com.android.cts.verifier.audioquality.Native;
-import com.android.cts.verifier.audioquality.Utils;
-
-import android.content.Context;
-import android.media.AudioFormat;
-import android.media.AudioManager;
-import android.media.AudioRecord;
-import android.media.AudioTrack;
-import android.media.MediaRecorder.AudioSource;
-
-import java.util.concurrent.Callable;
-import java.util.concurrent.CyclicBarrier;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-/**
- * {@link Experiment} that measures how long it takes for a stimulus emitted
- * by a warmed up {@link AudioTrack} to be recorded by a warmed up
- * {@link AudioRecord} instance.
- */
-public class WarmLatencyExperiment extends Experiment {
-
- /** Milliseconds to wait before playing the sound. */
- private static final int DELAY_TIME = 2000;
-
- /** Target RMS value to detect before quitting the experiment. */
- private static final float TARGET_RMS = 4000;
-
- /** Target latency to react to the sound. */
- private static final long TARGET_LATENCY_MS = 200;
-
- private static final int CHANNEL_IN_CONFIG = AudioFormat.CHANNEL_IN_MONO;
- private static final int CHANNEL_OUT_CONFIG = AudioFormat.CHANNEL_OUT_MONO;
- private static final float FREQ = 625.0f;
- private static final int DURATION = 1;
- private static final int OUTPUT_AMPL = 5000;
- private static final float RAMP = 0.0f;
- private static final int BUFFER_TIME_MS = 100;
- private static final int READ_TIME = 25;
-
- public WarmLatencyExperiment() {
- super(true);
- }
-
- @Override
- protected String lookupName(Context context) {
- return context.getString(R.string.aq_warm_latency);
- }
-
- @Override
- public void run() {
- ExecutorService executor = Executors.newFixedThreadPool(2);
- CyclicBarrier barrier = new CyclicBarrier(2);
- PlaybackTask playbackTask = new PlaybackTask(barrier);
- RecordingTask recordingTask = new RecordingTask(barrier);
-
- Future<Long> playbackTimeFuture = executor.submit(playbackTask);
- Future<Long> recordTimeFuture = executor.submit(recordingTask);
-
- try {
- // Get the time when the sound is detected or throw an exception...
- long recordTime = recordTimeFuture.get(DELAY_TIME * 2, TimeUnit.MILLISECONDS);
-
- // Stop the playback now since the sound was detected. Get the time playback started.
- playbackTask.stopPlaying();
- long playbackTime = playbackTimeFuture.get();
-
- if (recordTime == -1 || playbackTime == -1) {
- setScore(getString(R.string.aq_fail));
- } else {
- long latency = recordTime - playbackTime;
- setScore(latency < TARGET_LATENCY_MS
- ? getString(R.string.aq_pass)
- : getString(R.string.aq_fail));
- setReport(String.format(getString(R.string.aq_warm_latency_report_normal),
- latency));
- }
- } catch (InterruptedException e) {
- setExceptionReport(e);
- } catch (ExecutionException e) {
- setExceptionReport(e);
- } catch (TimeoutException e) {
- setScore(getString(R.string.aq_fail));
- setReport(String.format(getString(R.string.aq_warm_latency_report_error),
- recordingTask.getLastRms(), TARGET_RMS));
- } finally {
- playbackTask.stopPlaying();
- recordingTask.stopRecording();
- mTerminator.terminate(false);
- }
- }
-
- private void setExceptionReport(Exception e) {
- setScore(getString(R.string.aq_fail));
- setReport(String.format(getString(R.string.aq_exception_error), e.getClass().getName()));
- }
-
- @Override
- public int getTimeout() {
- return 10; // seconds
- }
-
- /**
- * Task that plays a sinusoid after playing silence for a couple of seconds.
- * Returns the playback start time.
- */
- private class PlaybackTask implements Callable<Long> {
-
- private final byte[] mData;
-
- private final int mBufferSize;
-
- private final CyclicBarrier mReadyBarrier;
-
- private int mPosition;
-
- private boolean mKeepPlaying = true;
-
- public PlaybackTask(CyclicBarrier barrier) {
- this.mData = getAudioData();
- this.mBufferSize = getBufferSize();
- this.mReadyBarrier = barrier;
- }
-
- private byte[] getAudioData() {
- short[] sinusoid = mNative.generateSinusoid(FREQ, DURATION,
- AudioQualityVerifierActivity.SAMPLE_RATE, OUTPUT_AMPL, RAMP);
- return Utils.shortToByteArray(sinusoid);
- }
-
- private int getBufferSize() {
- int minBufferSize = (BUFFER_TIME_MS * AudioQualityVerifierActivity.SAMPLE_RATE
- * AudioQualityVerifierActivity.BYTES_PER_SAMPLE) / 1000;
- return Utils.getAudioTrackBufferSize(minBufferSize);
- }
-
- public Long call() throws Exception {
- if (mBufferSize == -1) {
- setReport(getString(R.string.aq_audiotrack_buffer_size_error));
- return -1l;
- }
-
- AudioTrack track = null;
- try {
- track = new AudioTrack(AudioManager.STREAM_MUSIC,
- AudioQualityVerifierActivity.SAMPLE_RATE, CHANNEL_OUT_CONFIG,
- AudioQualityVerifierActivity.AUDIO_FORMAT, mBufferSize,
- AudioTrack.MODE_STREAM);
-
- if (track.getPlayState() != AudioTrack.STATE_INITIALIZED) {
- setReport(getString(R.string.aq_init_audiotrack_error));
- return -1l;
- }
-
- track.play();
- while (track.getPlayState() != AudioTrack.PLAYSTATE_PLAYING) {
- // Wait until we've started playing...
- }
-
- // Wait until the recording thread has started and is recording...
- mReadyBarrier.await(1, TimeUnit.SECONDS);
-
- long time = System.currentTimeMillis();
- while (System.currentTimeMillis() - time < DELAY_TIME) {
- synchronized (this) {
- if (!mKeepPlaying) {
- break;
- }
- }
- // Play nothing...
- }
-
- long playTime = System.currentTimeMillis();
- writeAudio(track);
- while (true) {
- synchronized (this) {
- if (!mKeepPlaying) {
- break;
- }
- }
- writeAudio(track);
- }
-
- return playTime;
- } finally {
- if (track != null) {
- if (track.getPlayState() == AudioTrack.PLAYSTATE_PLAYING) {
- track.stop();
- }
- track.release();
- track = null;
- }
- }
- }
-
- private void writeAudio(AudioTrack track) {
- int length = mData.length;
- int writeBytes = Math.min(mBufferSize, length - mPosition);
- int numBytesWritten = track.write(mData, mPosition, writeBytes);
- if (numBytesWritten < 0) {
- throw new IllegalStateException("Couldn't write any data to the track!");
- } else {
- mPosition += numBytesWritten;
- if (mPosition == length) {
- mPosition = 0;
- }
- }
- }
-
- public void stopPlaying() {
- synchronized (this) {
- mKeepPlaying = false;
- }
- }
- }
-
- /** Task that records until detecting a sound of the target RMS. Returns the detection time. */
- private class RecordingTask implements Callable<Long> {
-
- private final int mSamplesToRead;
-
- private final byte[] mBuffer;
-
- private final CyclicBarrier mBarrier;
-
- private boolean mKeepRecording = true;
-
- private float mLastRms = 0.0f;
-
- public RecordingTask(CyclicBarrier barrier) {
- this.mSamplesToRead = (READ_TIME * AudioQualityVerifierActivity.SAMPLE_RATE) / 1000;
- this.mBuffer = new byte[mSamplesToRead * AudioQualityVerifierActivity.BYTES_PER_SAMPLE];
- this.mBarrier = barrier;
- }
-
- public Long call() throws Exception {
- int minBufferSize = BUFFER_TIME_MS / 1000
- * AudioQualityVerifierActivity.SAMPLE_RATE
- * AudioQualityVerifierActivity.BYTES_PER_SAMPLE;
- int bufferSize = Utils.getAudioRecordBufferSize(minBufferSize);
- if (bufferSize < 0) {
- setReport(getString(R.string.aq_audiorecord_buffer_size_error));
- return -1l;
- }
-
- long recordTime = -1;
- AudioRecord record = null;
- try {
- record = new AudioRecord(AudioSource.VOICE_RECOGNITION,
- AudioQualityVerifierActivity.SAMPLE_RATE, CHANNEL_IN_CONFIG,
- AudioQualityVerifierActivity.AUDIO_FORMAT, bufferSize);
-
- if (record.getRecordingState() != AudioRecord.STATE_INITIALIZED) {
- setReport(getString(R.string.aq_init_audiorecord_error));
- return -1l;
- }
-
- record.startRecording();
- while (record.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
- // Wait until we can start recording...
- }
-
- // Wait until the playback thread has started and is playing...
- mBarrier.await(1, TimeUnit.SECONDS);
-
- int maxBytes = mSamplesToRead * AudioQualityVerifierActivity.BYTES_PER_SAMPLE;
- while (true) {
- synchronized (this) {
- if (!mKeepRecording) {
- break;
- }
- }
- int numBytesRead = record.read(mBuffer, 0, maxBytes);
- if (numBytesRead < 0) {
- setReport(getString(R.string.aq_recording_error));
- return -1l;
- } else if (numBytesRead > 2) {
- // TODO: Could be improved to use a sliding window?
- short[] samples = Utils.byteToShortArray(mBuffer, 0, numBytesRead);
- float[] results = mNative.measureRms(samples,
- AudioQualityVerifierActivity.SAMPLE_RATE, -1.0f);
- mLastRms = results[Native.MEASURE_RMS_RMS];
- if (mLastRms >= TARGET_RMS) {
- recordTime = System.currentTimeMillis();
- break;
- }
- }
- }
-
- return recordTime;
- } finally {
- if (record != null) {
- if (record.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING) {
- record.stop();
- }
- record.release();
- record = null;
- }
- }
- }
-
- public float getLastRms() {
- return mLastRms;
- }
-
- public void stopRecording() {
- synchronized (this) {
- mKeepRecording = false;
- }
- }
- }
-}