8.1.1 播放合成声音

    下面的一个简单的示例,展示了如何构造一个AudioTrack类,并传入数据进行播放。关于用于构造AudioTrack对象的参数的完整讨论,请参阅7.5节。

     此示例使用一个内部类AudioSynthesisTask,其扩展了AsyncTask。AsyncTask定义一个称为doInBackground的方法,它在一个单独的线程中运行其中放置的代码,而且该线程与活动的主线程分离。这样就使活动及其UI可以保持响应,否则向AudioTrack对象的write方法提供数据的循环会使他们阻塞。

 1 package com.nthm.androidtestActivity;
 2 
 3 import com.nthm.androidtest.R;
 4 import android.app.Activity;
 5 import android.media.AudioFormat;
 6 import android.media.AudioManager;
 7 import android.media.AudioTrack;
 8 import android.os.AsyncTask;
 9 import android.os.Bundle;
10 import android.view.View;
11 import android.view.View.OnClickListener;
12 import android.widget.Button;
13 
14 public class AudioSynthesis extends Activity implements OnClickListener {
15     private Button startSound;
16     private Button endSound;
17     private AudioSynthesisTask audioSynth;
18     private boolean keepGoing=false;
19     @Override
20     protected void onCreate(Bundle savedInstanceState) {
21         super.onCreate(savedInstanceState);
22         setContentView(R.layout.audiosynthesis);
23         startSound=(Button) findViewById(R.id.StartSound);
24         startSound.setOnClickListener(this);
25         endSound=(Button) findViewById(R.id.EndSound);
26         endSound.setOnClickListener(this);
27         
28         endSound.setEnabled(false);
29     }
30      
31     @Override
32     protected void onPause() {
33         super.onPause();
34         keepGoing=false;
35         endSound.setEnabled(false);
36         startSound.setEnabled(true);
37     }
38 
39     @Override
40     public void onClick(View v) {
41          if(v==startSound){
42              keepGoing=true;
43              audioSynth=new AudioSynthesisTask();
44              audioSynth.execute();
45              endSound.setEnabled(true);
46              startSound.setEnabled(false);
47          }else if(v==endSound){
48              keepGoing=false;
49              endSound.setEnabled(false);
50              startSound.setEnabled(true);
51          }
52     }
53     private class AudioSynthesisTask extends AsyncTask<Void, Void, Void>{
54 
55         @Override
56         protected Void doInBackground(Void... params) {
57             final int SAMPLE_RATE=11025;
58             int minSize=AudioTrack.getMinBufferSize(SAMPLE_RATE, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
59             AudioTrack audioTrack=new AudioTrack(AudioManager.STREAM_MUSIC, SAMPLE_RATE, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, minSize, AudioTrack.MODE_STREAM);
60             audioTrack.play();
61             short[] buffer={8130,15752,22389,27625,31134,32695,32210,29711,25354,19410,12253,4329,-3865,-11818,-19032,-25055,-29511,-32121,-32722,-31276,-27874,-22728,-16160,-8582,-466};
62             while(keepGoing){
63                 audioTrack.write(buffer, 0, buffer.length);
64             }
65             return null;
66         }
67     }
68 }

    以下是用于上述活动的布局XML。

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     android:layout_width="match_parent"
 3     android:layout_height="match_parent"
 4     android:orientation="vertical"
 5     >
 6  
 7  <Button 
 8      android:layout_width="wrap_content"
 9      android:layout_height="wrap_content"
10      android:id="@+id/StartSound"
11      android:text="Start Sound"/>
12  <Button 
13      android:layout_width="wrap_content"
14      android:layout_height="wrap_content"
15      android:id="@+id/EndSound"
16      android:text="End Sound"/>
17  
18 </LinearLayout>

    上述代码的关键是一个short数组。他们是音频样本,通过write方法不断的传递给AudioTrack对象。在当前情况下,这些样本从8130震荡到32965,向下震荡到-32121,然后回到-466。如果在图表上画出这些值,那么这些样本合在一起将构成一个波形。因为声音是以震荡压的方式创建的,而且每个样本表示一个压力值,所以利用这些样本来表示波形是创建声音所必须的步骤。改变这个波形将允许创建不同类型的音频。以下的样本集合描述了而一个短波形,其中只有10个样本,因此表示一个高频声音,即每秒钟存在许多震荡。而低频声音的波形将会以一个固定的采样率覆盖更多的样本。

1             short[] buffer={8130,15752,32695,12253,4329,-3865,-19232,-32722,-16160,-466};

 

posted on 2014-09-02 14:29  宁静致远,一览众山小  阅读(326)  评论(0编辑  收藏  举报

导航