GVKun编程网logo

Android提高之AudioRecord实现助听器的方法(安卓助听器)

8

如果您对Android提高之AudioRecord实现助听器的方法感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于Android提高之AudioRecord实现助听器的方法的

如果您对Android提高之AudioRecord实现助听器的方法感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于Android提高之AudioRecord实现助听器的方法的详细内容,我们还将为您解答安卓助听器的相关问题,并且为您提供关于Android 4.4中AudioRecord用例 - 录制系统内置声音、Android AudioRecord 的使用、android AudioRecorder简单心得分享、Android AudioRecord初始化延迟的有价值信息。

本文目录一览:

Android提高之AudioRecord实现助听器的方法(安卓助听器)

Android提高之AudioRecord实现助听器的方法(安卓助听器)

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

此处需要注意:由于目前的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,audioEncoding);
 // -----------------------------------------
 audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,frequency,audioEncoding,recBufSize);

 audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,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,recBufSize);

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

希望本文所述实例对大家的Android项目开发有一定的借鉴价值。

您可能感兴趣的文章:

  • Android音频录制MediaRecorder之简易的录音软件实现代码
  • Android使用AudioRecord实现暂停录音功能实例代码
  • Android录音--AudioRecord、MediaRecorder的使用
  • Android使用AudioRecord判断是否有音频输入
  • Android音频处理之通过AudioRecord去保存PCM文件进行录制,播放,停止,删除功能
  • android AudioRecorder简单心得分享
  • Android利用AudioRecord类实现音频录制程序

Android 4.4中AudioRecord用例 - 录制系统内置声音

Android 4.4中AudioRecord用例 - 录制系统内置声音

通过API 19新加的MediaRecorder.AudioSource.REMOTE_SUBMIX參数能够让系统App录制系统内置的声音,也就是扬声器的声音。以下是一个巨简单的样例来演示样例怎样通过AudioRecord配合REMOTE_SUBMIX參数进行录制。


1. 编译apk

MainActivity.java:

package com.example.audiotest;

import java.io.FileOutputStream;
import java.io.IOException;

import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends Activity {
	private static String TAG = "JZJ";
	AudioRecord mRecord = null;
	boolean mReqStop = false;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		init();
		(new Thread() {
			@Override
			public void run() {
				recordAndPlay();
			}
		}).start();
	}

	private final int kSampleRate = 44100;
	private final int kChannelMode = AudioFormat.CHANNEL_IN_STEREO;
	private final int kEncodeFormat = AudioFormat.ENCODING_PCM_16BIT;

	private void init() {
		int minBufferSize = AudioRecord.getMinBufferSize(kSampleRate, kChannelMode,
				kEncodeFormat);
		mRecord = new AudioRecord(MediaRecorder.AudioSource.REMOTE_SUBMIX,
				kSampleRate, kChannelMode, kEncodeFormat, minBufferSize * 2);
	}

	private final int kFrameSize = 2048;
	private String filePath = "/sdcard/voice.pcm";

	private void recordAndPlay() {
		FileOutputStream os = null;
		mRecord.startRecording();
		try {
			os = new FileOutputStream(filePath);
			byte[] buffer = new byte[kFrameSize];
			int num = 0;
			while (!mReqStop) {
				num = mRecord.read(buffer, 0, kFrameSize);
				Log.d(TAG, "buffer = " + buffer.toString() + ", num = " + num);
				os.write(buffer, 0, num);
			}

			Log.d(TAG, "exit loop");
			os.close();
		} catch (IOException e) {
			e.printStackTrace();
			Log.e(TAG, "Dump PCM to file failed");
		}
		mRecord.stop();
		mRecord.release();
		mRecord = null;
		Log.d(TAG, "clean up");
	}

	public void stop(View view) {
		mReqStop = true;
		Button stopBtn = (Button) findViewById(R.id.stopBtn);
		stopBtn.setText("Stopped");
		stopBtn.setEnabled(false);
	}
}

布局文件activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <Button
        android:id="@+id/stopBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="stop"
        android:text="Stop" />

</RelativeLayout>

配置文件AndroidManifest.xml,注意要加上的几个权限:

<?xml version="1.0" encoding="utf-8"?

> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.audiotest" android:versionCode="1" android:versionName="1.0" > <uses-permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT" /> <uses-permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT"/> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="19" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.example.audiotest.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>


编译生成Test.apk。


