FileDocCategorySizeDatePackage
AudioRecord.javaAPI DocAndroid 1.5 API29818Wed May 06 22:42:00 BST 2009android.media

AudioRecord

public class AudioRecord extends Object
The AudioRecord class manages the audio resources for Java applications to record audio from the audio input hardware of the platform. This is achieved by "pulling" (reading) the data from the AudioRecord object. The application is responsible for polling the AudioRecord object in time using one of the following three methods: {@link #read(byte[],int, int)}, {@link #read(short[], int, int)} or {@link #read(ByteBuffer, int)}. The choice of which method to use will be based on the audio data storage format that is the most convenient for the user of AudioRecord.

Upon creation, an AudioRecord object initializes its associated audio buffer that it will fill with the new audio data. The size of this buffer, specified during the construction, determines how long an AudioRecord can record before "over-running" data that has not been read yet. Data should be read from the audio hardware in chunks of sizes inferior to the total recording buffer size.

Fields Summary
public static final int
STATE_UNINITIALIZED
indicates AudioRecord state is not successfully initialized.
public static final int
STATE_INITIALIZED
indicates AudioRecord state is ready to be used
public static final int
RECORDSTATE_STOPPED
indicates AudioRecord recording state is not recording
public static final int
RECORDSTATE_RECORDING
indicates AudioRecord recording state is recording
public static final int
SUCCESS
Denotes a successful operation.
public static final int
ERROR
Denotes a generic operation failure.
public static final int
ERROR_BAD_VALUE
Denotes a failure due to the use of an invalid value.
public static final int
ERROR_INVALID_OPERATION
Denotes a failure due to the improper use of a method.
private static final int
AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT
private static final int
AUDIORECORD_ERROR_SETUP_INVALIDCHANNELCOUNT
private static final int
AUDIORECORD_ERROR_SETUP_INVALIDFORMAT
private static final int
AUDIORECORD_ERROR_SETUP_INVALIDSTREAMTYPE
private static final int
AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED
private static final int
NATIVE_EVENT_MARKER
Event id denotes when record head has reached a previously set marker.
private static final int
NATIVE_EVENT_NEW_POS
Event id denotes when previously set update period has elapsed during recording.
private static final String
TAG
private int
mNativeRecorderInJavaObj
Accessed by native methods: provides access to C++ AudioRecord object
private static final int
SOURCE_DEFAULT
Accessed by native methods: provides access to record source constants
private static final int
SOURCE_MIC
private int
mNativeCallbackCookie
Accessed by native methods: provides access to the callback data.
private int
mSampleRate
The audio data sampling rate in Hz.
private int
mChannelCount
The number of input audio channels (1 is mono, 2 is stereo)
private int
mChannelConfiguration
The current audio channel configuration
private int
mAudioFormat
The encoding of the audio samples.
private int
mRecordSource
Where the audio data is recorded from.
private int
mState
Indicates the state of the AudioRecord instance.
private int
mRecordingState
Indicates the recording state of the AudioRecord instance.
private Object
mRecordingStateLock
Lock to make sure mRecordingState updates are reflecting the actual state of the object.
private OnRecordPositionUpdateListener
mPositionListener
The listener the AudioRecord notifies when the record position reaches a marker or for periodic updates during the progression of the record head.
private final Object
mPositionListenerLock
Lock to protect position listener updates against event notifications
private NativeEventHandler
mEventHandler
Handler for marker events coming from the native code
private android.os.Looper
mInitializationLooper
Looper associated with the thread that creates the AudioRecord instance
private int
mNativeBufferSizeInBytes
Size of the native audio buffer.
Constructors Summary
public AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes)
Class constructor.

