Error code -20 when initializing native AudioRecord object.

来源:互联网 发布:上海网络机柜 编辑:程序博客网 时间:2024/04/28 09:39


E/AudioRecord(5152): Could not get audio input for record source 1
E/AudioRecord-JNI(5152): Error creating AudioRecord instance: initialization check failed.
09-22 16:37:26.277: E/com.harlan.wavdemo.ExtAudioRecorder(2232): start() called on illegal state
09-22 16:37:31.157: E/com.harlan.wavdemo.ExtAudioRecorder(2232): prepare() method called on illegal state
09-22 16:37:31.157: E/com.harlan.wavdemo.ExtAudioRecorder(2232): start() called on illegal state

E/AudioRecord-Java(5152): [ android.media.AudioRecord ] Error code -20  when initializing native  AudioRecord object.


09-22 16:37:26.277: E/com.harlan.wavdemo.ExtAudioRecorder(2232): prepare() method called on illegal state


开发项目工程中我使用的是ExtAudioRecorder工具类来录制wav文件。

这个类在索尼l36h就正常使用,但放在lt26i上面,就会出现以上问题。

百思不得其解。

百度之,说是重启之后就好了,链接如下:

http://stackoverflow.com/questions/4342482/cannot-access-audiorecorder


可是重启之后,使用一次,还是会出现以上问题。

这可不是个好方法。

遂研究之。

吭哧吭哧研究过程%……%%¥%¥…………TU&^略过。。。。。

研究之后发现,这个ExtAudioRecorder工具类还是有缺陷的,改之。

简而言之,就是把原类中没有顾及到的情况考虑到了。

最终结果类如下:

