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