soxr-code/src/cr-core.c

298 lines
7.3 KiB
C

/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net
* Licence for this file: LGPL v2.1 See LICENCE for details.
*
* Constant-rate resampling engine-specific code. */
#include <math.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include "filter.h"
#if defined SOXR_LIB
#include "internal.h"
#include "cr.h"
#if CORE_TYPE & CORE_DBL
typedef double sample_t;
#if CORE_TYPE & CORE_SIMD_DFT
#define RDFT_CB _soxr_rdft64s_cb
#else
#define RDFT_CB _soxr_rdft64_cb
#endif
#else
typedef float sample_t;
#if CORE_TYPE & CORE_SIMD_DFT
#define RDFT_CB _soxr_rdft32s_cb
#else
#define RDFT_CB _soxr_rdft32_cb
#endif
#endif
#if CORE_TYPE & (CORE_SIMD_POLY|CORE_SIMD_HALF|CORE_SIMD_DFT)
#if CORE_TYPE & CORE_DBL
#include "simd64.h"
#include "simd64-dev.h"
#else
#include "simd32.h"
#include "simd32-dev.h"
#endif
#endif
extern fn_t RDFT_CB[];
#else
#define RDFT_CB 0
#endif
static void cubic_stage_fn(stage_t * p, fifo_t * output_fifo)
{
sample_t const * input = stage_read_p(p);
int num_in = min(stage_occupancy(p), p->input_size);
int i, max_num_out = 1 + (int)(num_in * p->out_in_ratio);
sample_t * output = fifo_reserve(output_fifo, max_num_out);
for (i = 0; p->at.integer < num_in; ++i, p->at.whole += p->step.whole) {
sample_t const * s = input + p->at.integer;
double x = p->at.fraction * (1 / MULT32);
double b = .5*(s[1]+s[-1])-*s, a = (1/6.)*(s[2]-s[1]+s[-1]-*s-4*b);
double c = s[1]-*s-a-b;
output[i] = (sample_t)(p->mult * (((a*x + b)*x + c)*x + *s));
}
assert(max_num_out - i >= 0);
fifo_trim_by(output_fifo, max_num_out - i);
fifo_read(&p->fifo, p->at.integer, NULL);
p->at.integer = 0;
}
#if CORE_TYPE & CORE_DBL
#define SIMD_AVX ((CORE_TYPE & CORE_SIMD_HALF) && defined __AVX__)
#define SIMD_SSE 0
#else
#define SIMD_SSE ((CORE_TYPE & CORE_SIMD_HALF) && (defined __x86_64__ || defined _M_X64 || defined i386 || defined _M_IX86))
#define SIMD_AVX 0
#endif
#define SIMD_NEON ((CORE_TYPE & CORE_SIMD_HALF) && defined __arm__)
#include "half-coefs.h"
#if !(CORE_TYPE & CORE_SIMD_HALF)
#define FUNCTION_H h7
#define CONVOLVE ____ __ _
#include "half-fir.h"
#endif
#define FUNCTION_H h8
#define CONVOLVE ____ ____
#include "half-fir.h"
#define FUNCTION_H h9
#define CONVOLVE ____ ____ _
#include "half-fir.h"
#if CORE_TYPE & CORE_DBL
#define FUNCTION_H h10
#define CONVOLVE ____ ____ __
#include "half-fir.h"
#define FUNCTION_H h11
#define CONVOLVE ____ ____ __ _
#include "half-fir.h"
#define FUNCTION_H h12
#define CONVOLVE ____ ____ ____
#include "half-fir.h"
#define FUNCTION_H h13
#define CONVOLVE ____ ____ ____ _
#include "half-fir.h"
#endif
static half_fir_info_t const half_firs[] = {
#if !(CORE_TYPE & CORE_SIMD_HALF)
{ 7, half_fir_coefs_7 , h7 , 0 , 120.65f},
#endif
{ 8, half_fir_coefs_8 , h8 , 0 , 136.51f},
{ 9, half_fir_coefs_9 , h9 , 0 , 152.32f},
#if CORE_TYPE & CORE_DBL
{10, half_fir_coefs_10, h10, 0 , 168.08f},
{11, half_fir_coefs_11, h11, 0 , 183.79f},
{12, half_fir_coefs_12, h12, 0 , 199.46f},
{13, half_fir_coefs_13, h13, 0 , 215.12f},
#endif
};
#undef SIMD_AVX
#undef SIMD_NEON
#undef SIMD_SSE
#if CORE_TYPE & CORE_DBL
#define SIMD_AVX ((CORE_TYPE & CORE_SIMD_POLY) && defined __AVX__)
#define SIMD_SSE 0
#else
#define SIMD_SSE ((CORE_TYPE & CORE_SIMD_POLY) && (defined __x86_64__ || defined _M_X64 || defined i386 || defined _M_IX86))
#define SIMD_AVX 0
#endif
#define SIMD_NEON ((CORE_TYPE & CORE_SIMD_POLY) && defined __arm__)
#define HI_PREC_CLOCK
#define COEFS (sample_t * __restrict)p->shared->poly_fir_coefs
#define VAR_LENGTH p->n
#define VAR_CONVOLVE(n) while (j < (n)) _
#define VAR_POLY_PHASE_BITS p->phase_bits
#define FUNCTION vpoly0
#define FIR_LENGTH VAR_LENGTH
#define CONVOLVE(n) VAR_CONVOLVE(n)
#include "poly-fir0.h"
#define FUNCTION vpoly1
#define COEF_INTERP 1
#define PHASE_BITS VAR_POLY_PHASE_BITS
#define FIR_LENGTH VAR_LENGTH
#define CONVOLVE(n) VAR_CONVOLVE(n)
#include "poly-fir.h"
#define FUNCTION vpoly2
#define COEF_INTERP 2
#define PHASE_BITS VAR_POLY_PHASE_BITS
#define FIR_LENGTH VAR_LENGTH
#define CONVOLVE(n) VAR_CONVOLVE(n)
#include "poly-fir.h"
#define FUNCTION vpoly3
#define COEF_INTERP 3
#define PHASE_BITS VAR_POLY_PHASE_BITS
#define FIR_LENGTH VAR_LENGTH
#define CONVOLVE(n) VAR_CONVOLVE(n)
#include "poly-fir.h"
#if !(CORE_TYPE & CORE_SIMD_POLY)
#define poly_fir_convolve_U100 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
#define FUNCTION U100_0
#define FIR_LENGTH U100_l
#define CONVOLVE(n) poly_fir_convolve_U100
#include "poly-fir0.h"
#define u100_l 11
#define poly_fir_convolve_u100 _ _ _ _ _ _ _ _ _ _ _
#define FUNCTION u100_0
#define FIR_LENGTH u100_l
#define CONVOLVE(n) poly_fir_convolve_u100
#include "poly-fir0.h"
#define FUNCTION u100_1
#define COEF_INTERP 1
#define PHASE_BITS 8
#define FIR_LENGTH u100_l
#define CONVOLVE(n) poly_fir_convolve_u100
#include "poly-fir.h"
#define FUNCTION u100_2
#define COEF_INTERP 2
#define PHASE_BITS 6
#define FIR_LENGTH u100_l
#define CONVOLVE(n) poly_fir_convolve_u100
#include "poly-fir.h"
#endif
#define u100_1_b 8
#define u100_2_b 6
static poly_fir_t const poly_firs[] = {
{-1, {{0, vpoly0}, { 7.2f, vpoly1}, {5.0f, vpoly2}}},
{-1, {{0, vpoly0}, { 9.4f, vpoly1}, {6.7f, vpoly2}}},
{-1, {{0, vpoly0}, {12.4f, vpoly1}, {7.8f, vpoly2}}},
{-1, {{0, vpoly0}, {13.6f, vpoly1}, {9.3f, vpoly2}}},
{-1, {{0, vpoly0}, {10.5f, vpoly2}, {8.4f, vpoly3}}},
{-1, {{0, vpoly0}, {11.85f,vpoly2}, {9.0f, vpoly3}}},
{-1, {{0, vpoly0}, { 8.0f, vpoly1}, {5.3f, vpoly2}}},
{-1, {{0, vpoly0}, { 8.6f, vpoly1}, {5.7f, vpoly2}}},
{-1, {{0, vpoly0}, {10.6f, vpoly1}, {6.75f,vpoly2}}},
{-1, {{0, vpoly0}, {12.6f, vpoly1}, {8.6f, vpoly2}}},
{-1, {{0, vpoly0}, { 9.6f, vpoly2}, {7.6f, vpoly3}}},
{-1, {{0, vpoly0}, {11.4f, vpoly2}, {8.65f,vpoly3}}},
#if CORE_TYPE & CORE_SIMD_POLY
{10.62f, {{0, vpoly0}, {0, 0}, {0, 0}}},
{-1, {{0, vpoly0}, {u100_1_b, vpoly1}, {u100_2_b, vpoly2}}},
#else
{10.62f, {{U100_l, U100_0}, {0, 0}, {0, 0}}},
{11.28f, {{u100_l, u100_0}, {u100_1_b, u100_1}, {u100_2_b, u100_2}}},
#endif
{-1, {{0, vpoly0}, { 9, vpoly1}, { 6, vpoly2}}},
{-1, {{0, vpoly0}, { 11, vpoly1}, { 7, vpoly2}}},
{-1, {{0, vpoly0}, { 13, vpoly1}, { 8, vpoly2}}},
{-1, {{0, vpoly0}, { 10, vpoly2}, { 8, vpoly3}}},
{-1, {{0, vpoly0}, { 12, vpoly2}, { 9, vpoly3}}},
};
static cr_core_t const cr_core = {
#if CORE_TYPE & CORE_SIMD_POLY
{SIMD_ALIGNED_MALLOC, SIMD_ALIGNED_CALLOC, SIMD_ALIGNED_FREE},
#else
{malloc, calloc, free},
#endif
half_firs, array_length(half_firs),
0, 0,
cubic_stage_fn,
poly_firs, RDFT_CB
};
#if defined SOXR_LIB
#include "soxr.h"
static char const * rate_create(void * channel, void * shared, double io_ratio,
soxr_quality_spec_t * q_spec, soxr_runtime_spec_t * r_spec, double scale)
{
return _soxr_init(channel, shared, io_ratio, q_spec, r_spec, scale,
&cr_core, CORE_TYPE);
}
static char const * id(void) {return CORE_STR;}
fn_t RATE_CB[] = {
(fn_t)_soxr_input,
(fn_t)_soxr_process,
(fn_t)_soxr_output,
(fn_t)_soxr_flush,
(fn_t)_soxr_close,
(fn_t)_soxr_delay,
(fn_t)_soxr_sizes,
(fn_t)rate_create,
(fn_t)0,
(fn_t)id,
};
#endif