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

Commit 3c4e6b50 authored by Phil Burk's avatar Phil Burk
Browse files

aaudio: use actual DSP burst size in timing model

This will more accurately track the read or write
position of the DSP.

The client sometimes aggregates multiple hardware bursts
to avoid waking up too often. This can make it look like the DSP has
processed a larger amount of memory than it really has.
With this change, the timing model will advance in sync with the hardware.

Bug: 117834966
Bug: 130911274
Test: see bug for repro steps
Change-Id: Id22f1f313e02f0514665ee5ac144cab4684e3bc1
parent 9730f4d7
Loading
Loading
Loading
Loading
+21 −3
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) {
    aaudio_result_t result = AAUDIO_OK;
    int32_t capacity;
    int32_t framesPerBurst;
    int32_t framesPerHardwareBurst;
    AAudioStreamRequest request;
    AAudioStreamConfiguration configurationOutput;

@@ -90,6 +91,9 @@ aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) {
        return result;
    }

    const int32_t burstMinMicros = AAudioProperty_getHardwareBurstMinMicros();
    int32_t burstMicros = 0;

    // We have to do volume scaling. So we prefer FLOAT format.
    if (getFormat() == AUDIO_FORMAT_DEFAULT) {
        setFormat(AUDIO_FORMAT_PCM_FLOAT);
@@ -173,8 +177,22 @@ aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) {
        goto error;
    }

    // Validate result from server.
    framesPerBurst = mEndpointDescriptor.dataQueueDescriptor.framesPerBurst;
    framesPerHardwareBurst = mEndpointDescriptor.dataQueueDescriptor.framesPerBurst;

    // Scale up the burst size to meet the minimum equivalent in microseconds.
    // This is to avoid waking the CPU too often when the HW burst is very small
    // or at high sample rates.
    framesPerBurst = framesPerHardwareBurst;
    do {
        if (burstMicros > 0) {  // skip first loop
            framesPerBurst *= 2;
        }
        burstMicros = framesPerBurst * static_cast<int64_t>(1000000) / getSampleRate();
    } while (burstMicros < burstMinMicros);
    ALOGD("%s() original HW burst = %d, minMicros = %d => SW burst = %d\n",
          __func__, framesPerHardwareBurst, burstMinMicros, framesPerBurst);

    // Validate final burst size.
    if (framesPerBurst < MIN_FRAMES_PER_BURST || framesPerBurst > MAX_FRAMES_PER_BURST) {
        ALOGE("%s - framesPerBurst out of range = %d", __func__, framesPerBurst);
        result = AAUDIO_ERROR_OUT_OF_RANGE;
@@ -190,7 +208,7 @@ aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) {
    }

    mClockModel.setSampleRate(getSampleRate());
    mClockModel.setFramesPerBurst(mFramesPerBurst);
    mClockModel.setFramesPerBurst(framesPerHardwareBurst);

    if (isDataCallbackSet()) {
        mCallbackFrames = builder.getFramesPerDataCallback();
+5 −20
Original line number Diff line number Diff line
@@ -77,9 +77,6 @@ aaudio_result_t AAudioServiceEndpointMMAP::open(const aaudio::AAudioStreamReques
    audio_config_base_t config;
    audio_port_handle_t deviceId;

    int32_t burstMinMicros = AAudioProperty_getHardwareBurstMinMicros();
    int32_t burstMicros = 0;

    copyFrom(request.getConstantConfiguration());

    aaudio_direction_t direction = getDirection();
@@ -235,24 +232,12 @@ aaudio_result_t AAudioServiceEndpointMMAP::open(const aaudio::AAudioStreamReques
    setFormat(config.format);
    setSampleRate(config.sample_rate);

    // Scale up the burst size to meet the minimum equivalent in microseconds.
    // This is to avoid waking the CPU too often when the HW burst is very small
    // or at high sample rates.
    do {
        if (burstMicros > 0) {  // skip first loop
            mFramesPerBurst *= 2;
        }
        burstMicros = mFramesPerBurst * static_cast<int64_t>(1000000) / getSampleRate();
    } while (burstMicros < burstMinMicros);

    ALOGD("%s() original burst = %d, minMicros = %d => burst = %d\n",
          __func__, mMmapBufferinfo.burst_size_frames, burstMinMicros, mFramesPerBurst);

    ALOGD("%s() actual rate = %d, channels = %d, deviceId = %d\n",
          __func__, getSampleRate(), getSamplesPerFrame(), deviceId);
    ALOGD("%s() actual rate = %d, channels = %d"
          ", deviceId = %d, capacity = %d\n",
          __func__, getSampleRate(), getSamplesPerFrame(), deviceId, getBufferCapacity());

    ALOGD("%s() format = 0x%08x, frame size = %d",
          __func__, getFormat(), calculateBytesPerFrame());
    ALOGD("%s() format = 0x%08x, frame size = %d, burst size = %d",
          __func__, getFormat(), calculateBytesPerFrame(), mFramesPerBurst);

    return result;