Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android Audio的系統結構

Android Audio的系統結構

編輯:Android開發實例

 Audio系統負責Android中的PCM數據的錄制輸入流和播放輸出流的傳輸和控制,以及音頻設備的管理和設置。這裡主要介紹播放和錄制環節在各個層次的內容,整個結構層次分明,包括了java接口層,JNI層,本地框架層,audio服務層,硬件抽象層等5層。它的結構圖如下

                                                       圖1-1 Audio系統結構

  一、java接口層

    AudioManager:音頻管理對外的接口,提供了音量和ringtone模式的管理,由getSystemService(Context.AUDIO_SERVICE)返回。
Audioservice:是一個非常重要的java層的系統服務,所有的用戶發起的調用都是由它往底層轉發的。
AudioSystem:提供管理native接口,只時提供在media包的AudioService內部使用,不對用戶直接提供接口。
AudioTrack:提供用戶從java層直接輸出pcm數據的接口write函數,以及部分播放控制函數。
AudioRecord:提供用戶在java層直接從外部獲取pcm數據的接口read函數。
下面貼一段邊錄邊播放的例子代碼說明這些函數的使用

 
  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[recBufSize];   
  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[bufferReadResult];   
  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.     } 

    這些java class接口類在android.media包中,源碼目錄:frameworks/base/media/java/android/media。這些接口為使用media包的用戶提供了音量和路由設置,播放和錄制的pcm數據的接口。

  JNI層

    (android_media_AudioSystem, android_audio_AudioTrack, android_audio_AudioRecord),在libandroid_runtime.so包中
本地框架層

    AudioSystem:media庫提供給上層的audio管理的接口,它的實現主要在audiopolicymanger和audioflinger中
    AudioTrack:放音部分對上層的接口,stagefright部分也是調用該接口創建和控制playback track
AudioRecord:錄音部分對上層的接口,stagefright部分也是調用該接口創建一路record track
IAudioTrack, IAudioRecord, IAudioFlinger:這三個是聲明需要底層audioflinger實現的接口函數
這些c接口類在libmedia.so庫中,源碼目錄:frameworks/av/media/libmedia

  audio服務層

    AudioFlinger:這一層主要實現了track的創建,Android層共享內存的分配,多路混音等
硬件抽象層

    AudioHardwareInterface:這一層需要根據不同的硬件由廠商自己實現,如Primary,Usb,spdif,a2dp等,每一種硬件設備需要繼承audioHardwareInterface,實現一個控制硬件so庫。主要的類有AudioStreamOut和AudioStreamIn分別是audio輸出環節和輸入環節,負責write數據流到硬件和從硬件read數據流。

  六總結

    通過對各層一個概括性的介紹,對Audio系統的系統結構和源碼分布有一個清楚的理解。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved