Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit adfb7f62 authored by Phil Burk's avatar Phil Burk
Browse files

AudioTrack: add setBufferSizeInFrames()



Also add getBufferCapacityInFrames().
These can be used to dynamically raise or lower latency.

Bug: 21019153
Change-Id: I3403982894c5fe101f45d0466b00ff3036b28417
Signed-off-by: default avatarPhil Burk <philburk@google.com>
parent e5480cc5
Loading
Loading
Loading
Loading
+50 −5
Original line number Diff line number Diff line
@@ -656,17 +656,58 @@ static jint android_media_AudioTrack_write_native_bytes(JNIEnv *env, jobject th
}

// ----------------------------------------------------------------------------
static jint android_media_AudioTrack_get_native_frame_count(JNIEnv *env,  jobject thiz) {
static jint android_media_AudioTrack_get_buffer_size_frames(JNIEnv *env,  jobject thiz) {
    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
    if (lpTrack == NULL) {
        jniThrowException(env, "java/lang/IllegalStateException",
            "Unable to retrieve AudioTrack pointer for frameCount()");
            "Unable to retrieve AudioTrack pointer for getBufferSizeInFrames()");
        return (jint)AUDIO_JAVA_ERROR;
    }

    return lpTrack->frameCount();
    ssize_t result = lpTrack->getBufferSizeInFrames();
    if (result < 0) {
        jniThrowException(env, "java/lang/IllegalStateException",
            "Internal error detected in getBufferSizeInFrames() = " + result);
        return (jint)AUDIO_JAVA_ERROR;
    }
    return (jint)result;
}

// ----------------------------------------------------------------------------
static jint android_media_AudioTrack_set_buffer_size_frames(JNIEnv *env,
        jobject thiz, jint bufferSizeInFrames) {
    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
    if (lpTrack == NULL) {
        jniThrowException(env, "java/lang/IllegalStateException",
            "Unable to retrieve AudioTrack pointer for setBufferSizeInFrames()");
        return (jint)AUDIO_JAVA_ERROR;
    }
    // Value will be coerced into the valid range.
    // But internal values are unsigned, size_t, so we need to clip
    // against zero here where it is signed.
    if (bufferSizeInFrames < 0) {
        bufferSizeInFrames = 0;
    }
    ssize_t result = lpTrack->setBufferSizeInFrames(bufferSizeInFrames);
    if (result < 0) {
        jniThrowException(env, "java/lang/IllegalStateException",
            "Internal error detected in setBufferSizeInFrames() = " + result);
        return (jint)AUDIO_JAVA_ERROR;
    }
    return (jint)result;
}

// ----------------------------------------------------------------------------
static jint android_media_AudioTrack_get_buffer_capacity_frames(JNIEnv *env,  jobject thiz) {
    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
    if (lpTrack == NULL) {
        jniThrowException(env, "java/lang/IllegalStateException",
            "Unable to retrieve AudioTrack pointer for getBufferCapacityInFrames()");
        return (jint)AUDIO_JAVA_ERROR;
    }

    return lpTrack->frameCount();
}

