@@ -0,0 +1,41 @@
|
||||
|
||||
#ifndef ALLOCATOR_HPP
|
||||
#define ALLOCATOR_HPP
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "SIMDSupport.hpp"
|
||||
|
||||
namespace impl
|
||||
{
|
||||
typedef void *(*allocate_function)(size_t);
|
||||
typedef void (*free_function)(void *);
|
||||
};
|
||||
|
||||
// Atemplate for wrapping functions as an allocator
|
||||
|
||||
template<impl::allocate_function alloc, impl::free_function dealloc>
|
||||
struct function_allocator
|
||||
{
|
||||
template <typename T>
|
||||
T* allocate(size_t size) { return reinterpret_cast<T*>(alloc(size * sizeof(T))); }
|
||||
|
||||
template <typename T>
|
||||
void deallocate(T *ptr) { dealloc(ptr); }
|
||||
};
|
||||
|
||||
using malloc_allocator = function_allocator<malloc, free>;
|
||||
|
||||
// Aligned allocator
|
||||
|
||||
struct aligned_allocator
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
T* allocate(size_t size) { return allocate_aligned<T>(size); }
|
||||
|
||||
template <typename T>
|
||||
void deallocate(T *ptr) { deallocate_aligned(ptr); }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "HISSTools_FFT.h"
|
||||
#include "HISSTools_FFT_Core.h"
|
||||
|
||||
#ifdef USE_APPLE_FFT
|
||||
#if defined(USE_APPLE_FFT)
|
||||
|
||||
// This file provides bindings to the relevant Apple or HISSTools template routines.
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ template <class T> struct Split
|
||||
|
||||
// Type defintions for Apple / HISSTools FFT
|
||||
|
||||
#ifdef USE_APPLE_FFT
|
||||
#if defined(USE_APPLE_FFT)
|
||||
|
||||
#include <Accelerate/Accelerate.h>
|
||||
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
#ifdef __arm__
|
||||
#if defined(__arm__) || defined(__arm64)
|
||||
#include <arm_neon.h>
|
||||
#include <memory.h>
|
||||
#else
|
||||
#ifndef __APPLE__
|
||||
#if defined(__WIN32__)
|
||||
#include <malloc.h>
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
#include <emmintrin.h>
|
||||
@@ -15,8 +17,8 @@
|
||||
|
||||
// Microsoft Visual Studio doesn't ever define __SSE__ so if necessary we derive it from other defines
|
||||
|
||||
#ifndef __SSE__
|
||||
#if defined _M_X64 || (defined _M_IX86_FP && _M_IX86_FP > 0)
|
||||
#if !defined(__SSE__)
|
||||
#if defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP > 0)
|
||||
#define __SSE__ 1
|
||||
#endif
|
||||
#endif
|
||||
@@ -52,15 +54,15 @@ namespace hisstools_fft_impl{
|
||||
template<> struct SIMDLimits<double> { static const int max_size = 2; };
|
||||
template<> struct SIMDLimits<float> { static const int max_size = 4; };
|
||||
|
||||
#elif defined(__arm__)
|
||||
#elif defined(__arm__) || defined(__arm64__)
|
||||
|
||||
template<> struct SIMDLimits<float> { static const int max_size = 4; };
|
||||
|
||||
#endif
|
||||
|
||||
// Aligned Allocation
|
||||
|
||||
#ifdef __APPLE__
|
||||
// Aligned Allocation
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
||||
template <class T>
|
||||
T *allocate_aligned(size_t size)
|
||||
@@ -68,15 +70,17 @@ namespace hisstools_fft_impl{
|
||||
return static_cast<T *>(malloc(size * sizeof(T)));
|
||||
}
|
||||
|
||||
#elif defined(__linux__)
|
||||
|
||||
template <class T>
|
||||
void deallocate_aligned(T *ptr)
|
||||
T *allocate_aligned(size_t size)
|
||||
{
|
||||
free(ptr);
|
||||
void *mem;
|
||||
posix_memalign(&mem, SIMDLimits<T>::max_size * sizeof(T), size * sizeof(T));
|
||||
return static_cast<T *>(mem);
|
||||
}
|
||||
|
||||
#elif defined(__arm__)
|
||||
|
||||
#include <memory.h>
|
||||
#elif defined(__arm__) || defined(__arm64__)
|
||||
|
||||
template <class T>
|
||||
T *allocate_aligned(size_t size)
|
||||
@@ -84,14 +88,7 @@ namespace hisstools_fft_impl{
|
||||
return static_cast<T *>(aligned_alloc(16, size * sizeof(T)));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void deallocate_aligned(T *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
#else
|
||||
#include <malloc.h>
|
||||
#elif defined(__WIN32__)
|
||||
|
||||
template <class T>
|
||||
T *allocate_aligned(size_t size)
|
||||
@@ -99,16 +96,24 @@ namespace hisstools_fft_impl{
|
||||
return static_cast<T *>(_aligned_malloc(size * sizeof(T), 16));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Aligned deallocation
|
||||
|
||||
#if !defined(__WIN32__)
|
||||
|
||||
template <class T>
|
||||
void deallocate_aligned(T *ptr)
|
||||
{
|
||||
_aligned_free(ptr);
|
||||
}
|
||||
void deallocate_aligned(T *ptr) { free(ptr); }
|
||||
|
||||
#else
|
||||
|
||||
template <class T>
|
||||
void deallocate_aligned(T *ptr) { _aligned_free(ptr); }
|
||||
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
bool isAligned(const T *ptr) { return !(reinterpret_cast<uintptr_t>(ptr) % 16); }
|
||||
bool is_aligned(const T *ptr) { return !(reinterpret_cast<uintptr_t>(ptr) % 16); }
|
||||
|
||||
// Offset for Table
|
||||
|
||||
@@ -305,7 +310,7 @@ namespace hisstools_fft_impl{
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__arm__)
|
||||
#if defined(__arm__) || defined(__arm64__)
|
||||
|
||||
template<>
|
||||
struct SIMDVector<float, 4> : public SIMDVectorBase<float, float32x4_t, 4>
|
||||
@@ -585,7 +590,7 @@ namespace hisstools_fft_impl{
|
||||
|
||||
#endif
|
||||
|
||||
#if defined (__arm__)
|
||||
#if defined(__arm__) || defined(__arm64__)
|
||||
|
||||
// Template Specialisation for an ARM Float Packed (1 SIMD Element)
|
||||
|
||||
@@ -1142,7 +1147,7 @@ namespace hisstools_fft_impl{
|
||||
|
||||
// ******************** Unzip and Zip ******************** //
|
||||
|
||||
#ifdef USE_APPLE_FFT
|
||||
#if defined(USE_APPLE_FFT)
|
||||
|
||||
template<class T>
|
||||
void unzip_complex(const T *input, DSPSplitComplex *output, uintptr_t half_length)
|
||||
@@ -1204,7 +1209,7 @@ namespace hisstools_fft_impl{
|
||||
{
|
||||
const int v_size = SIMDLimits<T>::max_size;
|
||||
|
||||
if (isAligned(input) && isAligned(output->realp) && isAligned(output->imagp))
|
||||
if (is_aligned(input) && is_aligned(output->realp) && is_aligned(output->imagp))
|
||||
{
|
||||
uintptr_t v_length = (half_length / v_size) * v_size;
|
||||
unzip_impl<T, v_size>(input, output->realp, output->imagp, v_length);
|
||||
@@ -1234,7 +1239,7 @@ namespace hisstools_fft_impl{
|
||||
{
|
||||
const int v_size = SIMDLimits<T>::max_size;
|
||||
|
||||
if (isAligned(output) && isAligned(input->realp) && isAligned(input->imagp))
|
||||
if (is_aligned(output) && is_aligned(input->realp) && is_aligned(input->imagp))
|
||||
{
|
||||
uintptr_t v_length = (half_length / v_size) * v_size;
|
||||
zip_impl<T, v_size>(input->realp, input->imagp, output, v_length);
|
||||
@@ -1318,7 +1323,7 @@ namespace hisstools_fft_impl{
|
||||
{
|
||||
if (fft_log2 >= 4)
|
||||
{
|
||||
if (!isAligned(input->realp) || !isAligned(input->imagp))
|
||||
if (!is_aligned(input->realp) || !is_aligned(input->imagp))
|
||||
fft_passes<T, 1>(input, setup, fft_log2);
|
||||
else
|
||||
fft_passes<T, SIMDLimits<T>::max_size>(input, setup, fft_log2);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
#ifndef INTERPOLATION_H
|
||||
#define INTERPOLATION_H
|
||||
#ifndef INTERPOLATION_HPP
|
||||
#define INTERPOLATION_HPP
|
||||
|
||||
// Enumeration of interpolation types
|
||||
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
|
||||
#ifndef KERNELSMOOTHER_HPP
|
||||
#define KERNELSMOOTHER_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
#include "Allocator.hpp"
|
||||
#include "SIMDSupport.hpp"
|
||||
#include "SpectralProcessor.hpp"
|
||||
|
||||
template <typename T, typename Allocator = aligned_allocator, bool auto_resize_fft = false>
|
||||
class kernel_smoother : private spectral_processor<T, Allocator>
|
||||
{
|
||||
using Split = typename FFTTypes<T>::Split;
|
||||
|
||||
using processor = spectral_processor<T, Allocator>;
|
||||
using binary_sizes = typename processor::binary_sizes;
|
||||
using zipped_pointer = typename processor::zipped_pointer;
|
||||
using in_ptr = typename processor::in_ptr;
|
||||
|
||||
template <bool B>
|
||||
using enable_if_t = typename std::enable_if<B>::type;
|
||||
|
||||
public:
|
||||
|
||||
enum SmoothMode { kSmoothZeroPad, kSmoothWrap, kSmoothFold };
|
||||
|
||||
template <typename U = Allocator, typename = enable_if_t<std::is_default_constructible<U>::value>>
|
||||
kernel_smoother()
|
||||
{
|
||||
set_max_fft_size(1 << 18);
|
||||
}
|
||||
|
||||
template <typename U = Allocator, typename = enable_if_t<std::is_copy_constructible<U>::value>>
|
||||
kernel_smoother(const Allocator& allocator) : spectral_processor<T, Allocator>(allocator)
|
||||
{
|
||||
set_max_fft_size(1 << 18);
|
||||
}
|
||||
|
||||
template <typename U = Allocator, typename = enable_if_t<std::is_move_constructible<U>::value>>
|
||||
kernel_smoother(Allocator&& allocator) : spectral_processor<T, Allocator>(allocator)
|
||||
{
|
||||
set_max_fft_size(1 << 18);
|
||||
}
|
||||
|
||||
void set_max_fft_size(uintptr_t size) { processor::set_max_fft_size(size); }
|
||||
|
||||
void smooth(T *out, const T *in, const T *kernel, uintptr_t length, uintptr_t kernel_length, double width_lo, double width_hi, SmoothMode mode)
|
||||
{
|
||||
Allocator& allocator = processor::m_allocator;
|
||||
|
||||
const int N = SIMDLimits<T>::max_size;
|
||||
|
||||
width_lo = std::min(static_cast<double>(length), std::max(1.0, width_lo));
|
||||
width_hi = std::min(static_cast<double>(length), std::max(1.0, width_hi));
|
||||
|
||||
double width_mul = (width_hi - width_lo) / (length - 1);
|
||||
|
||||
auto half_width_calc = [&](uintptr_t a)
|
||||
{
|
||||
return static_cast<uintptr_t>(std::round((width_lo + a * width_mul) * 0.5));
|
||||
};
|
||||
|
||||
uintptr_t filter_size = std::ceil(std::max(width_lo, width_hi) * 0.5);
|
||||
uintptr_t filter_full = filter_size * 2 - 1;
|
||||
uintptr_t max_per_filter = width_mul ? (2.0 / width_mul) + 1.0 : length;
|
||||
uintptr_t data_width = max_per_filter + (filter_size - 1) * 2;
|
||||
|
||||
binary_sizes sizes(filter_full, data_width);
|
||||
|
||||
if (auto_resize_fft && processor::max_fft_size() < sizes.fft())
|
||||
set_max_fft_size(sizes.fft());
|
||||
|
||||
uintptr_t fft_size = processor::max_fft_size() >= sizes.fft() ? sizes.fft() : 0;
|
||||
|
||||
T *ptr = allocator.template allocate<T>(fft_size * 2 + filter_full + length + filter_size * 2);
|
||||
Split io { ptr, ptr + (fft_size >> 1) };
|
||||
Split st { io.realp + fft_size, io.imagp + fft_size };
|
||||
T *filter = ptr + (fft_size << 1) + filter_size - 1;
|
||||
T *temp = filter + filter_size;
|
||||
|
||||
bool non_zero_end = true;
|
||||
|
||||
if (kernel_length)
|
||||
{
|
||||
const T max_value = *std::max_element(kernel, kernel + kernel_length);
|
||||
const T test_value = kernel[kernel_length - 1] / max_value;
|
||||
const T epsilon = std::numeric_limits<T>::epsilon();
|
||||
|
||||
if (test_value < epsilon)
|
||||
non_zero_end = false;
|
||||
}
|
||||
|
||||
// Copy data
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case kSmoothZeroPad:
|
||||
std::fill_n(temp, filter_size, 0.0);
|
||||
std::copy_n(in, length, temp + filter_size);
|
||||
std::fill_n(temp + filter_size + length, filter_size, 0.0);
|
||||
break;
|
||||
|
||||
case kSmoothWrap:
|
||||
std::copy_n(in + length - filter_size, filter_size, temp);
|
||||
std::copy_n(in, length, temp + filter_size);
|
||||
std::copy_n(in, filter_size, temp + filter_size + length);
|
||||
break;
|
||||
|
||||
case kSmoothFold:
|
||||
std::reverse_copy(in + 1, in + 1 + filter_size, temp);
|
||||
std::copy(in, in + length, temp + filter_size);
|
||||
std::reverse_copy(in + length - (filter_size + 1), in + length - 1, temp + filter_size + length);
|
||||
break;
|
||||
}
|
||||
|
||||
const double *data = temp + filter_size;
|
||||
|
||||
for (uintptr_t i = 0, j = 0; i < length; i = j)
|
||||
{
|
||||
uintptr_t half_width = static_cast<uintptr_t>(half_width_calc(i));
|
||||
const T filter_normalise = make_filter(filter, kernel, kernel_length, half_width, non_zero_end);
|
||||
|
||||
for (j = i; (j < length) && half_width == half_width_calc(j); j++);
|
||||
|
||||
//uintptr_t optimal_fft = 1 << processor::calc_fft_size_log2(half_width * 4);
|
||||
uintptr_t n = j - i;
|
||||
uintptr_t k = 0;
|
||||
uintptr_t m = n;//std::min(optimal_fft / 2, n);
|
||||
|
||||
m = use_fft(n, half_width, fft_size) ? m : 0;
|
||||
|
||||
for (; k + (m - 1) < n; k += m)
|
||||
apply_filter_fft(out + i + k, data + i + k, filter, io, st, half_width, m, filter_normalise);
|
||||
|
||||
for (; k + (N - 1) < n; k += N)
|
||||
apply_filter<N>(out + i + k, data + i + k, filter, half_width, filter_normalise);
|
||||
|
||||
for (; k < n; k++)
|
||||
apply_filter<1>(out + i + k, data + i + k, filter, half_width, filter_normalise);
|
||||
}
|
||||
/*
|
||||
for (uintptr_t i = 0; i < length; i++)
|
||||
{
|
||||
// FIX - not safe
|
||||
double width = width_lo + i * width_mul;
|
||||
double width_normalise = 2.0 / width;
|
||||
uintptr_t half_width = width * 0.5;
|
||||
|
||||
T filter_sum = kernel[0];
|
||||
T filter_val = data[i] * filter_sum;
|
||||
|
||||
for (uintptr_t j = 1; j < half_width; j++)
|
||||
{
|
||||
T filter = filter_kernel(kernel, j * (kernel_length - 1) * width_normalise);
|
||||
filter_val += filter * (data[i - j] + data[i + j]);
|
||||
filter_sum += filter + filter;
|
||||
}
|
||||
|
||||
out[i] = filter_val / filter_sum;
|
||||
}*/
|
||||
|
||||
allocator.deallocate(ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
bool use_fft(uintptr_t n, uintptr_t half_width, uintptr_t fft_size)
|
||||
{
|
||||
return fft_size && n > 2 && half_width > 2 && (32 * n > half_width);
|
||||
}
|
||||
|
||||
T filter_kernel(const T *kernel, double position)
|
||||
{
|
||||
uintptr_t index = static_cast<uintptr_t>(position);
|
||||
|
||||
const T lo = kernel[index];
|
||||
const T hi = kernel[index + 1];
|
||||
|
||||
return static_cast<T>(lo + (position - index) * (hi - lo));
|
||||
}
|
||||
|
||||
T make_filter(T *filter, const T *kernel, uintptr_t kernel_length, uintptr_t half_width, bool non_zero_end)
|
||||
{
|
||||
const double width_normalise = 1.0 / std::max(uintptr_t(1), half_width - (non_zero_end ? 1 : 0));
|
||||
T filter_sum = 0.0;
|
||||
|
||||
uintptr_t loop_size = non_zero_end ? half_width - 1 : half_width;
|
||||
|
||||
for (uintptr_t j = 0; j < loop_size; j++)
|
||||
{
|
||||
filter[j] = filter_kernel(kernel, j * (kernel_length - 1) * width_normalise);
|
||||
filter_sum += filter[j];
|
||||
}
|
||||
|
||||
if (non_zero_end)
|
||||
{
|
||||
filter[half_width - 1] = kernel[kernel_length - 1];
|
||||
filter_sum += filter[half_width - 1];
|
||||
}
|
||||
|
||||
return T(1) / (filter_sum * T(2) - filter[0]);
|
||||
}
|
||||
|
||||
template <int N>
|
||||
void apply_filter(T *out, const T *data, const T *filter, uintptr_t half_width, T gain)
|
||||
{
|
||||
using VecType = SIMDType<double, N>;
|
||||
|
||||
VecType filter_val = SIMDType<double, N>(data) * filter[0];
|
||||
|
||||
for (uintptr_t j = 1; j < half_width; j++)
|
||||
filter_val += filter[j] * (VecType(data - j) + VecType(data + j));
|
||||
|
||||
filter_val *= gain;
|
||||
filter_val.store(out);
|
||||
}
|
||||
|
||||
void apply_filter_fft(T *out, const T *data, T *filter, Split& io, Split& temp, uintptr_t half_width, uintptr_t n, T gain)
|
||||
{
|
||||
uintptr_t filter_width = half_width * 2 - 1;
|
||||
uintptr_t data_width = n + (half_width - 1) * 2;
|
||||
binary_sizes sizes(data_width, filter_width);
|
||||
in_ptr data_in(data - (half_width - 1), data_width);
|
||||
in_ptr filter_in(filter - (half_width - 1), filter_width);
|
||||
|
||||
// Mirror the filter
|
||||
|
||||
for (intptr_t i = 1; i < (intptr_t) half_width; i++)
|
||||
filter[-i] = filter[i];
|
||||
|
||||
// Process
|
||||
|
||||
processor::template binary_op<ir_convolve_real>(io, temp, sizes, data_in, filter_in);
|
||||
|
||||
// Copy output with scaling
|
||||
|
||||
zipped_pointer p(io, half_width - 1);
|
||||
|
||||
for (uintptr_t i = 0; i < n; i++)
|
||||
out[i] = *p++ * gain;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,11 +1,11 @@
|
||||
|
||||
#ifndef SIMDSUPPORT
|
||||
#define SIMDSUPPORT
|
||||
#ifndef SIMDSUPPORT_HPP
|
||||
#define SIMDSUPPORT_HPP
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <emmintrin.h>
|
||||
#include <immintrin.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
@@ -23,10 +23,14 @@ template <class T> void deallocate_aligned(T *ptr)
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
// Forward declation
|
||||
|
||||
template <class T> struct SIMDLimits;
|
||||
|
||||
template <class T> T *allocate_aligned(size_t size)
|
||||
{
|
||||
void *mem;
|
||||
posix_memalign(&mem, 16, size * sizeof(T));
|
||||
posix_memalign(&mem, SIMDLimits<T>::byte_width, size * sizeof(T));
|
||||
return static_cast<T *>(mem);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,440 @@
|
||||
|
||||
#ifndef SPECTRALFUNCTIONS_HPP
|
||||
#define SPECTRALFUNCTIONS_HPP
|
||||
|
||||
#include "HISSTools_FFT/HISSTools_FFT.h"
|
||||
#include "SIMDSupport.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <complex>
|
||||
|
||||
namespace impl
|
||||
{
|
||||
template <typename T>
|
||||
struct Infer {};
|
||||
|
||||
template <>
|
||||
struct Infer<FFT_SPLIT_COMPLEX_D>
|
||||
{
|
||||
using Setup = FFT_SETUP_D;
|
||||
using Type = double;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Infer<FFT_SPLIT_COMPLEX_F>
|
||||
{
|
||||
using Setup = FFT_SETUP_F;
|
||||
using Type = float;
|
||||
};
|
||||
|
||||
template<int N, typename Split, typename Op>
|
||||
void simd_operation(Split *out, Split *in1, Split *in2, uintptr_t fft_size, double scale, Op op)
|
||||
{
|
||||
using VecType = SIMDType<typename Infer<Split>::Type, N>;
|
||||
|
||||
const VecType *r_in1 = reinterpret_cast<const VecType *>(in1->realp);
|
||||
const VecType *i_in1 = reinterpret_cast<const VecType *>(in1->imagp);
|
||||
const VecType *r_in2 = reinterpret_cast<const VecType *>(in2->realp);
|
||||
const VecType *i_in2 = reinterpret_cast<const VecType *>(in2->imagp);
|
||||
VecType *r_out = reinterpret_cast<VecType *>(out->realp);
|
||||
VecType *i_out = reinterpret_cast<VecType *>(out->imagp);
|
||||
|
||||
VecType v_scale(scale);
|
||||
|
||||
for (uintptr_t i = 0; i < (fft_size / N); i++)
|
||||
op(r_out[i], i_out[i], r_in1[i], i_in1[i], r_in2[i], i_in2[i], v_scale, i);
|
||||
}
|
||||
|
||||
template<typename Split, typename Op>
|
||||
void complex_operation(Split *out, Split *in1, Split *in2, uintptr_t fft_size, typename Infer<Split>::Type scale, Op op)
|
||||
{
|
||||
const int N = SIMDLimits<typename Infer<Split>::Type>::max_size;
|
||||
constexpr int M = N / 2 ? N / 2: 1;
|
||||
|
||||
if (fft_size == 1 || fft_size < M)
|
||||
simd_operation<1>(out, in1, in2, fft_size, scale, op);
|
||||
else if (fft_size < N)
|
||||
simd_operation<M>(out, in1, in2, fft_size, scale, op);
|
||||
else
|
||||
simd_operation<N>(out, in1, in2, fft_size, scale, op);
|
||||
}
|
||||
|
||||
template<typename Split, typename Op>
|
||||
void real_operation(Split *out, Split *in1, Split *in2, uintptr_t fft_size, typename Infer<Split>::Type scale, Op op)
|
||||
{
|
||||
using T = typename Infer<Split>::Type;
|
||||
|
||||
T temp1(0);
|
||||
T temp2(0);
|
||||
T dc_value;
|
||||
T nq_value;
|
||||
|
||||
// DC and Nyquist
|
||||
|
||||
op(dc_value, temp1, in1->realp[0], temp1, in2->realp[0], temp1, scale, 0);
|
||||
op(nq_value, temp2, in1->imagp[0], temp1, in2->imagp[0], temp1, scale, fft_size >> 1);
|
||||
|
||||
complex_operation(out, in1, in2, fft_size >> 1, scale, op);
|
||||
|
||||
// Set DC and Nyquist bins
|
||||
|
||||
out->realp[0] = dc_value;
|
||||
out->imagp[0] = nq_value;
|
||||
}
|
||||
|
||||
template <typename Split, typename Op>
|
||||
void real_operation(Split *out, const Split *in, uintptr_t fft_size, Op op)
|
||||
{
|
||||
using T = typename Infer<Split>::Type;
|
||||
|
||||
const T *r_in = in->realp;
|
||||
const T *i_in = in->imagp;
|
||||
T *r_out = out->realp;
|
||||
T *i_out = out->imagp;
|
||||
|
||||
T temp1(0);
|
||||
T temp2(0);
|
||||
|
||||
// DC and Nyquist
|
||||
|
||||
op(r_out[0], temp1, r_in[0], temp1, 0);
|
||||
op(i_out[0], temp2, i_in[0], temp2, fft_size >> 1);
|
||||
|
||||
// Other bins
|
||||
|
||||
for (uintptr_t i = 1; i < (fft_size >> 1); i++)
|
||||
op(r_out[i], i_out[i], r_in[i], i_in[i], i);
|
||||
}
|
||||
|
||||
template <typename Split, typename Op>
|
||||
void real_operation(Split *out, uintptr_t fft_size, Op op)
|
||||
{
|
||||
using T = typename Infer<Split>::Type;
|
||||
|
||||
T *r_out = out->realp;
|
||||
T *i_out = out->imagp;
|
||||
|
||||
T temp(0);
|
||||
|
||||
// DC and Nyquist
|
||||
|
||||
op(r_out[0], temp, 0);
|
||||
op(i_out[0], temp, fft_size >> 1);
|
||||
|
||||
// Other bins
|
||||
|
||||
for (uintptr_t i = 1; i < (fft_size >> 1); i++)
|
||||
op(r_out[i], i_out[i], i);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void store(T& r_out, T& i_out, T r_in, T i_in)
|
||||
{
|
||||
r_out = r_in;
|
||||
i_out = i_in;
|
||||
}
|
||||
|
||||
// Functors
|
||||
|
||||
struct copy
|
||||
{
|
||||
template <typename T>
|
||||
void operator()(T& r_out, T& i_out, T r_in, T i_in, uintptr_t i)
|
||||
{
|
||||
store(r_out, i_out, r_in, i_in);
|
||||
}
|
||||
};
|
||||
|
||||
struct amplitude
|
||||
{
|
||||
template <typename T>
|
||||
void operator()(T& r_out, T& i_out, T r_in, T i_in, uintptr_t i)
|
||||
{
|
||||
store(r_out, i_out, std::sqrt(r_in * r_in + i_in * i_in), T(0));
|
||||
}
|
||||
};
|
||||
|
||||
struct amplitude_linear
|
||||
{
|
||||
template <typename T>
|
||||
void operator()(T& r_out, T& i_out, T r_in, T i_in, uintptr_t i)
|
||||
{
|
||||
store(r_out, i_out, std::sqrt(r_in * r_in + i_in * i_in) * (i & 0x1 ? T(-1) : T(1)), T(0));
|
||||
}
|
||||
};
|
||||
|
||||
struct conjugate
|
||||
{
|
||||
template <typename T>
|
||||
void operator()(T& r_out, T& i_out, T r_in, T i_in, uintptr_t i)
|
||||
{
|
||||
store(r_out, i_out, r_in, -i_in);
|
||||
}
|
||||
};
|
||||
|
||||
struct log_power
|
||||
{
|
||||
template <typename T>
|
||||
void operator()(T& r_out, T& i_out, T r_in, T i_in, uintptr_t i)
|
||||
{
|
||||
static T min_power = std::pow(10.0, -300.0 / 10.0);
|
||||
store(r_out, i_out, T(0.5) * log(std::max(r_in * r_in + i_in * i_in, min_power)), T(0));
|
||||
}
|
||||
};
|
||||
|
||||
struct complex_exponential
|
||||
{
|
||||
template <typename T>
|
||||
void operator()(T& r_out, T& i_out, T r_in, T i_in, uintptr_t i)
|
||||
{
|
||||
const std::complex<T> c = std::exp(std::complex<T>(r_in, i_in));
|
||||
store(r_out, i_out, std::real(c), std::imag(c));
|
||||
}
|
||||
};
|
||||
|
||||
struct complex_exponential_conjugate
|
||||
{
|
||||
template <typename T>
|
||||
void operator()(T& r_out, T& i_out, T r_in, T i_in, uintptr_t i)
|
||||
{
|
||||
const std::complex<T> c = std::exp(std::complex<T>(r_in, i_in));
|
||||
store(r_out, i_out, std::real(c), -std::imag(c));
|
||||
}
|
||||
};
|
||||
|
||||
struct phase_interpolate
|
||||
{
|
||||
phase_interpolate(double phase, double fft_size, bool zero_center)
|
||||
{
|
||||
// N.B. - induce a delay of -1 sample for anything over linear to avoid wraparound
|
||||
|
||||
const double delay_factor = (phase <= 0.5) ? 0.0 : 1.0 / fft_size;
|
||||
|
||||
phase = std::max(0.0, std::min(1.0, phase));
|
||||
min_factor = 1.0 - (2.0 * phase);
|
||||
lin_factor = zero_center ? 0.0 : (-2.0 * M_PI * (phase - delay_factor));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void operator()(T& r_out, T& i_out, T r_in, T i_in, uintptr_t i)
|
||||
{
|
||||
const double amp = std::exp(r_in);
|
||||
const double phase = lin_factor * i + min_factor * i_in;
|
||||
store(r_out, i_out, T(amp * std::cos(phase)), T(amp * std::sin(phase)));
|
||||
}
|
||||
|
||||
double min_factor;
|
||||
double lin_factor;
|
||||
};
|
||||
|
||||
struct spike
|
||||
{
|
||||
spike(double position, double fft_size)
|
||||
{
|
||||
spike_constant = ((long double) (2.0 * M_PI)) * -position / fft_size;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void operator()(T& r_out, T& i_out, uintptr_t i)
|
||||
{
|
||||
const long double phase = spike_constant * i;
|
||||
|
||||
store(r_out, i_out, static_cast<T>(std::cos(phase)), static_cast<T>(std::sin(phase)));
|
||||
}
|
||||
|
||||
long double spike_constant;
|
||||
};
|
||||
|
||||
struct delay_calc : private spike
|
||||
{
|
||||
delay_calc(double delay, double fft_size) : spike(delay, fft_size) {}
|
||||
|
||||
template <typename T>
|
||||
void operator()(T& r_out, T& i_out, T r_in, T i_in, uintptr_t i)
|
||||
{
|
||||
using complex = std::complex<T>;
|
||||
|
||||
const long double phase = spike::spike_constant * i;
|
||||
const complex c = complex(r_in, i_in) * complex(std::cos(phase), std::sin(phase));
|
||||
|
||||
store(r_out, i_out, std::real(c), std::imag(c));
|
||||
}
|
||||
};
|
||||
|
||||
struct correlate
|
||||
{
|
||||
template<class T>
|
||||
void operator()(T& r_out, T& i_out, const T& a, const T& b, const T& c, const T& d, const T& scale, uintptr_t i)
|
||||
{
|
||||
r_out = scale * (a * c + b * d);
|
||||
i_out = scale * (b * c - a * d);
|
||||
}
|
||||
};
|
||||
|
||||
struct convolve
|
||||
{
|
||||
template<class T>
|
||||
void operator()(T& r_out, T& i_out, const T& a, const T& b, const T& c, const T& d, const T& scale, uintptr_t i)
|
||||
{
|
||||
r_out = scale * (a * c - b * d);
|
||||
i_out = scale * (a * d + b * c);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Split>
|
||||
void minimum_phase_components(typename Infer<Split>::Setup setup, Split *out, Split *in, uintptr_t fft_size)
|
||||
{
|
||||
using T = typename Infer<Split>::Type;
|
||||
|
||||
T *r_out = out->realp;
|
||||
T *i_out = out->imagp;
|
||||
|
||||
// FIX - what is this value?
|
||||
|
||||
uintptr_t fft_size_log2 = 0;
|
||||
|
||||
for (uintptr_t i = fft_size; i; i >>= 1)
|
||||
fft_size_log2++;
|
||||
|
||||
fft_size_log2--;
|
||||
|
||||
// Take Log of Power Spectrum
|
||||
|
||||
real_operation(out, in, fft_size, log_power());
|
||||
|
||||
// Do Real iFFT
|
||||
|
||||
hisstools_rifft(setup, out, fft_size_log2);
|
||||
|
||||
// Double Causal Values / Zero Non-Casual Values / Scale All Remaining
|
||||
|
||||
// N.B. - doubling is implicit because the real FFT will double the result
|
||||
// - (0.5 multiples needed where no doubling should take place)
|
||||
|
||||
double scale = 1.0 / fft_size;
|
||||
|
||||
r_out[0] *= 0.5 * scale;
|
||||
i_out[0] *= scale;
|
||||
|
||||
for (uintptr_t i = 1; i < (fft_size >> 2); i++)
|
||||
{
|
||||
r_out[i] *= scale;
|
||||
i_out[i] *= scale;
|
||||
}
|
||||
|
||||
r_out[fft_size >> 2] *= 0.5 * scale;
|
||||
i_out[fft_size >> 2] = 0.0;
|
||||
|
||||
for (unsigned long i = (fft_size >> 2) + 1; i < (fft_size >> 1); i++)
|
||||
{
|
||||
r_out[i] = 0.0;
|
||||
i_out[i] = 0.0;
|
||||
}
|
||||
|
||||
// Forward Real FFT (here there is a scaling issue to consider)
|
||||
|
||||
hisstools_rfft(setup, out, fft_size_log2);
|
||||
}
|
||||
}
|
||||
|
||||
// Types
|
||||
|
||||
template <typename T>
|
||||
struct FFTTypes
|
||||
{
|
||||
using Split = void;
|
||||
using Setup = void;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct FFTTypes<float>
|
||||
{
|
||||
using Split = FFT_SPLIT_COMPLEX_F;
|
||||
using Setup = FFT_SETUP_F;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct FFTTypes<double>
|
||||
{
|
||||
using Split = FFT_SPLIT_COMPLEX_D;
|
||||
using Setup = FFT_SETUP_D;
|
||||
};
|
||||
|
||||
// Function calls
|
||||
|
||||
template <typename Split>
|
||||
void ir_copy(Split *out, const Split *in, uintptr_t fft_size)
|
||||
{
|
||||
impl::real_operation(out, in, fft_size, impl::copy());
|
||||
}
|
||||
|
||||
template <typename Split>
|
||||
void ir_spike(Split *out, uintptr_t fft_size, double spike_position)
|
||||
{
|
||||
impl::real_operation(out, fft_size, impl::spike(spike_position, fft_size));
|
||||
}
|
||||
|
||||
template <typename Split>
|
||||
void ir_delay(Split *out, const Split *in, uintptr_t fft_size, double delay)
|
||||
{
|
||||
if (delay != 0.0)
|
||||
impl::real_operation(out, in, fft_size, impl::delay_calc(delay, fft_size));
|
||||
else if (in != out)
|
||||
ir_copy(out, in, fft_size);
|
||||
}
|
||||
|
||||
template <typename Split>
|
||||
void ir_time_reverse(Split *out, const Split *in, uintptr_t fft_size)
|
||||
{
|
||||
impl::real_operation(out, in, fft_size, impl::conjugate());
|
||||
}
|
||||
|
||||
template <typename Setup, typename Split>
|
||||
void ir_phase(Setup setup, Split *out, Split *in, uintptr_t fft_size, double phase, bool zero_center = false)
|
||||
{
|
||||
if (phase == 0.5)
|
||||
{
|
||||
if (zero_center)
|
||||
impl::real_operation(out, in, fft_size, impl::amplitude());
|
||||
else
|
||||
impl::real_operation(out, in, fft_size, impl::amplitude_linear());
|
||||
}
|
||||
else
|
||||
{
|
||||
impl::minimum_phase_components(setup, out, in, fft_size);
|
||||
|
||||
if (phase == 1.0 && zero_center)
|
||||
impl::real_operation(out, out, fft_size, impl::complex_exponential_conjugate());
|
||||
else if (phase == 0.0)
|
||||
impl::real_operation(out, out, fft_size, impl::complex_exponential());
|
||||
else
|
||||
impl::real_operation(out, out, fft_size, impl::phase_interpolate(phase, fft_size, zero_center));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Split, typename T>
|
||||
void ir_convolve_complex(Split *out, Split *in1, Split *in2, uintptr_t fft_size, T scale)
|
||||
{
|
||||
impl::complex_operation(out, in1, in2, fft_size, scale, impl::convolve());
|
||||
}
|
||||
|
||||
template <typename Split, typename T>
|
||||
void ir_convolve_real(Split *out, Split *in1, Split *in2, uintptr_t fft_size, T scale)
|
||||
{
|
||||
impl::real_operation(out, in1, in2, fft_size, scale, impl::convolve());
|
||||
}
|
||||
|
||||
template <typename Split, typename T>
|
||||
void ir_correlate_complex(Split *out, Split *in1, Split *in2, uintptr_t fft_size, T scale)
|
||||
{
|
||||
impl::complex_operation(out, in1, in2, fft_size, scale, impl::correlate());
|
||||
}
|
||||
|
||||
template <typename Split, typename T>
|
||||
void ir_correlate_real(Split *out, Split *in1, Split *in2, uintptr_t fft_size, T scale)
|
||||
{
|
||||
impl::real_operation(out, in1, in2, fft_size, scale, impl::correlate());
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,526 @@
|
||||
|
||||
#ifndef SPECTRALPROCESSOR_H
|
||||
#define SPECTRALPROCESSOR_H
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "Allocator.hpp"
|
||||
#include "HISSTools_FFT/HISSTools_FFT.h"
|
||||
#include "SpectralFunctions.hpp"
|
||||
#include <type_traits>
|
||||
|
||||
template <typename T, typename Allocator = aligned_allocator>
|
||||
class spectral_processor
|
||||
{
|
||||
using Split = typename FFTTypes<T>::Split;
|
||||
using Setup = typename FFTTypes<T>::Setup;
|
||||
|
||||
template <bool B>
|
||||
using enable_if_t = typename std::enable_if<B>::type;
|
||||
|
||||
public:
|
||||
|
||||
enum EdgeMode { kEdgeLinear, kEdgeWrap, kEdgeWrapCentre, kEdgeFold };
|
||||
|
||||
struct in_ptr
|
||||
{
|
||||
in_ptr(const T* ptr, uintptr_t size) : m_ptr(ptr), m_size(size) {}
|
||||
|
||||
const T* m_ptr;
|
||||
const uintptr_t m_size;
|
||||
};
|
||||
|
||||
// Constructor
|
||||
|
||||
template <typename U = Allocator, typename = enable_if_t<std::is_default_constructible<U>::value>>
|
||||
spectral_processor() : m_max_fft_size_log2(0)
|
||||
{
|
||||
set_max_fft_size(32768);
|
||||
}
|
||||
|
||||
template <typename U = Allocator, typename = enable_if_t<std::is_copy_constructible<U>::value>>
|
||||
spectral_processor(const Allocator& allocator) : m_allocator(allocator), m_max_fft_size_log2(0)
|
||||
{
|
||||
set_max_fft_size(32768);
|
||||
}
|
||||
|
||||
template <typename U = Allocator, typename = enable_if_t<std::is_move_constructible<U>::value>>
|
||||
spectral_processor(Allocator&& allocator) : m_allocator(allocator), m_max_fft_size_log2(0)
|
||||
{
|
||||
set_max_fft_size(32768);
|
||||
}
|
||||
|
||||
~spectral_processor()
|
||||
{
|
||||
if (m_max_fft_size_log2)
|
||||
hisstools_destroy_setup(m_fft_setup);
|
||||
}
|
||||
|
||||
void set_max_fft_size(uintptr_t size)
|
||||
{
|
||||
uintptr_t fft_size_log2 = calc_fft_size_log2(size);
|
||||
|
||||
if (fft_size_log2 != m_max_fft_size_log2)
|
||||
{
|
||||
if (m_max_fft_size_log2)
|
||||
hisstools_destroy_setup(m_fft_setup);
|
||||
if (fft_size_log2)
|
||||
hisstools_create_setup(&m_fft_setup, fft_size_log2);
|
||||
m_max_fft_size_log2 = fft_size_log2;
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t max_fft_size() const { return 1 << m_max_fft_size_log2; }
|
||||
|
||||
// Transforms
|
||||
|
||||
void fft(Split& io, uintptr_t fft_size_log2)
|
||||
{
|
||||
hisstools_fft(m_fft_setup, &io, fft_size_log2);
|
||||
}
|
||||
|
||||
void rfft(Split& io, uintptr_t fft_size_log2)
|
||||
{
|
||||
hisstools_rfft(m_fft_setup, &io, fft_size_log2);
|
||||
}
|
||||
|
||||
void rfft(Split& output, const T *input, uintptr_t size, uintptr_t fft_size_log2)
|
||||
{
|
||||
hisstools_rfft(m_fft_setup, input, &output, size, fft_size_log2);
|
||||
}
|
||||
|
||||
void ifft(Split& io, uintptr_t fft_size_log2)
|
||||
{
|
||||
hisstools_ifft(m_fft_setup, &io, fft_size_log2);
|
||||
}
|
||||
|
||||
void rifft(Split& io, uintptr_t fft_size_log2)
|
||||
{
|
||||
hisstools_rifft(m_fft_setup, &io, fft_size_log2);
|
||||
}
|
||||
|
||||
void rifft(T *output, Split& input, uintptr_t fft_size_log2)
|
||||
{
|
||||
hisstools_rifft(m_fft_setup, &input, output, fft_size_log2);
|
||||
}
|
||||
|
||||
// Convolution
|
||||
|
||||
void convolve(T *r_out, T *i_out, in_ptr r_in1, in_ptr i_in1, in_ptr r_in2, in_ptr i_in2, EdgeMode mode)
|
||||
{
|
||||
binary_op<ir_convolve_complex, arrange_convolve<Split>>(r_out, i_out, r_in1, i_in1, r_in2, i_in2, mode);
|
||||
}
|
||||
|
||||
void convolve(T *output, in_ptr in1, in_ptr in2, EdgeMode mode)
|
||||
{
|
||||
binary_op<ir_convolve_real, arrange_convolve<T*>>(output, in1, in2, mode);
|
||||
}
|
||||
|
||||
// Correlation
|
||||
|
||||
void correlate(T *r_out, T *i_out, in_ptr r_in1, in_ptr i_in1, in_ptr r_in2, in_ptr i_in2, EdgeMode mode)
|
||||
{
|
||||
binary_op<ir_correlate_complex, arrange_correlate<Split>>(r_out, i_out, r_in1, i_in1, r_in2, i_in2, mode);
|
||||
}
|
||||
|
||||
void correlate(T *output, in_ptr in1, in_ptr in2, EdgeMode mode)
|
||||
{
|
||||
binary_op<&ir_correlate_real, &arrange_correlate<T*>>(output, in1, in2, mode);
|
||||
}
|
||||
|
||||
// Phase
|
||||
|
||||
void change_phase(T *output, const T *input, uintptr_t size, double phase)
|
||||
{
|
||||
uintptr_t fft_size_log2 = calc_fft_size_log2(size);
|
||||
uintptr_t fft_size = 1 << fft_size_log2;
|
||||
|
||||
temporary_buffers<1> buffer(m_allocator, fft_size >> 1);
|
||||
|
||||
rfft(buffer.m_spectra[0], input, size, fft_size_log2);
|
||||
ir_phase(m_fft_setup, &buffer.m_spectra[0], &buffer.m_spectra[0], fft_size, phase);
|
||||
rifft(output, buffer.m_spectra[0], fft_size_log2);
|
||||
|
||||
scale_vector(output, fft_size, T(0.5) / (T) fft_size);
|
||||
}
|
||||
|
||||
uintptr_t convolved_size(uintptr_t size1, uintptr_t size2, EdgeMode mode) const
|
||||
{
|
||||
return calc_conv_corr_size(size1, size2, mode);
|
||||
}
|
||||
|
||||
uintptr_t correlated_size(uintptr_t size1, uintptr_t size2, EdgeMode mode) const
|
||||
{
|
||||
return calc_conv_corr_size(size1, size2, mode);
|
||||
}
|
||||
|
||||
static uintptr_t calc_fft_size_log2(uintptr_t size)
|
||||
{
|
||||
uintptr_t bit_shift = size;
|
||||
uintptr_t bit_count = 0;
|
||||
|
||||
while (bit_shift)
|
||||
{
|
||||
bit_shift >>= 1U;
|
||||
bit_count++;
|
||||
}
|
||||
|
||||
if (bit_count && size == 1U << (bit_count - 1U))
|
||||
return bit_count - 1U;
|
||||
else
|
||||
return bit_count;
|
||||
}
|
||||
|
||||
// Scale Vector
|
||||
|
||||
void scale_vector(T *io, uintptr_t size, T scale)
|
||||
{
|
||||
if (scale == 1.0)
|
||||
return;
|
||||
|
||||
for (uintptr_t i = 0; i < size; i++)
|
||||
io[i] *= scale;
|
||||
}
|
||||
|
||||
// Scale Spectrum
|
||||
|
||||
void scale_spectrum(Split &io, uintptr_t size, T scale)
|
||||
{
|
||||
if (scale == 1.0)
|
||||
return;
|
||||
|
||||
for (uintptr_t i = 0; i < size; i++)
|
||||
{
|
||||
io.realp[i] *= scale;
|
||||
io.imagp[i] *= scale;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// Temporary Memory
|
||||
|
||||
template <int N>
|
||||
struct temporary_buffers
|
||||
{
|
||||
temporary_buffers(Allocator& allocator, uintptr_t size) : m_allocator(allocator)
|
||||
{
|
||||
T* ptr = m_allocator.template allocate<T>(size * 2 * N * sizeof(T));
|
||||
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
m_spectra[i].realp = ptr + (i * 2 * size);
|
||||
m_spectra[i].imagp = ptr + ((i * 2 + 1) * size);
|
||||
}
|
||||
}
|
||||
|
||||
temporary_buffers(const temporary_buffers&) = delete;
|
||||
temporary_buffers & operator=(const temporary_buffers&) = delete;
|
||||
|
||||
~temporary_buffers() { m_allocator.deallocate(m_spectra[0].realp); }
|
||||
|
||||
operator bool() { return m_spectra[0].realp; }
|
||||
|
||||
Allocator &m_allocator;
|
||||
Split m_spectra[N];
|
||||
};
|
||||
|
||||
struct zipped_pointer
|
||||
{
|
||||
zipped_pointer(const Split spectrum, uintptr_t offset)
|
||||
: p1(spectrum.realp + (offset >> 1)), p2(spectrum.imagp + (offset >> 1))
|
||||
{
|
||||
if (offset & 1U)
|
||||
(*this)++;
|
||||
}
|
||||
|
||||
const T *operator ++()
|
||||
{
|
||||
std::swap(++p1, p2);
|
||||
return p1;
|
||||
}
|
||||
|
||||
const T *operator ++(int)
|
||||
{
|
||||
std::swap(p1, p2);
|
||||
return p2++;
|
||||
}
|
||||
|
||||
const T *operator --()
|
||||
{
|
||||
std::swap(p1, --p2);
|
||||
return p1;
|
||||
}
|
||||
|
||||
const T *operator --(int)
|
||||
{
|
||||
std::swap(p1, --p2);
|
||||
return p2;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
const T *p1, *p2;
|
||||
};
|
||||
|
||||
struct binary_sizes
|
||||
{
|
||||
binary_sizes(uintptr_t size1, uintptr_t size2)
|
||||
: m_size1(size1), m_size2(size2), m_fft_size_log2(calc_fft_size_log2(linear())) {}
|
||||
|
||||
uintptr_t linear() const { return m_size1 + m_size2 - 1; }
|
||||
uintptr_t min() const { return std::min(m_size1, m_size2); }
|
||||
uintptr_t max() const { return std::max(m_size1, m_size2); }
|
||||
uintptr_t min_m1() const { return min() - 1; }
|
||||
uintptr_t fft() const { return 1 << m_fft_size_log2; }
|
||||
uintptr_t fft_log2() const { return m_fft_size_log2; }
|
||||
|
||||
private:
|
||||
|
||||
uintptr_t m_size1, m_size2, m_fft_size_log2;
|
||||
};
|
||||
|
||||
// Memory manipulation (complex)
|
||||
|
||||
static void copy_zero(T* output, in_ptr in, uintptr_t size)
|
||||
{
|
||||
std::copy_n(in.m_ptr, in.m_size, output);
|
||||
std::fill_n(output + in.m_size, size - in.m_size, 0.0);
|
||||
}
|
||||
|
||||
static void copy(Split& output, const Split& spectrum, uintptr_t oOffset, uintptr_t offset, uintptr_t size)
|
||||
{
|
||||
std::copy_n(spectrum.realp + offset, size, output.realp + oOffset);
|
||||
std::copy_n(spectrum.imagp + offset, size, output.imagp + oOffset);
|
||||
}
|
||||
|
||||
static void wrap(Split& output, const Split& spectrum, uintptr_t oOffset, uintptr_t offset, uintptr_t size)
|
||||
{
|
||||
for (uintptr_t i = 0; i < size; i++)
|
||||
{
|
||||
output.realp[i + oOffset] += spectrum.realp[i + offset];
|
||||
output.imagp[i + oOffset] += spectrum.imagp[i + offset];
|
||||
}
|
||||
}
|
||||
|
||||
static void fold(Split& output, const Split& spectrum, uintptr_t oOffset, uintptr_t offset, uintptr_t size)
|
||||
{
|
||||
for (uintptr_t i = 0; i < size; i++)
|
||||
{
|
||||
output.realp[i + oOffset] += spectrum.realp[offset - (i + 1)];
|
||||
output.imagp[i + oOffset] += spectrum.imagp[offset - (i + 1)];
|
||||
}
|
||||
}
|
||||
|
||||
// Memory manipulation (real)
|
||||
|
||||
static void copy(T *output, const Split& spectrum, uintptr_t oOffset, uintptr_t offset, uintptr_t size)
|
||||
{
|
||||
zipped_pointer p(spectrum, offset);
|
||||
|
||||
for (uintptr_t i = 0; i < size; i++)
|
||||
output[oOffset + i] = *p++;
|
||||
}
|
||||
|
||||
static void wrap(T *output, const Split& spectrum, uintptr_t oOffset, uintptr_t offset, uintptr_t size)
|
||||
{
|
||||
zipped_pointer p(spectrum, offset);
|
||||
|
||||
for (uintptr_t i = 0; i < size; i++)
|
||||
output[oOffset + i] += *p++;
|
||||
}
|
||||
|
||||
static void fold(T *output, const Split& spectrum, uintptr_t oOffset, uintptr_t offset, uintptr_t size)
|
||||
{
|
||||
zipped_pointer p(spectrum, offset);
|
||||
|
||||
for (uintptr_t i = 0; i < size; i++)
|
||||
output[oOffset + i] += *--p;
|
||||
}
|
||||
|
||||
// Arranges for convolution and correlation
|
||||
|
||||
template <class U>
|
||||
static void arrange_convolve(U output, Split spectrum, binary_sizes& sizes, EdgeMode mode)
|
||||
{
|
||||
uintptr_t folded = sizes.min() / 2;
|
||||
uintptr_t wrapped1 = sizes.min_m1() / 2;
|
||||
uintptr_t wrapped2 = sizes.min_m1() - wrapped1;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case kEdgeLinear:
|
||||
copy(output, spectrum, 0, 0, sizes.linear());
|
||||
break;
|
||||
|
||||
case kEdgeWrap:
|
||||
copy(output, spectrum, 0, 0, sizes.max());
|
||||
wrap(output, spectrum, 0, sizes.max(), sizes.min_m1());
|
||||
break;
|
||||
|
||||
case kEdgeWrapCentre:
|
||||
copy(output, spectrum, 0, wrapped1, sizes.max());
|
||||
wrap(output, spectrum, 0, sizes.linear() - wrapped2, wrapped2);
|
||||
wrap(output, spectrum, sizes.max() - wrapped1, 0, wrapped1);
|
||||
break;
|
||||
|
||||
case kEdgeFold:
|
||||
copy(output, spectrum, 0, sizes.min_m1() / 2, sizes.max());
|
||||
fold(output, spectrum, 0, folded, folded);
|
||||
fold(output, spectrum, sizes.max() - folded, sizes.linear(), folded);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <class U>
|
||||
static void arrange_correlate(U output, Split spectrum, binary_sizes& sizes, EdgeMode mode)
|
||||
{
|
||||
uintptr_t offset = sizes.min() / 2;
|
||||
uintptr_t wrapped = sizes.min_m1() - offset;
|
||||
uintptr_t fft_minus_min_m1 = sizes.fft() - sizes.min_m1();
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case kEdgeLinear:
|
||||
copy(output, spectrum, 0, 0, sizes.max());
|
||||
copy(output, spectrum, sizes.max(), fft_minus_min_m1, sizes.min_m1());
|
||||
break;
|
||||
|
||||
case kEdgeWrap:
|
||||
copy(output, spectrum, 0, 0, sizes.max());
|
||||
wrap(output, spectrum, sizes.max() - sizes.min_m1(), fft_minus_min_m1, sizes.min_m1());
|
||||
break;
|
||||
|
||||
case kEdgeWrapCentre:
|
||||
copy(output, spectrum, 0, sizes.fft() - offset, offset);
|
||||
copy(output, spectrum, offset, 0, sizes.max() - offset);
|
||||
wrap(output, spectrum, 0, sizes.max() - offset, offset);
|
||||
wrap(output, spectrum, sizes.max() - wrapped, fft_minus_min_m1, wrapped);
|
||||
break;
|
||||
|
||||
case kEdgeFold:
|
||||
copy(output, spectrum, 0, sizes.fft() - offset, offset);
|
||||
copy(output, spectrum, offset, 0, sizes.max() - offset);
|
||||
fold(output, spectrum, 0, sizes.fft() + 1 - offset, offset);
|
||||
fold(output, spectrum, sizes.max() - offset, sizes.max(), offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Binary Operations
|
||||
|
||||
typedef void (*SpectralOp)(Split *, Split *, Split *, uintptr_t, T);
|
||||
typedef void (*ComplexArrange)(Split, Split, binary_sizes&, EdgeMode);
|
||||
typedef void (*RealArrange)(T *, Split, binary_sizes&, EdgeMode);
|
||||
|
||||
uintptr_t calc_conv_corr_size(uintptr_t size1, uintptr_t size2, EdgeMode mode) const
|
||||
{
|
||||
binary_sizes sizes(size1, size2);
|
||||
|
||||
if ((sizes.fft() > max_fft_size()) || !size1 || !size2)
|
||||
return 0;
|
||||
|
||||
uintptr_t size = mode != kEdgeLinear ? sizes.max() : sizes.linear();
|
||||
|
||||
if (mode == kEdgeFold && !(sizes.min() & 1U))
|
||||
return size + 1;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
template<SpectralOp Op>
|
||||
void binary_op(Split& io, Split& temp, binary_sizes& sizes, in_ptr r_in1, in_ptr i_in1, in_ptr r_in2, in_ptr i_in2)
|
||||
{
|
||||
copy_zero(io.realp, r_in1, sizes.fft());
|
||||
copy_zero(io.imagp, i_in1, sizes.fft());
|
||||
copy_zero(temp.realp, r_in2, sizes.fft());
|
||||
copy_zero(temp.imagp, i_in2, sizes.fft());
|
||||
|
||||
fft(io, sizes.fft_log2());
|
||||
fft(temp, sizes.fft_log2());
|
||||
|
||||
Op(&io, &io, &temp, sizes.fft(), 1.0 / (T) sizes.fft());
|
||||
|
||||
ifft(io, sizes.fft_log2());
|
||||
}
|
||||
|
||||
template<SpectralOp Op, ComplexArrange arrange>
|
||||
void binary_op(T *r_out, T *i_out, in_ptr r_in1, in_ptr i_in1, in_ptr r_in2, in_ptr i_in2, EdgeMode mode)
|
||||
{
|
||||
uintptr_t size1 = std::max(r_in1.m_size, i_in1.m_size);
|
||||
uintptr_t size2 = std::max(r_in2.m_size, i_in2.m_size);
|
||||
|
||||
if (!calc_conv_corr_size(size1, size2, mode))
|
||||
return;
|
||||
|
||||
// Special case for single sample inputs
|
||||
|
||||
if (size1 == 1 && size2 == 1)
|
||||
{
|
||||
r_out[0] = r_in1.m_ptr[0] * r_in2.m_ptr[0] + i_in1.m_ptr[0] * i_in2.m_ptr[0];
|
||||
i_out[0] = r_in1.m_ptr[0] * i_in2.m_ptr[0] - i_in1.m_ptr[0] * i_in1.m_ptr[0];
|
||||
return;
|
||||
}
|
||||
|
||||
// Assign temporary memory
|
||||
|
||||
binary_sizes sizes(size1, size2);
|
||||
temporary_buffers<2> buffers(m_allocator, sizes.fft());
|
||||
Split output {r_out, i_out};
|
||||
|
||||
// Process
|
||||
|
||||
if (buffers)
|
||||
{
|
||||
binary_op<Op>(buffers.m_spectra[0], buffers.m_spectra[1], sizes, r_in1, i_in1, r_in2, i_in2);
|
||||
arrange(output, buffers.m_spectra[0], sizes, mode);
|
||||
}
|
||||
}
|
||||
|
||||
template<SpectralOp Op>
|
||||
void binary_op(Split& io, Split& temp, binary_sizes& sizes, in_ptr in1, in_ptr in2)
|
||||
{
|
||||
rfft(io, in1.m_ptr, in1.m_size, sizes.fft_log2());
|
||||
rfft(temp, in2.m_ptr, in2.m_size, sizes.fft_log2());
|
||||
|
||||
Op(&io, &io, &temp, sizes.fft(), 0.25 / (T) sizes.fft());
|
||||
|
||||
rifft(io, sizes.fft_log2());
|
||||
}
|
||||
|
||||
template<SpectralOp Op, RealArrange arrange>
|
||||
void binary_op(T *output, in_ptr in1, in_ptr in2, EdgeMode mode)
|
||||
{
|
||||
if (!calc_conv_corr_size(in1.m_size, in2.m_size, mode))
|
||||
return;
|
||||
|
||||
// Special case for single sample inputs
|
||||
|
||||
if (in1.m_size == 1 && in2.m_size == 1)
|
||||
{
|
||||
output[0] = in1.m_ptr[0] * in2.m_ptr[0];
|
||||
return;
|
||||
}
|
||||
|
||||
// Assign temporary memory
|
||||
|
||||
binary_sizes sizes(in1.m_size, in2.m_size);
|
||||
temporary_buffers<2> buffers(m_allocator, sizes.fft() >> 1);
|
||||
|
||||
// Process
|
||||
|
||||
if (buffers)
|
||||
{
|
||||
binary_op<Op>(buffers.m_spectra[0], buffers.m_spectra[1], sizes, in1, in2);
|
||||
arrange(output, buffers.m_spectra[0], sizes, mode);
|
||||
}
|
||||
}
|
||||
|
||||
// Data
|
||||
|
||||
Allocator m_allocator;
|
||||
Setup m_fft_setup;
|
||||
uintptr_t m_max_fft_size_log2;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
#ifndef STATISTICS_H
|
||||
#define STATISTICS_H
|
||||
#ifndef STATISTICS_HPP
|
||||
#define STATISTICS_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
#ifndef TABLEREADER_H
|
||||
#define TABLEREADER_H
|
||||
#ifndef TABLEREADER_HPP
|
||||
#define TABLEREADER_HPP
|
||||
|
||||
#include "SIMDSupport.hpp"
|
||||
#include "Interpolation.hpp"
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#ifndef WINDOWFUNCTIONS_HPP
|
||||
#define WINDOWFUNCTIONS_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#define WINDOW_PI 3.14159265358979323846
|
||||
@@ -284,3 +287,5 @@ public:
|
||||
WindowFunctions<T, uint16_t>::add(kWindowKaiser, window_flat_top);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -27,7 +27,7 @@ class FrameLib_DSP : public FrameLib_Block, public FrameLib_Queueable<FrameLib_D
|
||||
using Queue = FrameLib_Queueable<FrameLib_Block>::Queue;
|
||||
using LocalQueue = FrameLib_Queueable<FrameLib_DSP>::Queue;
|
||||
using Serial = FrameLib_Parameters::Serial;
|
||||
|
||||
|
||||
friend class FrameLib_ProcessingQueue;
|
||||
|
||||
protected:
|
||||
@@ -96,6 +96,7 @@ private:
|
||||
@brief a struct that represents an output frame.
|
||||
|
||||
*/
|
||||
|
||||
struct Output
|
||||
{
|
||||
Output() : mMemory(nullptr), mType(kFrameNormal), mCurrentType(kFrameNormal), mRequestedType(kFrameNormal), mCurrentSize(0), mRequestedSize(0), mPointerOffset(0) {}
|
||||
@@ -113,6 +114,8 @@ private:
|
||||
|
||||
public:
|
||||
|
||||
using Allocator = FrameLib_Block::Allocator;
|
||||
|
||||
// Constructor / Destructor
|
||||
|
||||
FrameLib_DSP(ObjectType type, FrameLib_Context context, FrameLib_Proxy *proxy, FrameLib_Parameters::Info *info, unsigned long nIns, unsigned long nOuts, unsigned long nAudioChans = 0);
|
||||
|
||||
@@ -379,7 +379,6 @@ public:
|
||||
FrameLib_LocalAllocator(const FrameLib_LocalAllocator&) = delete;
|
||||
FrameLib_LocalAllocator& operator=(const FrameLib_LocalAllocator&) = delete;
|
||||
|
||||
|
||||
// Allocate / Deallocate Memory
|
||||
|
||||
void *alloc(size_t size);
|
||||
|
||||
@@ -165,6 +165,25 @@ public:
|
||||
using Queue = typename FrameLib_Queueable<T>::Queue;
|
||||
using Connection = FrameLib_Connection<T, unsigned long>;
|
||||
|
||||
// An allocator that you can pass to other objects/code whilst this object exists
|
||||
|
||||
class Allocator
|
||||
{
|
||||
public:
|
||||
|
||||
Allocator(FrameLib_Object& object) : mObject(object) {}
|
||||
|
||||
template <class U>
|
||||
U *allocate(size_t N) { return mObject.alloc<U>(N); }
|
||||
|
||||
template <class U>
|
||||
void deallocate(U *& ptr) { mObject.dealloc(ptr); }
|
||||
|
||||
private:
|
||||
|
||||
FrameLib_Object &mObject;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
// A connector is a thing with one input and many outputs
|
||||
|
||||
@@ -19,7 +19,7 @@ void FrameLib_ProcessingQueue::add(FrameLib_DSP *object)
|
||||
// Get time
|
||||
|
||||
mClock.start();
|
||||
unsigned long count = 0;
|
||||
int count = 0;
|
||||
|
||||
while (mTop)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
#include "FrameLib_FIRPhase.h"
|
||||
#include "FrameLib_MaxClass.h"
|
||||
|
||||
extern "C" int C74_EXPORT main(void)
|
||||
{
|
||||
FrameLib_MaxClass_Expand<FrameLib_FIRPhase>::makeClass(CLASS_BOX, "fl.firphase~");
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
#include "FrameLib_KernelSmooth.h"
|
||||
#include "FrameLib_MaxClass.h"
|
||||
|
||||
extern "C" int C74_EXPORT main(void)
|
||||
{
|
||||
FrameLib_MaxClass_Expand<FrameLib_KernelSmooth>::makeClass(CLASS_BOX, "fl.kernelsmooth~");
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
|
||||
#ifndef FRAMELIB_SPECTRAL_FUNCTIONS_H
|
||||
#define FRAMELIB_SPECTRAL_FUNCTIONS_H
|
||||
|
||||
static unsigned long ilog2(unsigned long value)
|
||||
{
|
||||
unsigned long bitShift = value;
|
||||
unsigned long bitCount = 0;
|
||||
|
||||
while (bitShift)
|
||||
{
|
||||
bitShift >>= 1U;
|
||||
bitCount++;
|
||||
}
|
||||
|
||||
if (bitCount && value == 1U << (bitCount - 1U))
|
||||
return bitCount - 1U;
|
||||
else
|
||||
return bitCount;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -60,7 +60,7 @@ FrameLib_Map::ParameterInfo FrameLib_Map::sParamInfo;
|
||||
FrameLib_Map::ParameterInfo::ParameterInfo()
|
||||
{
|
||||
add("Sets the type of output scaling: linear / log / exp - scaling as specified. "
|
||||
"pow - scale the input range to [0-1], apply the specifiedexponent and then scale to the output range. "
|
||||
"pow - scale the input range to [0-1], apply the specified exponent and then scale to the output range. "
|
||||
"db / invdb - output / input respectively are set in dB but scaled as gain values. "
|
||||
"transpose / invtranspose - output / input respectively are set in semitones but scaled as ratios for transposition.");
|
||||
add("Sets the low input value.");
|
||||
|
||||
@@ -1,526 +0,0 @@
|
||||
|
||||
#ifndef FRAMELIB_CONVOLUTION_TOOLS_H
|
||||
#define FRAMELIB_CONVOLUTION_TOOLS_H
|
||||
|
||||
#include <algorithm>
|
||||
#include "../../FrameLib_Dependencies/SIMDSupport.hpp"
|
||||
#include "../../FrameLib_Dependencies/HISSTools_FFT/HISSTools_FFT.h"
|
||||
#include "FrameLib_Spectral_Functions.h"
|
||||
|
||||
enum EdgeMode { kEdgeLinear, kEdgeWrap, kEdgeWrapCentre, kEdgeFold };
|
||||
|
||||
class Spectral
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
// Constructor
|
||||
|
||||
Spectral(FrameLib_Context context) : mAllocator(context)
|
||||
{
|
||||
unsigned long maxLength = 32768;
|
||||
unsigned long maxFFTSizeLog2 = ilog2(maxLength);
|
||||
hisstools_create_setup(&mFFTSetup, maxFFTSizeLog2);
|
||||
mMaxFFTSize = 1 << maxFFTSizeLog2;
|
||||
}
|
||||
|
||||
~Spectral()
|
||||
{
|
||||
hisstools_destroy_setup(mFFTSetup);
|
||||
}
|
||||
|
||||
void setMaxFFTSize(unsigned long maxLength)
|
||||
{
|
||||
if (maxLength != mMaxFFTSize)
|
||||
{
|
||||
hisstools_destroy_setup(mFFTSetup);
|
||||
unsigned long maxFFTSizeLog2 = ilog2(maxLength);
|
||||
hisstools_create_setup(&mFFTSetup, maxFFTSizeLog2);
|
||||
mMaxFFTSize = 1 << maxFFTSizeLog2;
|
||||
}
|
||||
}
|
||||
|
||||
// Scale Vector
|
||||
|
||||
void scaleVector(double *io, unsigned long dataLength, double scale)
|
||||
{
|
||||
if (scale == 1.0)
|
||||
return;
|
||||
|
||||
for (unsigned long i = 0; i < dataLength; i++)
|
||||
io[i] *= scale;
|
||||
}
|
||||
|
||||
// Scale Spectrum
|
||||
|
||||
void scaleSpectrum(FFT_SPLIT_COMPLEX_D &io, unsigned long dataLength, double scale)
|
||||
{
|
||||
if (scale == 1.0)
|
||||
return;
|
||||
|
||||
for (unsigned long i = 0; i < dataLength; i++)
|
||||
{
|
||||
io.realp[i] *= scale;
|
||||
io.imagp[i] *= scale;
|
||||
}
|
||||
}
|
||||
|
||||
// Complex Forward Transform
|
||||
|
||||
void transformForward(FFT_SPLIT_COMPLEX_D &io, unsigned long FFTSizelog2)
|
||||
{
|
||||
hisstools_fft(mFFTSetup, &io, FFTSizelog2);
|
||||
}
|
||||
|
||||
// Real Forward Transform (in-place)
|
||||
|
||||
void transformForwardReal(FFT_SPLIT_COMPLEX_D &io, unsigned long FFTSizelog2)
|
||||
{
|
||||
hisstools_rfft(mFFTSetup, &io, FFTSizelog2);
|
||||
}
|
||||
|
||||
// Real Forward Tansform (with unzipping)
|
||||
|
||||
void transformForwardReal(FFT_SPLIT_COMPLEX_D &output, const double *input, unsigned long size, unsigned long FFTSizelog2)
|
||||
{
|
||||
hisstools_rfft(mFFTSetup, input, &output, size, FFTSizelog2);
|
||||
}
|
||||
|
||||
// Complex Inverse Transform
|
||||
|
||||
void transformInverse(FFT_SPLIT_COMPLEX_D &io, unsigned long FFTSizelog2)
|
||||
{
|
||||
hisstools_ifft(mFFTSetup, &io, FFTSizelog2);
|
||||
}
|
||||
|
||||
// Real Inverse Transform (in-place)
|
||||
|
||||
void transformInverseReal(FFT_SPLIT_COMPLEX_D &io, unsigned long FFTSizelog2)
|
||||
{
|
||||
hisstools_rifft(mFFTSetup, &io, FFTSizelog2);
|
||||
}
|
||||
|
||||
// Real Inverse Transform (with zipping)
|
||||
|
||||
void transformInverseReal(double *output, FFT_SPLIT_COMPLEX_D &input, unsigned long FFTSizelog2)
|
||||
{
|
||||
hisstools_rifft(mFFTSetup, &input, output, FFTSizelog2);
|
||||
}
|
||||
|
||||
struct CorrelateOp
|
||||
{
|
||||
template<class T>
|
||||
void operator()(T &outR, T &outI, const T a, const T b, const T c, const T d, T scale)
|
||||
{
|
||||
outR = scale * (a * c + b * d);
|
||||
outI = scale * (b * c - a * d);
|
||||
}
|
||||
};
|
||||
|
||||
struct ConvolveOp
|
||||
{
|
||||
template<class T>
|
||||
void operator()(T &outR, T &outI, const T a, const T b, const T c, const T d, T scale)
|
||||
{
|
||||
outR = scale * (a * c - b * d);
|
||||
outI = scale * (a * d + b * c);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Op>
|
||||
void binaryOp(FFT_SPLIT_COMPLEX_D &io1, FFT_SPLIT_COMPLEX_D &in2, unsigned long dataLength, double scale, Op op)
|
||||
{
|
||||
const int vec_size = SIMDLimits<double>::max_size;
|
||||
|
||||
if (dataLength == 1 || dataLength < (vec_size / 2))
|
||||
{
|
||||
op(io1.realp[0], io1.imagp[0], io1.realp[0], io1.imagp[0], in2.realp[0], in2.imagp[0], scale);
|
||||
}
|
||||
else if (dataLength < vec_size)
|
||||
{
|
||||
constexpr int max_vec_size = SIMDLimits<double>::max_size / 2;
|
||||
constexpr int current_vec_size = max_vec_size ? max_vec_size : 1;
|
||||
|
||||
SIMDType<double, current_vec_size> *real1 = reinterpret_cast<SIMDType<double, current_vec_size> *>(io1.realp);
|
||||
SIMDType<double, current_vec_size> *imag1 = reinterpret_cast<SIMDType<double, current_vec_size> *>(io1.imagp);
|
||||
SIMDType<double, current_vec_size> *real2 = reinterpret_cast<SIMDType<double, current_vec_size> *>(in2.realp);
|
||||
SIMDType<double, current_vec_size> *imag2 = reinterpret_cast<SIMDType<double, current_vec_size> *>(in2.imagp);
|
||||
|
||||
SIMDType<double, current_vec_size> scaleVec(scale);
|
||||
|
||||
for (unsigned long i = 0; i < (dataLength / current_vec_size); i++)
|
||||
op(real1[i], imag1[i], real1[i], imag1[i], real2[i], imag2[i], scaleVec);
|
||||
}
|
||||
else
|
||||
{
|
||||
SIMDType<double, vec_size> *real1 = reinterpret_cast<SIMDType<double, vec_size> *>(io1.realp);
|
||||
SIMDType<double, vec_size> *imag1 = reinterpret_cast<SIMDType<double, vec_size> *>(io1.imagp);
|
||||
SIMDType<double, vec_size> *real2 = reinterpret_cast<SIMDType<double, vec_size> *>(in2.realp);
|
||||
SIMDType<double, vec_size> *imag2 = reinterpret_cast<SIMDType<double, vec_size> *>(in2.imagp);
|
||||
|
||||
SIMDType<double, vec_size> scaleVec(scale);
|
||||
|
||||
for (unsigned long i = 0; i < (dataLength / vec_size); i++)
|
||||
op(real1[i], imag1[i], real1[i], imag1[i], real2[i], imag2[i], scaleVec);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Op>
|
||||
void binaryOpReal(FFT_SPLIT_COMPLEX_D &spectrum1, FFT_SPLIT_COMPLEX_D &spectrum2, unsigned long dataLength, double scale, Op op)
|
||||
{
|
||||
// Store DC and Nyquist Results
|
||||
|
||||
const double DC = spectrum1.realp[0] * spectrum2.realp[0] * scale;
|
||||
const double Nyquist = spectrum1.imagp[0] * spectrum2.imagp[0] * scale;
|
||||
|
||||
binaryOp(spectrum1, spectrum2, dataLength, scale, op);
|
||||
|
||||
// Set DC and Nyquist bins
|
||||
|
||||
spectrum1.realp[0] = DC;
|
||||
spectrum1.imagp[0] = Nyquist;
|
||||
}
|
||||
|
||||
template<typename Op>
|
||||
void binarySpectralOperation(FFT_SPLIT_COMPLEX_D &io1, FFT_SPLIT_COMPLEX_D &in2, unsigned long FFTSizelog2, Op op)
|
||||
{
|
||||
unsigned long FFTSize = 1 << FFTSizelog2;
|
||||
|
||||
// Take the Forward FFTs
|
||||
|
||||
transformForward(io1, FFTSizelog2);
|
||||
transformForward(in2, FFTSizelog2);
|
||||
|
||||
// Operate
|
||||
|
||||
double scale = 1.0 / (double) FFTSize;
|
||||
binaryOp(io1, in2, FFTSize, scale, Op());
|
||||
|
||||
// Inverse iFFT
|
||||
|
||||
transformInverse(io1, FFTSizelog2);
|
||||
}
|
||||
|
||||
// Memory manipulation (complex)
|
||||
|
||||
void copyZero(double *output, const double *input, unsigned long inSize, unsigned long outSize)
|
||||
{
|
||||
std::copy(input, input + inSize, output);
|
||||
std::fill_n(output + inSize, outSize - inSize, 0.0);
|
||||
}
|
||||
|
||||
void copy(FFT_SPLIT_COMPLEX_D output, const FFT_SPLIT_COMPLEX_D spectrum, unsigned long outOffset, unsigned long offset, unsigned long size)
|
||||
{
|
||||
std::copy(spectrum.realp + offset, spectrum.realp + size + offset, output.realp + outOffset);
|
||||
std::copy(spectrum.imagp + offset, spectrum.imagp + size + offset, output.imagp + outOffset);
|
||||
}
|
||||
|
||||
void wrap(FFT_SPLIT_COMPLEX_D output, const FFT_SPLIT_COMPLEX_D spectrum, unsigned long outOffset, unsigned long offset, unsigned long size)
|
||||
{
|
||||
for (unsigned long i = 0; i < size; i++)
|
||||
{
|
||||
output.realp[i + outOffset] += spectrum.realp[i + offset];
|
||||
output.imagp[i + outOffset] += spectrum.imagp[i + offset];
|
||||
}
|
||||
}
|
||||
|
||||
void fold(FFT_SPLIT_COMPLEX_D output, const FFT_SPLIT_COMPLEX_D spectrum, unsigned long outOffset, unsigned long endOffset, unsigned long size)
|
||||
{
|
||||
for (unsigned long i = 1; i <= size; i++)
|
||||
{
|
||||
output.realp[i + outOffset - 1] += spectrum.realp[endOffset - i];
|
||||
output.imagp[i + outOffset - 1] += spectrum.imagp[endOffset - i];
|
||||
}
|
||||
}
|
||||
|
||||
// Memory manipulation (real)
|
||||
|
||||
struct assign { void operator()(double *output, const double *ptr) { *output = *ptr; } };
|
||||
struct accum { void operator()(double *output, const double *ptr) { *output += *ptr; } };
|
||||
struct increment { template<class T> T *operator()(T *&ptr) { return ptr++; } };
|
||||
struct decrement { template<class T> T *operator()(T *&ptr) { return ptr--; } };
|
||||
|
||||
template <typename Op, typename PtrOp>
|
||||
void zip(double *output, const double *p1, const double *p2, unsigned long size, Op op, PtrOp pOp)
|
||||
{
|
||||
for (unsigned long i = 0; i < (size >> 1); i++)
|
||||
{
|
||||
op(pOp(output), pOp(p1));
|
||||
op(pOp(output), pOp(p2));
|
||||
}
|
||||
|
||||
if (size & 1U)
|
||||
op(pOp(output), pOp(p1));
|
||||
}
|
||||
|
||||
void copy(double *output, const FFT_SPLIT_COMPLEX_D spectrum, unsigned long outOffset, unsigned long offset, unsigned long size)
|
||||
{
|
||||
const double *p1 = (offset & 1U) ? spectrum.imagp + (offset >> 1) : spectrum.realp + (offset >> 1);
|
||||
const double *p2 = (offset & 1U) ? spectrum.realp + (offset >> 1) + 1 : spectrum.imagp + (offset >> 1);
|
||||
|
||||
zip(output + outOffset, p1, p2, size, assign(), increment());
|
||||
}
|
||||
|
||||
void wrap(double *output, const FFT_SPLIT_COMPLEX_D spectrum, unsigned long outOffset, unsigned long offset, unsigned long size)
|
||||
{
|
||||
const double *p1 = (offset & 1U) ? spectrum.imagp + (offset >> 1) : spectrum.realp + (offset >> 1);
|
||||
const double *p2 = (offset & 1U) ? spectrum.realp + (offset >> 1) + 1 : spectrum.imagp + (offset >> 1);
|
||||
|
||||
zip(output + outOffset, p1, p2, size, accum(), increment());
|
||||
}
|
||||
|
||||
void fold(double *output, const FFT_SPLIT_COMPLEX_D spectrum, unsigned long outOffset, unsigned long endOffset, unsigned long size)
|
||||
{
|
||||
const double *p1 = (endOffset & 1U) ? spectrum.realp + (endOffset >> 1) : spectrum.imagp + (endOffset >> 1) - 1;
|
||||
const double *p2 = (endOffset & 1U) ? spectrum.imagp + (endOffset >> 1) - 1 : spectrum.realp + (endOffset >> 1) - 1;
|
||||
|
||||
zip(output + outOffset, p1, p2, size, accum(), decrement());
|
||||
}
|
||||
|
||||
// Temporary Memory
|
||||
|
||||
void tempSpectra(FFT_SPLIT_COMPLEX_D &spectrum1, FFT_SPLIT_COMPLEX_D &spectrum2, unsigned long dataSize)
|
||||
{
|
||||
spectrum1.realp = allocTemp(dataSize * 4 * sizeof(double));
|
||||
spectrum1.imagp = spectrum1.realp + dataSize;
|
||||
spectrum2.realp = spectrum1.imagp + dataSize;
|
||||
spectrum2.imagp = spectrum2.realp + dataSize;
|
||||
}
|
||||
|
||||
unsigned long calcLinearSize(unsigned long size1, unsigned long size2)
|
||||
{
|
||||
return size1 + size2 - 1;
|
||||
}
|
||||
|
||||
unsigned long calcSize(unsigned long size1, unsigned long size2, EdgeMode mode)
|
||||
{
|
||||
unsigned long linearSize = size1 + size2 - 1;
|
||||
unsigned long sizeOut = mode != kEdgeLinear ? std::max(size1, size2) : linearSize;
|
||||
unsigned long FFTSizelog2 = ilog2(linearSize);
|
||||
unsigned long FFTSize = 1 << FFTSizelog2;
|
||||
|
||||
if (mode == kEdgeFold && !(std::min(size1, size2) & 1U))
|
||||
sizeOut++;
|
||||
|
||||
if ((FFTSize > mMaxFFTSize) || !size1 || !size2)
|
||||
return 0;
|
||||
|
||||
return sizeOut;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void arrangeOutput(T output, FFT_SPLIT_COMPLEX_D spectrum, unsigned long minSize, unsigned long sizeOut, unsigned long linearSize, unsigned long FFTSize, EdgeMode mode, ConvolveOp op)
|
||||
{
|
||||
unsigned long offset = (mode == kEdgeFold || mode == kEdgeWrapCentre) ? (minSize - 1) / 2: 0;
|
||||
|
||||
copy(output, spectrum, 0, offset, sizeOut);
|
||||
|
||||
if (mode == kEdgeWrap)
|
||||
wrap(output, spectrum, 0, sizeOut, linearSize - sizeOut);
|
||||
|
||||
if (mode == kEdgeWrapCentre)
|
||||
{
|
||||
unsigned long endWrap = (minSize - 1) - offset;
|
||||
|
||||
wrap(output, spectrum, 0, linearSize - endWrap, endWrap);
|
||||
wrap(output, spectrum, sizeOut - offset, 0, offset);
|
||||
}
|
||||
|
||||
if (mode == kEdgeFold)
|
||||
{
|
||||
unsigned long foldSize = minSize / 2;
|
||||
unsigned long foldOffset = sizeOut - foldSize;
|
||||
|
||||
fold(output, spectrum, 0, foldSize, foldSize);
|
||||
fold(output, spectrum, foldOffset, linearSize, foldSize);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void arrangeOutput(T output, FFT_SPLIT_COMPLEX_D spectrum, unsigned long minSize, unsigned long sizeOut, unsigned long linearSize, unsigned long FFTSize, EdgeMode mode, CorrelateOp op)
|
||||
{
|
||||
unsigned long maxSize = (linearSize - minSize) + 1;
|
||||
|
||||
if (mode == kEdgeLinear || mode == kEdgeWrap)
|
||||
{
|
||||
unsigned long extraSize = minSize - 1;
|
||||
|
||||
copy(output, spectrum, 0, 0, maxSize);
|
||||
|
||||
if (mode == kEdgeLinear)
|
||||
copy(output, spectrum, maxSize, FFTSize - extraSize, extraSize);
|
||||
else
|
||||
wrap(output, spectrum, (linearSize - (2 * (minSize - 1))), FFTSize - extraSize, extraSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned long offset = minSize / 2;
|
||||
|
||||
copy(output, spectrum, 0, FFTSize - offset, offset);
|
||||
copy(output, spectrum, offset, 0, sizeOut - offset);
|
||||
|
||||
if (mode == kEdgeWrapCentre)
|
||||
{
|
||||
unsigned long endWrap = minSize - offset - 1;
|
||||
|
||||
wrap(output, spectrum, 0, maxSize - offset, offset);
|
||||
wrap(output, spectrum, sizeOut - endWrap, FFTSize - (minSize - 1), endWrap);
|
||||
}
|
||||
else
|
||||
{
|
||||
fold(output, spectrum, 0, FFTSize - (offset - 1), offset);
|
||||
fold(output, spectrum, sizeOut - offset, maxSize, offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Op>
|
||||
void binarySpectralOperation(double *rOut, double *iOut, const double *rIn1, unsigned long sizeR1, const double *iIn1, unsigned long sizeI1,
|
||||
const double *rIn2, unsigned long sizeR2, const double *iIn2, unsigned long sizeI2, EdgeMode mode, Op op)
|
||||
{
|
||||
FFT_SPLIT_COMPLEX_D spectrum1;
|
||||
FFT_SPLIT_COMPLEX_D spectrum2;
|
||||
unsigned long size1 = std::max(sizeR1, sizeI1);
|
||||
unsigned long size2 = std::max(sizeR2, sizeI2);
|
||||
|
||||
unsigned long linearSize = calcLinearSize(size1, size2);
|
||||
unsigned long sizeOut = calcSize(size1, size2, mode);
|
||||
unsigned long FFTSizelog2 = ilog2(linearSize);
|
||||
unsigned long FFTSize = 1 << FFTSizelog2;
|
||||
|
||||
// Special cases for short inputs
|
||||
|
||||
if (!sizeOut)
|
||||
return;
|
||||
|
||||
if (sizeOut == 1)
|
||||
{
|
||||
ConvolveOp()(rOut[0], iOut[0], rIn1[0], iIn1[0], rIn2[0], iIn2[0], 1.0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Assign temporary memory
|
||||
|
||||
tempSpectra(spectrum1, spectrum2, FFTSize);
|
||||
|
||||
if (spectrum1.realp)
|
||||
{
|
||||
FFT_SPLIT_COMPLEX_D output;
|
||||
output.realp = rOut;
|
||||
output.imagp = iOut;
|
||||
|
||||
// Copy to the inputs
|
||||
|
||||
copyZero(spectrum1.realp, rIn1, sizeR1, FFTSize);
|
||||
copyZero(spectrum1.imagp, iIn1, sizeI1, FFTSize);
|
||||
copyZero(spectrum2.realp, rIn2, sizeR2, FFTSize);
|
||||
copyZero(spectrum2.imagp, iIn2, sizeI2, FFTSize);
|
||||
|
||||
binarySpectralOperation(spectrum1, spectrum2, FFTSizelog2, op);
|
||||
arrangeOutput(output, spectrum1, std::min(size1, size2), sizeOut, linearSize, FFTSize, mode, op);
|
||||
}
|
||||
|
||||
// Deallocate
|
||||
|
||||
deallocTemp(spectrum1.realp);
|
||||
}
|
||||
|
||||
template<typename Op>
|
||||
void binarySpectralOperationReal(double *output, const double *in1, unsigned long size1, const double *in2, unsigned long size2, EdgeMode mode, Op op)
|
||||
{
|
||||
FFT_SPLIT_COMPLEX_D spectrum1;
|
||||
FFT_SPLIT_COMPLEX_D spectrum2;
|
||||
|
||||
unsigned long linearSize = calcLinearSize(size1, size2);
|
||||
unsigned long sizeOut = calcSize(size1, size2, mode);
|
||||
unsigned long FFTSizelog2 = ilog2(linearSize);
|
||||
unsigned long FFTSize = 1 << FFTSizelog2;
|
||||
|
||||
// Special cases for short inputs
|
||||
|
||||
if (!sizeOut)
|
||||
return;
|
||||
|
||||
if (sizeOut == 1)
|
||||
{
|
||||
output[0] = in1[0] * in2[0];
|
||||
return;
|
||||
}
|
||||
|
||||
// Assign temporary memory
|
||||
|
||||
tempSpectra(spectrum1, spectrum2, FFTSize >> 1);
|
||||
|
||||
if (spectrum1.realp)
|
||||
{
|
||||
// Take the Forward Real FFTs
|
||||
|
||||
transformForwardReal(spectrum1, in1, size1, FFTSizelog2);
|
||||
transformForwardReal(spectrum2, in2, size2, FFTSizelog2);
|
||||
|
||||
// Operate
|
||||
|
||||
double scale = 0.25 / (double) FFTSize;
|
||||
binaryOpReal(spectrum1, spectrum2, FFTSize >> 1, scale, Op());
|
||||
|
||||
// Inverse iFFT
|
||||
|
||||
transformInverseReal(spectrum1, FFTSizelog2);
|
||||
arrangeOutput(output, spectrum1, std::min(size1, size2), sizeOut, linearSize, FFTSize, mode, op);
|
||||
}
|
||||
|
||||
// Deallocate
|
||||
|
||||
deallocTemp(spectrum1.realp);
|
||||
}
|
||||
|
||||
void convolveReal(double *output, const double *in1, unsigned long size1, const double *in2, unsigned long size2, EdgeMode mode)
|
||||
{
|
||||
binarySpectralOperationReal(output, in1, size1, in2, size2, mode, ConvolveOp());
|
||||
}
|
||||
|
||||
void correlateReal(double *output, const double *in1, unsigned long size1, const double *in2, unsigned long size2, EdgeMode mode)
|
||||
{
|
||||
binarySpectralOperationReal(output, in1, size1, in2, size2, mode, CorrelateOp());
|
||||
}
|
||||
|
||||
void convolve(double *rOut, double *iOut, const double *rIn1, unsigned long sizeR1, const double *iIn1, unsigned long sizeI1,
|
||||
const double *rIn2, unsigned long sizeR2, const double *iIn2, unsigned long sizeI2, EdgeMode mode)
|
||||
{
|
||||
binarySpectralOperation(rOut, iOut, rIn1, sizeR1, iIn1, sizeI1, rIn2, sizeR2, iIn2, sizeI2, mode, ConvolveOp());
|
||||
}
|
||||
|
||||
void correlate(double *rOut, double *iOut, const double *rIn1, unsigned long sizeR1, const double *iIn1, unsigned long sizeI1,
|
||||
const double *rIn2, unsigned long sizeR2, const double *iIn2, unsigned long sizeI2, EdgeMode mode)
|
||||
{
|
||||
binarySpectralOperation(rOut, iOut, rIn1, sizeR1, iIn1, sizeI1, rIn2, sizeR2, iIn2, sizeI2, mode, CorrelateOp());
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
double *allocTemp(unsigned long N)
|
||||
{
|
||||
return reinterpret_cast<double *>(mAllocator->alloc(sizeof(double) * N));
|
||||
}
|
||||
|
||||
void deallocTemp(double *& ptr)
|
||||
{
|
||||
mAllocator->dealloc(ptr);
|
||||
}
|
||||
|
||||
// Allocator
|
||||
|
||||
FrameLib_Context::Allocator mAllocator;
|
||||
|
||||
// FFT Setup
|
||||
|
||||
FFT_SETUP_D mFFTSetup;
|
||||
|
||||
// Maximum FFT Size
|
||||
|
||||
unsigned long mMaxFFTSize;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
|
||||
#include "FrameLib_Convolve.h"
|
||||
#include "FrameLib_Spectral_Functions.h"
|
||||
|
||||
FrameLib_Convolve::FrameLib_Convolve(FrameLib_Context context, FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy) : FrameLib_Processor(context, proxy, &sParamInfo, 2, 1), Spectral(context)
|
||||
FrameLib_Convolve::FrameLib_Convolve(FrameLib_Context context, FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy) : FrameLib_Processor(context, proxy, &sParamInfo, 2, 1), mProcessor(*this)
|
||||
{
|
||||
mParameters.addInt(kMaxLength, "maxlength", 16384, 0);
|
||||
mParameters.setMin(0);
|
||||
@@ -12,15 +11,15 @@ FrameLib_Convolve::FrameLib_Convolve(FrameLib_Context context, FrameLib_Paramete
|
||||
mParameters.addEnumItem(kComplex, "complex");
|
||||
mParameters.setInstantiation();
|
||||
mParameters.addEnum(kEdgeMode, "edges");
|
||||
mParameters.addEnumItem(kEdgeLinear, "linear");
|
||||
mParameters.addEnumItem(kEdgeWrap, "circular");
|
||||
mParameters.addEnumItem(kEdgeWrapCentre, "wrap");
|
||||
mParameters.addEnumItem(kEdgeFold, "fold");
|
||||
mParameters.addEnumItem(EdgeMode::kEdgeLinear, "linear");
|
||||
mParameters.addEnumItem(EdgeMode::kEdgeWrap, "circular");
|
||||
mParameters.addEnumItem(EdgeMode::kEdgeWrapCentre, "wrap");
|
||||
mParameters.addEnumItem(EdgeMode::kEdgeFold, "fold");
|
||||
mParameters.setInstantiation();
|
||||
|
||||
mParameters.set(serialisedParameters);
|
||||
|
||||
setMaxFFTSize(mParameters.getInt(kMaxLength));
|
||||
mProcessor.set_max_fft_size(mParameters.getInt(kMaxLength));
|
||||
|
||||
mMode = static_cast<Mode>(mParameters.getInt(kMode));
|
||||
|
||||
@@ -90,14 +89,14 @@ void FrameLib_Convolve::process()
|
||||
|
||||
// Get Output Size
|
||||
|
||||
unsigned long sizeOut = calcSize(sizeIn1, sizeIn2, edgeMode);
|
||||
unsigned long sizeOut = mProcessor.convolved_size(sizeIn1, sizeIn2, edgeMode);
|
||||
|
||||
// Get output
|
||||
|
||||
requestOutputSize(0, sizeOut);
|
||||
|
||||
if (allocateOutputs())
|
||||
convolveReal(getOutput(0, &sizeOut), input1, sizeIn1, input2, sizeIn2, edgeMode);
|
||||
mProcessor.convolve(getOutput(0, &sizeOut), {input1, sizeIn1}, {input2, sizeIn2}, edgeMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -112,14 +111,19 @@ void FrameLib_Convolve::process()
|
||||
|
||||
// Get Output Size
|
||||
|
||||
unsigned long sizeOut = calcSize(std::max(sizeR1, sizeI1), std::max(sizeR2, sizeI2), edgeMode);
|
||||
unsigned long sizeOut = mProcessor.convolved_size(std::max(sizeR1, sizeI1), std::max(sizeR2, sizeI2), edgeMode);
|
||||
|
||||
// Get output
|
||||
|
||||
requestOutputSize(0, sizeOut);
|
||||
requestOutputSize(1, sizeOut);
|
||||
|
||||
|
||||
if (allocateOutputs())
|
||||
convolve(getOutput(0, &sizeOut), getOutput(1, &sizeOut), inR1, sizeR1, inI1, sizeI1, inR2, sizeR2, inI2, sizeI2, edgeMode);
|
||||
{
|
||||
double *rOut = getOutput(0, &sizeOut);
|
||||
double *iOut = getOutput(1, &sizeOut);
|
||||
|
||||
mProcessor.convolve(rOut, iOut, {inR1, sizeR1}, {inI1, sizeI1}, {inR2, sizeR2}, {inI2, sizeI2}, edgeMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
#define FRAMELIB_CONVOLVE_H
|
||||
|
||||
#include "FrameLib_DSP.h"
|
||||
#include "FrameLib_Convolution_Tools.h"
|
||||
#include "../../FrameLib_Dependencies/SpectralProcessor.hpp"
|
||||
|
||||
class FrameLib_Convolve final : public FrameLib_Processor, private Spectral
|
||||
class FrameLib_Convolve final : public FrameLib_Processor
|
||||
{
|
||||
using EdgeMode = spectral_processor<double, FrameLib_DSP::Allocator>::EdgeMode;
|
||||
|
||||
// Parameter Enums and Info
|
||||
|
||||
enum ParameterList { kMaxLength, kMode, kEdgeMode };
|
||||
@@ -16,7 +18,7 @@ class FrameLib_Convolve final : public FrameLib_Processor, private Spectral
|
||||
|
||||
public:
|
||||
|
||||
// Constructor / Destructor
|
||||
// Constructor
|
||||
|
||||
FrameLib_Convolve(FrameLib_Context context, FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy);
|
||||
|
||||
@@ -39,6 +41,10 @@ private:
|
||||
Mode mMode;
|
||||
|
||||
static ParameterInfo sParamInfo;
|
||||
|
||||
// Processor
|
||||
|
||||
spectral_processor<double, FrameLib_DSP::Allocator> mProcessor;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
|
||||
#include "FrameLib_Correlate.h"
|
||||
#include "FrameLib_Spectral_Functions.h"
|
||||
|
||||
FrameLib_Correlate::FrameLib_Correlate(FrameLib_Context context, FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy) : FrameLib_Processor(context, proxy, &sParamInfo, 2, 1), Spectral(context)
|
||||
FrameLib_Correlate::FrameLib_Correlate(FrameLib_Context context, FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy) : FrameLib_Processor(context, proxy, &sParamInfo, 2, 1), mProcessor(*this)
|
||||
{
|
||||
mParameters.addInt(kMaxLength, "maxlength", 16384, 0);
|
||||
mParameters.setMin(0);
|
||||
@@ -12,15 +11,15 @@ FrameLib_Correlate::FrameLib_Correlate(FrameLib_Context context, FrameLib_Parame
|
||||
mParameters.addEnumItem(kComplex, "complex");
|
||||
mParameters.setInstantiation();
|
||||
mParameters.addEnum(kEdgeMode, "edges");
|
||||
mParameters.addEnumItem(kEdgeLinear, "linear");
|
||||
mParameters.addEnumItem(kEdgeWrap, "circular");
|
||||
mParameters.addEnumItem(kEdgeWrapCentre, "wrap");
|
||||
mParameters.addEnumItem(kEdgeFold, "fold");
|
||||
mParameters.addEnumItem(EdgeMode::kEdgeLinear, "linear");
|
||||
mParameters.addEnumItem(EdgeMode::kEdgeWrap, "circular");
|
||||
mParameters.addEnumItem(EdgeMode::kEdgeWrapCentre, "wrap");
|
||||
mParameters.addEnumItem(EdgeMode::kEdgeFold, "fold");
|
||||
mParameters.setInstantiation();
|
||||
|
||||
mParameters.set(serialisedParameters);
|
||||
|
||||
setMaxFFTSize(mParameters.getInt(kMaxLength));
|
||||
mProcessor.set_max_fft_size(mParameters.getInt(kMaxLength));
|
||||
|
||||
mMode = static_cast<Mode>(mParameters.getInt(kMode));
|
||||
|
||||
@@ -91,14 +90,14 @@ void FrameLib_Correlate::process()
|
||||
|
||||
// Get Output Size
|
||||
|
||||
unsigned long sizeOut = calcSize(sizeIn1, sizeIn2, edgeMode);
|
||||
unsigned long sizeOut = mProcessor.correlated_size(sizeIn1, sizeIn2, edgeMode);
|
||||
|
||||
// Get output
|
||||
|
||||
requestOutputSize(0, sizeOut);
|
||||
|
||||
if (allocateOutputs())
|
||||
correlateReal(getOutput(0, &sizeOut), input1, sizeIn1, input2, sizeIn2, edgeMode);
|
||||
mProcessor.correlate(getOutput(0, &sizeOut), {input1, sizeIn1}, {input2, sizeIn2}, edgeMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -113,7 +112,7 @@ void FrameLib_Correlate::process()
|
||||
|
||||
// Get Output Size
|
||||
|
||||
unsigned long sizeOut = calcSize(std::max(sizeR1, sizeI1), std::max(sizeR2, sizeI2), edgeMode);
|
||||
unsigned long sizeOut = mProcessor.correlated_size(std::max(sizeR1, sizeI1), std::max(sizeR2, sizeI2), edgeMode);
|
||||
|
||||
// Get output
|
||||
|
||||
@@ -121,6 +120,11 @@ void FrameLib_Correlate::process()
|
||||
requestOutputSize(1, sizeOut);
|
||||
|
||||
if (allocateOutputs())
|
||||
correlate(getOutput(0, &sizeOut), getOutput(1, &sizeOut), inR1, sizeR1, inI1, sizeI1, inR2, sizeR2, inI2, sizeI2, edgeMode);
|
||||
{
|
||||
double *rOut = getOutput(0, &sizeOut);
|
||||
double *iOut = getOutput(1, &sizeOut);
|
||||
|
||||
mProcessor.correlate(rOut, iOut, {inR1, sizeR1}, {inI1, sizeI1}, {inR2, sizeR2}, {inI2, sizeI2}, edgeMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
#define FRAMELIB_CORRELATE_H
|
||||
|
||||
#include "FrameLib_DSP.h"
|
||||
#include "FrameLib_Convolution_Tools.h"
|
||||
#include "../../FrameLib_Dependencies/SpectralProcessor.hpp"
|
||||
|
||||
class FrameLib_Correlate final : public FrameLib_Processor, private Spectral
|
||||
class FrameLib_Correlate final : public FrameLib_Processor
|
||||
{
|
||||
using EdgeMode = spectral_processor<double, FrameLib_DSP::Allocator>::EdgeMode;
|
||||
|
||||
// Parameter Enums and Info
|
||||
|
||||
enum ParameterList { kMaxLength, kMode, kEdgeMode };
|
||||
@@ -16,7 +18,7 @@ class FrameLib_Correlate final : public FrameLib_Processor, private Spectral
|
||||
|
||||
public:
|
||||
|
||||
// Constructor / Destructor
|
||||
// Constructor
|
||||
|
||||
FrameLib_Correlate(FrameLib_Context context, FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy);
|
||||
|
||||
@@ -39,6 +41,10 @@ private:
|
||||
Mode mMode;
|
||||
|
||||
static ParameterInfo sParamInfo;
|
||||
|
||||
// Processor
|
||||
|
||||
spectral_processor<double, FrameLib_DSP::Allocator> mProcessor;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
|
||||
#include "FrameLib_FFT.h"
|
||||
#include "FrameLib_Spectral_Functions.h"
|
||||
|
||||
// Constructor / Destructor
|
||||
|
||||
FrameLib_FFT::FrameLib_FFT(FrameLib_Context context, FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy) : FrameLib_Processor(context, proxy, &sParamInfo, 1, 2)
|
||||
FrameLib_FFT::FrameLib_FFT(FrameLib_Context context, FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy) : FrameLib_Processor(context, proxy, &sParamInfo, 1, 2), mProcessor(*this)
|
||||
{
|
||||
mParameters.addInt(kMaxLength, "maxlength", 16384, 0);
|
||||
mParameters.setMin(0);
|
||||
@@ -19,13 +18,10 @@ FrameLib_FFT::FrameLib_FFT(FrameLib_Context context, FrameLib_Parameters::Serial
|
||||
|
||||
mParameters.set(serialisedParameters);
|
||||
|
||||
unsigned long maxFFTSizeLog2 = ilog2(mParameters.getInt(kMaxLength));
|
||||
|
||||
hisstools_create_setup(&mFFTSetup, maxFFTSizeLog2);
|
||||
mProcessor.set_max_fft_size(mParameters.getInt(kMaxLength));
|
||||
|
||||
// Store parameters
|
||||
|
||||
mMaxFFTSize = 1 << maxFFTSizeLog2;
|
||||
mMode = static_cast<Mode>(mParameters.getInt(kMode));
|
||||
mNormalise = mParameters.getBool(kNormalise);
|
||||
|
||||
@@ -35,11 +31,6 @@ FrameLib_FFT::FrameLib_FFT(FrameLib_Context context, FrameLib_Parameters::Serial
|
||||
setIO(2, 2);
|
||||
}
|
||||
|
||||
FrameLib_FFT::~FrameLib_FFT()
|
||||
{
|
||||
hisstools_destroy_setup(mFFTSetup);
|
||||
}
|
||||
|
||||
// Info
|
||||
|
||||
std::string FrameLib_FFT::objectInfo(bool verbose)
|
||||
@@ -93,13 +84,13 @@ void FrameLib_FFT::process()
|
||||
|
||||
// Get FFT size log 2
|
||||
|
||||
unsigned long FFTSizelog2 = ilog2(std::max(sizeInR, sizeInI));
|
||||
unsigned long FFTSize = 1 << FFTSizelog2;
|
||||
unsigned long FFTSizeLog2 = mProcessor.calc_fft_size_log2(std::max(sizeInR, sizeInI));
|
||||
unsigned long FFTSize = 1 << FFTSizeLog2;
|
||||
sizeOut = mMode == kReal ? (FFTSize >> 1) + 1 : FFTSize;
|
||||
|
||||
// Check size
|
||||
|
||||
if (FFTSize > mMaxFFTSize || (!sizeInR && !sizeInI))
|
||||
if (FFTSize > mProcessor.max_fft_size() || (!sizeInR && !sizeInI))
|
||||
sizeOut = 0;
|
||||
|
||||
// Calculate output size
|
||||
@@ -123,11 +114,11 @@ void FrameLib_FFT::process()
|
||||
copyVector(spectrum.imagp, inputI, sizeInI);
|
||||
zeroVector(spectrum.imagp + sizeInI, sizeOut - sizeInI);
|
||||
|
||||
hisstools_fft(mFFTSetup, &spectrum, FFTSizelog2);
|
||||
mProcessor.fft(spectrum, FFTSizeLog2);
|
||||
}
|
||||
else
|
||||
{
|
||||
hisstools_rfft(mFFTSetup, inputR, &spectrum, sizeInR, FFTSizelog2);
|
||||
mProcessor.rfft(spectrum, inputR, sizeInR, FFTSizeLog2);
|
||||
|
||||
// Move Nyquist Bin
|
||||
|
||||
@@ -145,20 +136,12 @@ void FrameLib_FFT::process()
|
||||
spectrum.imagp[i] = -spectrum.imagp[FFTSize - i];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Scale
|
||||
|
||||
double scale = mNormalise ? 1.0 / (double) FFTSize : ((mMode == kComplex) ? 1.0 : 0.5);
|
||||
double scale = ((mMode == kComplex) ? 1.0 : 0.5) / (mNormalise ? (double) FFTSize : 1.0);
|
||||
|
||||
if (scale != 1.0)
|
||||
{
|
||||
for (unsigned long i = 0; i < sizeOut; i++)
|
||||
{
|
||||
spectrum.realp[i] *= scale;
|
||||
spectrum.imagp[i] *= scale;
|
||||
}
|
||||
}
|
||||
mProcessor.scale_spectrum(spectrum, sizeOut, scale);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#define FRAMELIB_FFT_H
|
||||
|
||||
#include "FrameLib_DSP.h"
|
||||
#include "../../FrameLib_Dependencies/HISSTools_FFT/HISSTools_FFT.h"
|
||||
#include "../../FrameLib_Dependencies/SpectralProcessor.hpp"
|
||||
|
||||
// FIX - add zero padding (why not do this prior to FFT with the pad object?)
|
||||
|
||||
@@ -18,10 +18,9 @@ class FrameLib_FFT final : public FrameLib_Processor
|
||||
|
||||
public:
|
||||
|
||||
// Constructor / Destructor
|
||||
// Constructor
|
||||
|
||||
FrameLib_FFT(FrameLib_Context context, FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy);
|
||||
~FrameLib_FFT();
|
||||
|
||||
// Info
|
||||
|
||||
@@ -35,19 +34,18 @@ private:
|
||||
|
||||
void process() override;
|
||||
|
||||
// Data
|
||||
// Param Info
|
||||
|
||||
// FFT Setup
|
||||
static ParameterInfo sParamInfo;
|
||||
|
||||
FFT_SETUP_D mFFTSetup;
|
||||
|
||||
// Instantiation Params
|
||||
|
||||
unsigned long mMaxFFTSize;
|
||||
Mode mMode;
|
||||
bool mNormalise;
|
||||
|
||||
static ParameterInfo sParamInfo;
|
||||
// Processor
|
||||
|
||||
spectral_processor<double, FrameLib_DSP::Allocator> mProcessor;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
|
||||
#include "FrameLib_FIRPhase.h"
|
||||
|
||||
// Constructor / Destructor
|
||||
|
||||
FrameLib_FIRPhase::FrameLib_FIRPhase(FrameLib_Context context, FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy) : FrameLib_Processor(context, proxy, &sParamInfo, 1, 1), mProcessor(*this)
|
||||
{
|
||||
mParameters.addInt(kMaxLength, "maxlength", 16384, 0);
|
||||
mParameters.setMin(0);
|
||||
mParameters.setInstantiation();
|
||||
mParameters.addDouble(kPhase, "phase", 0.0, 1);
|
||||
mParameters.setClip(0.0, 1.0);
|
||||
|
||||
mParameters.set(serialisedParameters);
|
||||
|
||||
mProcessor.set_max_fft_size(mParameters.getInt(kMaxLength));
|
||||
}
|
||||
|
||||
// Info
|
||||
|
||||
std::string FrameLib_FIRPhase::objectInfo(bool verbose)
|
||||
{
|
||||
return formatInfo("Calculate the real Fast Fourier Transform of an input frame: All FFTs performed will use a power of two size. "
|
||||
"Output frames will be (N / 2) + 1 in length where N is the FFT size. Inputs which are not a power of two are zero-padded to the next power of two. "
|
||||
"Real and imaginary values are output as separate frames.",
|
||||
"Calculate the real Fast Fourier Transform of an input frame.", verbose);
|
||||
}
|
||||
|
||||
std::string FrameLib_FIRPhase::inputInfo(unsigned long idx, bool verbose)
|
||||
{
|
||||
return "IR Time Domain Input";
|
||||
}
|
||||
|
||||
std::string FrameLib_FIRPhase::outputInfo(unsigned long idx, bool verbose)
|
||||
{
|
||||
return "IR Time Domain Output";
|
||||
}
|
||||
|
||||
// Parameter Info
|
||||
|
||||
FrameLib_FIRPhase::ParameterInfo FrameLib_FIRPhase::sParamInfo;
|
||||
|
||||
FrameLib_FIRPhase::ParameterInfo::ParameterInfo()
|
||||
{
|
||||
add("Sets the maximum input length / FFT size.");
|
||||
add("When on the output is normalised so that sine waves produce the same level output regardless of the FFT size.");
|
||||
add("Sets the type of input expected / output produced.");
|
||||
}
|
||||
|
||||
// Process
|
||||
|
||||
void FrameLib_FIRPhase::process()
|
||||
{
|
||||
// Get Input(s)
|
||||
|
||||
unsigned long sizeIn, sizeOut;
|
||||
const double *input = getInput(0, &sizeIn);
|
||||
|
||||
// Get FFT size log 2
|
||||
|
||||
unsigned long FFTSizeLog2 = mProcessor.calc_fft_size_log2(sizeIn);
|
||||
unsigned long FFTSize = 1 << FFTSizeLog2;
|
||||
sizeOut = FFTSize;
|
||||
|
||||
// Check size
|
||||
|
||||
if (FFTSize > mProcessor.max_fft_size() || !sizeIn)
|
||||
sizeOut = 0;
|
||||
|
||||
// Calculate output size
|
||||
|
||||
requestOutputSize(0, sizeOut);
|
||||
allocateOutputs();
|
||||
double *output = getOutput(0, &sizeOut);
|
||||
|
||||
// Transform
|
||||
|
||||
if (sizeOut)
|
||||
mProcessor.change_phase(output, input, sizeIn, mParameters.getValue(kPhase));
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
|
||||
#ifndef FRAMELIB_FIRPHASE_H
|
||||
#define FRAMELIB_FIRPHASE_H
|
||||
|
||||
#include "FrameLib_DSP.h"
|
||||
#include "../../FrameLib_Dependencies/SpectralProcessor.hpp"
|
||||
|
||||
// FIX - add zero padding (why not do this prior to FFT with the pad object?)
|
||||
|
||||
class FrameLib_FIRPhase final : public FrameLib_Processor
|
||||
{
|
||||
// Parameter Enums and Info
|
||||
|
||||
enum ParameterList { kMaxLength, kPhase };
|
||||
|
||||
struct ParameterInfo : public FrameLib_Parameters::Info { ParameterInfo(); };
|
||||
|
||||
public:
|
||||
|
||||
// Constructor
|
||||
|
||||
FrameLib_FIRPhase(FrameLib_Context context, FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy);
|
||||
|
||||
// Info
|
||||
|
||||
std::string objectInfo(bool verbose) override;
|
||||
std::string inputInfo(unsigned long idx, bool verbose) override;
|
||||
std::string outputInfo(unsigned long idx, bool verbose) override;
|
||||
|
||||
private:
|
||||
|
||||
// Process
|
||||
|
||||
void process() override;
|
||||
|
||||
// Data
|
||||
|
||||
static ParameterInfo sParamInfo;
|
||||
|
||||
// Processor
|
||||
|
||||
spectral_processor<double, FrameLib_DSP::Allocator> mProcessor;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,10 +1,9 @@
|
||||
|
||||
#include "FrameLib_Multitaper.h"
|
||||
#include "FrameLib_Spectral_Functions.h"
|
||||
|
||||
// Constructor / Destructor
|
||||
|
||||
FrameLib_Multitaper::FrameLib_Multitaper(FrameLib_Context context, FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy) : FrameLib_Processor(context, proxy, &sParamInfo, 1, 1)
|
||||
FrameLib_Multitaper::FrameLib_Multitaper(FrameLib_Context context, FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy) : FrameLib_Processor(context, proxy, &sParamInfo, 1, 1), mProcessor(*this)
|
||||
{
|
||||
mParameters.addInt(kMaxLength, "maxlength", 16384, 0);
|
||||
mParameters.setMin(0);
|
||||
@@ -14,16 +13,8 @@ FrameLib_Multitaper::FrameLib_Multitaper(FrameLib_Context context, FrameLib_Para
|
||||
mParameters.setMin(1);
|
||||
|
||||
mParameters.set(serialisedParameters);
|
||||
|
||||
unsigned long maxFFTSizeLog2 = ilog2(mParameters.getInt(kMaxLength));
|
||||
|
||||
hisstools_create_setup(&mFFTSetup, maxFFTSizeLog2 + 1);
|
||||
mMaxFFTSize = 1 << maxFFTSizeLog2;
|
||||
}
|
||||
|
||||
FrameLib_Multitaper::~FrameLib_Multitaper()
|
||||
{
|
||||
hisstools_destroy_setup(mFFTSetup);
|
||||
mProcessor.set_max_fft_size(mParameters.getInt(kMaxLength) * 2);
|
||||
}
|
||||
|
||||
// Helpers
|
||||
@@ -88,13 +79,13 @@ void FrameLib_Multitaper::process()
|
||||
|
||||
// Get FFT size log 2
|
||||
|
||||
unsigned long FFTSizelog2 = ilog2(sizeIn);
|
||||
unsigned long FFTSize = 1 << FFTSizelog2;
|
||||
unsigned long FFTSizeLog2 = mProcessor.calc_fft_size_log2(sizeIn);
|
||||
unsigned long FFTSize = 1 << FFTSizeLog2;
|
||||
sizeOut = (FFTSize >> 1) + 1;
|
||||
|
||||
// Check size
|
||||
|
||||
if (FFTSize > mMaxFFTSize || !sizeIn)
|
||||
if ((FFTSize * 2) > mProcessor.max_fft_size() || !sizeIn)
|
||||
sizeOut = 0;
|
||||
|
||||
// Calculate output size
|
||||
@@ -118,7 +109,7 @@ void FrameLib_Multitaper::process()
|
||||
|
||||
// Take the real fft
|
||||
|
||||
hisstools_rfft(mFFTSetup, input, &spectrum, sizeIn, (FFTSizelog2 + 1));
|
||||
mProcessor.rfft(spectrum, input, sizeIn, (FFTSizeLog2 + 1));
|
||||
|
||||
// Move Nyquist Bin
|
||||
|
||||
@@ -128,11 +119,7 @@ void FrameLib_Multitaper::process()
|
||||
|
||||
// Scale
|
||||
|
||||
for (unsigned long i = 0; i < (FFTSize + 1); i++)
|
||||
{
|
||||
spectrum.realp[i] *= 0.5;
|
||||
spectrum.imagp[i] *= 0.5;
|
||||
}
|
||||
mProcessor.scale_spectrum(spectrum, FFTSize + 1, 0.5);
|
||||
|
||||
// Do Multitaper
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#define FRAMELIB_MULTITAPER_H
|
||||
|
||||
#include "FrameLib_DSP.h"
|
||||
#include "../../FrameLib_Dependencies/HISSTools_FFT/HISSTools_FFT.h"
|
||||
#include "../../FrameLib_Dependencies/SpectralProcessor.hpp"
|
||||
|
||||
class FrameLib_Multitaper final : public FrameLib_Processor
|
||||
{
|
||||
@@ -15,10 +15,9 @@ class FrameLib_Multitaper final : public FrameLib_Processor
|
||||
|
||||
public:
|
||||
|
||||
// Constructor / Destructor
|
||||
// Constructor
|
||||
|
||||
FrameLib_Multitaper(FrameLib_Context context, FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy);
|
||||
~FrameLib_Multitaper();
|
||||
|
||||
// Info
|
||||
|
||||
@@ -35,18 +34,12 @@ private:
|
||||
// Process
|
||||
|
||||
void process() override;
|
||||
|
||||
protected:
|
||||
|
||||
// FFT Setup
|
||||
|
||||
FFT_SETUP_D mFFTSetup;
|
||||
|
||||
// Maximum FFT Size
|
||||
|
||||
unsigned long mMaxFFTSize;
|
||||
|
||||
static ParameterInfo sParamInfo;
|
||||
|
||||
// Processor
|
||||
|
||||
spectral_processor<double, FrameLib_DSP::Allocator> mProcessor;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
|
||||
#include "FrameLib_iFFT.h"
|
||||
#include "FrameLib_Spectral_Functions.h"
|
||||
|
||||
// Constructor / Destructor
|
||||
|
||||
FrameLib_iFFT::FrameLib_iFFT(FrameLib_Context context, FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy) : FrameLib_Processor(context, proxy, &sParamInfo, 2, 1)
|
||||
FrameLib_iFFT::FrameLib_iFFT(FrameLib_Context context, FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy) : FrameLib_Processor(context, proxy, &sParamInfo, 2, 1), mProcessor(*this)
|
||||
{
|
||||
mParameters.addInt(kMaxLength, "maxlength", 16384, 0);
|
||||
mParameters.setMin(0);
|
||||
@@ -18,14 +17,11 @@ FrameLib_iFFT::FrameLib_iFFT(FrameLib_Context context, FrameLib_Parameters::Seri
|
||||
mParameters.setInstantiation();
|
||||
|
||||
mParameters.set(serialisedParameters);
|
||||
|
||||
unsigned long maxFFTSizeLog2 = ilog2(mParameters.getInt(kMaxLength));
|
||||
|
||||
hisstools_create_setup(&mFFTSetup, maxFFTSizeLog2);
|
||||
|
||||
|
||||
mProcessor.set_max_fft_size(mParameters.getInt(kMaxLength));
|
||||
|
||||
// Store parameters
|
||||
|
||||
mMaxFFTSize = 1 << maxFFTSizeLog2;
|
||||
mMode = static_cast<Mode>(mParameters.getInt(kMode));
|
||||
mNormalise = mParameters.getBool(kNormalise);
|
||||
|
||||
@@ -35,11 +31,6 @@ FrameLib_iFFT::FrameLib_iFFT(FrameLib_Context context, FrameLib_Parameters::Seri
|
||||
setIO(2, 2);
|
||||
}
|
||||
|
||||
FrameLib_iFFT::~FrameLib_iFFT()
|
||||
{
|
||||
hisstools_destroy_setup(mFFTSetup);
|
||||
}
|
||||
|
||||
// Info
|
||||
|
||||
std::string FrameLib_iFFT::objectInfo(bool verbose)
|
||||
@@ -80,7 +71,7 @@ void FrameLib_iFFT::process()
|
||||
FFT_SPLIT_COMPLEX_D spectrum;
|
||||
|
||||
unsigned long sizeInR, sizeInI, sizeIn, sizeOut, spectrumSize;
|
||||
unsigned long FFTSizelog2 = 0;
|
||||
unsigned long FFTSizeLog2 = 0;
|
||||
|
||||
// Get Inputs
|
||||
|
||||
@@ -92,15 +83,15 @@ void FrameLib_iFFT::process()
|
||||
if (sizeIn)
|
||||
{
|
||||
unsigned long calcSize = mMode == kReal ? (sizeIn - 1) << 1 : sizeIn;
|
||||
FFTSizelog2 = ilog2(calcSize);
|
||||
sizeOut = 1 << FFTSizelog2;
|
||||
FFTSizeLog2 = mProcessor.calc_fft_size_log2(calcSize);
|
||||
sizeOut = 1 << FFTSizeLog2;
|
||||
}
|
||||
else
|
||||
sizeOut = 0;
|
||||
|
||||
// Sanity Check
|
||||
|
||||
if (sizeOut > mMaxFFTSize)
|
||||
if (sizeOut > mProcessor.max_fft_size())
|
||||
sizeOut = 0;
|
||||
|
||||
// Calculate output size
|
||||
@@ -134,7 +125,7 @@ void FrameLib_iFFT::process()
|
||||
|
||||
if (sizeOut && spectrum.realp)
|
||||
{
|
||||
double scale = mNormalise ? 1.0 : 1.0 / static_cast<double>(1 << FFTSizelog2);
|
||||
double scale = mNormalise ? 1.0 : 1.0 / static_cast<double>(1 << FFTSizeLog2);
|
||||
|
||||
// Copy Spectrum
|
||||
|
||||
@@ -148,17 +139,10 @@ void FrameLib_iFFT::process()
|
||||
|
||||
if (mMode == kComplex)
|
||||
{
|
||||
// Convert to time domain
|
||||
// Convert to time domain and scale
|
||||
|
||||
hisstools_ifft(mFFTSetup, &spectrum, FFTSizelog2);
|
||||
|
||||
// Scale
|
||||
|
||||
for (unsigned long i = 0; i < sizeOut; i++)
|
||||
{
|
||||
spectrum.realp[i] *= scale;
|
||||
spectrum.imagp[i] *= scale;
|
||||
}
|
||||
mProcessor.ifft(spectrum, FFTSizeLog2);
|
||||
mProcessor.scale_spectrum(spectrum, sizeOut, scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -167,14 +151,10 @@ void FrameLib_iFFT::process()
|
||||
if (sizeInR >= ((sizeOut >> 1) + 1))
|
||||
spectrum.imagp[0] = inputR[sizeOut >> 1];
|
||||
|
||||
// Convert to time domain
|
||||
// Convert to time domain and scale
|
||||
|
||||
hisstools_rifft(mFFTSetup, &spectrum, outputR, FFTSizelog2);
|
||||
|
||||
// Scale
|
||||
|
||||
for (unsigned long i = 0; i < sizeOut; i++)
|
||||
outputR[i] *= scale;
|
||||
mProcessor.rifft(outputR, spectrum, FFTSizeLog2);
|
||||
mProcessor.scale_vector(outputR, sizeOut, scale);
|
||||
|
||||
dealloc(spectrum.realp);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#define FRAMELIB_IFFT_H
|
||||
|
||||
#include "FrameLib_DSP.h"
|
||||
#include "../../FrameLib_Dependencies/HISSTools_FFT/HISSTools_FFT.h"
|
||||
#include "../../FrameLib_Dependencies/SpectralProcessor.hpp"
|
||||
|
||||
// FIX - review FFTSetup
|
||||
|
||||
@@ -18,10 +18,9 @@ class FrameLib_iFFT final : public FrameLib_Processor
|
||||
|
||||
public:
|
||||
|
||||
// Constructor / Destructor
|
||||
// Constructor
|
||||
|
||||
FrameLib_iFFT(FrameLib_Context context, FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy);
|
||||
~FrameLib_iFFT();
|
||||
|
||||
// Info
|
||||
|
||||
@@ -35,19 +34,18 @@ private:
|
||||
|
||||
void process() override;
|
||||
|
||||
// Data
|
||||
// Param Info
|
||||
|
||||
static ParameterInfo sParamInfo;
|
||||
|
||||
// FFT Setup
|
||||
|
||||
FFT_SETUP_D mFFTSetup;
|
||||
|
||||
// Instantiation Params
|
||||
|
||||
unsigned long mMaxFFTSize;
|
||||
Mode mMode;
|
||||
bool mNormalise;
|
||||
|
||||
static ParameterInfo sParamInfo;
|
||||
// Processor
|
||||
|
||||
spectral_processor<double, FrameLib_DSP::Allocator> mProcessor;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
|
||||
#include "FrameLib_KernelSmooth.h"
|
||||
|
||||
// Constructor
|
||||
|
||||
FrameLib_KernelSmooth::FrameLib_KernelSmooth(FrameLib_Context context, FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy) : FrameLib_Processor(context, proxy, &sParamInfo, 2, 1), mSmoother(*this)
|
||||
{
|
||||
mParameters.addVariableDoubleArray(kSmooth, "smooth", 0.0, 2, 0);
|
||||
mParameters.setMin(0.0);
|
||||
|
||||
mParameters.set(serialisedParameters);
|
||||
}
|
||||
|
||||
// Info
|
||||
|
||||
std::string FrameLib_KernelSmooth::objectInfo(bool verbose)
|
||||
{
|
||||
return formatInfo("Splits a frame sequentially into smaller frames based on the trigger input.", verbose);
|
||||
}
|
||||
|
||||
std::string FrameLib_KernelSmooth::inputInfo(unsigned long idx, bool verbose)
|
||||
{
|
||||
if (idx)
|
||||
return "Kernel Input";
|
||||
else
|
||||
return "Input Frame";
|
||||
}
|
||||
|
||||
std::string FrameLib_KernelSmooth::outputInfo(unsigned long idx, bool verbose)
|
||||
{
|
||||
return "Smoothed Frame";
|
||||
}
|
||||
|
||||
// Parameter Info
|
||||
|
||||
FrameLib_KernelSmooth::ParameterInfo FrameLib_KernelSmooth::sParamInfo;
|
||||
|
||||
FrameLib_KernelSmooth::ParameterInfo::ParameterInfo()
|
||||
{
|
||||
add("Set the amount of smoothing." );
|
||||
}
|
||||
|
||||
// Process
|
||||
|
||||
void FrameLib_KernelSmooth::process()
|
||||
{
|
||||
unsigned long sizeIn1, sizeIn2, sizeOut;
|
||||
const double *input = getInput(0, &sizeIn1);
|
||||
const double *kernel = getInput(1, &sizeIn2);
|
||||
|
||||
sizeOut = sizeIn1;
|
||||
|
||||
requestOutputSize(0, sizeOut);
|
||||
allocateOutputs();
|
||||
|
||||
double *output = getOutput(0, &sizeOut);
|
||||
|
||||
if (output)
|
||||
{
|
||||
if (!sizeIn2)
|
||||
{
|
||||
copyVector(output, input, sizeOut);
|
||||
return;
|
||||
}
|
||||
|
||||
Allocator allocator(*this);
|
||||
|
||||
unsigned long widthSize;
|
||||
double width_lo = 0.0;
|
||||
double width_hi = 0.0;
|
||||
|
||||
const double *widths = mParameters.getArray(kSmooth, &widthSize);
|
||||
|
||||
if (widthSize == 2)
|
||||
{
|
||||
width_lo = widths[0];
|
||||
width_hi = widths[1];
|
||||
}
|
||||
else if (widthSize == 1)
|
||||
{
|
||||
width_lo = width_hi = widths[0];
|
||||
|
||||
}
|
||||
|
||||
mSmoother.smooth(output, input, kernel, sizeIn1, sizeIn2, width_lo, width_hi, Smoother::kSmoothFold);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
|
||||
#ifndef FRAMELIB_KERNELSMOOTH_H
|
||||
#define FRAMELIB_KERNELSMOOTH_H
|
||||
|
||||
#include "FrameLib_DSP.h"
|
||||
#include "../../FrameLib_Dependencies/KernelSmoother.hpp"
|
||||
|
||||
class FrameLib_KernelSmooth final : public FrameLib_Processor
|
||||
{
|
||||
using Smoother = kernel_smoother<double, FrameLib_DSP::Allocator>;
|
||||
|
||||
enum ParameterList { kSmooth };
|
||||
|
||||
struct ParameterInfo : public FrameLib_Parameters::Info { ParameterInfo(); };
|
||||
|
||||
public:
|
||||
|
||||
// Constructor
|
||||
|
||||
FrameLib_KernelSmooth(FrameLib_Context context, FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy);
|
||||
|
||||
// Info
|
||||
|
||||
std::string objectInfo(bool verbose) override;
|
||||
std::string inputInfo(unsigned long idx, bool verbose) override;
|
||||
std::string outputInfo(unsigned long idx, bool verbose) override;
|
||||
|
||||
private:
|
||||
|
||||
// Process
|
||||
|
||||
void process() override;
|
||||
|
||||
// Data
|
||||
|
||||
static ParameterInfo sParamInfo;
|
||||
|
||||
Smoother mSmoother;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,5 @@
|
||||
|
||||
#include "FrameLib_Pattern.h"
|
||||
#include <algorithm>
|
||||
|
||||
// Constructor
|
||||
|
||||
|
||||
@@ -89,6 +89,7 @@
|
||||
B826E4A61F3148AB00B920C8 /* MaxAudioAPI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B87E879819C8F61A00B1D0CD /* MaxAudioAPI.framework */; };
|
||||
B826E4B01F31490100B920C8 /* FrameLib_Once.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B826E4AE1F31490100B920C8 /* FrameLib_Once.cpp */; };
|
||||
B826E4B51F314AA800B920C8 /* fl.once~.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B826E4B41F314AA800B920C8 /* fl.once~.cpp */; };
|
||||
B82A042523043E1B00F887E7 /* HISSTools_FFT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B85435731F65BF03001BA1AA /* HISSTools_FFT.cpp */; };
|
||||
B82CC23D1F851CCD00077ECB /* MaxAudioAPI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B87E879819C8F61A00B1D0CD /* MaxAudioAPI.framework */; };
|
||||
B82CC24B1F851DBC00077ECB /* fl.streamid~.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B82CC24A1F851DBC00077ECB /* fl.streamid~.cpp */; };
|
||||
B83E029F206674D4005925DD /* PDClass_Base.h in Headers */ = {isa = PBXBuildFile; fileRef = B83E0297206674CD005925DD /* PDClass_Base.h */; };
|
||||
@@ -128,6 +129,13 @@
|
||||
B854357A1F65BF03001BA1AA /* HISSTools_FFT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B85435731F65BF03001BA1AA /* HISSTools_FFT.cpp */; };
|
||||
B854357B1F65BF03001BA1AA /* HISSTools_FFT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B85435731F65BF03001BA1AA /* HISSTools_FFT.cpp */; };
|
||||
B854357C1F65BF03001BA1AA /* HISSTools_FFT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B85435731F65BF03001BA1AA /* HISSTools_FFT.cpp */; };
|
||||
B85536DD22FEB88100D10495 /* FrameLib_Info.h in Headers */ = {isa = PBXBuildFile; fileRef = B83F0461223A76CF00AF1F8E /* FrameLib_Info.h */; };
|
||||
B85536DE22FEB88100D10495 /* FrameLib_FIRPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = B8A2100422FCD88E00DF86D8 /* FrameLib_FIRPhase.h */; };
|
||||
B85536E722FEB88100D10495 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B88F558E207AB15C007774AD /* Accelerate.framework */; };
|
||||
B85536E822FEB88100D10495 /* libframelib.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B89ABA901FA73483006DAD53 /* libframelib.a */; };
|
||||
B85536E922FEB88100D10495 /* MaxAudioAPI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B87E879819C8F61A00B1D0CD /* MaxAudioAPI.framework */; };
|
||||
B85536F022FEB8F600D10495 /* FrameLib_KernelSmooth.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B85536D622FEB74E00D10495 /* FrameLib_KernelSmooth.cpp */; };
|
||||
B85536F222FEC0E800D10495 /* fl.kernelsmooth~.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B85536F122FEB91F00D10495 /* fl.kernelsmooth~.cpp */; };
|
||||
B85B689D19F1CEDC002D6F1D /* MaxAudioAPI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B87E879819C8F61A00B1D0CD /* MaxAudioAPI.framework */; };
|
||||
B85B68A719F1CF56002D6F1D /* fl.sallenkey~.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B85B689519F1CEB7002D6F1D /* fl.sallenkey~.cpp */; };
|
||||
B85B68B119F1D38F002D6F1D /* MaxAudioAPI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B87E879819C8F61A00B1D0CD /* MaxAudioAPI.framework */; };
|
||||
@@ -318,6 +326,16 @@
|
||||
B8A112902076CDEA000C74FC /* FrameLib_ToHost.h in Headers */ = {isa = PBXBuildFile; fileRef = B8A1128E2076CDEA000C74FC /* FrameLib_ToHost.h */; };
|
||||
B8A112922076DFAE000C74FC /* fl.tomax~.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B8A82AA21F75104E005CC75A /* fl.tomax~.cpp */; };
|
||||
B8A1F5BE1D5370DE00FA5FFC /* NumericTesting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B8A1F5BD1D5370DE00FA5FFC /* NumericTesting.cpp */; };
|
||||
B8A20FEF22FCD7E300DF86D8 /* FrameLib_Info.h in Headers */ = {isa = PBXBuildFile; fileRef = B83F0461223A76CF00AF1F8E /* FrameLib_Info.h */; };
|
||||
B8A20FF622FCD7E300DF86D8 /* libframelib.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B89ABA901FA73483006DAD53 /* libframelib.a */; };
|
||||
B8A20FF722FCD7E300DF86D8 /* MaxAudioAPI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B87E879819C8F61A00B1D0CD /* MaxAudioAPI.framework */; };
|
||||
B8A20FFF22FCD82700DF86D8 /* HISSTools_FFT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B85435731F65BF03001BA1AA /* HISSTools_FFT.cpp */; };
|
||||
B8A2100122FCD84500DF86D8 /* fl.firphase~.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B8A2100022FCD84500DF86D8 /* fl.firphase~.cpp */; };
|
||||
B8A2100222FCD84500DF86D8 /* fl.firphase~.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B8A2100022FCD84500DF86D8 /* fl.firphase~.cpp */; };
|
||||
B8A2100522FCD88F00DF86D8 /* FrameLib_FIRPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B8A2100322FCD88E00DF86D8 /* FrameLib_FIRPhase.cpp */; };
|
||||
B8A2100622FCD88F00DF86D8 /* FrameLib_FIRPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B8A2100322FCD88E00DF86D8 /* FrameLib_FIRPhase.cpp */; };
|
||||
B8A2100722FCD88F00DF86D8 /* FrameLib_FIRPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = B8A2100422FCD88E00DF86D8 /* FrameLib_FIRPhase.h */; };
|
||||
B8A2100822FCDC8800DF86D8 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B88F558E207AB15C007774AD /* Accelerate.framework */; };
|
||||
B8A46DF91F6EB3060032F831 /* FrameLib_RandGen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B80059BD1DAF96340073A866 /* FrameLib_RandGen.cpp */; };
|
||||
B8A46E041F6EB3770032F831 /* MemoryTesting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B8A46E031F6EB3770032F831 /* MemoryTesting.cpp */; };
|
||||
B8A46E051F6EB39E0032F831 /* FrameLib_Threading.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B8EDFD281DB0577D00833096 /* FrameLib_Threading.cpp */; };
|
||||
@@ -786,6 +804,13 @@
|
||||
remoteGlobalIDString = B89ABA8F1FA73483006DAD53;
|
||||
remoteInfo = framelib;
|
||||
};
|
||||
B85536DB22FEB88100D10495 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 089C1669FE841209C02AAC07 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = B89ABA8F1FA73483006DAD53;
|
||||
remoteInfo = framelib;
|
||||
};
|
||||
B85E1D3E20C8408E00DEEE6E /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 089C1669FE841209C02AAC07 /* Project object */;
|
||||
@@ -870,6 +895,13 @@
|
||||
remoteGlobalIDString = B89ABA8F1FA73483006DAD53;
|
||||
remoteInfo = FrameLib_Framework;
|
||||
};
|
||||
B8A20FED22FCD7E300DF86D8 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 089C1669FE841209C02AAC07 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = B89ABA8F1FA73483006DAD53;
|
||||
remoteInfo = framelib;
|
||||
};
|
||||
B8ACCA9320AF14770054E1E0 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 089C1669FE841209C02AAC07 /* Project object */;
|
||||
@@ -2017,6 +2049,10 @@
|
||||
B826E4AE1F31490100B920C8 /* FrameLib_Once.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FrameLib_Once.cpp; sourceTree = "<group>"; };
|
||||
B826E4AF1F31490100B920C8 /* FrameLib_Once.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FrameLib_Once.h; sourceTree = "<group>"; };
|
||||
B826E4B41F314AA800B920C8 /* fl.once~.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "fl.once~.cpp"; sourceTree = "<group>"; };
|
||||
B82A03F22301C6F400F887E7 /* SpectralProcessor.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = SpectralProcessor.hpp; sourceTree = "<group>"; };
|
||||
B82A03F52302DB2600F887E7 /* SpectralFunctions.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = SpectralFunctions.hpp; sourceTree = "<group>"; };
|
||||
B82A03F62302E49E00F887E7 /* SuperCollider.app */ = {isa = PBXFileReference; lastKnownFileType = wrapper.application; name = SuperCollider.app; path = ../../../../../Applications/SuperCollider.app; sourceTree = "<group>"; };
|
||||
B82A03F82302E58600F887E7 /* scsynth */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; name = scsynth; path = ../../../../../Applications/SuperCollider.app/Contents/Resources/scsynth; sourceTree = "<group>"; };
|
||||
B82CC2441F851CCD00077ECB /* fl.streamid~.mxo */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "fl.streamid~.mxo"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
B82CC2461F851D6F00077ECB /* FrameLib_StreamID.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FrameLib_StreamID.cpp; sourceTree = "<group>"; };
|
||||
B82CC2471F851D6F00077ECB /* FrameLib_StreamID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FrameLib_StreamID.h; sourceTree = "<group>"; };
|
||||
@@ -2066,6 +2102,11 @@
|
||||
B85435721F65BF03001BA1AA /* HISSTools_FFT_Core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HISSTools_FFT_Core.h; sourceTree = "<group>"; };
|
||||
B85435731F65BF03001BA1AA /* HISSTools_FFT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HISSTools_FFT.cpp; sourceTree = "<group>"; };
|
||||
B85435741F65BF03001BA1AA /* HISSTools_FFT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HISSTools_FFT.h; sourceTree = "<group>"; };
|
||||
B85536D622FEB74E00D10495 /* FrameLib_KernelSmooth.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FrameLib_KernelSmooth.cpp; sourceTree = "<group>"; };
|
||||
B85536D722FEB74F00D10495 /* FrameLib_KernelSmooth.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FrameLib_KernelSmooth.h; sourceTree = "<group>"; };
|
||||
B85536D822FEB7A100D10495 /* KernelSmoother.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = KernelSmoother.hpp; sourceTree = "<group>"; };
|
||||
B85536EE22FEB88100D10495 /* fl.kernelsmooth~.mxo */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "fl.kernelsmooth~.mxo"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
B85536F122FEB91F00D10495 /* fl.kernelsmooth~.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "fl.kernelsmooth~.cpp"; sourceTree = "<group>"; };
|
||||
B85753511F2E1FCB00478E9F /* FrameLib_Vector_Objects.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FrameLib_Vector_Objects.h; sourceTree = "<group>"; };
|
||||
B85753521F2E1FFA00478E9F /* FrameLib_Vector_Template.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FrameLib_Vector_Template.h; sourceTree = "<group>"; };
|
||||
B85753541F2E208100478E9F /* FrameLib_Binary_Objects.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FrameLib_Binary_Objects.h; path = Binary/FrameLib_Binary_Objects.h; sourceTree = "<group>"; };
|
||||
@@ -2195,7 +2236,6 @@
|
||||
B8891CF31F2C9A1400C5C4F0 /* FrameLib_iFFT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FrameLib_iFFT.cpp; sourceTree = "<group>"; };
|
||||
B8891CF51F2C9A3100C5C4F0 /* FrameLib_Multitaper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = FrameLib_Multitaper.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
|
||||
B8891CF71F2C9A4600C5C4F0 /* FrameLib_Convolve.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FrameLib_Convolve.cpp; sourceTree = "<group>"; };
|
||||
B8891CF91F2C9D4500C5C4F0 /* FrameLib_Spectral_Functions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FrameLib_Spectral_Functions.h; sourceTree = "<group>"; };
|
||||
B88A48292067DCC400CEB3AC /* FrameLib_SerialiseGraph.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FrameLib_SerialiseGraph.cpp; sourceTree = "<group>"; };
|
||||
B88A482A2067DCC400CEB3AC /* FrameLib_SerialiseGraph.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FrameLib_SerialiseGraph.h; sourceTree = "<group>"; };
|
||||
B88BD2171F03E40D0045E737 /* FrameLib_DSP.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = FrameLib_DSP.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
|
||||
@@ -2230,6 +2270,10 @@
|
||||
B8A1128E2076CDEA000C74FC /* FrameLib_ToHost.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FrameLib_ToHost.h; sourceTree = "<group>"; };
|
||||
B8A1F5BB1D5370DE00FA5FFC /* NumericTesting */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = NumericTesting; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
B8A1F5BD1D5370DE00FA5FFC /* NumericTesting.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = NumericTesting.cpp; sourceTree = "<group>"; };
|
||||
B8A20FFC22FCD7E300DF86D8 /* fl.firphase~.mxo */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "fl.firphase~.mxo"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
B8A2100022FCD84500DF86D8 /* fl.firphase~.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "fl.firphase~.cpp"; sourceTree = "<group>"; };
|
||||
B8A2100322FCD88E00DF86D8 /* FrameLib_FIRPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FrameLib_FIRPhase.cpp; sourceTree = "<group>"; };
|
||||
B8A2100422FCD88E00DF86D8 /* FrameLib_FIRPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FrameLib_FIRPhase.h; sourceTree = "<group>"; };
|
||||
B8A46E011F6EB3060032F831 /* MemoryTesting */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = MemoryTesting; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
B8A46E031F6EB3770032F831 /* MemoryTesting.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemoryTesting.cpp; sourceTree = "<group>"; };
|
||||
B8A4757019C9D9E30043DC65 /* FrameLib_Convolve.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FrameLib_Convolve.h; sourceTree = "<group>"; };
|
||||
@@ -2411,7 +2455,6 @@
|
||||
B8DCDB3820753A4F008361FA /* FrameLib_FromHost.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FrameLib_FromHost.h; sourceTree = "<group>"; };
|
||||
B8DE14DC0EB46B030050BDFE /* FrameLib_MaxClass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FrameLib_MaxClass.h; sourceTree = "<group>"; };
|
||||
B8DE5D911F06A5E4007B0601 /* FrameLib_Parameters.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FrameLib_Parameters.cpp; sourceTree = "<group>"; };
|
||||
B8DF113F1FBF117C00C6229D /* FrameLib_Convolution_Tools.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FrameLib_Convolution_Tools.h; sourceTree = "<group>"; };
|
||||
B8DF11401FBF970800C6229D /* fl.correlate~.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "fl.correlate~.cpp"; sourceTree = "<group>"; };
|
||||
B8DF11411FBF971600C6229D /* FrameLib_Correlate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FrameLib_Correlate.h; sourceTree = "<group>"; };
|
||||
B8DF11421FBF972200C6229D /* FrameLib_Correlate.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FrameLib_Correlate.cpp; sourceTree = "<group>"; };
|
||||
@@ -3039,6 +3082,16 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B85536E622FEB88100D10495 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B85536E722FEB88100D10495 /* Accelerate.framework in Frameworks */,
|
||||
B85536E822FEB88100D10495 /* libframelib.a in Frameworks */,
|
||||
B85536E922FEB88100D10495 /* MaxAudioAPI.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B85B689C19F1CEDC002D6F1D /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -3343,6 +3396,16 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B8A20FF522FCD7E300DF86D8 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B8A2100822FCDC8800DF86D8 /* Accelerate.framework in Frameworks */,
|
||||
B8A20FF622FCD7E300DF86D8 /* libframelib.a in Frameworks */,
|
||||
B8A20FF722FCD7E300DF86D8 /* MaxAudioAPI.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B8A46DFA1F6EB3060032F831 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -4193,6 +4256,8 @@
|
||||
B8EA6B882203209E00D23A86 /* fl.chain~.mxo */,
|
||||
B8EA6BA42203AEE500D23A86 /* fl.pattern~.mxo */,
|
||||
B83F045C223A762800AF1F8E /* fl.info~.mxo */,
|
||||
B8A20FFC22FCD7E300DF86D8 /* fl.firphase~.mxo */,
|
||||
B85536EE22FEB88100D10495 /* fl.kernelsmooth~.mxo */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@@ -4350,7 +4415,6 @@
|
||||
B850749619F1BB7C002315F4 /* Spectral */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B8DF113F1FBF117C00C6229D /* FrameLib_Convolution_Tools.h */,
|
||||
B846E61119F15A12005E9718 /* FrameLib_Window.h */,
|
||||
B8891CEF1F2C99E000C5C4F0 /* FrameLib_Window.cpp */,
|
||||
B87E875319C8EA4900B1D0CD /* FrameLib_FFT.h */,
|
||||
@@ -4363,6 +4427,8 @@
|
||||
B8891CF71F2C9A4600C5C4F0 /* FrameLib_Convolve.cpp */,
|
||||
B8DF11411FBF971600C6229D /* FrameLib_Correlate.h */,
|
||||
B8DF11421FBF972200C6229D /* FrameLib_Correlate.cpp */,
|
||||
B8A2100422FCD88E00DF86D8 /* FrameLib_FIRPhase.h */,
|
||||
B8A2100322FCD88E00DF86D8 /* FrameLib_FIRPhase.cpp */,
|
||||
);
|
||||
path = Spectral;
|
||||
sourceTree = "<group>";
|
||||
@@ -4372,7 +4438,6 @@
|
||||
children = (
|
||||
B8886F7E1FB7D715001C843E /* FrameLib_RingBuffer.h */,
|
||||
B8886F7F1FB7D715001C843E /* FrameLib_VectorSet.h */,
|
||||
B8891CF91F2C9D4500C5C4F0 /* FrameLib_Spectral_Functions.h */,
|
||||
B8F3EE171F34DB6C00D0E98E /* FrameLib_Scaling_Functions.h */,
|
||||
B861EB9F19CA2DCE00B89477 /* FrameLib_Sort_Functions.h */,
|
||||
B8C680371B80F2B800B74B90 /* FrameLib_RandGen.h */,
|
||||
@@ -4479,6 +4544,8 @@
|
||||
B88F5558207A5873007774AD /* FrameLib_Reverse.cpp */,
|
||||
B8EA6B942203AEC700D23A86 /* FrameLib_Pattern.h */,
|
||||
B8EA6BA92203B07800D23A86 /* FrameLib_Pattern.cpp */,
|
||||
B85536D722FEB74F00D10495 /* FrameLib_KernelSmooth.h */,
|
||||
B85536D622FEB74E00D10495 /* FrameLib_KernelSmooth.cpp */,
|
||||
);
|
||||
path = Vector;
|
||||
sourceTree = "<group>";
|
||||
@@ -4529,6 +4596,8 @@
|
||||
B89C1A4F2069A969009CA55B /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B82A03F82302E58600F887E7 /* scsynth */,
|
||||
B82A03F62302E49E00F887E7 /* SuperCollider.app */,
|
||||
B88F558E207AB15C007774AD /* Accelerate.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
@@ -4586,6 +4655,7 @@
|
||||
B85C8FCD1E605B28004D7D40 /* fl.multitaper~.cpp */,
|
||||
B87E877419C8EEEB00B1D0CD /* fl.fft~.cpp */,
|
||||
B87E877719C8F45700B1D0CD /* fl.ifft~.cpp */,
|
||||
B8A2100022FCD84500DF86D8 /* fl.firphase~.cpp */,
|
||||
);
|
||||
path = Spectral;
|
||||
sourceTree = "<group>";
|
||||
@@ -4625,11 +4695,14 @@
|
||||
B8A70CDE19C11171005BA4E3 /* Dependencies */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B8AD883419C7C2B500FFA238 /* SIMDSupport.hpp */,
|
||||
B8C89C061F55C67C00B4E700 /* WindowFunctions.hpp */,
|
||||
B8C2D6061F6BF933009A7C96 /* Interpolation.hpp */,
|
||||
B85536D822FEB7A100D10495 /* KernelSmoother.hpp */,
|
||||
B8AD883419C7C2B500FFA238 /* SIMDSupport.hpp */,
|
||||
B82A03F52302DB2600F887E7 /* SpectralFunctions.hpp */,
|
||||
B82A03F22301C6F400F887E7 /* SpectralProcessor.hpp */,
|
||||
B8C89C071F56D24500B4E700 /* Statistics.hpp */,
|
||||
B8C2D6071F6BFF60009A7C96 /* TableReader.hpp */,
|
||||
B8C89C061F55C67C00B4E700 /* WindowFunctions.hpp */,
|
||||
B87E876619C8EEB900B1D0CD /* HISSTools_FFT */,
|
||||
B8F6E4DA199D24820073E06D /* tlsf */,
|
||||
);
|
||||
@@ -5061,6 +5134,7 @@
|
||||
B8EA6BA62203AF5800D23A86 /* fl.pattern~.cpp */,
|
||||
B88F556F207A59E9007774AD /* fl.reverse~.cpp */,
|
||||
B84A406F1FD73EA700A30455 /* fl.accumpoint~.cpp */,
|
||||
B85536F122FEB91F00D10495 /* fl.kernelsmooth~.cpp */,
|
||||
);
|
||||
path = Vector;
|
||||
sourceTree = "<group>";
|
||||
@@ -5529,6 +5603,15 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B85536DC22FEB88100D10495 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B85536DD22FEB88100D10495 /* FrameLib_Info.h in Headers */,
|
||||
B85536DE22FEB88100D10495 /* FrameLib_FIRPhase.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B85B689719F1CEDC002D6F1D /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -5754,6 +5837,15 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B8A20FEE22FCD7E300DF86D8 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B8A20FEF22FCD7E300DF86D8 /* FrameLib_Info.h in Headers */,
|
||||
B8A2100722FCD88F00DF86D8 /* FrameLib_FIRPhase.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B8A4757419C9DDCD0043DC65 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -7523,6 +7615,26 @@
|
||||
productReference = B84BE8871C1F63E500A55F8C /* fl.medianfilter~.mxo */;
|
||||
productType = "com.apple.product-type.bundle";
|
||||
};
|
||||
B85536D922FEB88100D10495 /* fl.kernelsmooth~ */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = B85536EA22FEB88100D10495 /* Build configuration list for PBXNativeTarget "fl.kernelsmooth~" */;
|
||||
buildPhases = (
|
||||
B85536DC22FEB88100D10495 /* Headers */,
|
||||
B85536DF22FEB88100D10495 /* Resources */,
|
||||
B85536E022FEB88100D10495 /* Sources */,
|
||||
B85536E622FEB88100D10495 /* Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
B85536DA22FEB88100D10495 /* PBXTargetDependency */,
|
||||
);
|
||||
name = "fl.kernelsmooth~";
|
||||
productInstallPath = "$(HOME)/Library/Bundles";
|
||||
productName = MSPExternal;
|
||||
productReference = B85536EE22FEB88100D10495 /* fl.kernelsmooth~.mxo */;
|
||||
productType = "com.apple.product-type.bundle";
|
||||
};
|
||||
B85B689619F1CEDC002D6F1D /* fl.sallenkey~ */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = B85B68A019F1CEDC002D6F1D /* Build configuration list for PBXNativeTarget "fl.sallenkey~" */;
|
||||
@@ -8195,6 +8307,26 @@
|
||||
productReference = B8A1F5BB1D5370DE00FA5FFC /* NumericTesting */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
B8A20FEB22FCD7E300DF86D8 /* fl.firphase~ */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = B8A20FF822FCD7E300DF86D8 /* Build configuration list for PBXNativeTarget "fl.firphase~" */;
|
||||
buildPhases = (
|
||||
B8A20FEE22FCD7E300DF86D8 /* Headers */,
|
||||
B8A20FF022FCD7E300DF86D8 /* Resources */,
|
||||
B8A20FF122FCD7E300DF86D8 /* Sources */,
|
||||
B8A20FF522FCD7E300DF86D8 /* Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
B8A20FEC22FCD7E300DF86D8 /* PBXTargetDependency */,
|
||||
);
|
||||
name = "fl.firphase~";
|
||||
productInstallPath = "$(HOME)/Library/Bundles";
|
||||
productName = MSPExternal;
|
||||
productReference = B8A20FFC22FCD7E300DF86D8 /* fl.firphase~.mxo */;
|
||||
productType = "com.apple.product-type.bundle";
|
||||
};
|
||||
B8A46DF51F6EB3060032F831 /* MemoryTesting */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = B8A46DFC1F6EB3060032F831 /* Build configuration list for PBXNativeTarget "MemoryTesting" */;
|
||||
@@ -9630,6 +9762,8 @@
|
||||
B8A46DF51F6EB3060032F831 /* MemoryTesting */,
|
||||
B89ABA8F1FA73483006DAD53 /* framelib */,
|
||||
B8BA6FD12078D49200D3DB3D /* framelib_objects */,
|
||||
B88C0A3021733BF9007A65C0 /* FrameLib */,
|
||||
B83E029B206674D4005925DD /* framelib_pd */,
|
||||
B8CA31DE199A20BE005F30A1 /* fl.pack~ */,
|
||||
8D01CCC60486CAD60068D4B7 /* fl.unpack~ */,
|
||||
B8CA3215199A29C8005F30A1 /* fl.interval~ */,
|
||||
@@ -9792,8 +9926,8 @@
|
||||
B8EA6B792203209E00D23A86 /* fl.chain~ */,
|
||||
B8EA6B952203AEE500D23A86 /* fl.pattern~ */,
|
||||
B83F044D223A762800AF1F8E /* fl.info~ */,
|
||||
B83E029B206674D4005925DD /* framelib_pd */,
|
||||
B88C0A3021733BF9007A65C0 /* FrameLib */,
|
||||
B8A20FEB22FCD7E300DF86D8 /* fl.firphase~ */,
|
||||
B85536D922FEB88100D10495 /* fl.kernelsmooth~ */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@@ -10247,6 +10381,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B85536DF22FEB88100D10495 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B85B689819F1CEDC002D6F1D /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -10464,6 +10605,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B8A20FF022FCD7E300DF86D8 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B8A4757519C9DDCD0043DC65 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -11490,6 +11638,16 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B85536E022FEB88100D10495 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B85536F022FEB8F600D10495 /* FrameLib_KernelSmooth.cpp in Sources */,
|
||||
B85536F222FEC0E800D10495 /* fl.kernelsmooth~.cpp in Sources */,
|
||||
B82A042523043E1B00F887E7 /* HISSTools_FFT.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B85B689919F1CEDC002D6F1D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -11799,12 +11957,24 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B8A2100522FCD88F00DF86D8 /* FrameLib_FIRPhase.cpp in Sources */,
|
||||
B8A1F5BE1D5370DE00FA5FFC /* NumericTesting.cpp in Sources */,
|
||||
B8B961DD1F1000D500D174F2 /* FrameLib_FixedPoint.cpp in Sources */,
|
||||
B8A2100122FCD84500DF86D8 /* fl.firphase~.cpp in Sources */,
|
||||
B80059BF1DAF96340073A866 /* FrameLib_RandGen.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B8A20FF122FCD7E300DF86D8 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B8A2100622FCD88F00DF86D8 /* FrameLib_FIRPhase.cpp in Sources */,
|
||||
B8A2100222FCD84500DF86D8 /* fl.firphase~.cpp in Sources */,
|
||||
B8A20FFF22FCD82700DF86D8 /* HISSTools_FFT.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B8A46DF61F6EB3060032F831 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -12550,6 +12720,11 @@
|
||||
target = B89ABA8F1FA73483006DAD53 /* framelib */;
|
||||
targetProxy = B84A405D1FD73E5C00A30455 /* PBXContainerItemProxy */;
|
||||
};
|
||||
B85536DA22FEB88100D10495 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = B89ABA8F1FA73483006DAD53 /* framelib */;
|
||||
targetProxy = B85536DB22FEB88100D10495 /* PBXContainerItemProxy */;
|
||||
};
|
||||
B85E1D3D20C8408E00DEEE6E /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = B89ABA8F1FA73483006DAD53 /* framelib */;
|
||||
@@ -12610,6 +12785,11 @@
|
||||
target = B89ABA8F1FA73483006DAD53 /* framelib */;
|
||||
targetProxy = B89ABA9E1FA734E7006DAD53 /* PBXContainerItemProxy */;
|
||||
};
|
||||
B8A20FEC22FCD7E300DF86D8 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = B89ABA8F1FA73483006DAD53 /* framelib */;
|
||||
targetProxy = B8A20FED22FCD7E300DF86D8 /* PBXContainerItemProxy */;
|
||||
};
|
||||
B8ACCA9220AF14770054E1E0 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = B89ABA8F1FA73483006DAD53 /* framelib */;
|
||||
@@ -17539,6 +17719,94 @@
|
||||
};
|
||||
name = Deployment;
|
||||
};
|
||||
B85536EB22FEB88100D10495 /* Development */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = B81CE02C207FC02000EAC64C /* Config_FrameLib_Max.xcconfig */;
|
||||
buildSettings = {
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEBUGGING_SYMBOLS = YES;
|
||||
GCC_ALTIVEC_EXTENSIONS = YES;
|
||||
GCC_AUTO_VECTORIZATION = YES;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_FIX_AND_CONTINUE = YES;
|
||||
GCC_ENABLE_SSE3_EXTENSIONS = YES;
|
||||
GCC_ENABLE_TRIGRAPHS = NO;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
GCC_MODEL_PPC64 = NO;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_UNROLL_LOOPS = NO;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
|
||||
GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
|
||||
GCC_WARN_UNKNOWN_PRAGMAS = NO;
|
||||
OTHER_REZFLAGS = "";
|
||||
WARNING_CFLAGS = (
|
||||
"-Wmost",
|
||||
"-Wno-four-char-constants",
|
||||
"-Wno-unknown-pragmas",
|
||||
);
|
||||
ZERO_LINK = YES;
|
||||
};
|
||||
name = Development;
|
||||
};
|
||||
B85536EC22FEB88100D10495 /* Deployment */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = B81CE02C207FC02000EAC64C /* Config_FrameLib_Max.xcconfig */;
|
||||
buildSettings = {
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
GCC_ALTIVEC_EXTENSIONS = YES;
|
||||
GCC_AUTO_VECTORIZATION = YES;
|
||||
GCC_DEBUGGING_SYMBOLS = default;
|
||||
GCC_ENABLE_FIX_AND_CONTINUE = NO;
|
||||
GCC_ENABLE_SSE3_EXTENSIONS = YES;
|
||||
GCC_ENABLE_TRIGRAPHS = NO;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
GCC_MODEL_PPC64 = NO;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_UNROLL_LOOPS = NO;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
|
||||
GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
|
||||
GCC_WARN_UNKNOWN_PRAGMAS = NO;
|
||||
OTHER_REZFLAGS = "";
|
||||
WARNING_CFLAGS = (
|
||||
"-Wmost",
|
||||
"-Wno-four-char-constants",
|
||||
"-Wno-unknown-pragmas",
|
||||
);
|
||||
ZERO_LINK = NO;
|
||||
};
|
||||
name = Deployment;
|
||||
};
|
||||
B85536ED22FEB88100D10495 /* Public Testing */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = B81CE02C207FC02000EAC64C /* Config_FrameLib_Max.xcconfig */;
|
||||
buildSettings = {
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
GCC_ALTIVEC_EXTENSIONS = YES;
|
||||
GCC_AUTO_VECTORIZATION = YES;
|
||||
GCC_DEBUGGING_SYMBOLS = default;
|
||||
GCC_ENABLE_FIX_AND_CONTINUE = NO;
|
||||
GCC_ENABLE_SSE3_EXTENSIONS = YES;
|
||||
GCC_ENABLE_TRIGRAPHS = NO;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
GCC_MODEL_PPC64 = NO;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_UNROLL_LOOPS = NO;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
|
||||
GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
|
||||
GCC_WARN_UNKNOWN_PRAGMAS = NO;
|
||||
OTHER_REZFLAGS = "";
|
||||
WARNING_CFLAGS = (
|
||||
"-Wmost",
|
||||
"-Wno-four-char-constants",
|
||||
"-Wno-unknown-pragmas",
|
||||
);
|
||||
ZERO_LINK = NO;
|
||||
};
|
||||
name = "Public Testing";
|
||||
};
|
||||
B85A959F1F60A56C00D6C72B /* Public Testing */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = B80F698A19A77384008F748B /* Config_FrameLib.xcconfig */;
|
||||
@@ -23362,6 +23630,94 @@
|
||||
};
|
||||
name = Deployment;
|
||||
};
|
||||
B8A20FF922FCD7E300DF86D8 /* Development */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = B81CE02C207FC02000EAC64C /* Config_FrameLib_Max.xcconfig */;
|
||||
buildSettings = {
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEBUGGING_SYMBOLS = YES;
|
||||
GCC_ALTIVEC_EXTENSIONS = YES;
|
||||
GCC_AUTO_VECTORIZATION = YES;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_FIX_AND_CONTINUE = YES;
|
||||
GCC_ENABLE_SSE3_EXTENSIONS = YES;
|
||||
GCC_ENABLE_TRIGRAPHS = NO;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
GCC_MODEL_PPC64 = NO;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_UNROLL_LOOPS = NO;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
|
||||
GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
|
||||
GCC_WARN_UNKNOWN_PRAGMAS = NO;
|
||||
OTHER_REZFLAGS = "";
|
||||
WARNING_CFLAGS = (
|
||||
"-Wmost",
|
||||
"-Wno-four-char-constants",
|
||||
"-Wno-unknown-pragmas",
|
||||
);
|
||||
ZERO_LINK = YES;
|
||||
};
|
||||
name = Development;
|
||||
};
|
||||
B8A20FFA22FCD7E300DF86D8 /* Deployment */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = B81CE02C207FC02000EAC64C /* Config_FrameLib_Max.xcconfig */;
|
||||
buildSettings = {
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
GCC_ALTIVEC_EXTENSIONS = YES;
|
||||
GCC_AUTO_VECTORIZATION = YES;
|
||||
GCC_DEBUGGING_SYMBOLS = default;
|
||||
GCC_ENABLE_FIX_AND_CONTINUE = NO;
|
||||
GCC_ENABLE_SSE3_EXTENSIONS = YES;
|
||||
GCC_ENABLE_TRIGRAPHS = NO;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
GCC_MODEL_PPC64 = NO;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_UNROLL_LOOPS = NO;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
|
||||
GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
|
||||
GCC_WARN_UNKNOWN_PRAGMAS = NO;
|
||||
OTHER_REZFLAGS = "";
|
||||
WARNING_CFLAGS = (
|
||||
"-Wmost",
|
||||
"-Wno-four-char-constants",
|
||||
"-Wno-unknown-pragmas",
|
||||
);
|
||||
ZERO_LINK = NO;
|
||||
};
|
||||
name = Deployment;
|
||||
};
|
||||
B8A20FFB22FCD7E300DF86D8 /* Public Testing */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = B81CE02C207FC02000EAC64C /* Config_FrameLib_Max.xcconfig */;
|
||||
buildSettings = {
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
GCC_ALTIVEC_EXTENSIONS = YES;
|
||||
GCC_AUTO_VECTORIZATION = YES;
|
||||
GCC_DEBUGGING_SYMBOLS = default;
|
||||
GCC_ENABLE_FIX_AND_CONTINUE = NO;
|
||||
GCC_ENABLE_SSE3_EXTENSIONS = YES;
|
||||
GCC_ENABLE_TRIGRAPHS = NO;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
GCC_MODEL_PPC64 = NO;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_UNROLL_LOOPS = NO;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
|
||||
GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
|
||||
GCC_WARN_UNKNOWN_PRAGMAS = NO;
|
||||
OTHER_REZFLAGS = "";
|
||||
WARNING_CFLAGS = (
|
||||
"-Wmost",
|
||||
"-Wno-four-char-constants",
|
||||
"-Wno-unknown-pragmas",
|
||||
);
|
||||
ZERO_LINK = NO;
|
||||
};
|
||||
name = "Public Testing";
|
||||
};
|
||||
B8A46DFD1F6EB3060032F831 /* Development */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@@ -29126,6 +29482,16 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Development;
|
||||
};
|
||||
B85536EA22FEB88100D10495 /* Build configuration list for PBXNativeTarget "fl.kernelsmooth~" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
B85536EB22FEB88100D10495 /* Development */,
|
||||
B85536EC22FEB88100D10495 /* Deployment */,
|
||||
B85536ED22FEB88100D10495 /* Public Testing */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Development;
|
||||
};
|
||||
B85B68A019F1CEDC002D6F1D /* Build configuration list for PBXNativeTarget "fl.sallenkey~" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
@@ -29466,6 +29832,16 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Development;
|
||||
};
|
||||
B8A20FF822FCD7E300DF86D8 /* Build configuration list for PBXNativeTarget "fl.firphase~" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
B8A20FF922FCD7E300DF86D8 /* Development */,
|
||||
B8A20FFA22FCD7E300DF86D8 /* Deployment */,
|
||||
B8A20FFB22FCD7E300DF86D8 /* Public Testing */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Development;
|
||||
};
|
||||
B8A46DFC1F6EB3060032F831 /* Build configuration list for PBXNativeTarget "MemoryTesting" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
||||
Reference in New Issue
Block a user