/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "BufferProvider"
//#define LOG_NDEBUG 0

#include <audio_utils/primitives.h>
#include <audio_utils/format.h>
#include <external/sonic/sonic.h>
#include <media/audiohal/EffectBufferHalInterface.h>
#include <media/audiohal/EffectHalInterface.h>
#include <media/audiohal/EffectsFactoryHalInterface.h>
#include <media/AudioResamplerPublic.h>
#include <media/BufferProviders.h>
#include <system/audio_effects/effect_downmix.h>
#include <utils/Log.h>

#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
#endif

namespace android {

// ----------------------------------------------------------------------------

template <typename T>
static inline T min(const T& a, const T& b)
{
    return a < b ? a : b;
}

CopyBufferProvider::CopyBufferProvider(size_t inputFrameSize,
        size_t outputFrameSize, size_t bufferFrameCount) :
        mInputFrameSize(inputFrameSize),
        mOutputFrameSize(outputFrameSize),
        mLocalBufferFrameCount(bufferFrameCount),
        mLocalBufferData(NULL),
        mConsumed(0)
{
    ALOGV("CopyBufferProvider(%p)(%zu, %zu, %zu)", this,
            inputFrameSize, outputFrameSize, bufferFrameCount);
    LOG_ALWAYS_FATAL_IF(inputFrameSize < outputFrameSize && bufferFrameCount == 0,
            "Requires local buffer if inputFrameSize(%zu) < outputFrameSize(%zu)",
            inputFrameSize, outputFrameSize);
    if (mLocalBufferFrameCount) {
        (void)posix_memalign(&mLocalBufferData, 32, mLocalBufferFrameCount * mOutputFrameSize);
    }
    mBuffer.frameCount = 0;
}

CopyBufferProvider::~CopyBufferProvider()
{
    ALOGV("~CopyBufferProvider(%p)", this);
    if (mBuffer.frameCount != 0) {
        mTrackBufferProvider->releaseBuffer(&mBuffer);
    }
    free(mLocalBufferData);
}

status_t CopyBufferProvider::getNextBuffer(AudioBufferProvider::Buffer *pBuffer)
{
    //ALOGV("CopyBufferProvider(%p)::getNextBuffer(%p (%zu))",
    //        this, pBuffer, pBuffer->frameCount);
    if (mLocalBufferFrameCount == 0) {
        status_t res = mTrackBufferProvider->getNextBuffer(pBuffer);
        if (res == OK) {
            copyFrames(pBuffer->raw, pBuffer->raw, pBuffer->frameCount);
        }
        return res;
    }
    if (mBuffer.frameCount == 0) {
        mBuffer.frameCount = pBuffer->frameCount;
        status_t res = mTrackBufferProvider->getNextBuffer(&mBuffer);
        // At one time an upstream buffer provider had
        // res == OK and mBuffer.frameCount == 0, doesn't seem to happen now 7/18/2014.
        //
        // By API spec, if res != OK, then mBuffer.frameCount == 0.
        // but there may be improper implementations.
        ALOG_ASSERT(res == OK || mBuffer.frameCount == 0);
        if (res != OK || mBuffer.frameCount == 0) { // not needed by API spec, but to be safe.
            pBuffer->raw = NULL;
            pBuffer->frameCount = 0;
            return res;
        }
        mConsumed = 0;
    }
    ALOG_ASSERT(mConsumed < mBuffer.frameCount);
    size_t count = min(mLocalBufferFrameCount, mBuffer.frameCount - mConsumed);
    count = min(count, pBuffer->frameCount);
    pBuffer->raw = mLocalBufferData;
    pBuffer->frameCount = count;
    copyFrames(pBuffer->raw, (uint8_t*)mBuffer.raw + mConsumed * mInputFrameSize,
            pBuffer->frameCount);
    return OK;
}

void CopyBufferProvider::releaseBuffer(AudioBufferProvider::Buffer *pBuffer)
{
    //ALOGV("CopyBufferProvider(%p)::releaseBuffer(%p(%zu))",
    //        this, pBuffer, pBuffer->frameCount);
    if (mLocalBufferFrameCount == 0) {
        mTrackBufferProvider->releaseBuffer(pBuffer);
        return;
    }
    // LOG_ALWAYS_FATAL_IF(pBuffer->frameCount == 0, "Invalid framecount");
    mConsumed += pBuffer->frameCount; // TODO: update for efficiency to reuse existing content
    if (mConsumed != 0 && mConsumed >= mBuffer.frameCount) {
        mTrackBufferProvider->releaseBuffer(&mBuffer);
        ALOG_ASSERT(mBuffer.frameCount == 0);
    }
    pBuffer->raw = NULL;
    pBuffer->frameCount = 0;
}

void CopyBufferProvider::reset()
{
    if (mBuffer.frameCount != 0) {
        mTrackBufferProvider->releaseBuffer(&mBuffer);
    }
    mConsumed = 0;
}

DownmixerBufferProvider::DownmixerBufferProvider(
        audio_channel_mask_t inputChannelMask,
        audio_channel_mask_t outputChannelMask, audio_format_t format,
        uint32_t sampleRate, int32_t sessionId, size_t bufferFrameCount) :
        CopyBufferProvider(
            audio_bytes_per_sample(format) * audio_channel_count_from_out_mask(inputChannelMask),
            audio_bytes_per_sample(format) * audio_channel_count_from_out_mask(outputChannelMask),
            bufferFrameCount)  // set bufferFrameCount to 0 to do in-place
{
    ALOGV("DownmixerBufferProvider(%p)(%#x, %#x, %#x %u %d)",
            this, inputChannelMask, outputChannelMask, format,
            sampleRate, sessionId);
    if (!sIsMultichannelCapable) {
        ALOGE("DownmixerBufferProvider() error: not multichannel capable");
        return;
    }
    mEffectsFactory = EffectsFactoryHalInterface::create();
    if (mEffectsFactory == 0) {
        ALOGE("DownmixerBufferProvider() error: could not obtain the effects factory");
        return;
    }
    if (mEffectsFactory->createEffect(&sDwnmFxDesc.uuid,
                                      sessionId,
                                      SESSION_ID_INVALID_AND_IGNORED,
                                      &mDownmixInterface) != 0) {
         ALOGE("DownmixerBufferProvider() error creating downmixer effect");
         mDownmixInterface.clear();
         mEffectsFactory.clear();
         return;
     }
     // channel input configuration will be overridden per-track
     mDownmixConfig.inputCfg.channels = inputChannelMask;   // FIXME: Should be bits
     mDownmixConfig.outputCfg.channels = outputChannelMask; // FIXME: should be bits
     mDownmixConfig.inputCfg.format = format;
     mDownmixConfig.outputCfg.format = format;
     mDownmixConfig.inputCfg.samplingRate = sampleRate;
     mDownmixConfig.outputCfg.samplingRate = sampleRate;
     mDownmixConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
     mDownmixConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
     // input and output buffer provider, and frame count will not be used as the downmix effect
     // process() function is called directly (see DownmixerBufferProvider::getNextBuffer())
     mDownmixConfig.inputCfg.mask = EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS |
             EFFECT_CONFIG_FORMAT | EFFECT_CONFIG_ACC_MODE;
     mDownmixConfig.outputCfg.mask = mDownmixConfig.inputCfg.mask;

     status_t status;
     status = EffectBufferHalInterface::mirror(
             nullptr,
             audio_bytes_per_sample(format) * audio_channel_count_from_out_mask(inputChannelMask),
             &mInBuffer);
     if (status != 0) {
         ALOGE("DownmixerBufferProvider() error %d while creating input buffer", status);
         mDownmixInterface.clear();
         mEffectsFactory.clear();
         return;
     }
     status = EffectBufferHalInterface::mirror(
             nullptr,
             audio_bytes_per_sample(format) * audio_channel_count_from_out_mask(outputChannelMask),
             &mOutBuffer);
     if (status != 0) {
         ALOGE("DownmixerBufferProvider() error %d while creating output buffer", status);
         mInBuffer.clear();
         mDownmixInterface.clear();
         mEffectsFactory.clear();
         return;
     }
     mDownmixInterface->setInBuffer(mInBuffer);
     mDownmixInterface->setOutBuffer(mOutBuffer);

     int cmdStatus;
     uint32_t replySize = sizeof(int);

     // Configure downmixer
     status = mDownmixInterface->command(
             EFFECT_CMD_SET_CONFIG /*cmdCode*/, sizeof(effect_config_t) /*cmdSize*/,
             &mDownmixConfig /*pCmdData*/,
             &replySize, &cmdStatus /*pReplyData*/);
     if (status != 0 || cmdStatus != 0) {
         ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while configuring downmixer",
                 status, cmdStatus);
         mOutBuffer.clear();
         mInBuffer.clear();
         mDownmixInterface.clear();
         mEffectsFactory.clear();
         return;
     }