// ----------------------------------------------------------------------------
static jint android_media_AudioTrack_set_playback_rate(JNIEnv *env,  jobject thiz,
@@ -1073,8 +1114,12 @@ static const JNINativeMethod gMethods[] = {
    {"native_write_short",   "([SIIIZ)I",(void *)android_media_AudioTrack_writeArray<jshortArray>},
    {"native_write_float",   "([FIIIZ)I",(void *)android_media_AudioTrack_writeArray<jfloatArray>},
    {"native_setVolume",     "(FF)V",    (void *)android_media_AudioTrack_set_volume},
    {"native_get_native_frame_count",
                             "()I",      (void *)android_media_AudioTrack_get_native_frame_count},
    {"native_get_buffer_size_frames",
                             "()I",      (void *)android_media_AudioTrack_get_buffer_size_frames},
    {"native_set_buffer_size_frames",
                             "(I)I",     (void *)android_media_AudioTrack_set_buffer_size_frames},
    {"native_get_buffer_capacity_frames",
                             "()I",      (void *)android_media_AudioTrack_get_buffer_capacity_frames},
    {"native_set_playback_rate",
                             "(I)I",     (void *)android_media_AudioTrack_set_playback_rate},
    {"native_get_playback_rate",
+63 −6
Original line number Diff line number Diff line
@@ -1054,7 +1054,61 @@ public class AudioTrack implements AudioRouting
    }

    /**
     *  Returns the frame count of the native <code>AudioTrack</code> buffer.
     *  Returns the effective size of the <code>AudioTrack</code> buffer
     * that the application writes to.
     *  <p> This will be less than or equal to the result of
     * {@link AudioTrack#getBufferCapacityInFrames()}.
     * It will be equal if {@link AudioTrack#setBufferSizeInFrames()} has never been called.
     *  <p> If the track is subsequently routed to a different output sink, the buffer
     *  size and capacity may enlarge to accommodate.
     *  <p> If the <code>AudioTrack</code> encoding indicates compressed data,
     *  e.g. {@link AudioFormat#ENCODING_AC3}, then the frame count returned is
     *  the size of the native <code>AudioTrack</code> buffer in bytes.
     *  <p> See also {@link AudioManager#getProperty(String)} for key
     *  {@link AudioManager#PROPERTY_OUTPUT_FRAMES_PER_BUFFER}.
     *  @return current size in frames of the <code>AudioTrack</code> buffer.
     *  @throws IllegalStateException
     */
    public int getBufferSizeInFrames() {
        return native_get_buffer_size_frames();
    }

    /**
     * Limits the effective size of the <code>AudioTrack</code> buffer
     * that the application writes to.
     * <p> A write to this AudioTrack will not fill the buffer beyond this limit.
     * If a blocking write is used then the write will block until the the data
     * can fit within this limit.
     * <p>Changing this limit modifies the latency associated with
     * the buffer for this track. A smaller size will give lower latency
     * but there may be more glitches due to buffer underruns.
     *  <p>The actual size used may not be equal to this requested size.
     * It will be limited to a valid range with a maximum of
     * {@link AudioTrack#getBufferCapacityInFrames()}.
     * It may also be adjusted slightly for internal reasons.
     * If bufferSizeInFrames is less than zero then {@link #ERROR_BAD_VALUE}
     * will be returned.
     * <p>This method is only supported for PCM audio.
     * It is not supported for compressed audio tracks.
     *
     * @param bufferSizeInFrames requested buffer size
     * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
     *    {@link #ERROR_INVALID_OPERATION}
     *  @throws IllegalStateException
     * @hide
     */
    public int setBufferSizeInFrames(int bufferSizeInFrames) {
        if (mDataLoadMode == MODE_STATIC || mState == STATE_UNINITIALIZED) {
            return ERROR_INVALID_OPERATION;
        }
        if (bufferSizeInFrames < 0) {
            return ERROR_BAD_VALUE;
        }
        return native_set_buffer_size_frames(bufferSizeInFrames);
    }

    /**
     *  Returns the maximum size of the native <code>AudioTrack</code> buffer.
     *  <p> If the track's creation mode is {@link #MODE_STATIC},
     *  it is equal to the specified bufferSizeInBytes on construction, converted to frame units.
     *  A static track's native frame count will not change.
@@ -1069,11 +1123,12 @@ public class AudioTrack implements AudioRouting
     *  the size of the native <code>AudioTrack</code> buffer in bytes.
     *  <p> See also {@link AudioManager#getProperty(String)} for key
     *  {@link AudioManager#PROPERTY_OUTPUT_FRAMES_PER_BUFFER}.
     *  @return current size in frames of the <code>AudioTrack</code> buffer.
     *  @return maximum size in frames of the <code>AudioTrack</code> buffer.
     *  @throws IllegalStateException
     * @hide
     */
    public int getBufferSizeInFrames() {
        return native_get_native_frame_count();
    public int getBufferCapacityInFrames() {
        return native_get_buffer_capacity_frames();
    }

    /**
@@ -1084,7 +1139,7 @@ public class AudioTrack implements AudioRouting
     */
    @Deprecated
    protected int getNativeFrameCount() {
        return native_get_native_frame_count();
        return native_get_buffer_capacity_frames();
    }

    /**
@@ -2701,7 +2756,9 @@ public class AudioTrack implements AudioRouting

    private native final int native_reload_static();

    private native final int native_get_native_frame_count();
    private native final int native_get_buffer_size_frames();
    private native final int native_set_buffer_size_frames(int bufferSizeInFrames);
    private native final int native_get_buffer_capacity_frames();

    private native final void native_setVolume(float leftVolume, float rightVolume);