• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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