1 package com.android.cts.verifier.audio; 2 3 import android.media.AudioManager; 4 import android.media.AudioTrack; 5 6 import java.util.ArrayList; 7 import java.util.Random; 8 9 /** 10 * This class stores common constants and methods. 11 */ 12 public class Common { 13 14 public static final int RECORDING_SAMPLE_RATE_HZ 15 = AudioRecordHelper.getInstance().getSampleRate(); 16 public static final int PLAYING_SAMPLE_RATE_HZ 17 = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC); 18 19 // Default constants. 20 public static final double PASSING_THRESHOLD_DB = -40.0; 21 public static final double PIP_DURATION_S = 0.004; 22 public static final double PAUSE_DURATION_S = 0.016; 23 public static final int PREFIX_NUM_CHIPS = 1023; 24 public static final int PREFIX_SAMPLES_PER_CHIP = 4; 25 public static final double PREFIX_LENGTH_S = 0.1; 26 public static final double PAUSE_BEFORE_PREFIX_DURATION_S = 0.5; 27 public static final double PAUSE_AFTER_PREFIX_DURATION_S = 0.4; 28 public static final double MIN_FREQUENCY_HZ = 500; 29 public static final double MAX_FREQUENCY_HZ = 21000; 30 public static final double FREQUENCY_STEP_HZ = 100; 31 public static final int SIGNAL_MIN_STRENGTH_DB_ABOVE_NOISE = 10; 32 public static final int REPETITIONS = 5; 33 public static final int NOISE_SAMPLES = 3; 34 35 public static final double[] FREQUENCIES_ORIGINAL = originalFrequencies(); 36 public static final int PIP_NUM = FREQUENCIES_ORIGINAL.length; 37 public static final int[] ORDER = order(); 38 public static final double[] FREQUENCIES = frequencies(); 39 40 public static final double[] WINDOW_FOR_RECORDER = 41 hann(Util.toLength(PIP_DURATION_S, RECORDING_SAMPLE_RATE_HZ)); 42 public static final double[] WINDOW_FOR_PLAYER = 43 hann(Util.toLength(PIP_DURATION_S, PLAYING_SAMPLE_RATE_HZ)); 44 45 public static final double[] PREFIX_FOR_RECORDER = prefix(RECORDING_SAMPLE_RATE_HZ); 46 public static final double[] PREFIX_FOR_PLAYER = prefix(PLAYING_SAMPLE_RATE_HZ); 47 48 /** 49 * Get a Hann window. 50 */ hann(int windowWidth)51 private static double[] hann(int windowWidth) { 52 double[] envelopeArray = new double[windowWidth]; 53 for (int i = 0; i < windowWidth; i++) { 54 envelopeArray[i] = 0.5 55 * (1 - Math.cos(2 * Math.PI * i / windowWidth)); 56 } 57 return envelopeArray; 58 } 59 60 /** 61 * Get a maximum length sequence, used as prefix to indicate start of signal. 62 */ prefix(int rate)63 private static double[] prefix(int rate) { 64 double[] codeSequence = new double[PREFIX_NUM_CHIPS]; 65 for (int i = 0; i < PREFIX_NUM_CHIPS; i++) { 66 if (i < 10) { 67 codeSequence[i] = 1; 68 } else { 69 codeSequence[i] = -codeSequence[i - 6] * codeSequence[i - 7] 70 * codeSequence[i - 9] * codeSequence[i - 10]; 71 } 72 } 73 double[] prefixArray = new double[PREFIX_NUM_CHIPS * PREFIX_SAMPLES_PER_CHIP]; 74 int offset = 0; 75 for (int i = 0; i < PREFIX_NUM_CHIPS; i++) { 76 double value = codeSequence[i]; 77 for (int j = 0; j < PREFIX_SAMPLES_PER_CHIP; j++) { 78 prefixArray[offset + j] = value; 79 } 80 offset += PREFIX_SAMPLES_PER_CHIP; 81 } 82 int prefixLength = (int) Math.round(PREFIX_LENGTH_S * rate); 83 double[] samplePrefixArray = new double[prefixLength]; 84 for (int i = 0; i < prefixLength; i++) { 85 double index = (double) i / prefixLength * (prefixArray.length - 1); 86 samplePrefixArray[i] = (1 - index + Math.floor(index)) * prefixArray[(int) Math.floor(index)] 87 + (1 + index - Math.ceil(index)) * prefixArray[(int) Math.ceil(index)]; 88 } 89 return samplePrefixArray; 90 } 91 92 /** 93 * Returns array consists the frequencies of the test pips in the order that will be used in test. 94 */ frequencies()95 private static double[] frequencies() { 96 double[] originalFrequencies = originalFrequencies(); 97 98 double[] randomFrequencies = new double[Common.REPETITIONS * originalFrequencies.length]; 99 for (int i = 0; i < REPETITIONS * originalFrequencies.length; i++) { 100 randomFrequencies[i] = originalFrequencies[ORDER[i] % originalFrequencies.length]; 101 } 102 103 return randomFrequencies; 104 } 105 106 /** 107 * Returns array consists the frequencies of the test pips. 108 */ originalFrequencies()109 private static double[] originalFrequencies() { 110 ArrayList<Double> frequencies = new ArrayList<Double>(); 111 double frequency = Common.MIN_FREQUENCY_HZ; 112 while (frequency <= Common.MAX_FREQUENCY_HZ) { 113 frequencies.add(new Double(frequency)); 114 if ((frequency >= 18500) && (frequency < 20000)) { 115 frequency += Common.FREQUENCY_STEP_HZ; 116 } else { 117 frequency += Common.FREQUENCY_STEP_HZ * 10; 118 } 119 } 120 Double[] frequenciesArray = frequencies.toArray(new Double[frequencies.size()]); 121 double[] frequenciesPrimitiveArray = new double[frequenciesArray.length]; 122 for (int i = 0; i < frequenciesArray.length; i++) { 123 frequenciesPrimitiveArray[i] = frequenciesArray[i]; 124 } 125 return frequenciesPrimitiveArray; 126 } 127 128 /** 129 * Fisher-Yates shuffle. 130 */ order()131 private static int[] order() { 132 int[] order = new int[REPETITIONS * PIP_NUM]; 133 long seed = 0; 134 Random generator = new Random(seed); 135 for (int i = 0; i < REPETITIONS * PIP_NUM; i++) { 136 int j = generator.nextInt(i + 1); 137 order[i] = order[j]; 138 order[j] = i; 139 } 140 return order; 141 } 142 } 143