param
audioSource the recording source. See {@link MediaRecorder.AudioSource} for recording source definitions.
param
sampleRateInHz the sample rate expressed in Hertz. Examples of rates are (but not limited to) 44100, 22050 and 11025.
param
channelConfig describes the configuration of the audio channels. See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO} and {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO}
param
audioFormat the format in which the audio data is represented. See {@link AudioFormat#ENCODING_PCM_16BIT} and {@link AudioFormat#ENCODING_PCM_8BIT}
param
bufferSizeInBytes the total size (in bytes) of the buffer where audio data is written to during the recording. New audio data can be read from this buffer in smaller chunks than this size. See {@link #getMinBufferSize(int, int, int)} to determine the minimum required buffer size for the successful creation of an AudioRecord instance. Using values smaller than getMinBufferSize() will result in an initialization failure.
throws
java.lang.IllegalArgumentException



    //---------------------------------------------------------
    // Constructor, Finalize
    //--------------------
                                                                                                                                                                       
             
             
         
        mState = STATE_UNINITIALIZED;
        mRecordingState = RECORDSTATE_STOPPED;
        
        // remember which looper is associated with the AudioRecord instanciation
        if ((mInitializationLooper = Looper.myLooper()) == null) {
            mInitializationLooper = Looper.getMainLooper();
        }

        audioParamCheck(audioSource, sampleRateInHz, channelConfig, audioFormat);

        audioBuffSizeCheck(bufferSizeInBytes);

        // native initialization
        //TODO: update native initialization when information about hardware init failure
        //      due to capture device already open is available.
        int initResult = native_setup( new WeakReference<AudioRecord>(this), 
                mRecordSource, mSampleRate, mChannelCount, mAudioFormat, mNativeBufferSizeInBytes);
        if (initResult != SUCCESS) {
            loge("Error code "+initResult+" when initializing native AudioRecord object.");
            return; // with mState == STATE_UNINITIALIZED
        }

        mState = STATE_INITIALIZED;
    
Methods Summary
private voidaudioBuffSizeCheck(int audioBufferSize)

        // NB: this section is only valid with PCM data. 
        // To update when supporting compressed formats
        int frameSizeInBytes = mChannelCount 
            * (mAudioFormat == AudioFormat.ENCODING_PCM_8BIT ? 1 : 2);
        if ((audioBufferSize % frameSizeInBytes != 0) || (audioBufferSize < 1)) {
            throw (new IllegalArgumentException("Invalid audio buffer size."));
        }

        mNativeBufferSizeInBytes = audioBufferSize;
    
private voidaudioParamCheck(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat)


        //--------------
        // audio source
        if ( (audioSource != MediaRecorder.AudioSource.DEFAULT)
                && (audioSource != MediaRecorder.AudioSource.MIC) ) {
            throw (new IllegalArgumentException("Invalid audio source."));
        } else {
            mRecordSource = audioSource;
        }
        
        //--------------
        // sample rate
        if ( (sampleRateInHz < 4000) || (sampleRateInHz > 48000) ) {
            throw (new IllegalArgumentException(sampleRateInHz
                    + "Hz is not a supported sample rate."));
        } else { 
            mSampleRate = sampleRateInHz;
        }

        //--------------
        // channel config
        switch (channelConfig) {
        case AudioFormat.CHANNEL_CONFIGURATION_DEFAULT:
        case AudioFormat.CHANNEL_CONFIGURATION_MONO:
            mChannelCount = 1;
            mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
            break;
        case AudioFormat.CHANNEL_CONFIGURATION_STEREO:
            mChannelCount = 2;
            mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
            break;
        default:
            mChannelCount = 0;
        mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_INVALID;
        throw (new IllegalArgumentException("Unsupported channel configuration."));
        }

        //--------------
        // audio format
        switch (audioFormat) {
        case AudioFormat.ENCODING_DEFAULT:
            mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
            break;
        case AudioFormat.ENCODING_PCM_16BIT:
        case AudioFormat.ENCODING_PCM_8BIT:
            mAudioFormat = audioFormat;
            break;
        default:
            mAudioFormat = AudioFormat.ENCODING_INVALID;
        throw (new IllegalArgumentException("Unsupported sample encoding." 
                + " Should be ENCODING_PCM_8BIT or ENCODING_PCM_16BIT."));
        }
    
protected voidfinalize()

        native_finalize();
    
public intgetAudioFormat()
Returns the configured audio data format. See {@link AudioFormat#ENCODING_PCM_16BIT} and {@link AudioFormat#ENCODING_PCM_8BIT}.

        return mAudioFormat;
    
public intgetAudioSource()
Returns the audio recording source.

see
MediaRecorder.AudioSource

        return mRecordSource;
    
public intgetChannelConfiguration()
Returns the configured channel configuration. See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO} and {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO}.

        return mChannelConfiguration;
    
public intgetChannelCount()
Returns the configured number of channels.

        return mChannelCount;
    
public static intgetMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat)
Returns the minimum buffer size required for the successful creation of an AudioRecord object. Note that this size doesn't guarantee a smooth recording under load, and higher values should be chosen according to the expected frequency at which the AudioRecord instance will be polled for new data.

param
sampleRateInHz the sample rate expressed in Hertz.
param
channelConfig describes the configuration of the audio channels. See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO} and {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO}
param
audioFormat the format in which the audio data is represented. See {@link AudioFormat#ENCODING_PCM_16BIT}.
return
{@link #ERROR_BAD_VALUE} if the recording parameters are not supported by the hardware, or an invalid parameter was passed, or {@link #ERROR} if the implementation was unable to query the hardware for its output properties, or the minimum buffer size expressed in bytes.

        int channelCount = 0;
        switch(channelConfig) {
        case AudioFormat.CHANNEL_CONFIGURATION_DEFAULT:
        case AudioFormat.CHANNEL_CONFIGURATION_MONO:
            channelCount = 1;
            break;
        case AudioFormat.CHANNEL_CONFIGURATION_STEREO:
            channelCount = 2;
            break;
        case AudioFormat.CHANNEL_CONFIGURATION_INVALID:
        default:
            loge("getMinBufferSize(): Invalid channel configuration.");
            return AudioRecord.ERROR_BAD_VALUE;
        }
        
        // PCM_8BIT is not supported at the moment
        if (audioFormat != AudioFormat.ENCODING_PCM_16BIT) {
            loge("getMinBufferSize(): Invalid audio format.");
            return AudioRecord.ERROR_BAD_VALUE;
        }
        
        int size = native_get_min_buff_size(sampleRateInHz, channelCount, audioFormat);
        if (size == 0) {
            return AudioRecord.ERROR_BAD_VALUE;
        } 
        else if (size == -1) {
            return AudioRecord.ERROR;
        }
        else {
            return size;
        }
    
public intgetNotificationMarkerPosition()
Returns the notification marker position expressed in frames.

        return native_get_marker_pos();
    
public intgetPositionNotificationPeriod()
Returns the notification update period expressed in frames.

        return native_get_pos_update_period();
    
public intgetRecordingState()
Returns the recording state of the AudioRecord instance.

see
AudioRecord#RECORDSTATE_STOPPED
see
AudioRecord#RECORDSTATE_RECORDING

        return mRecordingState;
    
public intgetSampleRate()
Returns the configured audio data sample rate in Hz

        return mSampleRate;
    
public intgetState()
Returns the state of the AudioRecord instance. This is useful after the AudioRecord instance has been created to check if it was initialized properly. This ensures that the appropriate hardware resources have been acquired.

see
AudioRecord#STATE_INITIALIZED
see
AudioRecord#STATE_UNINITIALIZED

        return mState;
    
private static voidlogd(java.lang.String msg)

        Log.d(TAG, "[ android.media.AudioRecord ] " + msg);
    
private static voidloge(java.lang.String msg)

        Log.e(TAG, "[ android.media.AudioRecord ] " + msg);
    
private final native voidnative_finalize()

private final native intnative_get_marker_pos()

private static final native intnative_get_min_buff_size(int sampleRateInHz, int channelCount, int audioFormat)

private final native intnative_get_pos_update_period()

private final native intnative_read_in_byte_array(byte[] audioData, int offsetInBytes, int sizeInBytes)

private final native intnative_read_in_direct_buffer(java.lang.Object jBuffer, int sizeInBytes)

private final native intnative_read_in_short_array(short[] audioData, int offsetInShorts, int sizeInShorts)

private final native voidnative_release()

private final native intnative_set_marker_pos(int marker)

private final native intnative_set_pos_update_period(int updatePeriod)

private final native intnative_setup(java.lang.Object audiorecord_this, int recordSource, int sampleRate, int nbChannels, int audioFormat, int buffSizeInBytes)

private final native voidnative_start()

private final native voidnative_stop()

private static voidpostEventFromNative(java.lang.Object audiorecord_ref, int what, int arg1, int arg2, java.lang.Object obj)

        //logd("Event posted from the native side: event="+ what + " args="+ arg1+" "+arg2);
        AudioRecord recorder = (AudioRecord)((WeakReference)audiorecord_ref).get();
        if (recorder == null) {
            return;
        }
        
        if (recorder.mEventHandler != null) {
            Message m = 
                recorder.mEventHandler.obtainMessage(what, arg1, arg2, obj);
            recorder.mEventHandler.sendMessage(m);
        }

    
public intread(byte[] audioData, int offsetInBytes, int sizeInBytes)
Reads audio data from the audio hardware for recording into a buffer.

param
audioData the array to which the recorded audio data is written.
param
offsetInBytes index in audioData from which the data is written expressed in bytes.
param
sizeInBytes the number of requested bytes.
return
the number of bytes that were read or or {@link #ERROR_INVALID_OPERATION} if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes. The number of bytes will not exceed sizeInBytes.

        if (mState != STATE_INITIALIZED) {
            return ERROR_INVALID_OPERATION;
        }
        
        if ( (audioData == null) || (offsetInBytes < 0 ) || (sizeInBytes < 0) 
                || (offsetInBytes + sizeInBytes > audioData.length)) {
            return ERROR_BAD_VALUE;
        }

        return native_read_in_byte_array(audioData, offsetInBytes, sizeInBytes);
    
public intread(short[] audioData, int offsetInShorts, int sizeInShorts)
Reads audio data from the audio hardware for recording into a buffer.

param
audioData the array to which the recorded audio data is written.
param
offsetInShorts index in audioData from which the data is written expressed in shorts.
param
sizeInShorts the number of requested shorts.
return
the number of shorts that were read or or {@link #ERROR_INVALID_OPERATION} if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes. The number of shorts will not exceed sizeInShorts.

        if (mState != STATE_INITIALIZED) {
            return ERROR_INVALID_OPERATION;
        }
        
        if ( (audioData == null) || (offsetInShorts < 0 ) || (sizeInShorts < 0) 
                || (offsetInShorts + sizeInShorts > audioData.length)) {
            return ERROR_BAD_VALUE;
        }

        return native_read_in_short_array(audioData, offsetInShorts, sizeInShorts);
    
public intread(java.nio.ByteBuffer audioBuffer, int sizeInBytes)
Reads audio data from the audio hardware for recording into a direct buffer. If this buffer is not a direct buffer, this method will always return 0.

param
audioBuffer the direct buffer to which the recorded audio data is written.
param
sizeInBytes the number of requested bytes.
return
the number of bytes that were read or or {@link #ERROR_INVALID_OPERATION} if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes. The number of bytes will not exceed sizeInBytes.

        if (mState != STATE_INITIALIZED) {
            return ERROR_INVALID_OPERATION;
        }
        
        if ( (audioBuffer == null) || (sizeInBytes < 0) ) {
            return ERROR_BAD_VALUE;
        }

        return native_read_in_direct_buffer(audioBuffer, sizeInBytes);
    
public voidrelease()
Releases the native AudioRecord resources. The object can no longer be used and the reference should be set to null after a call to release()

        try {
            stop();
        } catch(IllegalStateException ise) { 
            // don't raise an exception, we're releasing the resources.
        }
        native_release();
        mState = STATE_UNINITIALIZED;
    
public intsetNotificationMarkerPosition(int markerInFrames)
Sets the marker position at which the listener is called, if set with {@link #setRecordPositionUpdateListener(OnRecordPositionUpdateListener)} or {@link #setRecordPositionUpdateListener(OnRecordPositionUpdateListener, Handler)}.

param
markerInFrames marker position expressed in frames
return
error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE}, {@link #ERROR_INVALID_OPERATION}

        return native_set_marker_pos(markerInFrames);
    
public intsetPositionNotificationPeriod(int periodInFrames)
Sets the period at which the listener is called, if set with {@link #setRecordPositionUpdateListener(OnRecordPositionUpdateListener)} or {@link #setRecordPositionUpdateListener(OnRecordPositionUpdateListener, Handler)}.

param
periodInFrames update period expressed in frames
return
error code or success, see {@link #SUCCESS}, {@link #ERROR_INVALID_OPERATION}

        return native_set_pos_update_period(periodInFrames);
    
public voidsetRecordPositionUpdateListener(android.media.AudioRecord$OnRecordPositionUpdateListener listener)
Sets the listener the AudioRecord notifies when a previously set marker is reached or for each periodic record head position update.

param
listener

        setRecordPositionUpdateListener(listener, null);
    
public voidsetRecordPositionUpdateListener(android.media.AudioRecord$OnRecordPositionUpdateListener listener, android.os.Handler handler)
Sets the listener the AudioRecord notifies when a previously set marker is reached or for each periodic record head position update. Use this method to receive AudioRecord events in the Handler associated with another thread than the one in which you created the AudioTrack instance.

param
listener
param
handler the Handler that will receive the event notification messages.

        synchronized (mPositionListenerLock) {
            
            mPositionListener = listener;
            
            if (listener != null) {
                if (handler != null) {
                    mEventHandler = new NativeEventHandler(this, handler.getLooper());
                } else {
                    // no given handler, use the looper the AudioRecord was created in
                    mEventHandler = new NativeEventHandler(this, mInitializationLooper);
                }
            } else {
                mEventHandler = null;
            }
        }
        
    
public voidstartRecording()
Starts recording from the AudioRecord instance.

throws
IllegalStateException

        if (mState != STATE_INITIALIZED) {
            throw(new IllegalStateException("startRecording() called on an "
                    +"uninitialized AudioRecord."));
        }

        // start recording
        synchronized(mRecordingStateLock) {
            native_start();
            mRecordingState = RECORDSTATE_RECORDING;
        }
    
public voidstop()
Stops recording.

throws
IllegalStateException

        if (mState != STATE_INITIALIZED) {
            throw(new IllegalStateException("stop() called on an uninitialized AudioRecord."));
        }

        // stop recording
        synchronized(mRecordingStateLock) {
            native_stop();
            mRecordingState = RECORDSTATE_STOPPED;
        }