GVKun编程网logo

Android利用AudioRecord类实现音频录制程序(android 音频录制)

8

想了解Android利用AudioRecord类实现音频录制程序的新动态吗?本文将为您提供详细的信息,我们还将为您解答关于android音频录制的相关问题,此外,我们还将为您介绍关于Android4.

想了解Android利用AudioRecord类实现音频录制程序的新动态吗?本文将为您提供详细的信息,我们还将为您解答关于android 音频录制的相关问题,此外,我们还将为您介绍关于Android 4.4中AudioRecord用例 - 录制系统内置声音、Android AudioRecord 的使用、Android AudioRecord初始化延迟、Android AudioRecord到文件,然后使用AudioTrack进行播放的新知识。

本文目录一览:

Android利用AudioRecord类实现音频录制程序(android 音频录制)

Android利用AudioRecord类实现音频录制程序(android 音频录制)

AudioRecord类相对于MediaRecorder来说,更加接近底层,为我们封装的方法也更少。然而实现一个AudioRecord的音频录制程序也很简单。本实例代码如下:

package demo.camera; 
import java.io.BufferedInputStream; 
import java.io.bufferedoutputstream; 
import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import android.app.Activity; 
import android.content.ContentValues; 
import android.content.Intent; 
import android.hardware.Camera.AutoFocusCallback; 
import android.media.AudioFormat; 
import android.media.AudioManager; 
import android.media.AudioRecord; 
import android.media.AudioTrack; 
import android.media.MediaPlayer; 
import android.media.MediaRecorder; 
import android.net.Uri; 
import android.os.AsyncTask; 
import android.os.Bundle; 
import android.os.Environment; 
import android.provider.MediaStore; 
import android.util.Log; 
import android.view.View; 
import android.widget.Button; 
import android.widget.TextView; 
/** 
 * 该实例中,我们使用AudioRecord类来完成我们的音频录制程序 
 * AudioRecord类,我们可以使用三种不同的read方法来完成录制工作, 
 * 每种方法都有其实用的场合 
 * 一、实例化一个AudioRecord类我们需要传入几种参数 
 * 1、AudioSource:这里可以是MediaRecorder.AudioSource.MIC 
 * 2、SampleRateInHz:录制频率,可以为8000hz或者11025hz等,不同的硬件设备这个值不同 
 * 3、ChannelConfig:录制通道,可以为AudioFormat.CHANNEL_CONfigURATION_MONO和AudioFormat.CHANNEL_CONfigURATION_STEREO 
 * 4、AudioFormat:录制编码格式,可以为AudioFormat.ENCODING_16BIT和8BIT,其中16BIT的仿真性比8BIT好,但是需要消耗更多的电量和存储空间 
 * 5、BufferSize:录制缓冲大小:可以通过getMinBufferSize来获取 
 * 这样我们就可以实例化一个AudioRecord对象了 
 * 二、创建一个文件,用于保存录制的内容 
 * 同上篇 
 * 三、打开一个输出流,指向创建的文件 
 * DataOutputStream dos = new DataOutputStream(new bufferedoutputstream(new FileOutputStream(file))) 
 * 四、现在就可以开始录制了,我们需要创建一个字节数组来存储从AudioRecorder中返回的音频数据,但是 
 * 注意,我们定义的数组要小于定义AudioRecord时指定的那个BufferSize 
 * short[]buffer = new short[BufferSize/4]; 
 * startRecording(); 
 * 然后一个循环,调用AudioRecord的read方法实现读取 
 * 另外使用MediaPlayer是无法播放使用AudioRecord录制的音频的,为了实现播放,我们需要 
 * 使用AudioTrack类来实现 
 * AudioTrack类允许我们播放原始的音频数据 
 * 
 * 
 * 一、实例化一个AudioTrack同样要传入几个参数 
 * 1、StreamType:在AudioManager中有几个常量,其中一个是STREAM_MUSIC; 
 * 2、SampleRateInHz:最好和AudioRecord使用的是同一个值 
 * 3、ChannelConfig:同上 
 * 4、AudioFormat:同上 
 * 5、BufferSize:通过AudioTrack的静态方法getMinBufferSize来获取 
 * 6、Mode:可以是AudioTrack.MODE_STREAM和MODE_STATIC,关于这两种不同之处,可以查阅文档 
 * 二、打开一个输入流,指向刚刚录制内容保存的文件,然后开始播放,边读取边播放 
 * 
 * 实现时,音频的录制和播放分别使用两个AsyncTask来完成 
 */ 
