/*
 * Copyright (C) 2013 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.
 */

#ifndef ANDROID_AUDIO_RESAMPLER_DYN_H
#define ANDROID_AUDIO_RESAMPLER_DYN_H

#include <stdint.h>
#include <sys/types.h>
#include <android/log.h>

#include <media/AudioResampler.h>

namespace android {

/* AudioResamplerDyn
 *
 * This class template is used for floating point and integer resamplers.
 *
 * Type variables:
 * TC = filter coefficient type (one of int16_t, int32_t, or float)
 * TI = input data type (one of int16_t or float)
 * TO = output data type (one of int32_t or float)
 *
 * For integer input data types TI, the coefficient type TC is either int16_t or int32_t.
 * For float input data types TI, the coefficient type TC is float.
 */

template<typename TC, typename TI, typename TO>
class AudioResamplerDyn: public AudioResampler {
public:
    AudioResamplerDyn(int inChannelCount,
            int32_t sampleRate, src_quality quality);

    virtual ~AudioResamplerDyn();

    virtual void init();

    virtual void setSampleRate(int32_t inSampleRate);

    virtual void setVolume(float left, float right);

    virtual size_t resample(int32_t* out, size_t outFrameCount,
            AudioBufferProvider* provider);

    // Make available key design criteria for testing
    int getHalfLength() const {
        return mConstants.mHalfNumCoefs;
    }

    const TC *getFilterCoefs() const {
        return mConstants.mFirCoefs;
    }

    int getPhases() const {
        return mConstants.mL;
    }

    double getStopbandAttenuationDb() const {
        return mStopbandAttenuationDb;
    }

    double getPassbandRippleDb() const {
        return mPassbandRippleDb;
    }

    double getNormalizedTransitionBandwidth() const {
        return mNormalizedTransitionBandwidth;
    }

    double getFilterAttenuation() const {
        return mFilterAttenuation;
    }

    double getNormalizedCutoffFrequency() const {
        return mNormalizedCutoffFrequency;
    }

private:

    class Constants { // stores the filter constants.
    public:
        Constants() :
            mL(0), mShift(0), mHalfNumCoefs(0), mFirCoefs(NULL)
        {}
        void set(int L, int halfNumCoefs,
                int inSampleRate, int outSampleRate);

                 int mL;            // interpolation phases in the filter.
                 int mShift;        // right shift to get polyphase index
        unsigned int mHalfNumCoefs; // filter half #coefs
           const TC* mFirCoefs;     // polyphase filter bank
    };

    class InBuffer { // buffer management for input type TI
    public:
        InBuffer();
        ~InBuffer();
        void init();

        void resize(int CHANNELS, int halfNumCoefs);

        // used for direct management of the mImpulse pointer
        inline TI* getImpulse() {
            return mImpulse;
        }

        inline void setImpulse(TI *impulse) {
            mImpulse = impulse;
        }

        template<int CHANNELS>
        inline void readAgain(TI*& impulse, const int halfNumCoefs,
                const TI* const in, const size_t inputIndex);

        template<int CHANNELS>
        inline void readAdvance(TI*& impulse, const int halfNumCoefs,
                const TI* const in, const size_t inputIndex);

        void reset();

    private:
        // tuning parameter guidelines: 2 <= multiple <= 8
        static const int kStateSizeMultipleOfFilterLength = 4;

        // in general, mRingFull = mState + mStateSize - halfNumCoefs*CHANNELS.
           TI* mState;      // base pointer for the input buffer storage
           TI* mImpulse;    // current location of the impulse response (centered)
           TI* mRingFull;   // mState <= mImpulse < mRingFull
        size_t mStateCount; // size of state in units of TI.
    };

    void createKaiserFir(Constants &c, double stopBandAtten,
            int inSampleRate, int outSampleRate, double tbwCheat);

    void createKaiserFir(Constants &c, double stopBandAtten, double fcr);

    template<int CHANNELS, bool LOCKED, int STRIDE>
    size_t resample(TO* out, size_t outFrameCount, AudioBufferProvider* provider);

    // define a pointer to member function type for resample
    typedef size_t (AudioResamplerDyn<TC, TI, TO>::*resample_ABP_t)(TO* out,
            size_t outFrameCount, AudioBufferProvider* provider);

    // data - the contiguous storage and layout of these is important.
           InBuffer mInBuffer;
          Constants mConstants;        // current set of coefficient parameters
    TO __attribute__ ((aligned (8))) mVolumeSimd[2]; // must be aligned or NEON may crash
     resample_ABP_t mResampleFunc;     // called function for resampling
            int32_t mFilterSampleRate; // designed filter sample rate.
        src_quality mFilterQuality;    // designed filter quality.
              void* mCoefBuffer;       // if a filter is created, this is not null

    // Property selected design parameters.
              // This will enable fixed high quality resampling.

              // 32 char PROP_NAME_MAX limit enforced before Android O

              // Use for sample rates greater than or equal to this value.
              // Set to non-negative to enable, negative to disable.
              int32_t mPropertyEnableAtSampleRate = 48000;
                      // "ro.audio.resampler.psd.enable_at_samplerate"

              // Specify HALF the resampling filter length.
              // Set to a value which is a multiple of 4.
              int32_t mPropertyHalfFilterLength = 32;
                      // "ro.audio.resampler.psd.halflength"

              // Specify the stopband attenuation in positive dB.
              // Set to a value greater or equal to 20.
              int32_t mPropertyStopbandAttenuation = 90;
                      // "ro.audio.resampler.psd.stopband"

              // Specify the cutoff frequency as a percentage of Nyquist.
              // Set to a value between 50 and 100.
              int32_t mPropertyCutoffPercent = 100;
                      // "ro.audio.resampler.psd.cutoff_percent"

    // Filter creation design parameters, see setSampleRate()
             double mStopbandAttenuationDb = 0.;
             double mPassbandRippleDb = 0.;
             double mNormalizedTransitionBandwidth = 0.;
             double mFilterAttenuation = 0.;
             double mNormalizedCutoffFrequency = 0.;
};

} // namespace android

#endif /*ANDROID_AUDIO_RESAMPLER_DYN_H*/
