Audio的系统结构
<div id="cnblogs_post_body"> 摘要:Audio系统负责Android中的PCM数据的录制输入流和播放输出流的传输和控制,以及音频设备的管理和设置。这里主要介绍播放和录制环节在各个层次的内容,整个结构层次分明,包括了java接口层,JNI层,本地框架层,audio服务层,硬件抽象层等5层。它的结构图如下http://images.cnblogs.com/cnblogs_com/cerberspace/416181/r_%e5%9b%be1-1.png 图1-1 Audio系统结构
一、java接口层
AudioManager:音频管理对外的接口,提供了音量和ringtone模式的管理,由getSystemService(Context.AUDIO_SERVICE)返回。
Audioservice:是一个非常重要的java层的系统服务,所有的用户发起的调用都是由它往底层转发的。
AudioSystem:提供管理native接口,只时提供在media包的AudioService内部使用,不对用户直接提供接口。
AudioTrack:提供用户从java层直接输出pcm数据的接口write函数,以及部分播放控制函数。
AudioRecord:提供用户在java层直接从外部获取pcm数据的接口read函数。
下面贴一段边录边播放的例子代码说明这些函数的使用
<div class="cnblogs_code" >http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gifhttp://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gifView Code <div id="cnblogs_code_open_5d50daaa-a516-4a74-9095-b5a3a6859ac7" class="cnblogs_code_hide">1 package test.Record;2 3 import java.io.BufferedInputStream;4 import java.io.File;5 import java.io.FileInputStream;6 import java.io.FileOutputStream;7 import java.io.InputStream;8 import java.io.OutputStream;9 10 import android.app.Activity; 11 import android.content.Intent; 12 import android.media.AudioFormat; 13 import android.media.AudioManager; 14 import android.media.AudioRecord; 15 import android.media.AudioTrack; 16 import android.media.MediaRecorder; 17 import android.os.Bundle; 18 import android.util.Log; 19 import android.view.View; 20 import android.widget.Button; 21 import android.widget.SeekBar; 22 import android.widget.Toast; 23 24 public class testRecord extends Activity { 25 /** Called when the activity is first created. */ 26 Button btnRecord, btnStop, btnExit; 27 SeekBar skbVolume;//调节音量 28 boolean isRecording = false;//是否录放的标记 29 static final int frequency = 44100; 30 static final int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO; 31 static final int audioEncoding = AudioFormat.ENCODING_PCM_16BIT; 32 int recBufSize,playBufSize; 33 AudioRecord audioRecord; 34 AudioTrack audioTrack; 35 36 @Override 37 public void onCreate(Bundle savedInstanceState) { 38 super.onCreate(savedInstanceState); 39 setContentView(R.layout.main); 40 setTitle("助听器"); 41 42 //------------------------------------------ 43 btnRecord = (Button) this.findViewById(R.id.btnRecord); 44 btnRecord.setOnClickListener(new ClickEvent()); 45 btnStop = (Button) this.findViewById(R.id.btnStop); 46 btnStop.setOnClickListener(new ClickEvent()); 47 btnExit = (Button) this.findViewById(R.id.btnExit); 48 btnExit.setOnClickListener(new ClickEvent()); 49 skbVolume=(SeekBar)this.findViewById(R.id.skbVolume); 50 skbVolume.setMax(100);//音量调节的极限 51 skbVolume.setProgress(100);//设置seekbar的位置值 52 //audioTrack.setStereoVolume(1.0f, 1.0f);//设置当前音量大小 53 skbVolume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 54 55 56 public void onStopTrackingTouch(SeekBar seekBar) { 57 float vol=(float)(seekBar.getProgress())/(float)(seekBar.getMax()); 58 //audioTrack.setStereoVolume(vol, vol);//设置音量 59 } 60 61 62 public void onStartTrackingTouch(SeekBar seekBar) { 63 // TODO Auto-generated method stub 64 } 65 66 67 public void onProgressChanged(SeekBar seekBar, int progress, 68 boolean fromUser) { 69 // TODO Auto-generated method stub 70 } 71 }); 72 } 73 74 @Override 75 protected void onDestroy() { 76 super.onDestroy(); 77 android.os.Process.killProcess(android.os.Process.myPid()); 78 } 79 80 class ClickEvent implements View.OnClickListener { 81 82 83 public void onClick(View v) { 84 if (v == btnRecord) { 85 if(!isRecording) { 86 isRecording = true; 87 AudioManager audioManager = (AudioManager) getSystemService(getApplicationContext().AUDIO_SERVICE); 88 audioManager.setMode(AudioManager.MODE_NORMAL); 89 recBufSize = AudioRecord.getMinBufferSize(frequency, 90 channelConfiguration, audioEncoding); 91 playBufSize=AudioTrack.getMinBufferSize(frequency, 92 channelConfiguration, audioEncoding); 93 94 audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, frequency, 95 channelConfiguration, audioEncoding, recBufSize); 96 97 audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, frequency, 98 channelConfiguration, audioEncoding, 99 playBufSize, AudioTrack.MODE_STREAM);100 101 new RecordPlayThread().start();// 开一条线程边录边放 102 } 103 } else if (v == btnStop) { 104 if(isRecording) {105 isRecording = false;106 AudioManager audioManager = (AudioManager) getSystemService(getApplicationContext().AUDIO_SERVICE);107 audioManager.setMode(AudioManager.MODE_NORMAL);108 } 109 } else if (v == btnExit) {110 isRecording = false; 111 AudioManager audioManager = (AudioManager) getSystemService(getApplicationContext().AUDIO_SERVICE);112 audioManager.setMode(AudioManager.MODE_NORMAL);113 testRecord.this.finish();114 }115 }116 }117 118 class RecordPlayThread extends Thread {119 public void run() {120 try {121 byte[] buffer = new byte;122 audioRecord.startRecording();//开始录制123 audioTrack.play();//开始播放 124 while (isRecording) {125 //从MIC保存数据到缓冲区126 int bufferReadResult = audioRecord.read(buffer, 0,127 recBufSize);128 byte[] tmpBuf = new byte;129 System.arraycopy(buffer, 0, tmpBuf, 0, bufferReadResult);130 //写入数据即播放131 audioTrack.write(tmpBuf, 0, tmpBuf.length);132 }133 audioTrack.stop();134 audioTrack.release(); 135 audioRecord.stop();136 audioRecord.release();137 } catch (Throwable t) {138 Toast.makeText(testRecord.this, t.getMessage(), 1000);139 }140 }141 }142 }
页:
[1]