<span style="font-family:Microsoft YaHei;font-size:18px;">package com.harlan.util;import java.io.File;import java.io.IOException;import java.io.RandomAccessFile;import android.media.AudioFormat;import android.media.AudioRecord;import android.media.MediaRecorder;import android.media.MediaRecorder.AudioSource;import android.os.Environment;import com.harlan.base.C;public class WavRecorder {private static final String TAG = WavRecorder.class.getSimpleName();private final static int[] sampleRates = { 44100, 22050, 11025, 8000 };private static WavRecorder result ;public static WavRecorder getInstanse(Boolean recordingCompressed) {if(result!=null){return result;}if (recordingCompressed) {result = new WavRecorder(false, AudioSource.MIC, sampleRates[3],AudioFormat.CHANNEL_IN_STEREO,AudioFormat.ENCODING_PCM_16BIT);} else {int i = 3;do {result = new WavRecorder(true, AudioSource.MIC, sampleRates[i],AudioFormat.CHANNEL_IN_STEREO,AudioFormat.ENCODING_PCM_16BIT);} while ((++i < sampleRates.length)& !(result.getState() == WavRecorder.State.INITIALIZING));}return result;}/** * INITIALIZING : recorder is initializing; READY : recorder has been * initialized, recorder not yet started RECORDING : recording ERROR : * reconstruction needed STOPPED: reset needed */public enum State {INITIALIZING, READY, RECORDING, ERROR, STOPPED};public static final boolean RECORDING_UNCOMPRESSED = true;public static final boolean RECORDING_COMPRESSED = false;// The interval in which the recorded samples are output to the file// Used only in uncompressed modeprivate static final int TIMER_INTERVAL = 120;// Toggles uncompressed recording on/off; RECORDING_UNCOMPRESSED /// RECORDING_COMPRESSEDprivate boolean rUncompressed;// Recorder used for uncompressed recordingprivate AudioRecord audioRecorder = null;// Recorder used for compressed recordingprivate MediaRecorder mediaRecorder = null;// Stores current amplitude (only in uncompressed mode)private int cAmplitude = 0;// Output file pathprivate String filePath = null;// Recorder state; see Stateprivate State state;// File writer (only in uncompressed mode)private RandomAccessFile randomAccessWriter;// Number of channels, sample rate, sample size(size in bits), buffer size,// audio source, sample size(see AudioFormat)private short nChannels;private int sRate;private short bSamples;private int bufferSize;private int aSource;private int aFormat;// Number of frames written to file on each output(only in uncompressed// mode)private int framePeriod;// Buffer for output(only in uncompressed mode)private byte[] buffer;// Number of bytes written to file after header(only in uncompressed mode)// after stop() is called, this size is written to the header/data chunk in// the wave fileprivate int payloadSize;/** *  * Returns the state of the recorder in a RehearsalAudioRecord.State typed * object. Useful, as no exceptions are thrown. *  * @return recorder state */public State getState() {return state;}/* *  * Method used for recording. */private AudioRecord.OnRecordPositionUpdateListener updateListener = new AudioRecord.OnRecordPositionUpdateListener() {public void onPeriodicNotification(AudioRecord recorder) {audioRecorder.read(buffer, 0, buffer.length); // Fill bufferLogTrace.d(TAG, "updateListener","recording is ing");try {randomAccessWriter.write(buffer); // Write buffer to filepayloadSize += buffer.length;if (bSamples == 16) {for (int i = 0; i < buffer.length / 2; i++) { // 16bit// sample// sizeshort curSample = getShort(buffer[i * 2],buffer[i * 2 + 1]);//LogTrace.e(TAG, "updateListener 16bit curSample",//curSample + "");if (curSample > cAmplitude) { // Check amplitudecAmplitude = curSample;}}} else { // 8bit sample sizefor (int i = 0; i < buffer.length; i++) {if (buffer[i] > cAmplitude) { // Check amplitudecAmplitude = buffer[i];}}}} catch (IOException e) {//Log.e(WavRecorder.class.getName(),//"Error occured in updateListener, recording is aborted");LogTrace.d(TAG, "updateListener", "record succ");// stop();reset();}}public void onMarkerReached(AudioRecord recorder) {// NOT USED}};/** *  *  * Default constructor *  * Instantiates a new recorder, in case of compressed recording the * parameters can be left as 0. In case of errors, no exception is thrown, * but the state is set to ERROR *  */@SuppressWarnings("deprecation")public WavRecorder(boolean uncompressed, int audioSource, int sampleRate,int channelConfig, int audioFormat) {try {rUncompressed = uncompressed;if (rUncompressed) { // RECORDING_UNCOMPRESSEDif (audioFormat == AudioFormat.ENCODING_PCM_16BIT) {bSamples = 16;} else {bSamples = 8;}if (channelConfig == AudioFormat.CHANNEL_CONFIGURATION_MONO) {nChannels = 1;} else {nChannels = 2;}aSource = audioSource;sRate = sampleRate;aFormat = audioFormat;framePeriod = sampleRate * TIMER_INTERVAL / 1000;bufferSize = framePeriod * 2 * bSamples * nChannels / 8;if (bufferSize < AudioRecord.getMinBufferSize(sampleRate,channelConfig, audioFormat)) { // Check to make sure// buffer size is not// smaller than the// smallest allowed onebufferSize = AudioRecord.getMinBufferSize(sampleRate,channelConfig, audioFormat);// Set frame period and timer interval accordinglyframePeriod = bufferSize / (2 * bSamples * nChannels / 8);LogTrace.w(TAG,"WavRecorder","Increasing buffer size to "+ Integer.toString(bufferSize));}audioRecorder = new AudioRecord(audioSource, sampleRate,channelConfig, audioFormat, bufferSize);if (audioRecorder.getState() != AudioRecord.STATE_INITIALIZED)throw new Exception("AudioRecord initialization failed");audioRecorder.setRecordPositionUpdateListener(updateListener);audioRecorder.setPositionNotificationPeriod(framePeriod);} else { // RECORDING_COMPRESSEDmediaRecorder = new MediaRecorder();mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);}cAmplitude = 0;filePath = null;state = State.INITIALIZING;} catch (Exception e) {if (e.getMessage() != null) {LogTrace.e(TAG,"WavRecorder", e.getMessage());} else {LogTrace.e(TAG,"WavRecorder", "Unknown error occured while initializing recording");}state = State.ERROR;}}/** * Sets output file path, call directly after construction/reset. *  * @param output *            file path *  */public void setOutputFile(String argPath) {try {if (state == State.INITIALIZING) {filePath = argPath;if (!rUncompressed) {mediaRecorder.setOutputFile(filePath);}}} catch (Exception e) {if (e.getMessage() != null) {LogTrace.e(TAG,"setOutputFile",e.getMessage());} else {LogTrace.e(TAG,"setOutputFile","Unknown error occured while setting output path");}state = State.ERROR;}}/** *  * Returns the largest amplitude sampled since the last call to this method. *  * @return returns the largest amplitude since the last call, or 0 when not *         in recording state. *  */public int getMaxAmplitude() {if (state == State.RECORDING) {if (rUncompressed) {int result = cAmplitude;cAmplitude = 0;return result;} else {try {return mediaRecorder.getMaxAmplitude();} catch (IllegalStateException e) {return 0;}}} else {return 0;}}/** *  * Prepares the recorder for recording, in case the recorder is not in the * INITIALIZING state and the file path was not set the recorder is set to * the ERROR state, which makes a reconstruction necessary. In case * uncompressed recording is toggled, the header of the wave file is * written. In case of an exception, the state is changed to ERROR *  */public void prepare() {LogTrace.d(TAG, "prepare prepare state:",state+"");LogTrace.d(TAG, "prepare prepare filePath:",filePath+"");LogTrace.d(TAG, "prepare audioRecorder.getState():",audioRecorder.getState()+"");try {if (state == State.INITIALIZING) {if (rUncompressed) {if ((audioRecorder.getState() == AudioRecord.STATE_INITIALIZED)& (filePath != null)) {// write file headerrandomAccessWriter = new RandomAccessFile(filePath,"rw");randomAccessWriter.setLength(0); // Set file length to// 0, to prevent// unexpected// behavior in case// the file already// existedrandomAccessWriter.writeBytes("RIFF");randomAccessWriter.writeInt(0); // Final file size not// known yet, write 0randomAccessWriter.writeBytes("WAVE");randomAccessWriter.writeBytes("fmt ");randomAccessWriter.writeInt(Integer.reverseBytes(16)); // Sub-chunk// size,// 16// for// PCMrandomAccessWriter.writeShort(Short.reverseBytes((short) 1)); // AudioFormat, 1 for// PCMrandomAccessWriter.writeShort(Short.reverseBytes(nChannels));// Number of channels,// 1 for mono, 2 for// stereorandomAccessWriter.writeInt(Integer.reverseBytes(sRate)); // Sample// raterandomAccessWriter.writeInt(Integer.reverseBytes(sRate* bSamples * nChannels / 8)); // Byte rate,// SampleRate*NumberOfChannels*BitsPerSample/8randomAccessWriter.writeShort(Short.reverseBytes((short) (nChannels* bSamples / 8))); // Block// align,// NumberOfChannels*BitsPerSample/8randomAccessWriter.writeShort(Short.reverseBytes(bSamples)); // Bits per samplerandomAccessWriter.writeBytes("data");randomAccessWriter.writeInt(0); // Data chunk size not// known yet, write 0buffer = new byte[framePeriod * bSamples / 8* nChannels];state = State.READY;} else {LogTrace.e(TAG,"prepare","prepare() method called on uninitialized recorder");state = State.ERROR;}} else {mediaRecorder.prepare();state = State.READY;}}else if (state == State.STOPPED||state == State.ERROR){String fileTempPath = filePath;reset();setOutputFile(fileTempPath);prepare();} else {LogTrace.e(TAG,"prepare","prepare() method called on illegal state");release();state = State.ERROR;}} catch (Exception e) {if (e.getMessage() != null) {LogTrace.e(TAG,"prepare",e.getMessage());} else {LogTrace.e(TAG,"prepare","Unknown error occured in prepare()");}state = State.ERROR;}}/** *  *  * Releases the resources associated with this class, and removes the * unnecessary files, when necessary *  */public void release() {if (state == State.RECORDING) {stop();} else {if ((state == State.READY) & (rUncompressed)) {try {randomAccessWriter.close(); // Remove prepared file} catch (IOException e) {LogTrace.e(TAG,"release","I/O exception occured while closing output file");}(new File(filePath)).delete();}}if (rUncompressed) {if (audioRecorder != null) {audioRecorder.release();}} else {if (mediaRecorder != null) {mediaRecorder.release();}}}/** *  *  * Resets the recorder to the INITIALIZING state, as if it was just created. * In case the class was in RECORDING state, the recording is stopped. In * case of exceptions the class is set to the ERROR state. *  */public void reset() {try {if (state != State.ERROR) {release();filePath = null; // Reset file pathcAmplitude = 0; // Reset amplitudeif (rUncompressed) {audioRecorder = new AudioRecord(aSource, sRate,nChannels + 1, aFormat, bufferSize);} else {mediaRecorder = new MediaRecorder();mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);}state = State.INITIALIZING;}} catch (Exception e) {LogTrace.e(TAG,"reset",e.getMessage());state = State.ERROR;}}/** *  *  * Starts the recording, and sets the state to RECORDING. Call after * prepare(). *  */public void start() {if (state == State.READY) {if (rUncompressed) {payloadSize = 0;audioRecorder.setRecordPositionUpdateListener(updateListener);audioRecorder.setPositionNotificationPeriod(framePeriod);audioRecorder.startRecording();audioRecorder.read(buffer, 0, buffer.length);} else {mediaRecorder.start();}state = State.RECORDING;} else {LogTrace.e(TAG,"start","called on illegal state");state = State.ERROR;}}/** *  *  * Stops the recording, and sets the state to STOPPED. In case of further * usage, a reset is needed. Also finalizes the wave file in case of * uncompressed recording. *  */public void stop() {if (state == State.RECORDING) {if (rUncompressed) {audioRecorder.stop();try {randomAccessWriter.seek(4); // Write size to RIFF headerrandomAccessWriter.writeInt(Integer.reverseBytes(36 + payloadSize));randomAccessWriter.seek(40); // Write size to Subchunk2Size// fieldrandomAccessWriter.writeInt(Integer.reverseBytes(payloadSize));randomAccessWriter.close();} catch (IOException e) {LogTrace.e(TAG,"stop","I/O exception occured while closing output file");state = State.ERROR;}} else {mediaRecorder.stop();}state = State.STOPPED;} else {LogTrace.e(TAG,"stop","called on illegal state");state = State.ERROR;}}/* *  * Converts a byte[2] to a short, in LITTLE_ENDIAN format */private short getShort(byte argB1, byte argB2) {return (short) (argB1 | (argB2 << 8));}/** * 录制wav格式文件 *  * @param path *            : 文件路径 */public void recordChat(String fileName) {if (!Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {return;}String file = new String(makeFileStroagePath().getAbsolutePath() + "/"+ fileName);// 设置输出文件setOutputFile(file);prepare();// 开始录音start();}/** * 停止录音 *  * @param mediaRecorder *            待停止的录音机 * @return 返回 */public void stopRecord() {stop();release();}public File makeFileStroagePath() {File file = new File(C.normal.voice_path);try {if (!file.exists()) {file.mkdirs();return file;}} catch (Exception e) {e.printStackTrace();return null;}return file;}}</span>


0 0