     // Enable downmixer
     replySize = sizeof(int);
     status = mDownmixInterface->command(
             EFFECT_CMD_ENABLE /*cmdCode*/, 0 /*cmdSize*/, NULL /*pCmdData*/,
             &replySize, &cmdStatus /*pReplyData*/);
     if (status != 0 || cmdStatus != 0) {
         ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while enabling downmixer",
                 status, cmdStatus);
         mOutBuffer.clear();
         mInBuffer.clear();
         mDownmixInterface.clear();
         mEffectsFactory.clear();
         return;
     }

     // Set downmix type
     // parameter size rounded for padding on 32bit boundary
     const int psizePadded = ((sizeof(downmix_params_t) - 1)/sizeof(int) + 1) * sizeof(int);
     const int downmixParamSize =
             sizeof(effect_param_t) + psizePadded + sizeof(downmix_type_t);
     effect_param_t * const param = (effect_param_t *) malloc(downmixParamSize);
     param->psize = sizeof(downmix_params_t);
     const downmix_params_t downmixParam = DOWNMIX_PARAM_TYPE;
     memcpy(param->data, &downmixParam, param->psize);
     const downmix_type_t downmixType = DOWNMIX_TYPE_FOLD;
     param->vsize = sizeof(downmix_type_t);
     memcpy(param->data + psizePadded, &downmixType, param->vsize);
     replySize = sizeof(int);
     status = mDownmixInterface->command(
             EFFECT_CMD_SET_PARAM /* cmdCode */, downmixParamSize /* cmdSize */,
             param /*pCmdData*/, &replySize, &cmdStatus /*pReplyData*/);
     free(param);
     if (status != 0 || cmdStatus != 0) {
         ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while setting downmix type",
                 status, cmdStatus);
         mOutBuffer.clear();
         mInBuffer.clear();
         mDownmixInterface.clear();
         mEffectsFactory.clear();
         return;
     }
     ALOGV("DownmixerBufferProvider() downmix type set to %d", (int) downmixType);
}

