HardBirch

Android提高第十篇之AudioRecord实现“助听器”

时间:10-11-22 栏目:安卓入门与提高 作者:张飞不张,文采横飞 评论:64 点击: 28,778 次

       Android可以通过MediaRecorder和AudioRecord这两个工具来实现录音,MediaRecorder直接把麦克风的数据存到文件,并且能够直接进行编码(如AMR,MP3等),而AudioRecord则是读取麦克风的音频流。本文使用AudioRecord读取音频流,使用AudioTrack播放音频流,通过“边读边播放”以及增大音量的方式来实现一个简单的助听器程序。

PS:由于目前的Android模拟器还不支持AudioRecord,因此本程序需要编译之后放到真机运行。

先贴出本文程序运行截图:


PS:程序音量调节只是程序内部调节音量而已,要调到最大音量还需要手动设置系统音量。

使用AudioRecord必须要申请许可,在AndroidManifest.xml里面添加这句:

main.xml的源码如下:




<Button android:layout_height="wrap_content" android:id="@+id/btnRecord"
android:layout_width="fill_parent" android:text="开始边录边放"></Button>
<Button android:layout_height="wrap_content"
android:layout_width="fill_parent" android:text="停止" android:id="@+id/btnStop"></Button>
<Button android:layout_height="wrap_content" android:id="@+id/btnExit"
android:layout_width="fill_parent" android:text="退出"></Button>
<TextView android:id="@+id/TextView01" android:layout_height="wrap_content"
android:text="程序音量调节" android:layout_width="fill_parent"></TextView>
<SeekBar android:layout_height="wrap_content" android:id="@+id/skbVolume"
android:layout_width="fill_parent"></SeekBar>

</LinearLayout>

testRecord.java的源码如下:

import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.Toast;

public class testRecord extends Activity {
/** Called when the activity is first created. */
Button btnRecord, btnStop, btnExit;
SeekBar skbVolume;//调节音量
boolean isRecording = false;//是否录放的标记
static final int frequency = 44100;
static final int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
static final int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
int recBufSize,playBufSize;
AudioRecord audioRecord;
AudioTrack audioTrack;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setTitle("助听器");
recBufSize = AudioRecord.getMinBufferSize(frequency,
channelConfiguration, audioEncoding);

playBufSize=AudioTrack.getMinBufferSize(frequency,
channelConfiguration, audioEncoding);
// -----------------------------------------
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, frequency,
channelConfiguration, audioEncoding, recBufSize);

audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, frequency,
channelConfiguration, audioEncoding,
playBufSize, AudioTrack.MODE_STREAM);
//------------------------------------------
btnRecord = (Button) this.findViewById(R.id.btnRecord);
btnRecord.setOnClickListener(new ClickEvent());
btnStop = (Button) this.findViewById(R.id.btnStop);
btnStop.setOnClickListener(new ClickEvent());
btnExit = (Button) this.findViewById(R.id.btnExit);
btnExit.setOnClickListener(new ClickEvent());
skbVolume=(SeekBar)this.findViewById(R.id.skbVolume);
skbVolume.setMax(100);//音量调节的极限
skbVolume.setProgress(70);//设置seekbar的位置值
audioTrack.setStereoVolume(0.7f, 0.7f);//设置当前音量大小
skbVolume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {

@Override
public void onStopTrackingTouch(SeekBar seekBar) {
float vol=(float)(seekBar.getProgress())/(float)(seekBar.getMax());
audioTrack.setStereoVolume(vol, vol);//设置音量
}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}

@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
}
});
}

@Override
protected void onDestroy() {
super.onDestroy();
android.os.Process.killProcess(android.os.Process.myPid());
}

class ClickEvent implements View.OnClickListener {

@Override
public void onClick(View v) {
if (v == btnRecord) {
isRecording = true;
new RecordPlayThread().start();// 开一条线程边录边放
} else if (v == btnStop) {
isRecording = false;
} else if (v == btnExit) {
isRecording = false;
testRecord.this.finish();
}
}
}

