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