DownmixerBufferProvider::~DownmixerBufferProvider()
{
    ALOGV("~DownmixerBufferProvider (%p)", this);
    if (mDownmixInterface != 0) {
        mDownmixInterface->close();
    }
}

void DownmixerBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
{
    mInBuffer->setExternalData(const_cast<void*>(src));
    mInBuffer->setFrameCount(frames);
    mInBuffer->update();
    mOutBuffer->setExternalData(dst);
    mOutBuffer->setFrameCount(frames);
    mOutBuffer->update();
    // may be in-place if src == dst.
    status_t res = mDownmixInterface->process();
    if (res == OK) {
        mOutBuffer->commit();
    } else {
        ALOGE("DownmixBufferProvider error %d", res);
    }
}

/* call once in a pthread_once handler. */
/*static*/ status_t DownmixerBufferProvider::init()
{
    // find multichannel downmix effect if we have to play multichannel content
    sp<EffectsFactoryHalInterface> effectsFactory = EffectsFactoryHalInterface::create();
    if (effectsFactory == 0) {
        ALOGE("AudioMixer() error: could not obtain the effects factory");
        return NO_INIT;
    }
    uint32_t numEffects = 0;
    int ret = effectsFactory->queryNumberEffects(&numEffects);
    if (ret != 0) {
        ALOGE("AudioMixer() error %d querying number of effects", ret);
        return NO_INIT;
    }
    ALOGV("EffectQueryNumberEffects() numEffects=%d", numEffects);

    for (uint32_t i = 0 ; i < numEffects ; i++) {
        if (effectsFactory->getDescriptor(i, &sDwnmFxDesc) == 0) {
            ALOGV("effect %d is called %s", i, sDwnmFxDesc.name);
            if (memcmp(&sDwnmFxDesc.type, EFFECT_UIID_DOWNMIX, sizeof(effect_uuid_t)) == 0) {
                ALOGI("found effect \"%s\" from %s",
                        sDwnmFxDesc.name, sDwnmFxDesc.implementor);
                sIsMultichannelCapable = true;
                break;
            }
        }
    }
    ALOGW_IF(!sIsMultichannelCapable, "unable to find downmix effect");
    return NO_INIT;
}

