Merge pull request #30 from AlexHarker/ir-manipulation

Ir manipulation
This commit is contained in:
AlexHarker
2019-08-28 14:01:26 +01:00
committed by GitHub
37 changed files with 2096 additions and 748 deletions
+41
View File
@@ -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);
+2 -2
View File
@@ -1,6 +1,6 @@
#ifndef INTERPOLATION_H
#define INTERPOLATION_H
#ifndef INTERPOLATION_HPP
#define INTERPOLATION_HPP
// Enumeration of interpolation types
+251
View File
@@ -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
+8 -4
View File
@@ -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);
}
+440
View File
@@ -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
+526
View File
@@ -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
+2 -2
View File
@@ -1,6 +1,6 @@
#ifndef STATISTICS_H
#define STATISTICS_H
#ifndef STATISTICS_HPP
#define STATISTICS_HPP
#include <algorithm>
#include <numeric>
+2 -2
View File
@@ -1,6 +1,6 @@
#ifndef TABLEREADER_H
#define TABLEREADER_H
#ifndef TABLEREADER_HPP
#define TABLEREADER_HPP
#include "SIMDSupport.hpp"
#include "Interpolation.hpp"
+6 -1
View File
@@ -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
+4 -1
View File
@@ -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);
-1
View File
@@ -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);
+19
View File
@@ -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
+1 -1
View File
@@ -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
+16 -12
View File
@@ -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
+9 -26
View File
@@ -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);
}
}
+7 -9
View File
@@ -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
+15 -35
View File
@@ -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);
}
+8 -10
View File
@@ -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
+384 -8
View File
@@ -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 = (