/*
 * Audio resampling
 *
 * Copyright (c) 2004-2012 Michael Niedermayer <michaelni@gmx.at>
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "config.h"

#include "libavutil/cpu.h"
#include "libavutil/avassert.h"

#include "libavutil/arm/cpu.h"
#include "libswresample/resample.h"

#define DECLARE_RESAMPLE_COMMON_TEMPLATE(TYPE, DELEM, FELEM, FELEM2, OUT)                         \
                                                                                                  \
void ff_resample_common_apply_filter_x4_##TYPE##_neon(FELEM2 *acc, const DELEM *src,              \
                                                      const FELEM *filter, int length);           \
                                                                                                  \
void ff_resample_common_apply_filter_x8_##TYPE##_neon(FELEM2 *acc, const DELEM *src,              \
                                                      const FELEM *filter, int length);           \
                                                                                                  \
static int ff_resample_common_##TYPE##_neon(ResampleContext *c, void *dest, const void *source,   \
                                            int n, int update_ctx)                                \
{                                                                                                 \
    DELEM *dst = dest;                                                                            \
    const DELEM *src = source;                                                                    \
    int dst_index;                                                                                \
    int index = c->index;                                                                         \
    int frac = c->frac;                                                                           \
    int sample_index = 0;                                                                         \
    int x4_aligned_filter_length = c->filter_length & ~3;                                         \
    int x8_aligned_filter_length = c->filter_length & ~7;                                         \
                                                                                                  \
    while (index >= c->phase_count) {                                                             \
        sample_index++;                                                                           \
        index -= c->phase_count;                                                                  \
    }                                                                                             \
                                                                                                  \
    for (dst_index = 0; dst_index < n; dst_index++) {                                             \
        FELEM *filter = ((FELEM *) c->filter_bank) + c->filter_alloc * index;                     \
                                                                                                  \
        FELEM2 val = 0;                                                                             \
        int i = 0;                                                                                \
        if (x8_aligned_filter_length >= 8) {                                                      \
            ff_resample_common_apply_filter_x8_##TYPE##_neon(&val, &src[sample_index],            \
                                                             filter, x8_aligned_filter_length);   \
            i += x8_aligned_filter_length;                                                        \
                                                                                                  \
        } else if (x4_aligned_filter_length >= 4) {                                               \
            ff_resample_common_apply_filter_x4_##TYPE##_neon(&val, &src[sample_index],            \
                                                             filter, x4_aligned_filter_length);   \
            i += x4_aligned_filter_length;                                                        \
        }                                                                                         \
        for (; i < c->filter_length; i++) {                                                       \
            val += src[sample_index + i] * (FELEM2)filter[i];                                     \
        }                                                                                         \
        OUT(dst[dst_index], val);                                                                 \
                                                                                                  \
        frac  += c->dst_incr_mod;                                                                 \
        index += c->dst_incr_div;                                                                 \
        if (frac >= c->src_incr) {                                                                \
            frac -= c->src_incr;                                                                  \
            index++;                                                                              \
        }                                                                                         \
                                                                                                  \
        while (index >= c->phase_count) {                                                         \
            sample_index++;                                                                       \
            index -= c->phase_count;                                                              \
        }                                                                                         \
    }                                                                                             \
                                                                                                  \
    if (update_ctx) {                                                                             \
        c->frac = frac;                                                                           \
        c->index = index;                                                                         \
    }                                                                                             \
                                                                                                  \
    return sample_index;                                                                          \
}                                                                                                 \

#define OUT(d, v) d = v
DECLARE_RESAMPLE_COMMON_TEMPLATE(float, float, float, float, OUT)
#undef OUT

#define OUT(d, v) (v) = ((v) + (1<<(14)))>>15; (d) = av_clip_int16(v)
DECLARE_RESAMPLE_COMMON_TEMPLATE(s16, int16_t, int16_t, int32_t, OUT)
#undef OUT

av_cold void swri_resample_dsp_arm_init(ResampleContext *c)
{
    int cpu_flags = av_get_cpu_flags();

    if (!have_neon(cpu_flags))
        return;

    switch(c->format) {
    case AV_SAMPLE_FMT_FLTP:
        c->dsp.resample_common = ff_resample_common_float_neon;
        break;
    case AV_SAMPLE_FMT_S16P:
        c->dsp.resample_common = ff_resample_common_s16_neon;
        break;
    }
}