/*static*/ bool DownmixerBufferProvider::sIsMultichannelCapable = false;
/*static*/ effect_descriptor_t DownmixerBufferProvider::sDwnmFxDesc;

RemixBufferProvider::RemixBufferProvider(audio_channel_mask_t inputChannelMask,
        audio_channel_mask_t outputChannelMask, audio_format_t format,
        size_t bufferFrameCount) :
        CopyBufferProvider(
                audio_bytes_per_sample(format)
                    * audio_channel_count_from_out_mask(inputChannelMask),
                audio_bytes_per_sample(format)
                    * audio_channel_count_from_out_mask(outputChannelMask),
                bufferFrameCount),
        mFormat(format),
        mSampleSize(audio_bytes_per_sample(format)),
        mInputChannels(audio_channel_count_from_out_mask(inputChannelMask)),
        mOutputChannels(audio_channel_count_from_out_mask(outputChannelMask))
{
    ALOGV("RemixBufferProvider(%p)(%#x, %#x, %#x) %zu %zu",
            this, format, inputChannelMask, outputChannelMask,
            mInputChannels, mOutputChannels);
    (void) memcpy_by_index_array_initialization_from_channel_mask(
            mIdxAry, ARRAY_SIZE(mIdxAry), outputChannelMask, inputChannelMask);
}

void RemixBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
{
    memcpy_by_index_array(dst, mOutputChannels,
            src, mInputChannels, mIdxAry, mSampleSize, frames);
}

ReformatBufferProvider::ReformatBufferProvider(int32_t channelCount,
        audio_format_t inputFormat, audio_format_t outputFormat,
        size_t bufferFrameCount) :
        CopyBufferProvider(
                channelCount * audio_bytes_per_sample(inputFormat),
                channelCount * audio_bytes_per_sample(outputFormat),
                bufferFrameCount),
        mChannelCount(channelCount),
        mInputFormat(inputFormat),
        mOutputFormat(outputFormat)
{
    ALOGV("ReformatBufferProvider(%p)(%u, %#x, %#x)",
            this, channelCount, inputFormat, outputFormat);
}

void ReformatBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
{
    memcpy_by_audio_format(dst, mOutputFormat, src, mInputFormat, frames * mChannelCount);
}

TimestretchBufferProvider::TimestretchBufferProvider(int32_t channelCount,
        audio_format_t format, uint32_t sampleRate, const AudioPlaybackRate &playbackRate) :
        mChannelCount(channelCount),
        mFormat(format),
        mSampleRate(sampleRate),
        mFrameSize(channelCount * audio_bytes_per_sample(format)),
        mLocalBufferFrameCount(0),
        mLocalBufferData(NULL),
        mRemaining(0),
        mSonicStream(sonicCreateStream(sampleRate, mChannelCount)),
        mFallbackFailErrorShown(false),
        mAudioPlaybackRateValid(false)
{
    LOG_ALWAYS_FATAL_IF(mSonicStream == NULL,
            "TimestretchBufferProvider can't allocate Sonic stream");

    setPlaybackRate(playbackRate);
    ALOGV("TimestretchBufferProvider(%p)(%u, %#x, %u %f %f %d %d)",
            this, channelCount, format, sampleRate, playbackRate.mSpeed,
            playbackRate.mPitch, playbackRate.mStretchMode, playbackRate.mFallbackMode);
    mBuffer.frameCount = 0;
}