public class MyAudioRecord2 extends Activity{ 
   
  private TextView stateView; 
   
  private Button btnStart,btnStop,btnPlay,btnFinish; 
   
  private RecordTask recorder; 
  private PlayTask player; 
   
  private File audioFile; 
   
  private boolean isRecording=true,isPlaying=false; //标记 
   
  private int frequence = 8000; //录制频率,单位hz.这里的值注意了,写的不好,可能实例化AudioRecord对象的时候,会出错。我开始写成11025就不行。这取决于硬件设备 
  private int channelConfig = AudioFormat.CHANNEL_CONfigURATION_MONO; 
  private int audioEncoding = AudioFormat.ENCODING_PCM_16BIT; 
   
   
  public void onCreate(Bundle savedInstanceState){ 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.my_audio_record); 
     
    stateView = (TextView)this.findViewById(R.id.view_state); 
    stateView.setText("准备开始"); 
    btnStart = (Button)this.findViewById(R.id.btn_start); 
    btnStop = (Button)this.findViewById(R.id.btn_stop); 
    btnPlay = (Button)this.findViewById(R.id.btn_play); 
    btnFinish = (Button)this.findViewById(R.id.btn_finish); 
    btnFinish.setText("停止播放"); 
    btnStop.setEnabled(false); 
    btnPlay.setEnabled(false); 
    btnFinish.setEnabled(false); 
     
    //在这里我们创建一个文件,用于保存录制内容 
    File fpath = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/data/files/"); 
    fpath.mkdirs();//创建文件夹 
    try { 
      //创建临时文件,注意这里的格式为.pcm 
      audioFile = File.createTempFile("recording",".pcm",fpath); 
    } catch (IOException e) { 
      // Todo Auto-generated catch block 
      e.printstacktrace(); 
    }     
  } 
   
   
  public void onClick(View v){ 
    int id = v.getId(); 
    switch(id){ 
    case R.id.btn_start: 
      //开始录制 
       
      //这里启动录制任务 
      recorder = new RecordTask(); 
      recorder.execute(); 
       
      break; 
    case R.id.btn_stop: 
      //停止录制 
      this.isRecording = false; 
      //更新状态 
      //在录制完成时设置,在RecordTask的onPostExecute中完成 
      break; 
    case R.id.btn_play: 
       
      player = new PlayTask(); 
      player.execute(); 
      break; 
    case R.id.btn_finish: 
      //完成播放 
      this.isPlaying = false; 
      break; 
       
    } 
  } 
   
  class RecordTask extends AsyncTask<Void,Integer,Void>{ 
    @Override 
    protected Void doInBackground(Void... arg0) { 
      isRecording = true; 
      try { 
        //开通输出流到指定的文件 
        DataOutputStream dos = new DataOutputStream(new bufferedoutputstream(new FileOutputStream(audioFile))); 
        //根据定义好的几个配置,来获取合适的缓冲大小 
        int bufferSize = AudioRecord.getMinBufferSize(frequence,channelConfig,audioEncoding); 
        //实例化AudioRecord 
        AudioRecord record = new AudioRecord(MediaRecorder.AudioSource.MIC,frequence,audioEncoding,bufferSize); 
        //定义缓冲 
        short[] buffer = new short[bufferSize]; 
         
        //开始录制 
        record.startRecording(); 
         
        int r = 0; //存储录制进度 
        //定义循环,根据isRecording的值来判断是否继续录制 
        while(isRecording){ 
          //从bufferSize中读取字节,返回读取的short个数 
          //这里老是出现buffer overflow,不知道是什么原因,试了好几个值,都没用,Todo:待解决 
          int bufferReadResult = record.read(buffer,buffer.length); 
          //循环将buffer中的音频数据写入到OutputStream中 
          for(int i=0; i<bufferReadResult; i++){ 
            dos.writeShort(buffer[i]); 
          } 
          publishProgress(new Integer(r)); //向UI线程报告当前进度 
          r++; //自增进度值 
        } 
        //录制结束 
        record.stop(); 
        Log.v("The DOS available:","::"+audioFile.length()); 
        dos.close(); 
      } catch (Exception e) { 
        // Todo: handle exception 
      } 
      return null; 
    } 
     
    //当在上面方法中调用publishProgress时,该方法触发,该方法在UI线程中被执行 
    protected void onProgressUpdate(Integer...progress){ 
      stateView.setText(progress[0].toString()); 
    } 
     
    protected void onPostExecute(Void result){ 
      btnStop.setEnabled(false); 
      btnStart.setEnabled(true); 
      btnPlay.setEnabled(true); 
      btnFinish.setEnabled(false); 
    } 
     
    protected void onPreExecute(){ 
      //stateView.setText("正在录制"); 
      btnStart.setEnabled(false); 
      btnPlay.setEnabled(false); 
      btnFinish.setEnabled(false); 
      btnStop.setEnabled(true);     
    } 
     
  } 
   
  class PlayTask extends AsyncTask<Void,Void>{ 
    @Override 
    protected Void doInBackground(Void... arg0) { 
      isPlaying = true; 
      int bufferSize = AudioTrack.getMinBufferSize(frequence,audioEncoding); 
      short[] buffer = new short[bufferSize/4]; 
      try { 
        //定义输入流,将音频写入到AudioTrack类中,实现播放 
        DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(audioFile))); 
        //实例AudioTrack 
        AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC,bufferSize,AudioTrack.MODE_STREAM); 
        //开始播放 
        track.play(); 
        //由于AudioTrack播放的是流,所以,我们需要一边播放一边读取 
        while(isPlaying && dis.available()>0){ 
          int i = 0; 
          while(dis.available()>0 && i<buffer.length){ 
            buffer[i] = dis.readShort(); 
            i++; 
          } 
          //然后将数据写入到AudioTrack中 
          track.write(buffer,buffer.length); 
           
        } 
         
        //播放结束 
        track.stop(); 
        dis.close(); 
      } catch (Exception e) { 
        // Todo: handle exception 
      } 
      return null; 
    } 
     
    protected void onPostExecute(Void result){ 
      btnPlay.setEnabled(true); 
      btnFinish.setEnabled(false); 
      btnStart.setEnabled(true); 
      btnStop.setEnabled(false); 
    } 
     
    protected void onPreExecute(){  
       
      //stateView.setText("正在播放"); 
      btnStart.setEnabled(false); 
      btnStop.setEnabled(false); 
      btnPlay.setEnabled(false); 
      btnFinish.setEnabled(true);      
    } 
     
  } 
}

