Fields Summary |
---|
private static final float | VOLUME_MINMinimum value for a channel volume |
private static final float | VOLUME_MAXMaximum value for a channel volume |
public static final int | PLAYSTATE_STOPPEDindicates AudioTrack state is stopped |
public static final int | PLAYSTATE_PAUSEDindicates AudioTrack state is paused |
public static final int | PLAYSTATE_PLAYINGindicates AudioTrack state is playing |
public static final int | MODE_STATICCreation mode where audio data is transferred from Java to the native layer
only once before the audio starts playing. |
public static final int | MODE_STREAMCreation mode where audio data is streamed from Java to the native layer
as the audio is playing. |
public static final int | STATE_UNINITIALIZEDState of an AudioTrack that was not successfully initialized upon creation. |
public static final int | STATE_INITIALIZEDState of an AudioTrack that is ready to be used. |
public static final int | STATE_NO_STATIC_DATAState of a successfully initialized AudioTrack that uses static data,
but that hasn't received that data yet. |
public static final int | SUCCESSDenotes a successful operation. |
public static final int | ERRORDenotes a generic operation failure. |
public static final int | ERROR_BAD_VALUEDenotes a failure due to the use of an invalid value. |
public static final int | ERROR_INVALID_OPERATIONDenotes a failure due to the improper use of a method. |
private static final int | ERROR_NATIVESETUP_AUDIOSYSTEM |
private static final int | ERROR_NATIVESETUP_INVALIDCHANNELCOUNT |
private static final int | ERROR_NATIVESETUP_INVALIDFORMAT |
private static final int | ERROR_NATIVESETUP_INVALIDSTREAMTYPE |
private static final int | ERROR_NATIVESETUP_NATIVEINITFAILED |
private static final int | NATIVE_EVENT_MARKEREvent id denotes when playback head has reached a previously set marker. |
private static final int | NATIVE_EVENT_NEW_POSEvent id denotes when previously set update period has elapsed during playback. |
private static final String | TAG |
private int | mStateIndicates the state of the AudioTrack instance. |
private int | mPlayStateIndicates the play state of the AudioTrack instance. |
private final Object | mPlayStateLockLock to make sure mPlayState updates are reflecting the actual state of the object. |
private OnPlaybackPositionUpdateListener | mPositionListenerThe listener the AudioTrack notifies when the playback position reaches a marker
or for periodic updates during the progression of the playback head. |
private final Object | mPositionListenerLockLock to protect event listener updates against event notifications. |
private int | mNativeBufferSizeInBytesSize of the native audio buffer. |
private NativeEventHandlerDelegate | mEventHandlerDelegateHandler for marker events coming from the native code. |
private android.os.Looper | mInitializationLooperLooper associated with the thread that creates the AudioTrack instance. |
private int | mSampleRateThe audio data sampling rate in Hz. |
private int | mChannelCountThe number of input audio channels (1 is mono, 2 is stereo). |
private int | mStreamTypeThe type of the audio stream to play. See
{@link AudioManager#STREAM_VOICE_CALL}, {@link AudioManager#STREAM_SYSTEM},
{@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC} and
{@link AudioManager#STREAM_ALARM} |
private int | mDataLoadModeThe way audio is consumed by the hardware, streaming or static. |
private int | mChannelConfigurationThe current audio channel configuration. |
private int | mAudioFormatThe encoding of the audio samples. |
private int | mNativeTrackInJavaObjAccessed by native methods: provides access to C++ AudioTrack object. |
private int | mJniDataAccessed by native methods: provides access to the JNI data (i.e. resources used by
the native AudioTrack object, but not stored in it). |
Methods Summary |
---|
private void | audioBuffSizeCheck(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 void | audioParamCheck(int streamType, int sampleRateInHz, int channelConfig, int audioFormat, int mode)
//--------------
// stream type
if( (streamType != AudioManager.STREAM_ALARM) && (streamType != AudioManager.STREAM_MUSIC)
&& (streamType != AudioManager.STREAM_RING) && (streamType != AudioManager.STREAM_SYSTEM)
&& (streamType != AudioManager.STREAM_VOICE_CALL)
&& (streamType != AudioManager.STREAM_NOTIFICATION)
&& (streamType != AudioManager.STREAM_BLUETOOTH_SCO)) {
throw (new IllegalArgumentException("Invalid stream type."));
} else {
mStreamType = streamType;
}
//--------------
// 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."));
}
//--------------
// audio load mode
if ( (mode != MODE_STREAM) && (mode != MODE_STATIC) ) {
throw(new IllegalArgumentException("Invalid mode."));
} else {
mDataLoadMode = mode;
}
|
protected void | finalize()
native_finalize();
|
public void | flush()Flushes the audio data currently queued for playback.
if (mState == STATE_INITIALIZED) {
// flush the data in native layer
native_flush();
}
|
public int | getAudioFormat()Returns the configured audio data format. See {@link AudioFormat#ENCODING_PCM_16BIT}
and {@link AudioFormat#ENCODING_PCM_8BIT}.
return mAudioFormat;
|
public int | getChannelConfiguration()Returns the configured channel configuration.
See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO}
and {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO}.
return mChannelConfiguration;
|
public int | getChannelCount()Returns the configured number of channels.
return mChannelCount;
|
public static float | getMaxVolume()Returns the maximum valid volume value. Volume values set above this one will
be clamped at this value.
return AudioTrack.VOLUME_MAX;
|
public static int | getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat)Returns the minimum buffer size required for the successful creation of an AudioTrack
object to be created in the {@link #MODE_STREAM} mode. Note that this size doesn't
guarantee a smooth playback under load, and higher values should be chosen according to
the expected frequency at which the buffer will be refilled with additional data to play.
int channelCount = 0;
switch(channelConfig) {
case AudioFormat.CHANNEL_CONFIGURATION_MONO:
channelCount = 1;
break;
case AudioFormat.CHANNEL_CONFIGURATION_STEREO:
channelCount = 2;
break;
default:
loge("getMinBufferSize(): Invalid channel configuration.");
return AudioTrack.ERROR_BAD_VALUE;
}
if ((audioFormat != AudioFormat.ENCODING_PCM_16BIT)
&& (audioFormat != AudioFormat.ENCODING_PCM_8BIT)) {
loge("getMinBufferSize(): Invalid audio format.");
return AudioTrack.ERROR_BAD_VALUE;
}
if ( (sampleRateInHz < 4000) || (sampleRateInHz > 48000) ) {
loge("getMinBufferSize(): " + sampleRateInHz +"Hz is not a supported sample rate.");
return AudioTrack.ERROR_BAD_VALUE;
}
int size = native_get_min_buff_size(sampleRateInHz, channelCount, audioFormat);
if ((size == -1) || (size == 0)) {
loge("getMinBufferSize(): error querying hardware");
return AudioTrack.ERROR;
}
else {
return size;
}
|
public static float | getMinVolume()Returns the minimum valid volume value. Volume values set under this one will
be clamped at this value.
return AudioTrack.VOLUME_MIN;
|
protected int | getNativeFrameCount()Returns the native frame count used by the hardware.
return native_get_native_frame_count();
|
public static int | getNativeOutputSampleRate(int streamType)Returns the hardware output sample rate
return native_get_output_sample_rate(streamType);
|
public int | getNotificationMarkerPosition()Returns marker position expressed in frames.
return native_get_marker_pos();
|
public int | getPlayState()Returns the playback state of the AudioTrack instance.
return mPlayState;
|
public int | getPlaybackHeadPosition()Returns the playback head position expressed in frames
return native_get_position();
|
public int | getPlaybackRate()Returns the current playback rate in Hz. Note that this rate may differ from the one set
with {@link #setPlaybackRate(int)} as the value effectively used is implementation-dependent.
return native_get_playback_rate();
|
public int | getPositionNotificationPeriod()Returns the notification update period expressed in frames.
return native_get_pos_update_period();
|
public int | getSampleRate()Returns the configured audio data sample rate in Hz
return mSampleRate;
|
public int | getState()Returns the state of the AudioTrack instance. This is useful after the
AudioTrack instance has been created to check if it was initialized
properly. This ensures that the appropriate hardware resources have been
acquired.
return mState;
|
public int | getStreamType()Returns the type of audio stream this AudioTrack is configured for.
Compare the result against {@link AudioManager#STREAM_VOICE_CALL},
{@link AudioManager#STREAM_SYSTEM}, {@link AudioManager#STREAM_RING},
{@link AudioManager#STREAM_MUSIC} or {@link AudioManager#STREAM_ALARM}
return mStreamType;
|
private static void | logd(java.lang.String msg)
Log.d(TAG, "[ android.media.AudioTrack ] " + msg);
|
private static void | loge(java.lang.String msg)
Log.e(TAG, "[ android.media.AudioTrack ] " + msg);
|
private final native void | native_finalize()
|
private final native void | native_flush()
|
private final native int | native_get_marker_pos()
|
private static final native int | native_get_min_buff_size(int sampleRateInHz, int channelConfig, int audioFormat)
|
private final native int | native_get_native_frame_count()
|
private static final native int | native_get_output_sample_rate(int streamType)
|
private final native int | native_get_playback_rate()
|
private final native int | native_get_pos_update_period()
|
private final native int | native_get_position()
|
private final native void | native_pause()
|
private final native void | native_release()
|
private final native int | native_reload_static()
|
private final native void | native_setVolume(float leftVolume, float rightVolume)
|
private final native int | native_set_loop(int start, int end, int loopCount)
|
private final native int | native_set_marker_pos(int marker)
|
private final native void | native_set_playback_rate(int sampleRateInHz)
|
private final native int | native_set_pos_update_period(int updatePeriod)
|
private final native int | native_set_position(int position)
|
private final native int | native_setup(java.lang.Object audiotrack_this, int streamType, int sampleRate, int nbChannels, int audioFormat, int buffSizeInBytes, int mode)
|
private final native void | native_start()
|
private final native void | native_stop()
|
private final native int | native_write_byte(byte[] audioData, int offsetInBytes, int sizeInBytes, int format)
|
private final native int | native_write_short(short[] audioData, int offsetInShorts, int sizeInShorts, int format)
|
public void | pause()Pauses the playback of the audio data.
if (mState != STATE_INITIALIZED) {
throw(new IllegalStateException("pause() called on uninitialized AudioTrack."));
}
//logd("pause()");
// pause playback
synchronized(mPlayStateLock) {
native_pause();
mPlayState = PLAYSTATE_PAUSED;
}
|
public void | play()Starts playing an AudioTrack.
if (mState != STATE_INITIALIZED) {
throw(new IllegalStateException("play() called on uninitialized AudioTrack."));
}
synchronized(mPlayStateLock) {
native_start();
mPlayState = PLAYSTATE_PLAYING;
}
|
private static void | postEventFromNative(java.lang.Object audiotrack_ref, int what, int arg1, int arg2, java.lang.Object obj)
//logd("Event posted from the native side: event="+ what + " args="+ arg1+" "+arg2);
AudioTrack track = (AudioTrack)((WeakReference)audiotrack_ref).get();
if (track == null) {
return;
}
if (track.mEventHandlerDelegate != null) {
Message m =
track.mEventHandlerDelegate.getHandler().obtainMessage(what, arg1, arg2, obj);
track.mEventHandlerDelegate.getHandler().sendMessage(m);
}
|
public void | release()Releases the native AudioTrack resources.
// even though native_release() stops the native AudioTrack, we need to stop
// AudioTrack subclasses too.
try {
stop();
} catch(IllegalStateException ise) {
// don't raise an exception, we're releasing the resources.
}
native_release();
mState = STATE_UNINITIALIZED;
|
public int | reloadStaticData()Notifies the native resource to reuse the audio data already loaded in the native
layer. This call is only valid with AudioTrack instances that don't use the streaming
model.
if (mDataLoadMode == MODE_STREAM) {
return ERROR_INVALID_OPERATION;
}
return native_reload_static();
|
public int | setLoopPoints(int startInFrames, int endInFrames, int loopCount)Sets the loop points and the loop count. The loop can be infinite.
if (mDataLoadMode == MODE_STREAM) {
return ERROR_INVALID_OPERATION;
}
return native_set_loop(startInFrames, endInFrames, loopCount);
|
public int | setNotificationMarkerPosition(int markerInFrames)Sets the position of the notification marker.
if (mState != STATE_INITIALIZED) {
return ERROR_INVALID_OPERATION;
}
return native_set_marker_pos(markerInFrames);
|
public int | setPlaybackHeadPosition(int positionInFrames)Sets the playback head position. The track must be stopped for the position to be changed.
synchronized(mPlayStateLock) {
if ((mPlayState == PLAYSTATE_STOPPED) || (mPlayState == PLAYSTATE_PAUSED)) {
return native_set_position(positionInFrames);
} else {
return ERROR_INVALID_OPERATION;
}
}
|
public void | setPlaybackPositionUpdateListener(android.media.AudioTrack$OnPlaybackPositionUpdateListener listener)Sets the listener the AudioTrack notifies when a previously set marker is reached or
for each periodic playback head position update.
Notifications will be received in the same thread as the one in which the AudioTrack
instance was created.
setPlaybackPositionUpdateListener(listener, null);
|
public void | setPlaybackPositionUpdateListener(android.media.AudioTrack$OnPlaybackPositionUpdateListener listener, android.os.Handler handler)Sets the listener the AudioTrack notifies when a previously set marker is reached or
for each periodic playback head position update.
Use this method to receive AudioTrack events in the Handler associated with another
thread than the one in which you created the AudioTrack instance.
synchronized (mPositionListenerLock) {
mPositionListener = listener;
}
if (listener != null) {
mEventHandlerDelegate = new NativeEventHandlerDelegate(this, handler);
}
|
public int | setPlaybackRate(int sampleRateInHz)Sets the playback sample rate for this track. This sets the sampling rate at which
the audio data will be consumed and played back, not the original sampling rate of the
content. Setting it to half the sample rate of the content will cause the playback to
last twice as long, but will also result result in a negative pitch shift.
The current implementation supports a maximum sample rate of 64kHz.
Use {@link #getSampleRate()} to check the rate actually used in hardware after
potential clamping.
if (mState != STATE_INITIALIZED) {
return ERROR_INVALID_OPERATION;
}
if (sampleRateInHz <= 0) {
return ERROR_BAD_VALUE;
}
native_set_playback_rate(sampleRateInHz);
return SUCCESS;
|
public int | setPositionNotificationPeriod(int periodInFrames)Sets the period for the periodic notification event.
if (mState != STATE_INITIALIZED) {
return ERROR_INVALID_OPERATION;
}
return native_set_pos_update_period(periodInFrames);
|
protected void | setState(int state)Sets the initialization state of the instance. To be used in an AudioTrack subclass
constructor to set a subclass-specific post-initialization state.
mState = state;
|
public int | setStereoVolume(float leftVolume, float rightVolume)Sets the specified left/right output volume values on the AudioTrack. Values are clamped
to the ({@link #getMinVolume()}, {@link #getMaxVolume()}) interval if outside this range.
if (mState != STATE_INITIALIZED) {
return ERROR_INVALID_OPERATION;
}
// clamp the volumes
if (leftVolume < getMinVolume()) {
leftVolume = getMinVolume();
}
if (leftVolume > getMaxVolume()) {
leftVolume = getMaxVolume();
}
if (rightVolume < getMinVolume()) {
rightVolume = getMinVolume();
}
if (rightVolume > getMaxVolume()) {
rightVolume = getMaxVolume();
}
native_setVolume(leftVolume, rightVolume);
return SUCCESS;
|
public void | stop()Stops playing the audio data.
if (mState != STATE_INITIALIZED) {
throw(new IllegalStateException("stop() called on uninitialized AudioTrack."));
}
// stop playing
synchronized(mPlayStateLock) {
native_stop();
mPlayState = PLAYSTATE_STOPPED;
}
|
public int | write(byte[] audioData, int offsetInBytes, int sizeInBytes)Writes the audio data to the audio hardware for playback.
if ((mDataLoadMode == MODE_STATIC)
&& (mState == STATE_NO_STATIC_DATA)
&& (sizeInBytes > 0)) {
mState = STATE_INITIALIZED;
}
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_write_byte(audioData, offsetInBytes, sizeInBytes, mAudioFormat);
|
public int | write(short[] audioData, int offsetInShorts, int sizeInShorts)Writes the audio data to the audio hardware for playback.
if ((mDataLoadMode == MODE_STATIC)
&& (mState == STATE_NO_STATIC_DATA)
&& (sizeInShorts > 0)) {
mState = STATE_INITIALIZED;
}
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_write_short(audioData, offsetInShorts, sizeInShorts, mAudioFormat);
|