TimestretchBufferProvider::~TimestretchBufferProvider()
{
    ALOGV("~TimestretchBufferProvider(%p)", this);
    sonicDestroyStream(mSonicStream);
    if (mBuffer.frameCount != 0) {
        mTrackBufferProvider->releaseBuffer(&mBuffer);
    }
    free(mLocalBufferData);
}

status_t TimestretchBufferProvider::getNextBuffer(
        AudioBufferProvider::Buffer *pBuffer)
{
    ALOGV("TimestretchBufferProvider(%p)::getNextBuffer(%p (%zu))",
            this, pBuffer, pBuffer->frameCount);

    // BYPASS
    //return mTrackBufferProvider->getNextBuffer(pBuffer);

    // check if previously processed data is sufficient.
    if (pBuffer->frameCount <= mRemaining) {
        ALOGV("previous sufficient");
        pBuffer->raw = mLocalBufferData;
        return OK;
    }

    // do we need to resize our buffer?
    if (pBuffer->frameCount > mLocalBufferFrameCount) {
        void *newmem;
        if (posix_memalign(&newmem, 32, pBuffer->frameCount * mFrameSize) == OK) {
            if (mRemaining != 0) {
                memcpy(newmem, mLocalBufferData, mRemaining * mFrameSize);
            }
            free(mLocalBufferData);
            mLocalBufferData = newmem;
            mLocalBufferFrameCount = pBuffer->frameCount;
        }
    }

    // need to fetch more data
    const size_t outputDesired = pBuffer->frameCount - mRemaining;
    size_t dstAvailable;
    do {
        mBuffer.frameCount = mPlaybackRate.mSpeed == AUDIO_TIMESTRETCH_SPEED_NORMAL
                ? outputDesired : outputDesired * mPlaybackRate.mSpeed + 1;

        status_t res = mTrackBufferProvider->getNextBuffer(&mBuffer);

        ALOG_ASSERT(res == OK || mBuffer.frameCount == 0);
        if (res != OK || mBuffer.frameCount == 0) { // not needed by API spec, but to be safe.
            ALOGV("upstream provider cannot provide data");
            if (mRemaining == 0) {
                pBuffer->raw = NULL;
                pBuffer->frameCount = 0;
                return res;
            } else { // return partial count
                pBuffer->raw = mLocalBufferData;
                pBuffer->frameCount = mRemaining;
                return OK;
            }
        }

        // time-stretch the data
        dstAvailable = min(mLocalBufferFrameCount - mRemaining, outputDesired);
        size_t srcAvailable = mBuffer.frameCount;
        processFrames((uint8_t*)mLocalBufferData + mRemaining * mFrameSize, &dstAvailable,
                mBuffer.raw, &srcAvailable);

        // release all data consumed
        mBuffer.frameCount = srcAvailable;
        mTrackBufferProvider->releaseBuffer(&mBuffer);
    } while (dstAvailable == 0); // try until we get output data or upstream provider fails.

    // update buffer vars with the actual data processed and return with buffer
    mRemaining += dstAvailable;

    pBuffer->raw = mLocalBufferData;
    pBuffer->frameCount = mRemaining;

    return OK;
}

void TimestretchBufferProvider::releaseBuffer(AudioBufferProvider::Buffer *pBuffer)
{
    ALOGV("TimestretchBufferProvider(%p)::releaseBuffer(%p (%zu))",
       this, pBuffer, pBuffer->frameCount);

    // BYPASS
    //return mTrackBufferProvider->releaseBuffer(pBuffer);

    // LOG_ALWAYS_FATAL_IF(pBuffer->frameCount == 0, "Invalid framecount");
    if (pBuffer->frameCount < mRemaining) {
        memcpy(mLocalBufferData,
                (uint8_t*)mLocalBufferData + pBuffer->frameCount * mFrameSize,
                (mRemaining - pBuffer->frameCount) * mFrameSize);
        mRemaining -= pBuffer->frameCount;
    } else if (pBuffer->frameCount == mRemaining) {
        mRemaining = 0;
    } else {
        LOG_ALWAYS_FATAL("Releasing more frames(%zu) than available(%zu)",
                pBuffer->frameCount, mRemaining);
    }

    pBuffer->raw = NULL;
    pBuffer->frameCount = 0;
}