可惜,本实例测试时有个问题,在录制的时候,会出现buffer over。缓存泄露,待解决。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

您可能感兴趣的文章:

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

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 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到文件,然后使用AudioTrack进行播放

Android AudioRecord到文件,然后使用AudioTrack进行播放

基本上,我使用AudioRecord将声音文件录制到sdcard目录中.录制5秒钟,然后使用AudioTrack播放.

好吧,对我来说,录制的文件不存在.可能录制失败.录制时我做错了什么?播放部分呢?

 public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    int minBufferSize = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_CONfigURATION_MONO, 
            AudioFormat.ENCODING_PCM_16BIT);

  audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONfigURATION_MONO, 
        AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STREAM); 


  recordSound();
 }



private void recordSound(){
    File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/"+"recordsound");
    //    /mnt/sdcard/recordsound
    // Delete any prevIoUs recording.
    if (file.exists())
            file.delete();

    try {
                    file.createNewFile();

                    // Create a DataOuputStream to write the audio data into the saved file.
                    OutputStream os = new FileOutputStream(file);
                    bufferedoutputstream bos = new bufferedoutputstream(os);
                     dos = new DataOutputStream(bos);



                    // Create a new AudioRecord object to record the audio.
                    int bufferSize = audioRecord.getMinBufferSize(FREQUENCY, CHANNEL_CONfigURATION, AUdio_ENCODING);
                     audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, FREQUENCY, CHANNEL_CONfigURATION, AUdio_ENCODING, bufferSize);

                    short[] buffer = new short[bufferSize]; 
                    audioRecord.startRecording();

                    new Timer().schedule(stop(), 5000);  //time in miliseconds

                  //  while (audioRecord.RECORDSTATE_RECORDING==1) 
                    {
                            int bufferReadResult = audioRecord.read(buffer, 0, bufferSize);
                            for (int i = 0; i < bufferReadResult; i++)
                                    dos.writeShort(buffer[i]);
                    }



                   // dos.close();
            } catch (FileNotFoundException e) {
                    // Todo Auto-generated catch block
                    e.printstacktrace();
            } catch (IllegalArgumentException e) {
                    // Todo Auto-generated catch block
                    e.printstacktrace();
            } catch (IllegalStateException e) {
                    // Todo Auto-generated catch block
                    e.printstacktrace();
            } catch (IOException e) {
                    // Todo Auto-generated catch block
                    e.printstacktrace();
            }

}

