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) 编辑 收藏 举报