1 package com.android.cts.verifier.audio;
2 
3 /**
4  * Sound generator.
5  */
6 public class SoundGenerator {
7 
8   private static SoundGenerator instance;
9 
10   private final byte[] generatedSound;
11   private final double[] sample;
12 
SoundGenerator()13   private SoundGenerator() {
14     // Initialize sample.
15     int pipNum = Common.PIP_NUM;
16     int prefixTotalLength = Util.toLength(Common.PREFIX_LENGTH_S, Common.PLAYING_SAMPLE_RATE_HZ)
17         + Util.toLength(Common.PAUSE_BEFORE_PREFIX_DURATION_S, Common.PLAYING_SAMPLE_RATE_HZ)
18         + Util.toLength(Common.PAUSE_AFTER_PREFIX_DURATION_S, Common.PLAYING_SAMPLE_RATE_HZ);
19     int repetitionLength = pipNum * Util.toLength(
20         Common.PIP_DURATION_S + Common.PAUSE_DURATION_S, Common.PLAYING_SAMPLE_RATE_HZ);
21     int sampleLength = prefixTotalLength + Common.REPETITIONS * repetitionLength;
22     sample = new double[sampleLength];
23 
24     // Fill sample with prefix.
25     System.arraycopy(Common.PREFIX_FOR_PLAYER, 0, sample,
26         Util.toLength(Common.PAUSE_BEFORE_PREFIX_DURATION_S, Common.PLAYING_SAMPLE_RATE_HZ),
27         Common.PREFIX_FOR_PLAYER.length);
28 
29     // Fill the sample.
30     for (int i = 0; i < pipNum * Common.REPETITIONS; i++) {
31       double[] pip = getPip(Common.WINDOW_FOR_PLAYER, Common.FREQUENCIES[i]);
32       System.arraycopy(pip, 0, sample,
33           prefixTotalLength + i * Util.toLength(
34               Common.PIP_DURATION_S + Common.PAUSE_DURATION_S, Common.PLAYING_SAMPLE_RATE_HZ),
35           pip.length);
36     }
37 
38     // Convert sample to byte.
39     generatedSound = new byte[2 * sample.length];
40     int i = 0;
41     for (double dVal : sample) {
42       short val = (short) ((dVal * 32767));
43       generatedSound[i++] = (byte) (val & 0x00ff);
44       generatedSound[i++] = (byte) ((val & 0xff00) >>> 8);
45     }
46   }
47 
getInstance()48   public static SoundGenerator getInstance() {
49     if (instance == null) {
50       instance = new SoundGenerator();
51     }
52     return instance;
53   }
54 
55   /**
56    * Gets a pip sample.
57    */
getPip(double[] window, double frequency)58   private static double[] getPip(double[] window, double frequency) {
59     int pipArrayLength = window.length;
60     double[] pipArray = new double[pipArrayLength];
61     double radPerSample = 2 * Math.PI / (Common.PLAYING_SAMPLE_RATE_HZ / frequency);
62     for (int i = 0; i < pipArrayLength; i++) {
63       pipArray[i] = window[i] * Math.sin(i * radPerSample);
64     }
65     return pipArray;
66   }
67 
68   /**
69    * Get generated sound in byte[].
70    */
getByte()71   public byte[] getByte() {
72     return generatedSound;
73   }
74 
75   /**
76    * Get sample in double[].
77    */
getSample()78   public double[] getSample() {
79     return sample;
80   }
81 }
82