轉載自:http://blog.csdn.net/hellogv/
Android可以通過MediaRecorder和AudioRecord這兩個工具來實現錄音,MediaRecorder直接把麥克風的資料存到檔案,並且能夠直接進行編碼(如AMR,MP3等),而AudioRecord則是讀取麥克風的音頻流。本文使用AudioRecord讀取音頻流,使用AudioTrack播放音頻流,通過“邊讀邊播放”以及增大音量的方式來實現一個簡單的助聽器程式。
PS:由於目前的Android模擬器還不支援AudioRecord,因此本程式需要編譯之後放到真機運行。
先貼出本文程式運行:
PS:程式音量大小只是程式內部調節音量而已,要調到最大音量還需要手動設定系統音量。
使用AudioRecord必須要申請許可,在AndroidManifest.xml裡面添加這句:
<uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission>
main.xml的源碼如下:
01.<?xml version="1.0" encoding="utf-8"?> 02.<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 03. android:orientation="vertical" android:layout_width="fill_parent" 04. android:layout_height="fill_parent"> 05. 06. <Button android:layout_height="wrap_content" android:id="@+id/btnRecord" 07. android:layout_width="fill_parent" android:text="開始邊錄邊放"></Button> 08. <Button android:layout_height="wrap_content" 09. android:layout_width="fill_parent" android:text="停止" android:id="@+id/btnStop"></Button> 10. <Button android:layout_height="wrap_content" android:id="@+id/btnExit" 11. android:layout_width="fill_parent" android:text="退出"></Button> 12. <TextView android:id="@+id/TextView01" android:layout_height="wrap_content" 13. android:text="程式音量大小" android:layout_width="fill_parent"></TextView> 14. <SeekBar android:layout_height="wrap_content" android:id="@+id/skbVolume" 15. android:layout_width="fill_parent"></SeekBar> 16. 17.</LinearLayout>
testRecord.java的源碼如下:
01.package com.testRecord; 02. 03.import android.app.Activity; 04.import android.media.AudioFormat; 05.import android.media.AudioManager; 06.import android.media.AudioRecord; 07.import android.media.AudioTrack; 08.import android.media.MediaRecorder; 09.import android.os.Bundle; 10.import android.view.View; 11.import android.widget.Button; 12.import android.widget.SeekBar; 13.import android.widget.Toast; 14. 15.public class testRecord extends Activity { 16. /** Called when the activity is first created. */ 17. Button btnRecord, btnStop, btnExit; 18. SeekBar skbVolume;//調節音量 19. boolean isRecording = false;//是否錄放的標記 20. static final int frequency = 44100; 21. static final int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO; 22. static final int audioEncoding = AudioFormat.ENCODING_PCM_16BIT; 23. int recBufSize,playBufSize; 24. AudioRecord audioRecord; 25. AudioTrack audioTrack; 26. 27. @Override 28. public void onCreate(Bundle savedInstanceState) { 29. super.onCreate(savedInstanceState); 30. setContentView(R.layout.main); 31. setTitle("助聽器"); 32. recBufSize = AudioRecord.getMinBufferSize(frequency, 33. channelConfiguration, audioEncoding); 34. 35. playBufSize=AudioTrack.getMinBufferSize(frequency, 36. channelConfiguration, audioEncoding); 37. // ----------------------------------------- 38. audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, frequency, 39. channelConfiguration, audioEncoding, recBufSize); 40. 41. audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, frequency, 42. channelConfiguration, audioEncoding, 43. playBufSize, AudioTrack.MODE_STREAM); 44. //------------------------------------------ 45. btnRecord = (Button) this.findViewById(R.id.btnRecord); 46. btnRecord.setOnClickListener(new ClickEvent()); 47. btnStop = (Button) this.findViewById(R.id.btnStop); 48. btnStop.setOnClickListener(new ClickEvent()); 49. btnExit = (Button) this.findViewById(R.id.btnExit); 50. btnExit.setOnClickListener(new ClickEvent()); 51. skbVolume=(SeekBar)this.findViewById(R.id.skbVolume); 52. skbVolume.setMax(100);//音量大小的極限 53. skbVolume.setProgress(70);//設定seekbar的位置值 54. audioTrack.setStereoVolume(0.7f, 0.7f);//設定當前音量大小 55. skbVolume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 56. 57. @Override 58. public void onStopTrackingTouch(SeekBar seekBar) { 59. float vol=(float)(seekBar.getProgress())/(float)(seekBar.getMax()); 60. audioTrack.setStereoVolume(vol, vol);//設定音量 61. } 62. 63. @Override 64. public void onStartTrackingTouch(SeekBar seekBar) { 65. // TODO Auto-generated method stub 66. } 67. 68. @Override 69. public void onProgressChanged(SeekBar seekBar, int progress, 70. boolean fromUser) { 71. // TODO Auto-generated method stub 72. } 73. }); 74. } 75. 76. @Override 77. protected void onDestroy() { 78. super.onDestroy(); 79. android.os.Process.killProcess(android.os.Process.myPid()); 80. } 81. 82. class ClickEvent implements View.OnClickListener { 83. 84. @Override 85. public void onClick(View v) { 86. if (v == btnRecord) { 87. isRecording = true; 88. new RecordPlayThread().start();// 開一條線程邊錄邊放 89. } else if (v == btnStop) { 90. isRecording = false; 91. } else if (v == btnExit) { 92. isRecording = false; 93. testRecord.this.finish(); 94. } 95. } 96. } 97. 98. class RecordPlayThread extends Thread { 99. public void run() { 100. try { 101. byte[] buffer = new byte[recBufSize]; 102. audioRecord.startRecording();//開始錄製 103. audioTrack.play();//開始播放 104. 105. while (isRecording) { 106. //從MIC儲存資料到緩衝區 107. int bufferReadResult = audioRecord.read(buffer, 0, 108. recBufSize); 109. 110. byte[] tmpBuf = new byte[bufferReadResult]; 111. System.arraycopy(buffer, 0, tmpBuf, 0, bufferReadResult); 112. //寫入資料即播放 113. audioTrack.write(tmpBuf, 0, tmpBuf.length); 114. } 115. audioTrack.stop(); 116. audioRecord.stop(); 117. } catch (Throwable t) { 118. Toast.makeText(testRecord.this, t.getMessage(), 1000); 119. } 120. } 121. }; 122.}