private TimerTask stop()
{
    TimerTask t = new TimerTask() {

        @Override
        public void run() {
            // Todo Auto-generated method stub
            audioTrack.stop();
            audioTrack.release();
            try {
                dos.close();
            } catch (IOException e) {
                // Todo Auto-generated catch block
                e.printstacktrace();
            }



             try {
                    playfilesound();
                } catch (IOException e) {
                    // Todo Auto-generated catch block
                    e.printstacktrace();
                }



        }
    };
    return t;

}


private void playfilesound() throws IOException
{




    int count = 512 * 1024; // 512 kb
    //Reading the file..
    byte[] byteData = null; 
    File file = null; 
    file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/"+"recordsound");    //filePath

     if (file.exists())
     {
         int a=0;


     }

    byteData = new byte[(int)count];
    FileInputStream in = null;
    try {
    in = new FileInputStream( file );

    } catch (FileNotFoundException e) {
    // Todo Auto-generated catch block
    e.printstacktrace();
    }


    int bytesread = 0, ret = 0;
    int size = (int) file.length();
    audioTrack.play();


    while (bytesread < size) {    // Write the byte array to the track 
        ret = in.read( byteData,0, count);   //ret =size in bytes

        if (ret != -1) {
            audioTrack.write(byteData,0, ret);
            bytesread += ret; }  //ret
        else break; }   //while

        in.close(); audioTrack.stop(); audioTrack.release();
    }  

解决方法:

如果您的要求是在录制时应该播放(意味着循环播放音频),则在while循环线程中,您正在存储录制的数据(audioData bufer),您可以在while循环中将其本身复制到播放器对象( player.write(audioData,0,numShortsRead);).您说您的UI线程被卡住了,这可能是因为您给Audio Record线程赋予了更高的优先级.

检查以下我用于上述回送要求的代码:

boolean m_isRun=true;
    public void loopback() {
            // Prepare the AudioRecord & AudioTrack
            try {
                buffersize = AudioRecord.getMinBufferSize(SAMPLE_RATE,
                        AudioFormat.CHANNEL_CONfigURATION_MONO,
                        AudioFormat.ENCODING_PCM_16BIT);

            if (buffersize <= BUF_SIZE) {
                buffersize = BUF_SIZE;
            }
            Log.i(LOG_TAG,"Initializing Audio Record and Audio Playing objects");

            m_record = new AudioRecord(MediaRecorder.AudioSource.MIC,
                    SAMPLE_RATE, AudioFormat.CHANNEL_CONfigURATION_MONO,
                    AudioFormat.ENCODING_PCM_16BIT, buffersize * 1);

            m_track = new AudioTrack(AudioManager.STREAM_ALARM,
                    SAMPLE_RATE, AudioFormat.CHANNEL_CONfigURATION_MONO,
                    AudioFormat.ENCODING_PCM_16BIT, buffersize * 1,
                    AudioTrack.MODE_STREAM);

            m_track.setPlaybackRate(SAMPLE_RATE);
        } catch (Throwable t) {
            Log.e("Error", "Initializing Audio Record and Play objects Failed "+t.getLocalizedMessage());
        }

        m_record.startRecording();
        Log.i(LOG_TAG,"Audio Recording started");
        m_track.play();
        Log.i(LOG_TAG,"Audio Playing started");

        while (m_isRun) {
            m_record.read(buffer, 0, BUF_SIZE);
            m_track.write(buffer, 0, buffer.length);
        }

        Log.i(LOG_TAG, "loopback exit");
    }

    private void do_loopback() {
        m_thread = new Thread(new Runnable() {
            public void run() {
                loopback();
            }
        });

还有一件事,如果您的要求是先录制几秒钟然后播放,则在播放时应该重新开始录制,您可以使用带有超时的延迟处理程序线程来执行此操作,在该线程中您可以停止录制并复制缓冲区,然后开始录制.

我们今天的关于Android利用AudioRecord类实现音频录制程序android 音频录制的分享已经告一段落,感谢您的关注,如果您想了解更多关于Android 4.4中AudioRecord用例 - 录制系统内置声音、Android AudioRecord 的使用、Android AudioRecord初始化延迟、Android AudioRecord到文件,然后使用AudioTrack进行播放的相关信息,请在本站查询。

本文标签: