1 package com.android.cts.verifier.audio; 2 3 import org.apache.commons.math.complex.Complex; 4 import org.apache.commons.math.stat.descriptive.moment.Mean; 5 import org.apache.commons.math.stat.descriptive.moment.StandardDeviation; 6 import org.apache.commons.math.stat.descriptive.rank.Median; 7 import org.apache.commons.math.transform.FastFourierTransformer; 8 9 /** 10 * This class contains util functions used in the WavAnalyzer. 11 */ 12 public class Util { 13 14 /** 15 * Convert time in second to sample array length. 16 */ toLength(double duration, int sampleRate)17 public static int toLength(double duration, int sampleRate) { 18 return (int) Math.round(duration * sampleRate); 19 } 20 21 /** 22 * Calculate mean of data. 23 */ mean(double[] data)24 public static double mean(double[] data) { 25 Mean mean = new Mean(); 26 return mean.evaluate(data); 27 } 28 29 /** 30 * Calculate standard deviation of data. 31 */ std(double[] data)32 public static double std(double[] data) { 33 StandardDeviation std = new StandardDeviation(); 34 return std.evaluate(data); 35 } 36 37 /** 38 * Calculate median of data. 39 */ median(double[] data)40 public static double median(double[] data) { 41 Median median = new Median(); 42 median.setData(data); 43 return median.evaluate(); 44 } 45 46 /** 47 * Pad zeros at the end, total length of array will be specified as length. If length is smaller 48 * than the length of the data, it returns the data truncated to the length. 49 */ padZeros(Complex[] data, int length)50 public static Complex[] padZeros(Complex[] data, int length) { 51 Complex[] result = new Complex[length]; 52 if (length < data.length) { 53 System.arraycopy(data, 0, result, 0, length); 54 } else { 55 System.arraycopy(data, 0, result, 0, data.length); 56 for (int i = data.length; i < result.length; i++) { 57 result[i] = new Complex(0, 0); 58 } 59 } 60 return result; 61 } 62 63 /** 64 * Calculate cross correlation using FFT with periodic boundary handling. 65 */ computeCrossCorrelation(Complex[] data1, Complex[] data2)66 public static double[] computeCrossCorrelation(Complex[] data1, Complex[] data2) { 67 FastFourierTransformer fft = new FastFourierTransformer(); 68 int n = nextPowerOfTwo(Math.max(data1.length, data2.length)); 69 Complex[] data1Fft = fft.transform(padZeros(data1, n)); 70 Complex[] data2Fft = fft.transform(padZeros(data2, n)); 71 Complex[] dottedData = new Complex[n]; 72 for (int i = 0; i < n; i++) { 73 dottedData[i] = data1Fft[i].multiply(data2Fft[i].conjugate()); 74 } 75 Complex[] resultComplex = fft.inversetransform(dottedData); 76 double[] resultDouble = new double[resultComplex.length]; 77 for (int i = 0; i < resultComplex.length; i++) { 78 resultDouble[i] = resultComplex[i].abs(); 79 } 80 return resultDouble; 81 } 82 83 /** 84 * Convert an short array to a double array. 85 */ toDouble(short[] data)86 public static double[] toDouble(short[] data) { 87 double[] result = new double[data.length]; 88 for (int i = 0; i < data.length; i++) { 89 result[i] = data[i]; 90 } 91 return result; 92 } 93 94 /** 95 * Convert a double array to a complex array. 96 */ toComplex(double[] data)97 public static Complex[] toComplex(double[] data) { 98 Complex[] result = new Complex[data.length]; 99 for (int i = 0; i < data.length; i++) { 100 result[i] = new Complex(data[i], 0.0); 101 } 102 return result; 103 } 104 105 /** 106 * Calculates the next power of 2, greater than or equal to the input positive integer. If the 107 * input is not a positive integer, it returns 1. 108 */ nextPowerOfTwo(int n)109 public static int nextPowerOfTwo(int n) { 110 return 1 << (32 - Integer.numberOfLeadingZeros(n - 1)); 111 } 112 113 /** 114 * Find the index with the max value in an array. 115 */ findMaxIndex(double[] data)116 public static int findMaxIndex(double[] data) { 117 return findMaxIndex(data, 0, data.length - 1); 118 } 119 120 /** 121 * Find the index with the max value in a sub-array. 122 */ findMaxIndex(double[] data, int startIndex, int endIndex)123 public static int findMaxIndex(double[] data, int startIndex, int endIndex) { 124 int maxIndex = startIndex; 125 for (int i = startIndex + 1; i <= endIndex; i++) { 126 if (data[i] > data[maxIndex]) { 127 maxIndex = i; 128 } 129 } 130 return maxIndex; 131 } 132 133 /** 134 * Returns the index of an array with the array value closest to the desired value. 135 */ findClosest(double[] array, double value)136 public static int findClosest(double[] array, double value) { 137 double[] diffArray = new double[array.length]; 138 for (int i = 0; i < array.length; i++) { 139 diffArray[i] = Math.abs(value - array[i]); 140 } 141 int index = 0; 142 for (int i = 1; i < array.length; i++) { 143 if (diffArray[i] < diffArray[index]) { 144 index = i; 145 if (diffArray[index] == 0) { 146 break; 147 } 148 } 149 } 150 return index; 151 } 152 } 153