/*
 * Copyright (c) 2021 Arm Limited. All rights reserved.
 * SPDX-License-Identifier: Apache-2.0
 *
 * 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.
 */
#include "MelSpectrogram.hpp"

#include "PlatformMath.hpp"

#include <cfloat>

namespace arm {
namespace app {
namespace audio {

    MelSpecParams::MelSpecParams(
            const float samplingFreq,
            const uint32_t numFbankBins,
            const float melLoFreq,
            const float melHiFreq,
            const uint32_t frameLen,
            const bool useHtkMethod):
            m_samplingFreq(samplingFreq),
            m_numFbankBins(numFbankBins),
            m_melLoFreq(melLoFreq),
            m_melHiFreq(melHiFreq),
            m_frameLen(frameLen),

            /* Smallest power of 2 >= frame length. */
            m_frameLenPadded(pow(2, ceil((log(frameLen)/log(2))))),
            m_useHtkMethod(useHtkMethod)
    {}

    std::string MelSpecParams::Str()
    {
        char strC[1024];
        snprintf(strC, sizeof(strC) - 1, "\n   \
    \n\t Sampling frequency:         %f\
    \n\t Number of filter banks:     %u\
    \n\t Mel frequency limit (low):  %f\
    \n\t Mel frequency limit (high): %f\
    \n\t Frame length:               %u\
    \n\t Padded frame length:        %u\
    \n\t Using HTK for Mel scale:    %s\n",
                 this->m_samplingFreq, this->m_numFbankBins, this->m_melLoFreq,
                 this->m_melHiFreq, this->m_frameLen,
                 this->m_frameLenPadded, this->m_useHtkMethod ? "yes" : "no");
        return std::string{strC};
    }

    MelSpectrogram::MelSpectrogram(const MelSpecParams& params):
            _m_params(params),
            _m_filterBankInitialised(false)
    {
        this->_m_buffer = std::vector<float>(
                this->_m_params.m_frameLenPadded, 0.0);
        this->_m_frame = std::vector<float>(
                this->_m_params.m_frameLenPadded, 0.0);
        this->_m_melEnergies = std::vector<float>(
                this->_m_params.m_numFbankBins, 0.0);

        this->_m_windowFunc = std::vector<float>(this->_m_params.m_frameLen);
        const float multiplier = 2 * M_PI / this->_m_params.m_frameLen;

        /* Create window function. */
        for (size_t i = 0; i < this->_m_params.m_frameLen; ++i) {
            this->_m_windowFunc[i] = (0.5 - (0.5 *
                                             math::MathUtils::CosineF32(static_cast<float>(i) * multiplier)));
        }

        math::MathUtils::FftInitF32(this->_m_params.m_frameLenPadded, this->_m_fftInstance);
        debug("Instantiated Mel Spectrogram object: %s\n", this->_m_params.Str().c_str());
    }

    void MelSpectrogram::Init()
    {
        this->_InitMelFilterBank();
    }

    float MelSpectrogram::MelScale(const float freq, const bool useHTKMethod)
    {
        if (useHTKMethod) {
            return 1127.0f * logf (1.0f + freq / 700.0f);
        } else {
            /* Slaney formula for mel scale. */
            float mel = freq / ms_freqStep;

            if (freq >= ms_minLogHz) {
                mel = ms_minLogMel + logf(freq / ms_minLogHz) / ms_logStep;
            }
            return mel;
        }
    }

    float MelSpectrogram::InverseMelScale(const float melFreq, const bool useHTKMethod)
    {
        if (useHTKMethod) {
            return 700.0f * (expf (melFreq / 1127.0f) - 1.0f);
        } else {
            /* Slaney formula for inverse mel scale. */
            float freq = ms_freqStep * melFreq;

            if (melFreq >= ms_minLogMel) {
                freq = ms_minLogHz * expf(ms_logStep * (melFreq - ms_minLogMel));
            }
            return freq;
        }
    }

    bool MelSpectrogram::ApplyMelFilterBank(
            std::vector<float>&                 fftVec,
            std::vector<std::vector<float>>&    melFilterBank,
            std::vector<int32_t>&               filterBankFilterFirst,
            std::vector<int32_t>&               filterBankFilterLast,
            std::vector<float>&                 melEnergies)
    {
        const size_t numBanks = melEnergies.size();

        if (numBanks != filterBankFilterFirst.size() ||
            numBanks != filterBankFilterLast.size()) {
            printf_err("unexpected filter bank lengths\n");
            return false;
        }

        for (size_t bin = 0; bin < numBanks; ++bin) {
            auto filterBankIter = melFilterBank[bin].begin();
            float melEnergy = FLT_MIN; /* Avoid log of zero at later stages */
            int32_t firstIndex = filterBankFilterFirst[bin];
            int32_t lastIndex = filterBankFilterLast[bin];

            for (int i = firstIndex; i <= lastIndex; ++i) {
                float energyRep = math::MathUtils::SqrtF32(fftVec[i]);
                melEnergy += (*filterBankIter++ * energyRep);
            }

            melEnergies[bin] = melEnergy;
        }

        return true;
    }

    void MelSpectrogram::ConvertToLogarithmicScale(std::vector<float>& melEnergies)
    {
        for (size_t bin = 0; bin < melEnergies.size(); ++bin) {
            melEnergies[bin] = logf(melEnergies[bin]);
        }
    }