2. 加系统签名

java -jar signapk.jar platform.x509.pem platform.pk8 ./Test.apk final.apk


platform.x509.pem和platform.pk8在Android源代码的build/target/product/security文件夹下。

signapk.jar能够从https://code.google.com/p/signapk/下载。


3. 安装签名好的apk,执行

启动时即開始採集系统声音数据,结束时点击Stopbutton停止。这时採集数据会导出到/sdcard/voice.pcm文件。


4. 取出音频採样数据,播放

adb pull /sdcard/voice.pcm 

vlc --demux=rawaud --rawaud-channels 2 --rawaud-samplerate 44100 voice.pcm

这样就開始播放刚才录制的声音了。vlc是一个多媒体播放器(http://www.videolan.org/vlc/index.html)。支持播放PCM数据。当然也能够用其他支持播放PCM的播放器。


总结来说。这样的方法的缺点是录制时扬声器就不能输出,长处是不用改系统层。假设要两个同一时候输出能够參考这篇文章:http://xzpeter.org/?p=254。


Android AudioRecord 的使用

Android AudioRecord 的使用

AudioRecord

本工程实现pcm多配置(采样率、文件格式可选)的录音和播放工具,可用户音频的录制。

工程代码:https://github.com/worson/AudioRecord.git

在这里插入图片描述

录音参数

在安卓应用中,使用AudioRecord可实现更灵活的录音配置,AudioRecord录制的是原始的pcm数据。
AudioRecord的构造方法如下:

AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes)

audioSource: 音频录制的音原,具体如下

MediaRecorder.AudioSource.CAMCORDER 
设定录音来源于同方向的相机麦克风相同,若相机无内置相机或无法识别,则使用预设的麦克风
MediaRecorder.AudioSource.DEFAULT  默认音频源
MediaRecorder.AudioSource.MIC
设定录音来源为主麦克风。
MediaRecorder.AudioSource.VOICE_CALL
设定录音来源为语音拨出的语音与对方说话的声音
MediaRecorder.AudioSource.VOICE_COMMUNICATION
摄像头旁边的麦克风
MediaRecorder.AudioSource.VOICE_DOWNLINK
下行声音
MediaRecorder.AudioSource.VOICE_RECOGNITION
语音识别
MediaRecorder.AudioSource.VOICE_UPLINK
上行声音

sampleRateInHz:音频采样率,即可每秒中采集多少个音频数据

channelConfig: 录音通道,单通道为 AudioFormat.CHANNEL_CONfigURATION_MONO,双通道为AudioFormat.CHANNEL_CONfigURATION_STEREO

audioFormat: 音频每个采样点的位数,即音频的精度,通道选用AudioFormat.ENCODING_PCM_16BIT即pcm 16位即可

bufferSizeInBytes: 音频数据写入缓冲区的总数,通过 AudioRecord.getMinBufferSize 获取最小的缓冲区。

关于音频数据量的计算

对于采样率为16k位深有16bit的录制参数,每秒钟的byte数为:16000*2=32000,即每分钟为:32000*60 byte/min= 1.875 MB/min的数据量

录音流程

创建录音机

public PcmRecorder(int audioSource, int sampleRate, int channelCnt, Context context, RecordListener listener) {
        mListener = listener;
        int channelConfig = channelCnt == 1 ? AudioFormat.CHANNEL_CONfigURATION_MONO : AudioFormat.CHANNEL_CONfigURATION_STEREO;
        int minBufSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, AUdio_FORMAT);
        mBufSize = minBufSize;
        int bufferSizeInBytes = minBufSize;
        AILog.i(TAG, "PcmRecorder: bufferSizeInBytes " + bufferSizeInBytes);
        mAudioRecord = new AudioRecord(audioSource, sampleRate, channelConfig, AUdio_FORMAT, bufferSizeInBytes);
        AILog.d(TAG, "state: " + mAudioRecord.getState());
    }

开始录音

开始录音,并创建数据读取线程

public void start() {
        AILog.d(TAG, "onStartRecord");

        mAudioRecord.startRecording();
        mRecording = true;
        mRecordThread = new RecordThread("RecordThread");
        mRecordThread.start();
        if (mListener != null) {
            mListener.onStartRecord();
        } else {
            AILog.w(TAG, "start: mListener is null");
        }
    }

读取音频数据

不断读取 Buffer 中声音数据,并回调上层应用处理

