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 }

 

posted on 2015-04-27 08:31  zengjf  阅读(383)  评论(0编辑  收藏  举报

导航