Android使用录音(WAV格式)

来源:互联网 发布:linux 编译安装php5.3 编辑:程序博客网 时间:2024/06/03 14:53

一:使用到的工具类

package com.macro.record.utils;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.util.Log;public class ExtAudioRecorder {    private final static int[] sampleRates = { 44100, 22050, 11025, 8000 };    private static ExtAudioRecorder result = null;    public static ExtAudioRecorder getInstanse(Boolean recordingCompressed) {        if (recordingCompressed) {            result = new ExtAudioRecorder(false, AudioSource.MIC,                    sampleRates[3], AudioFormat.CHANNEL_CONFIGURATION_MONO,                    AudioFormat.ENCODING_PCM_16BIT);        } else {            int i = 3;            do {                result = new ExtAudioRecorder(true, AudioSource.MIC,                        sampleRates[i], AudioFormat.CHANNEL_CONFIGURATION_MONO,                        AudioFormat.ENCODING_PCM_16BIT);            } while ((++i < sampleRates.length)                    & !(result.getState() == ExtAudioRecorder.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 mode    private static final int TIMER_INTERVAL = 120;    // Toggles uncompressed recording on/off; RECORDING_UNCOMPRESSED /    // RECORDING_COMPRESSED    private boolean rUncompressed;    // Recorder used for uncompressed recording    private AudioRecord audioRecorder = null;    // Recorder used for compressed recording    private MediaRecorder mediaRecorder = null;    // Stores current amplitude (only in uncompressed mode)    private int cAmplitude = 0;    // Output file path    private String filePath = null;    // Recorder state; see State    private 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 file    private 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 buffer            try {                randomAccessWriter.write(buffer); // Write buffer to file                payloadSize += buffer.length;                if (bSamples == 16) {                    for (int i = 0; i  cAmplitude) { // Check amplitude                            cAmplitude = curSample;                        }                    }                } else { // 8bit sample size                    for (int i = 0; i  cAmplitude) { // Check amplitude                            cAmplitude = buffer[i];                        }                    }                }            } catch (IOException e) {                Log.e(ExtAudioRecorder.class.getName(),                        "Error occured in updateListener, recording is aborted");                // stop();            }        }        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     *      */    public ExtAudioRecorder(boolean uncompressed, int audioSource,            int sampleRate, int channelConfig, int audioFormat) {        try {            rUncompressed = uncompressed;            if (rUncompressed) { // RECORDING_UNCOMPRESSED                if (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 one                    bufferSize = AudioRecord.getMinBufferSize(sampleRate,                            channelConfig, audioFormat);                    // Set frame period and timer interval accordingly                    framePeriod = bufferSize / (2 * bSamples * nChannels / 8);                    Log.w(ExtAudioRecorder.class.getName(),                            "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_COMPRESSED                mediaRecorder = new MediaRecorder();                mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);                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) {                Log.e(ExtAudioRecorder.class.getName(), e.getMessage());            } else {                Log.e(ExtAudioRecorder.class.getName(),                        "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) {                Log.e(ExtAudioRecorder.class.getName(), e.getMessage());            } else {                Log.e(ExtAudioRecorder.class.getName(),                        "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() {        try {            if (state == State.INITIALIZING) {                if (rUncompressed) {                    if ((audioRecorder.getState() == AudioRecord.STATE_INITIALIZED)                            & (filePath != null)) {                        // write file header                        randomAccessWriter = new RandomAccessFile(filePath,                                "rw");                        randomAccessWriter.setLength(0); // Set file length to                                                            // 0, to prevent                                                            // unexpected                                                            // behavior in case                                                            // the file already                                                            // existed                        randomAccessWriter.writeBytes("RIFF");                        randomAccessWriter.writeInt(0); // Final file size not                                                        // known yet, write 0                        randomAccessWriter.writeBytes("WAVE");                        randomAccessWriter.writeBytes("fmt ");                        randomAccessWriter.writeInt(Integer.reverseBytes(16)); // Sub-chunk                                                                                // size,                                                                                // 16                                                                                // for                                                                                // PCM                        randomAccessWriter.writeShort(Short                                .reverseBytes((short) 1)); // AudioFormat, 1 for                                                            // PCM                        randomAccessWriter.writeShort(Short                                .reverseBytes(nChannels));// Number of channels,                                                            // 1 for mono, 2 for                                                            // stereo                        randomAccessWriter                                .writeInt(Integer.reverseBytes(sRate)); // Sample                                                                        // rate                        randomAccessWriter.writeInt(Integer.reverseBytes(sRate                                * bSamples * nChannels / 8)); // Byte rate,                                                                // SampleRate*NumberOfChannels*BitsPerSample/8                        randomAccessWriter                                .writeShort(Short                                        .reverseBytes((short) (nChannels                                                * bSamples / 8))); // Block                                                                    // align,                                                                    // NumberOfChannels*BitsPerSample/8                        randomAccessWriter.writeShort(Short                                .reverseBytes(bSamples)); // Bits per sample                        randomAccessWriter.writeBytes("data");                        randomAccessWriter.writeInt(0); // Data chunk size not                                                        // known yet, write 0                        buffer = new byte[framePeriod * bSamples / 8                                * nChannels];                        state = State.READY;                    } else {                        Log.e(ExtAudioRecorder.class.getName(),                                "prepare() method called on uninitialized recorder");                        state = State.ERROR;                    }                } else {                    mediaRecorder.prepare();                    state = State.READY;                }            } else {                Log.e(ExtAudioRecorder.class.getName(),                        "prepare() method called on illegal state");                release();                state = State.ERROR;            }        } catch (Exception e) {            if (e.getMessage() != null) {                Log.e(ExtAudioRecorder.class.getName(), e.getMessage());            } else {                Log.e(ExtAudioRecorder.class.getName(),                        "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) {                    Log.e(ExtAudioRecorder.class.getName(),                            "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 path                cAmplitude = 0; // Reset amplitude                if (rUncompressed) {                    audioRecorder = new AudioRecord(aSource, sRate,                            nChannels + 1, aFormat, bufferSize);                } else {                    mediaRecorder = new MediaRecorder();                    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);                    mediaRecorder                            .setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);                    mediaRecorder                            .setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);                }                state = State.INITIALIZING;            }        } catch (Exception e) {            Log.e(ExtAudioRecorder.class.getName(), 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.startRecording();                audioRecorder.read(buffer, 0, buffer.length);            } else {                mediaRecorder.start();            }            state = State.RECORDING;        } else {            Log.e(ExtAudioRecorder.class.getName(),                    "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 header                    randomAccessWriter.writeInt(Integer                            .reverseBytes(36 + payloadSize));                    randomAccessWriter.seek(40); // Write size to Subchunk2Size                                                    // field                    randomAccessWriter.writeInt(Integer                            .reverseBytes(payloadSize));                    randomAccessWriter.close();                } catch (IOException e) {                    Log.e(ExtAudioRecorder.class.getName(),                            "I/O exception occured while closing output file");                    state = State.ERROR;                }            } else {                mediaRecorder.stop();            }            state = State.STOPPED;        } else {            Log.e(ExtAudioRecorder.class.getName(),                    "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 <录音完成");recorder.stopRecord();}
0 0