class RecordThread extends Thread {

        public RecordThread(String name) {
            super(name);
        }

        @Override
        public void run() {
            AILog.v(TAG, "thread run");
            Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUdio);

            if (mAudioRecord.getState() == AudioRecord.STATE_UNINITIALIZED) {
                AILog.d(TAG, "unInit");
                return;
            }

            byte[] buffer = new byte[mBufSize];
            while (!mStopFlag) {
                int len = mAudioRecord.read(buffer, 0, buffer.length);
                if (len != mBufSize) {
                    AILog.e(TAG, "record read error:" + len);
                }
                if (mListener != null) {
                    mListener.onRecordData(buffer);
                    continue;
                }
            }
            AILog.v(TAG, "thread end");
        }
    }

停止录音

停止录音并释放相关资源

public void stop() {
        AILog.d(TAG, "stopRecord");
        mStopFlag = true;
        mRecording = false;
        try {
            mRecordThread.join();
        } catch (InterruptedException e) {
            AILog.d(TAG, "InterruptedException " + e.getMessage());
        } finally {
            if (mListener != null) {
                mListener.onStopRecord();
            } else {
                AILog.d(TAG, "stop: mListener is null");
            }
            mAudioRecord.stop();
            mAudioRecord.release();
        }
        mListener = null;
    }

上层应用调用

private void startRecord() {
    AILog.i(TAG, "startRecord: ");
    checkEnvirement();
    if (rb_channel_dual.isChecked()) {
        mRecorder = new PcmRecorder(getAudioSource(), getAudioFrequecy(), 2);
    } else {
        mRecorder = new PcmRecorder(getAudioSource(), getAudioFrequecy(), 1);
    }
    try {
        mOutputStream = new FileOutputStream(mTempRecordFile);
        mRecorder.setRecordListener(mRecordListener);
        mRecorder.start();
        tv_tips.setText("正在录音...");
        bt_recorder.setText("结束录音");
        bt_play.setVisibility(View.INVISIBLE);
        bt_delete.setVisibility(View.INVISIBLE);
    } catch (FileNotFoundException e) {
        e.printstacktrace();
        tv_tips.setText("录音启动失败...");
    }

}

private RecordListener mRecordListener = new RecordListener() {
    @Override
    public void onStartRecord() {
        AILog.i(TAG, "onStartRecord: ");
    }

    @Override
    public void onRecordData(byte[] bytes) {
        try {
            mOutputStream.write(bytes);
        } catch (IOException e) {
            e.printstacktrace();
        }
    }

    @Override
    public void onStopRecord() {
        AILog.i(TAG, "onStopRecord: ");
        //保存文件
    }
};

老马行空 发布了10 篇原创文章 · 获赞 0 · 访问量 9952 私信 关注

android AudioRecorder简单心得分享

android AudioRecorder简单心得分享

1.如何创建一个有效的AudioRecorder实例
Android各种设备的采样频率不同,输入的声道数也不同,如果采用固定的采样频率和声道数,那么得到的AudioRecorder不一定能够正常初始化。
为了正常使用,需要尝试各种不同的参数,得到在此设备上可以用的AudioRecorder实例。代码如下:
复制代码 代码如下:

private void createAudioRecord() {  
           for (int sampleRate : new int[]{44100,8000,11025,16000,22050,32000,  
            47250,48000}) {  
        for (short audioFormat : new short[]{  
                AudioFormat.ENCODING_PCM_16BIT,  
                AudioFormat.ENCODING_PCM_8BIT}) {  
            for (short channelConfig : new short[]{  
                    AudioFormat.CHANNEL_IN_MONO,  
                    AudioFormat.CHANNEL_IN_STEREO}) {  

                // Try to initialize  
                try {  
                    recBufSize = AudioRecord.getMinBufferSize(sampleRate,  
                            channelConfig,audioFormat);  

                    if (recBufSize < 0) {  
                        continue;  
                    }  

                    audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,  
                            sampleRate,channelConfig,audioFormat,  
                            recBufSize * 2);  

                    if (audioRecord.getState() == AudioRecord.STATE_INITIALIZED) {  

                        return;  
                    }  

                    audioRecord.release();  
                    audioRecord = null;  
                } catch (Exception e) {  
                    // Do nothing  
                }  
            }  
        }  
    }  

    throw new IllegalStateException(  
            "getInstance() Failed : no suitable audio configurations on this device.");  
}

