/* Copyright 2012 Dietrich Epp */ #pragma once #include #include #include "../lib/param.h" #include "../lib/filter.h" #include "../lib/types.h" #define LFR_PUBLIC #if defined(LFR_IMPLEMENTATION) # define LFR_PRIVATE #endif #if defined(_MSC_VER) # define LFR_INT64 __int64 #endif #if defined(__GNUC__) # undef LFR_PRIVATE # undef LFR_PUBLIC # if defined(LFR_IMPLEMENTATION) # define LFR_PRIVATE __attribute__((visibility("hidden"))) # if defined(__ELF__) # define LFR_PUBLIC __attribute__((visibility("protected"))) # else # define LFR_PUBLIC __attribute__((visibility("default"))) # endif # else # define LFR_PUBLIC # endif # define LFR_INT64 long long #endif #if defined(_M_X64) || defined(__x86_64__) # define LFR_CPU_X64 1 # define LFR_CPU_X86 1 #elif defined(_M_IX86) || defined(__i386__) # define LFR_CPU_X86 1 #elif defined(__ppc64__) # define LFR_CPU_PPC64 1 # define LFR_CPU_PPC 1 #elif defined(__ppc__) # define LFR_CPU_PPC 1 #endif #define LFR_LITTLE_ENDIAN 1234 #define LFR_BIG_ENDIAN 4321 #if defined(__BYTE_ORDER__) # if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ # define LFR_BYTE_ORDER LFR_BIG_ENDIAN # elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ # define LFR_BYTE_ORDER LFR_LITTLE_ENDIAN # endif #elif defined(__BIG_ENDIAN__) # define LFR_BYTE_ORDER LFR_BIG_ENDIAN #elif defined(__LITTLE_ENDIAN__) # define LFR_BYTE_ORDER LFR_LITTLE_ENDIAN #endif #if !defined(LFR_BYTE_ORDER) # if defined(LFR_CPU_X86) # define LFR_BYTE_ORDER LFR_LITTLE_ENDIAN # elif defined(LFR_CPU_PPC) # define LFR_BYTE_ORDER LFR_BIG_ENDIAN # else # error "cannot determine machine byte order" # endif #endif /* ======================================== CPU features ======================================== */ /* CPU features to use or disable. */ enum { #if defined(LFR_CPU_X86) LFR_CPUF_MMX = (1u << 0), LFR_CPUF_SSE = (1u << 1), LFR_CPUF_SSE2 = (1u << 2), LFR_CPUF_SSE3 = (1u << 3), LFR_CPUF_SSSE3 = (1u << 4), LFR_CPUF_SSE4_1 = (1u << 5), LFR_CPUF_SSE4_2 = (1u << 6), #else LFR_CPUF_MMX = 0u, LFR_CPUF_SSE = 0u, LFR_CPUF_SSE2 = 0u, LFR_CPUF_SSE3 = 0u, LFR_CPUF_SSSE3 = 0u, LFR_CPUF_SSE4_1 = 0u, LFR_CPUF_SSE4_2 = 0u, #endif #if defined(LFR_CPU_PPC) LFR_CPUF_ALTIVEC = (1u << 0), #else LFR_CPUF_ALTIVEC = 0u, #endif LFR_CPUF_NONE = 0u, LFR_CPUF_ALL = 0xffffffffu }; /* Information about a CPU flag. */ struct lfr_cpuf { char name[8]; unsigned flag; }; /* Array of names for the CPU features this architecture supports. Names are the lower case version of the flag names above, e.g., LFR_CPUF_MMX becomes "mmx". Terminated by a zeroed entry. */ LFR_PUBLIC extern const struct lfr_cpuf LFR_CPUF[]; /* Set which CPU features are allowed or disallowed. This is primarily used for comparing the performance and correctness of vector implementations and scalar implementations. It can also be used to prohibit features that your CPU supports but which your OS does not. Returns the CPU flags actually enabled, which will be the intersection of the set of allowed flags (the argument) with the set of features that the current CPU actually supports. */ LFR_PUBLIC unsigned lfr_setcpufeatures(unsigned flags); #if LFR_BYTE_ORDER == LFR_BIG_ENDIAN # define LFR_FMT_S16_NATIVE LFR_FMT_S16BE # define LFR_FMT_S16_SWAPPED LFR_FMT_S16LE # define LFR_FMT_F32_NATIVE LFR_FMT_F32BE # define LFR_FMT_F32_SWAPPED LFR_FMT_F32LE #else # define LFR_FMT_S16_NATIVE LFR_FMT_S16LE # define LFR_FMT_S16_SWAPPED LFR_FMT_S16BE # define LFR_FMT_F32_NATIVE LFR_FMT_F32LE # define LFR_FMT_F32_SWAPPED LFR_FMT_F32BE #endif /* Swap the byte order on 16-bit data. The destination can either be the same buffer as the source, or it can be a non-overlapping buffer. Behavior is undefined if the two buffers partially overlap. */ LFR_PUBLIC void lfr_swap16(void *dest, const void *src, size_t count); /* ======================================== Resampling parameters ======================================== */ /* Names for filter quality presets. */ enum { /* Low quality: Currently, quality 0..3 are identical, since further reductions in quality do not increase performance. */ LFR_QUALITY_LOW = 2, /* Medium quality: Transition band of 23%, nominal attenuation of 60 dB. Actual attenuation may be higher. */ LFR_QUALITY_MEDIUM = 5, /* High quality: Transition band of 10%, nominal attenuation of 96 dB. It is not normally reasonable to increase quality beyond this level unless you are competing for the prettiest spectrogram. */ LFR_QUALITY_HIGH = 8, /* Ultra quality: Transition band of 3%, nominal attenuation of 120 dB. Filter coefficients may not fit in L2 cache. Impulse response may be several milliseconds long. */ LFR_QUALITY_ULTRA = 10 }; /* Get the name of a parameter, or return NULL if the paramater does not exist. */ LFR_PUBLIC std::string_view lfr_param_name(lfr_param_t pname); /* Get the index of a parameter by name, or return -1 if the parameter does not exist. */ LFR_PUBLIC int lfr_param_lookup(const std::string_view& pname); /* ======================================== Resampling ======================================== */ /* Get the name of a filter info query, or return NULL if the info query does not exist. */ LFR_PUBLIC std::string_view lfr_info_name(int pname); /* Get the index of a filter info query by name, or return -1 if the info query does not exist. */ LFR_PUBLIC int lfr_info_lookup(const std::string_view& pname); /* Get a function for resampling native 16-bit data with the given number of channels. Returns NULL if no such function is available. This will always return non-NULL for mono and stereo data. */ LFR_PUBLIC lfr_resample_func_t lfr_resample_s16func(int nchan, const struct lfr_filter *filter);