    void MelSpectrogram::_ConvertToPowerSpectrum()
    {
        const uint32_t halfDim = this->_m_params.m_frameLenPadded / 2;

        /* Handle this special case. */
        float firstEnergy = this->_m_buffer[0] * this->_m_buffer[0];
        float lastEnergy = this->_m_buffer[1] * this->_m_buffer[1];

        math::MathUtils::ComplexMagnitudeSquaredF32(
                this->_m_buffer.data(),
                this->_m_buffer.size(),
                this->_m_buffer.data(),
                this->_m_buffer.size()/2);

        this->_m_buffer[0] = firstEnergy;
        this->_m_buffer[halfDim] = lastEnergy;
    }

    float MelSpectrogram::GetMelFilterBankNormaliser(
            const float&    leftMel,
            const float&    rightMel,
            const bool      useHTKMethod)
    {
        UNUSED(leftMel);
        UNUSED(rightMel);
        UNUSED(useHTKMethod);

        /* By default, no normalisation => return 1 */
        return 1.f;
    }

    void MelSpectrogram::_InitMelFilterBank()
    {
        if (!this->_IsMelFilterBankInited()) {
            this->_m_melFilterBank = this->_CreateMelFilterBank();
            this->_m_filterBankInitialised = true;
        }
    }

    bool MelSpectrogram::_IsMelFilterBankInited()
    {
        return this->_m_filterBankInitialised;
    }

    std::vector<float> MelSpectrogram::ComputeMelSpec(const std::vector<int16_t>& audioData, float trainingMean)
    {
        this->_InitMelFilterBank();

        /* TensorFlow way of normalizing .wav data to (-1, 1). */
        constexpr float normaliser = 1.0/(1<<15);
        for (size_t i = 0; i < this->_m_params.m_frameLen; ++i) {
            this->_m_frame[i] = static_cast<float>(audioData[i]) * normaliser;
        }

        /* Apply window function to input frame. */
        for(size_t i = 0; i < this->_m_params.m_frameLen; ++i) {
            this->_m_frame[i] *= this->_m_windowFunc[i];
        }

        /* Set remaining frame values to 0. */
        std::fill(this->_m_frame.begin() + this->_m_params.m_frameLen,this->_m_frame.end(), 0);

        /* Compute FFT. */
        math::MathUtils::FftF32(this->_m_frame, this->_m_buffer, this->_m_fftInstance);

        /* Convert to power spectrum. */
        this->_ConvertToPowerSpectrum();

        /* Apply mel filterbanks. */
        if (!this->ApplyMelFilterBank(this->_m_buffer,
                                      this->_m_melFilterBank,
                                      this->_m_filterBankFilterFirst,
                                      this->_m_filterBankFilterLast,
                                      this->_m_melEnergies)) {
            printf_err("Failed to apply MEL filter banks\n");
        }

        /* Convert to logarithmic scale */
        this->ConvertToLogarithmicScale(this->_m_melEnergies);

        /* Perform mean subtraction. */
        for (auto& energy:this->_m_melEnergies) {
            energy -= trainingMean;
        }

        return this->_m_melEnergies;
    }

    std::vector<std::vector<float>> MelSpectrogram::_CreateMelFilterBank()
    {
        size_t numFftBins = this->_m_params.m_frameLenPadded / 2;
        float fftBinWidth = static_cast<float>(this->_m_params.m_samplingFreq) / this->_m_params.m_frameLenPadded;

        float melLowFreq = MelSpectrogram::MelScale(this->_m_params.m_melLoFreq,
                                          this->_m_params.m_useHtkMethod);
        float melHighFreq = MelSpectrogram::MelScale(this->_m_params.m_melHiFreq,
                                           this->_m_params.m_useHtkMethod);
        float melFreqDelta = (melHighFreq - melLowFreq) / (this->_m_params.m_numFbankBins + 1);

        std::vector<float> thisBin = std::vector<float>(numFftBins);
        std::vector<std::vector<float>> melFilterBank(
                this->_m_params.m_numFbankBins);
        this->_m_filterBankFilterFirst =
                std::vector<int32_t>(this->_m_params.m_numFbankBins);
        this->_m_filterBankFilterLast =
                std::vector<int32_t>(this->_m_params.m_numFbankBins);

        for (size_t bin = 0; bin < this->_m_params.m_numFbankBins; bin++) {
            float leftMel = melLowFreq + bin * melFreqDelta;
            float centerMel = melLowFreq + (bin + 1) * melFreqDelta;
            float rightMel = melLowFreq + (bin + 2) * melFreqDelta;

            int32_t firstIndex = -1;
            int32_t lastIndex = -1;
            const float normaliser = this->GetMelFilterBankNormaliser(leftMel, rightMel, this->_m_params.m_useHtkMethod);

            for (size_t i = 0; i < numFftBins; ++i) {
                float freq = (fftBinWidth * i); /* Center freq of this fft bin. */
                float mel = MelSpectrogram::MelScale(freq, this->_m_params.m_useHtkMethod);
                thisBin[i] = 0.0;

                if (mel > leftMel && mel < rightMel) {
                    float weight;
                    if (mel <= centerMel) {
                        weight = (mel - leftMel) / (centerMel - leftMel);
                    } else {
                        weight = (rightMel - mel) / (rightMel - centerMel);
                    }

                    thisBin[i] = weight * normaliser;
                    if (firstIndex == -1) {
                        firstIndex = i;
                    }
                    lastIndex = i;
                }
            }

            this->_m_filterBankFilterFirst[bin] = firstIndex;
            this->_m_filterBankFilterLast[bin] = lastIndex;

            /* Copy the part we care about. */
            for (int32_t i = firstIndex; i <= lastIndex; ++i) {
                melFilterBank[bin].push_back(thisBin[i]);
            }
        }

        return melFilterBank;
    }

} /* namespace audio */
} /* namespace app */
} /* namespace arm */