2.常见错误
1.有些设备上面,即使你得到了有效的AudioRecorder实例,在audioRecord.startRecording()的时候还会报ERROR_BAD_VALUE错误。
这有可能是你使用了AudioManager而没有释放导致的。
其他错误都可以在网络上找到答案。

您可能感兴趣的文章:

  • Android音频录制MediaRecorder之简易的录音软件实现代码
  • Android使用AudioRecord实现暂停录音功能实例代码
  • Android录音--AudioRecord、MediaRecorder的使用
  • Android使用AudioRecord判断是否有音频输入
  • Android音频处理之通过AudioRecord去保存PCM文件进行录制,播放,停止,删除功能
  • Android提高之AudioRecord实现助听器的方法
  • Android利用AudioRecord类实现音频录制程序

Android AudioRecord初始化延迟

Android AudioRecord初始化延迟

这是正在处理的相关代码的示例:

AudioRecord recorder = setupAudio();
recorder.startRecording();

SetupAudio方法:

public AudioRecord setupAudio() {

        AudioRecord recorder;

        minBufferSizeInBytes = AudioRecord.getMinBufferSize(
                RECORDER_SAMPLERATE, AudioFormat.CHANNEL_IN_MONO,
                AudioFormat.ENCODING_PCM_16BIT);

        Log.e("MoverAudio","BufferSize: " + minBufferSizeInBytes);

        recorder = new AudioRecord(MediaRecorder.AudioSource.CAMCORDER,
                RECORDER_SAMPLERATE, AudioFormat.CHANNEL_IN_MONO,
                AudioFormat.ENCODING_PCM_16BIT, minBufferSizeInBytes);

        return recorder;
    }

RECORDER_SAMPLERATE = 8000;

我试图找出是否有任何方法可以缩短初始化时间.

目前,我正在3种设备上对其进行即时测试,结果如下:

银河S3

> setupAudio:〜200ms
> startRecording():〜280ms

galaxy S3 mini

> setupAudio:〜10ms
> startRecording():〜290ms

galaxy Nexus

> setupAudio:〜10ms
> startRecording():〜235ms

缓冲区大小:

>连结:704
> s3:1024
> s3 mini:640

但是,仅来自银河系联系的数据可用.
对于我的应用程序,我必须能够尽快获取音频数据.使用当前值,只有Nexus在可接受的时间内.

S3 mini看起来速度较快,因为它仅比Nexus花费更多,但是前200毫秒的示例被列为0,因此它不可用.

根据我对收集到的数据进行分析后的了解,S3和S3 mini上的音频似乎已经过某种程度的滤波,因为所得到的FFT更加干净,低频声音总是不那么明显.
这是S3mini和galaxy Nexus录制的音频的示例:

http://img41.imageshack.us/img41/4177/ox7h.png
S3迷你

http://img690.imageshack.us/img690/8717/iya6.png
galaxy Nexus

解决方法:

如果请求长缓冲区,则必须等待操作系统以当前采样率填充它.如果您要求的采样率不是硬件ADC正在运行的采样率,则必须另外等待重采样器滤波器的延迟.不同的Android设备和操作系统版本可能支持不同的最小缓冲区大小和本机硬件采样率.

隐藏延迟的一种技术是在应用程序的生命周期中尽早开始录制,并不断丢弃音频样本,直到应用程序需要它们为止.这样就没有启动开销.

补充:在某些设备/操作系统版本上,数据可能确实会以某种硬件采样率(例如在44.1k或48kHz时为4096)捕获到更长的OS驱动程序缓冲区中,并且仅在填充了其中一些缓冲区之后,才转换为另一个采样速率,然后切成较短的请求缓冲区长度,然后音频命令开始向应用发送数据.要绕过,即使有可能,您可能需要修改操作系统并编写自己的ADC驱动程序.但是,请尝试使用较高的采样率(44.1k或48k),并首先请求较短的缓冲区.

关于Android提高之AudioRecord实现助听器的方法安卓助听器的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于Android 4.4中AudioRecord用例 - 录制系统内置声音、Android AudioRecord 的使用、android AudioRecorder简单心得分享、Android AudioRecord初始化延迟的相关知识,请在本站寻找。

本文标签:

上一篇Android Studio使用ButterKnife和Zelezny的方法(android studio butterknife)

下一篇android AudioRecorder简单心得分享(安卓 audiorecord)