欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android提高之AudioRecord实现助听器的方法

程序员文章站 2022-11-05 15:11:25
通常来说,在进行android项目开发的时候可以通过mediarecorder和audiorecord这两个工具来实现录音的功能,mediarecorder直接把麦克风的数...

通常来说,在进行android项目开发的时候可以通过mediarecorder和audiorecord这两个工具来实现录音的功能,mediarecorder直接把麦克风的数据存到文件,并且能够直接进行编码(如amr,mp3等),而audiorecord则是读取麦克风的音频流。本文使用audiorecord读取音频流,使用audiotrack播放音频流,通过“边读边播放”以及增大音量的方式来实现一个简单的助听器程序。

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

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

另外还要注意:在本程序音量调节只是程序内部调节音量而已,要调到最大音量还需要手动设置系统音量。

Android提高之AudioRecord实现助听器的方法

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

<uses-permission android:name="android.permission.record_audio"></uses-permission>

main.xml的源码如下:

<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical" android:layout_width="fill_parent"
 android:layout_height="fill_parent">

 <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的源码如下:

package com.testrecord;
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项目开发有一定的借鉴价值。