bill最近在倒腾Android上录制声音的API——AudioRecord。但始终得到初始化失败的异常(最终原因是各大android设备所支持的音频采样率、声道数等不尽相同,虽然google官方说44100Hz是所有设备均支持的,但实际上......),甚是恼火。在stackoverflow上找到了灵感,并最终在Michael-Pardo的博客里发现了一个简洁且设计较好的工具类——AudioMeter。
Pardo对类的描述是AudioMeter包裹了AudioRecord,但bill在阅读后发现AudioMeter实际上隐藏了AudioRecord的接口(如read),当然Pardo的软件可能并不需要read接口,但作为AudioRecord的倒腾者,bill是需要的,因此对AudioMeter做了轻量级修改,开放了AudioRecord的部分常用接口,使用起来也比较方便,现分享出来,希望更多的朋友受益于此,大家可以根据自己的需要完善、扩充这个工具类:
- import java.nio.ByteBuffer;
-
- import android.media.AudioFormat;
- import android.media.AudioRecord;
- import android.media.MediaRecorder.AudioSource;
- import android.os.Process;
-
-
-
-
-
-
-
-
-
-
-
- public class AudioMeter extends Thread {
-
-
-
-
- private static final float MAX_REPORTABLE_AMP = 32767f;
- private static final float MAX_REPORTABLE_DB = 90.3087f;
-
-
-
-
- private AudioRecord mAudioRecord;
- private int mSampleRate;
- private short mAudioFormat;
- private short mChannelConfig;
-
- private short[] mBuffer;
- private int mBufferSize = AudioRecord.ERROR_BAD_VALUE;
-
- private int mLocks = 0;
-
-
-
-
- private AudioMeter() {
- Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO);
-
- createAudioRecord();
- }
-
-
-
-
- public static AudioMeter getInstance() {
- return InstanceHolder.INSTANCE;
- }
-
- public float getAmplitude() {
- return (float) (MAX_REPORTABLE_DB + (20 * Math.log10(getRawAmplitude()
- / MAX_REPORTABLE_AMP)));
- }
-
- public synchronized void startRecording() {
- if (mAudioRecord == null
- || mAudioRecord.getState() != AudioRecord.STATE_INITIALIZED) {
- throw new IllegalStateException(
- "startRecording() called on an uninitialized AudioRecord.");
- }
-
- if (mLocks == 0) {
- mAudioRecord.startRecording();
- }
-
- mLocks++;
- }
-
- public synchronized void stopRecording() {
- mLocks--;
-
- if (mLocks == 0) {
- if (mAudioRecord != null) {
- mAudioRecord.stop();
- mAudioRecord.release();
- mAudioRecord = null;
- }
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
- public int read(ByteBuffer audioBuffer, int sizeInBytes) {
- return mAudioRecord.read(audioBuffer, sizeInBytes);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public int read(short[] audioData, int offsetInShorts, int sizeInShorts) {
- return mAudioRecord.read(audioData, offsetInShorts, sizeInShorts);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public int read(byte[] audioData, int offsetInBytes, int sizeInBytes) {
- return mAudioRecord.read(audioData, offsetInBytes, sizeInBytes);
- }
-
-
-
-
- public int getSampleRate() {
- return mSampleRate;
- }
-
-
-
-
-
- public int getAudioFormat() {
- return mAudioFormat;
- }
-
-
-
-
-
- public int getChannelConfiguration() {
- return mChannelConfig;
- }
-
-
-
-
-
-
-
-
- public int getAudioRecordState() {
- return mAudioRecord.getState();
- }
-
-
-
-
- private void createAudioRecord() {
- if (mSampleRate > 0 && mAudioFormat > 0 && mChannelConfig > 0) {
- mAudioRecord = new AudioRecord(AudioSource.MIC, mSampleRate,
- mChannelConfig, mAudioFormat, mBufferSize);
- return;
- }
-
-
-
-
-
-
- for (int sampleRate : new int[] { 8000, 11025, 16000, 22050, 32000,
- 44100, 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,
- AudioFormat.CHANNEL_CONFIGURATION_MONO,
- AudioFormat.CHANNEL_CONFIGURATION_STEREO }) {
-
-
- try {
- mBufferSize = AudioRecord.getMinBufferSize(sampleRate,
- channelConfig, audioFormat);
-
- if (mBufferSize < 0) {
- continue;
- }
-
- mBuffer = new short[mBufferSize];
- mAudioRecord = new AudioRecord(AudioSource.MIC,
- sampleRate, channelConfig, audioFormat,
- mBufferSize);
-
- if (mAudioRecord.getState() == AudioRecord.STATE_INITIALIZED) {
- mSampleRate = sampleRate;
- mAudioFormat = audioFormat;
- mChannelConfig = channelConfig;
- return;
- }
-
- mAudioRecord.release();
- mAudioRecord = null;
- } catch (Exception e) {
-
- }
- }
- }
- }
-
-
- throw new IllegalStateException(
- "getInstance() failed : no suitable audio configurations on this device.");
- }
-
- private int getRawAmplitude() {
- if (mAudioRecord == null) {
- createAudioRecord();
- }
-
- final int bufferReadSize = mAudioRecord.read(mBuffer, 0, mBufferSize);
-
- if (bufferReadSize < 0) {
- return 0;
- }
-
- int sum = 0;
- for (int i = 0; i < bufferReadSize; i++) {
- sum += Math.abs(mBuffer[i]);
- }
-
- if (bufferReadSize > 0) {
- return sum / bufferReadSize;
- }
-
- return 0;
- }
-
-
-
-
-
- private static class InstanceHolder {
- private static final AudioMeter INSTANCE = new AudioMeter();
- }
- }
本文转自Bill_Hoo 51CTO博客,原文链接:http://blog.51cto.com/billhoo/1140064
,如需转载请自行联系原作者