class RecordPlayThread extends Thread {
public void run() {
try {
byte[] buffer = new byte[recBufSize];
audioRecord.startRecording();//开始录制
audioTrack.play();//开始播放

while (isRecording) {
//从MIC保存数据到缓冲区
int bufferReadResult = audioRecord.read(buffer, 0,
recBufSize);

byte[] tmpBuf = new byte[bufferReadResult];
System.arraycopy(buffer, 0, tmpBuf, 0, bufferReadResult);
//写入数据即播放
audioTrack.write(tmpBuf, 0, tmpBuf.length);
}
audioTrack.stop();
audioRecord.stop();
} catch (Throwable t) {
Toast.makeText(testRecord.this, t.getMessage(), 1000);
}
}
};
}

声明: 本文由( 张飞不张,文采横飞 )原创编译,转载请保留链接: Android提高第十篇之AudioRecord实现“助听器”

Android提高第十篇之AudioRecord实现“助听器”:目前有64 条留言

  1. 0楼
    hmc1985:

    [e01]由简入深,并和实际应用联系起来,不得不佩服呀!

    2010-11-22 11:03 [回复]
  2. 0楼
    yangc_83:

    [e01][e03]

    2010-11-22 11:04 [回复]
  3. 0楼
    kf156:

    [e03]很好的生活应用,顶虫哥

    2010-11-22 11:04 [回复]
  4. 0楼
    simayilong:

    [e01]

    2010-11-22 11:20 [回复]
  5. 0楼
    xuyan87101:

    [e01]虫哥要加油啊……俺会好好的跟进的[e04]

    2010-11-22 11:22 [回复]
  6. 0楼
    freemancy:

    顶顶更健康.[e01][e01][e01][e01]

    2010-11-22 18:18 [回复]
  7. 0楼
    stb2000:

    [e01]

    2010-11-23 11:05 [回复]
  8. 0楼
    stb2000:

    [e03]

    2010-11-23 11:06 [回复]
  9. 0楼
    Hope_Cao:

    如果要支持录取通话对方的声音以及播放本地文件到通话对方需要怎么样操作?谢谢!

    2010-11-23 16:06 [回复]
  10. hellogv依然很牛啊。。。佩服。

    2010-11-24 13:43 [回复]
  11. 0楼
    philips67:

    我做好后用中兴x876试了下外放声音大点就有很刺耳的啸叫和回音。。用耳机的话没啸叫了但是声音很小,没放大的感觉。。不知道问题在哪..

    2010-12-06 18:19 [回复]
  12. 0楼
    yanghuaixi:

    [e01]

    2010-12-29 15:23 [回复]
  13. 0楼
    chensylsl:

    专家就是专家

    2011-01-13 09:27 [回复]
  14. 0楼
    chensylsl:

    [e01]

    2011-01-13 09:27 [回复]
  15. 0楼
    kendy6225:

    请问楼主在真机上测试过了么,我也遇到同样问题,很刺耳的啸声,不知道有没好的解决方案

    2011-01-13 15:57 [回复]
  16. 0楼
    xmz198901:

    直接复制的上面代码,为什么报错
    java.lang.IllegalArgumentException: Invalid audio buffer size.

    2011-01-25 19:27 [回复]
  17. 0楼
    hellogv:

    回复 kendy6225:
    在XT720上测试通过,你先插入耳机线,再运行程序,别让手机喇叭发声,试试看

    2011-01-25 20:34 [回复]
  18. 0楼
    hellogv:

    回复 xmz198901:
    真机?

    2011-01-25 20:35 [回复]
  19. 0楼
    lqz1988:

    为什么我用真机测试的话,一按边录边放就程序就死了啊[e07]

    2011-02-18 10:38 [回复]
  20. 0楼
    lqz1988:

    为什么debug调试的时候进入catch (Throwable t) 会出现异常呢,跟你上面代码一样的

    2011-02-18 14:06 [回复]
  21. 0楼
    lqz1988:

    可以,[e04][e03]

    2011-02-21 11:30 [回复]
  22. 0楼
    s385326246:

    真机测试,报错:java.lang.IllegalArgumentException: Invalid audio buffer size. 出错代码行:39 估计是AudioRecorde 初始化错误,博主解决一下吧。

    2011-03-07 13:37 [回复]
  23. 第11篇中有AudioRecord卻可以在模擬器上實現
    這篇卻不行,不曉得為什麼…[e07]

    2011-04-13 22:29 [回复]
  24. 0楼
    hellogv:

    回复 license2005:
    涉及到硬件的最好用真机

    2011-04-14 09:31 [回复]
  25. 0楼
    limitfan:

    Nexus S测试的时候,不用耳机,问题很大。

    2011-05-08 14:42 [回复]
  26. 0楼
    hellogv:

    回复 limitfan:
    喇叭的声音 进入麦克风了吧

    2011-05-08 17:03 [回复]
  27. 0楼
    leomok1986:

    为什么外放就会出现啸叫和回音呢,是硬件还是软件问题?

    2011-06-15 09:57 [回复]
  28. 0楼
    hellogv:

    回复 leomok1986:
    带耳机就没了,外放的声音回到麦克风就是这样

    2011-06-15 12:46 [回复]
  29. 充电的时候不能工作阿

    2011-07-13 10:30 [回复]
  30. 取样大小设为8bit为什么不行呢?

    2011-07-19 11:50 [回复]
  31. 0楼
    junpeng88:

    很好,有个疑问,audioTrack可否直接来播放音频文件?

    2011-07-29 14:23 [回复]
  32. 0楼
    hellogv:

    [reply]junpeng88[/reply]
    MP3这类文件都是经过编码压缩的,播放前要自己解码

    2011-07-30 08:11 [回复]
  33. 0楼
    jdh99:

    感谢博主的工作,代码可用,我计划在您代码基础上加入speex,然后测试网络通话

    2011-08-15 16:39 [回复]
  34. RecordPlayThread run中audioRecord.startRecording()会报startRecording() called on an uninitialized AudioRecord.的错误,麻烦解决下呀

    2011-08-23 17:42 [回复]
  35. 是在真机上调试时报的错

    2011-08-23 17:43 [回复]
  36. 0楼
    hellogv:

    [reply]doupeng1985[/reply]
    uninitialized 。。。。。没初始化

    2011-08-24 18:38 [回复]
  37. AudioRecord 总是会初始化失败,偶尔会成功,但是找不到规律,请问这是什么原因

    2011-08-31 20:12 [回复]
  38. 0楼
    hellogv:

    [reply]doupeng1985[/reply]
    尝试改一下分辨率,每个手机支持的分辨率不一样

    2011-09-01 08:55 [回复]
  39. 0楼
    plhbao:

    怎么判断录的声音是长音还是短音啊?

    2011-09-13 11:05 [回复]
  40. 0楼
    plhbao:

    怎么判断我录的声音长短

    2011-09-13 11:06 [回复]
  41. 0楼
    zyleftwing:

    [reply]doupeng1985[/reply]
    我开始也是这个错误 后来加了权限就好了 不知道这个地方报错为什么没有提示权限的问题

    2011-09-24 21:47 [回复]
  42. 楼主你好,我用的是arm6410调试的,装的是android1.5 出来错误 could not find method android.meida.AudioRecord.getMinBufferSize
    AudioRecord也在AndroidManifest.xml注册了,这个错误是因为硬件还是android版本的问题

    2011-10-09 19:50 [回复]
  43. 楼主你好,我用MediaRecorder录音,为什么在start后报异常:
    E/StagefrightRecorder( 750): audio source is not initialized
    I/MPEG4Writer( 750): The mp4 file will not be streamable.
    E/MediaRecorder( 1238): start failed: -2147483648

    MediaRecorder可以用吗?

    2011-10-19 17:25 [回复]
  44. 0楼
    yechuanfei:

    无敌支持。。。

    2011-10-26 15:55 [回复]
  45. 0楼
    hellogv:

    [reply]zhangpf6699[/reply]
    视频录制的。。。

    2011-10-26 18:41 [回复]
  46. 0楼
    daim6n:

    挺不错的例子,谢谢分享

    2011-11-03 14:17 [回复]
  47. 0楼
    bear_1066:

    [reply]doupeng1985[/reply]
    是啊AudioRecord怎么总是不定时的初始化失败呢,你找到原因了吗?求赐教。

    2011-12-01 18:31 [回复]
  48. 楼主,你怎么做回音消除的啊?啸叫太严重了。

    2012-01-12 17:18 [回复]
  49. 0楼
    hellogv:

    [reply]HongMenzhouxiangang[/reply]
    戴耳机,不用喇叭输出

    2012-01-13 17:26 [回复]
  50. 0楼
    rrfcnqyng:

    看看,顶下。

    2012-01-15 01:03 [回复]
  51. 0楼
    MoLoveyou:

    额 我的无法安装 是怎么回事啊啊?显示是“应用程序未安装”

    2012-03-16 14:26 [回复]
  52. 0楼
    hellogv:

    [reply]MoLoveyou[/reply]
    testRecord.java是否launcher的主类?

    2012-03-16 23:14 [回复]
  53. 看不懂

    2012-03-17 09:58 [回复]
  54. 0楼
    cuityhj:

    [reply]marenjun0611[/reply]
    我也用6410试过 采样频率设置为8000就可以用了 呵呵

    2012-03-18 22:04 [回复]
  55. 0楼
    viaco2love:

    audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, frequency,
    42. channelConfiguration, audioEncoding,
    43. playBufSize, AudioTrack.MODE_STREAM);

    改为:STREAM_VOICE_CALL
    长啸会解决,至于为什么,好不好
    自己试试

    2012-05-20 01:43 [回复]
  56. 0楼
    viaco2love:

    AudioManager.STREAM_SYSTEM
    会大声点

    2012-05-20 01:46 [回复]
  57. 0楼
    viaco2love:

    有木有人,有更好的方法

    2012-05-20 01:47 [回复]
  58. 0楼
    noshape1:

    楼主,播放出来的声音有延时,这个有没有办法可以减少点?

    2012-05-29 13:49 [回复]
  59. 0楼
    MoLoveyou:

    [reply]hellogv[/reply]
    解决了,就是一个签名的问题。签名以后就可以在机器上安装了。

    2012-06-17 14:55 [回复]
  60. 0楼
    szw0732178:

    我是新手 ,这个程序总调试不出来 ,哪位大侠 抬抬手 把APK发到 755711861@qq.com 不胜感激!

    2012-06-18 00:23 [回复]
  61. 0楼
    readpan:

    用了你的这个 声音很小 估计这方法只是从听筒里发出顶声音[reply]viaco2love[/reply]

    2012-07-06 18:08 [回复]
  62. 0楼
    ownWell:

    [quote=viaco2love]AudioManager.STREAM_SYSTEM
    会大声点[/quote]
    不知道二师兄把这个参数反在哪

    2012-07-23 16:56 [回复]
  63. 0楼
    doushen1:

    请问,为什么要System.arraycopy拷贝数组啊?谢谢

    2012-07-30 19:04 [回复]
  64. 0楼
    a_xiaozhen:

    真的很厉害,我也想试试!

    2012-08-20 17:20 [回复]

发表评论


QQ群互动

Linux系统与内核学习群:194051772

WP建站技术学习交流群:194062106

魔豆之路QR

魔豆的Linux内核之路

魔豆的Linux内核之路

优秀工程师当看优秀书籍

优秀程序员,要看优秀书!

赞助商广告

友荐云推荐