Android可以通过MediaRecorder和AudioRecord这两个工具来实现录音,MediaRecorder直接把麦克风的数据存到文件,并且能够直接进行编码(如AMR,MP3等),而AudioRecord则是读取麦克风的音频流。本文使用AudioRecord读取音频流,使用AudioTrack播放音频流,通过“边读边播放”以及增大音量的方式来实现一个简单的助听器程序。
PS:由于目前的Android模拟器还不支持AudioRecord,因此本程序需要编译之后放到真机运行。
Activity_layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="@+id/bt_yinpinhuilu_testing_exit"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Close"
/>
</LinearLayout>
MainActivity:
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.content.pm.PackageManager;
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.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.util.LinkedList;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "ktv";
private Button bt_exit;
protected int m_in_buf_size;
private AudioRecord m_in_rec;
private byte[] m_in_bytes;
private LinkedList<byte[]> m_in_q;
private int m_out_buf_size;
private AudioTrack m_out_trk;
private byte[] m_out_bytes;
private Thread record;
private Thread play;
private boolean flag = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.setTitle("音频回路");
requestAllPower();
Log.d("dfdfd", "333333333333");
init();
record = new Thread(new recordSound());
play = new Thread(new playRecord());
// 启动录制线程
record.start();
// 启动播放线程
play.start();
}
private void init() {
bt_exit = findViewById(R.id.bt_yinpinhuilu_testing_exit);
Log.i(TAG, "bt_exit====" + bt_exit);
bt_exit.setOnClickListener(this);
// AudioRecord 得到录制最小缓冲区的大小
m_in_buf_size = AudioRecord.getMinBufferSize(8000,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
// 实例化播放音频对象
m_in_rec = new AudioRecord(MediaRecorder.AudioSource.MIC, 8000,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT, m_in_buf_size);
// 实例化一个字节数组,长度为最小缓冲区的长度
m_in_bytes = new byte[m_in_buf_size];
// 实例化一个链表,用来存放字节组数
m_in_q = new LinkedList<byte[]>();
// AudioTrack 得到播放最小缓冲区的大小
m_out_buf_size = AudioTrack.getMinBufferSize(8000,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
// 实例化播放音频对象
m_out_trk = new AudioTrack(AudioManager.STREAM_MUSIC, 8000,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT, m_out_buf_size,
AudioTrack.MODE_STREAM);
// 实例化一个长度为播放最小缓冲大小的字节数组
m_out_bytes = new byte[m_out_buf_size];
}
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.bt_yinpinhuilu_testing_exit:
flag = false;
m_in_rec.stop();
m_in_rec = null;
m_out_trk.stop();
m_out_trk = null;
this.finish();
}
}
class recordSound implements Runnable {
@Override
public void run() {
Log.i(TAG, "........recordSound run()......");
byte[] bytes_pkg;
// 开始录音
m_in_rec.startRecording();
while (flag) {
m_in_rec.read(m_in_bytes, 0, m_in_buf_size);
bytes_pkg = m_in_bytes.clone();
Log.i(TAG, "........recordSound bytes_pkg==" + bytes_pkg.length);
if (m_in_q.size() >= 2) {
m_in_q.removeFirst();
}
m_in_q.add(bytes_pkg);
}
}
}
class playRecord implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
Log.i(TAG, "........playRecord run()......");
byte[] bytes_pkg = null;
// 开始播放
m_out_trk.play();
while (flag) {
try {
m_out_bytes = m_in_q.getFirst();
bytes_pkg = m_out_bytes.clone();
m_out_trk.write(bytes_pkg, 0, bytes_pkg.length);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public void requestAllPower() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.RECORD_AUDIO)) {
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO,
Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 1) {
for (int i = 0; i < permissions.length; i++) {
Toast.makeText(this, "" + "权限" + permissions[i] + "申请成功", Toast.LENGTH_SHORT).show();
}
}
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.speex">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。