Generate And Play A Tone In Android hacking
1 /*********************************************************************************** 2 * Generate And Play A Tone In Android hacking 3 * 声明: 4 * 1. 源代码url: http://stackoverflow.com/questions/2413426/playing-an-arbitrary-tone-with-android 5 * 2. 主要功能是能够让Android手机发出一定频率的声音; 6 * 3. 当然我们也可以用来做各种波形发生器,这只是一个简单的Demo源码程序; 7 * 8 * 2015-4-27 周一 晴 深圳 平山村 曾剑锋 9 **********************************************************************************/ 10 public class PlaySound extends Activity { 11 // originally from http://marblemice.blogspot.com/2010/04/generate-and-play-tone-in-android.html 12 // and modified by Steve Pomeroy <steve@staticfree.info> 13 /* 声音持续3秒 */ 14 private final int duration = 3; // seconds 15 /* 采用率是8000 */ 16 private final int sampleRate = 8000; 17 /* 总共采样多少个点 */ 18 private final int numSamples = duration * sampleRate; 19 /* 利用总共采样的点数来生成数据数组 */ 20 private final double sample[] = new double[numSamples]; 21 /* 声音频率 */ 22 private final double freqOfTone = 440; // hz 23 24 /* 主要是因为采用的16位的数据 */ 25 private final byte generatedSnd[] = new byte[2 * numSamples]; 26 27 Handler handler = new Handler(); 28 29 @Override 30 public void onCreate(Bundle savedInstanceState) { 31 super.onCreate(savedInstanceState); 32 setContentView(R.layout.main); 33 } 34 35 @Override 36 protected void onResume() { 37 super.onResume(); 38 39 // Use a new tread as this can take a while 40 final Thread thread = new Thread(new Runnable() { 41 public void run() { 42 genTone(); 43 handler.post(new Runnable() { 44 45 public void run() { 46 playSound(); 47 } 48 }); 49 } 50 }); 51 thread.start(); 52 } 53 54 /** 55 * 生成上面参数对应的声音数据,保存在数组中 56 */ 57 void genTone(){ 58 // fill out the array 59 for (int i = 0; i < numSamples; ++i) { 60 /** 61 * 算法解析: 62 * 1. sampleRate/freqOfTone:每个周期才多少个点; 63 * 2. i / (sampleRate/freqOfTone):当前第i个点在整个周期的 64 * 采样点的比重(不知怎么表达 :) ); 65 * 3. 2 * Math.PI * i / (sampleRate/freqOfTone):当前第i个点对应的弧度制; 66 * 4. Math.sin(2 * Math.PI * i / (sampleRate/freqOfTone)):-1到1的sin函数值; 67 */ 68 sample[i] = Math.sin(2 * Math.PI * i / (sampleRate/freqOfTone)); 69 } 70 71 // convert to 16 bit pcm sound array 72 // assumes the sample buffer is normalised. 73 /** 74 * 将上面-1到1范围的sin函数值,转换成-32767到32767范围的值, 75 * 这个值是16位的值,放在对应的数组中 76 */ 77 int idx = 0; 78 for (final double dVal : sample) { 79 // scale to maximum amplitude 80 final short val = (short) ((dVal * 32767)); 81 // in 16 bit wav PCM, first byte is the low order byte 82 generatedSnd[idx++] = (byte) (val & 0x00ff); 83 generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8); 84 85 } 86 } 87 88 void playSound(){ 89 final AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 90 sampleRate, AudioFormat.CHANNEL_OUT_MONO, 91 AudioFormat.ENCODING_PCM_16BIT/*16位数据*/, generatedSnd.length, 92 AudioTrack.MODE_STATIC); 93 //将所有数据写出,相当于是发出声音 94 audioTrack.write(generatedSnd, 0, generatedSnd.length); 95 audioTrack.play(); 96 } 97 }