void TimestretchBufferProvider::reset()
{
    mRemaining = 0;
}

status_t TimestretchBufferProvider::setPlaybackRate(const AudioPlaybackRate &playbackRate)
{
    mPlaybackRate = playbackRate;
    mFallbackFailErrorShown = false;
    sonicSetSpeed(mSonicStream, mPlaybackRate.mSpeed);
    //TODO: pitch is ignored for now
    //TODO: optimize: if parameters are the same, don't do any extra computation.

    mAudioPlaybackRateValid = isAudioPlaybackRateValid(mPlaybackRate);
    return OK;
}

void TimestretchBufferProvider::processFrames(void *dstBuffer, size_t *dstFrames,
        const void *srcBuffer, size_t *srcFrames)
{
    ALOGV("processFrames(%zu %zu)  remaining(%zu)", *dstFrames, *srcFrames, mRemaining);
    // Note dstFrames is the required number of frames.

    if (!mAudioPlaybackRateValid) {
        //fallback mode
        // Ensure consumption from src is as expected.
        // TODO: add logic to track "very accurate" consumption related to speed, original sampling
        // rate, actual frames processed.

        const size_t targetSrc = *dstFrames * mPlaybackRate.mSpeed;
        if (*srcFrames < targetSrc) { // limit dst frames to that possible
            *dstFrames = *srcFrames / mPlaybackRate.mSpeed;
        } else if (*srcFrames > targetSrc + 1) {
            *srcFrames = targetSrc + 1;
        }
        if (*dstFrames > 0) {
            switch(mPlaybackRate.mFallbackMode) {
            case AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT:
                if (*dstFrames <= *srcFrames) {
                      size_t copySize = mFrameSize * *dstFrames;
                      memcpy(dstBuffer, srcBuffer, copySize);
                  } else {
                      // cyclically repeat the source.
                      for (size_t count = 0; count < *dstFrames; count += *srcFrames) {
                          size_t remaining = min(*srcFrames, *dstFrames - count);
                          memcpy((uint8_t*)dstBuffer + mFrameSize * count,
                                  srcBuffer, mFrameSize * remaining);
                      }
                  }
                break;
            case AUDIO_TIMESTRETCH_FALLBACK_DEFAULT:
            case AUDIO_TIMESTRETCH_FALLBACK_MUTE:
                memset(dstBuffer,0, mFrameSize * *dstFrames);
                break;
            case AUDIO_TIMESTRETCH_FALLBACK_FAIL:
            default:
                if(!mFallbackFailErrorShown) {
                    ALOGE("invalid parameters in TimestretchBufferProvider fallbackMode:%d",
                            mPlaybackRate.mFallbackMode);
                    mFallbackFailErrorShown = true;
                }
                break;
            }
        }
    } else {
        switch (mFormat) {
        case AUDIO_FORMAT_PCM_FLOAT:
            if (sonicWriteFloatToStream(mSonicStream, (float*)srcBuffer, *srcFrames) != 1) {
                ALOGE("sonicWriteFloatToStream cannot realloc");
                *srcFrames = 0; // cannot consume all of srcBuffer
            }
            *dstFrames = sonicReadFloatFromStream(mSonicStream, (float*)dstBuffer, *dstFrames);
            break;
        case AUDIO_FORMAT_PCM_16_BIT:
            if (sonicWriteShortToStream(mSonicStream, (short*)srcBuffer, *srcFrames) != 1) {
                ALOGE("sonicWriteShortToStream cannot realloc");
                *srcFrames = 0; // cannot consume all of srcBuffer
            }
            *dstFrames = sonicReadShortFromStream(mSonicStream, (short*)dstBuffer, *dstFrames);
            break;
        default:
            // could also be caught on construction
            LOG_ALWAYS_FATAL("invalid format %#x for TimestretchBufferProvider", mFormat);
        }
    }
}
// ----------------------------------------------------------------------------
} // namespace android
