| @@ -5,7 +5,7 @@ | |||||
| namespace rack { | namespace rack { | ||||
| /** Digital signal processing routines for plugins | |||||
| /** Digital signal processing routines | |||||
| */ | */ | ||||
| namespace dsp { | namespace dsp { | ||||
| @@ -69,5 +69,12 @@ inline float exponentialBipolar(float b, float x) { | |||||
| } | } | ||||
| /** Useful for storing arrays of samples in ring buffers and casting them to `float*` to be used by interleaved processors, like SampleRateConverter */ | |||||
| template <size_t CHANNELS> | |||||
| struct Frame { | |||||
| float samples[CHANNELS]; | |||||
| }; | |||||
| } // namespace dsp | } // namespace dsp | ||||
| } // namespace rack | } // namespace rack | ||||
| @@ -6,87 +6,64 @@ namespace rack { | |||||
| namespace dsp { | namespace dsp { | ||||
| /** Detects when a boolean changes from false to true */ | |||||
| struct BooleanTrigger { | |||||
| bool state = true; | |||||
| void reset() { | |||||
| state = true; | |||||
| } | |||||
| bool process(bool state) { | |||||
| bool triggered = (state && !this->state); | |||||
| this->state = state; | |||||
| return triggered; | |||||
| } | |||||
| }; | |||||
| /** Turns HIGH when value reaches 1.f, turns LOW when value reaches 0.f. */ | /** Turns HIGH when value reaches 1.f, turns LOW when value reaches 0.f. */ | ||||
| struct SchmittTrigger { | struct SchmittTrigger { | ||||
| enum State { | |||||
| LOW, | |||||
| HIGH, | |||||
| UNKNOWN | |||||
| }; | |||||
| State state; | |||||
| SchmittTrigger() { | |||||
| reset(); | |||||
| } | |||||
| bool state = true; | |||||
| void reset() { | void reset() { | ||||
| state = UNKNOWN; | |||||
| state = true; | |||||
| } | } | ||||
| /** Updates the state of the Schmitt Trigger given a value. | /** Updates the state of the Schmitt Trigger given a value. | ||||
| Returns true if triggered, i.e. the value increases from 0 to 1. | Returns true if triggered, i.e. the value increases from 0 to 1. | ||||
| If different trigger thresholds are needed, use | If different trigger thresholds are needed, use | ||||
| process(math::rescale(in, low, high, 0.f, 1.f)) | |||||
| process(rescale(in, low, high, 0.f, 1.f)) | |||||
| for example. | for example. | ||||
| */ | */ | ||||
| bool process(float in) { | bool process(float in) { | ||||
| switch (state) { | |||||
| case LOW: | |||||
| if (in >= 1.f) { | |||||
| state = HIGH; | |||||
| return true; | |||||
| } | |||||
| break; | |||||
| case HIGH: | |||||
| if (in <= 0.f) { | |||||
| state = LOW; | |||||
| } | |||||
| break; | |||||
| default: | |||||
| if (in >= 1.f) { | |||||
| state = HIGH; | |||||
| } | |||||
| else if (in <= 0.f) { | |||||
| state = LOW; | |||||
| } | |||||
| break; | |||||
| if (state) { | |||||
| // HIGH to LOW | |||||
| if (in <= 0.f) { | |||||
| state = false; | |||||
| } | |||||
| } | |||||
| else { | |||||
| // LOW to HIGH | |||||
| if (in >= 1.f) { | |||||
| state = true; | |||||
| return true; | |||||
| } | |||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| bool isHigh() { | bool isHigh() { | ||||
| return state == HIGH; | |||||
| } | |||||
| }; | |||||
| /** Detects when a boolean changes from false to true */ | |||||
| struct BooleanTrigger { | |||||
| bool state; | |||||
| BooleanTrigger() { | |||||
| reset(); | |||||
| } | |||||
| void reset() { | |||||
| state = true; | |||||
| } | |||||
| bool process(bool state) { | |||||
| bool triggered = (state && !this->state); | |||||
| this->state = state; | |||||
| return triggered; | |||||
| return state; | |||||
| } | } | ||||
| }; | }; | ||||
| /** When triggered, holds a high value for a specified time before going low again */ | /** When triggered, holds a high value for a specified time before going low again */ | ||||
| struct PulseGenerator { | struct PulseGenerator { | ||||
| float remaining; | |||||
| PulseGenerator() { | |||||
| reset(); | |||||
| } | |||||
| float remaining = 0.f; | |||||
| /** Immediately disables the pulse */ | /** Immediately disables the pulse */ | ||||
| void reset() { | void reset() { | ||||
| @@ -113,16 +90,13 @@ struct PulseGenerator { | |||||
| struct Timer { | struct Timer { | ||||
| float time; | |||||
| Timer() { | |||||
| reset(); | |||||
| } | |||||
| float time = 0.f; | |||||
| void reset() { | void reset() { | ||||
| time = 0.f; | time = 0.f; | ||||
| } | } | ||||
| /** Returns the time since last reset or initialization. */ | |||||
| float process(float deltaTime) { | float process(float deltaTime) { | ||||
| time += deltaTime; | time += deltaTime; | ||||
| return time; | return time; | ||||
| @@ -131,26 +105,22 @@ struct Timer { | |||||
| struct ClockDivider { | struct ClockDivider { | ||||
| int clock; | |||||
| int division = 1; | |||||
| ClockDivider() { | |||||
| reset(); | |||||
| } | |||||
| uint32_t clock = 0; | |||||
| uint32_t division = 1; | |||||
| void reset() { | void reset() { | ||||
| clock = 0; | clock = 0; | ||||
| } | } | ||||
| void setDivision(int division) { | |||||
| void setDivision(uint32_t division) { | |||||
| this->division = division; | this->division = division; | ||||
| } | } | ||||
| int getDivision() { | |||||
| uint32_t getDivision() { | |||||
| return division; | return division; | ||||
| } | } | ||||
| int getClock() { | |||||
| uint32_t getClock() { | |||||
| return clock; | return clock; | ||||
| } | } | ||||
| @@ -7,13 +7,16 @@ namespace rack { | |||||
| namespace dsp { | namespace dsp { | ||||
| template<typename T> | |||||
| T *alignedNew(size_t len) { | |||||
| /** Allocates an array to 64-byte boundaries. | |||||
| Must call alignedFree() on the buffer to free. | |||||
| */ | |||||
| template <typename T> | |||||
| T *alignedMalloc(size_t len) { | |||||
| return (T*) pffft_aligned_malloc(len * sizeof(T)); | return (T*) pffft_aligned_malloc(len * sizeof(T)); | ||||
| } | } | ||||
| template<typename T> | |||||
| void alignedDelete(T *p) { | |||||
| template <typename T> | |||||
| void alignedFree(T *p) { | |||||
| pffft_aligned_free(p); | pffft_aligned_free(p); | ||||
| } | } | ||||
| @@ -21,6 +24,7 @@ void alignedDelete(T *p) { | |||||
| /** Real-valued FFT context. | /** Real-valued FFT context. | ||||
| Wrapper for [PFFFT](https://bitbucket.org/jpommier/pffft/) | Wrapper for [PFFFT](https://bitbucket.org/jpommier/pffft/) | ||||
| `length` must be a multiple of 32. | `length` must be a multiple of 32. | ||||
| Buffers must be aligned to 16-byte boundaries, e.g. with alignedMalloc(). | |||||
| */ | */ | ||||
| struct RealFFT { | struct RealFFT { | ||||
| PFFFT_Setup *setup; | PFFFT_Setup *setup; | ||||
| @@ -106,29 +106,20 @@ struct ExponentialSlewLimiter { | |||||
| \f$ \frac{dy}{dt} = x \lambda \f$. | \f$ \frac{dy}{dt} = x \lambda \f$. | ||||
| */ | */ | ||||
| struct ExponentialFilter { | struct ExponentialFilter { | ||||
| float out; | |||||
| float out = 0.f; | |||||
| float lambda = 0.f; | float lambda = 0.f; | ||||
| ExponentialFilter() { | |||||
| reset(); | |||||
| } | |||||
| void reset() { | void reset() { | ||||
| out = NAN; | |||||
| out = 0.f; | |||||
| } | } | ||||
| float process(float deltaTime, float in) { | float process(float deltaTime, float in) { | ||||
| if (std::isnan(out)) { | |||||
| float y = out + (in - out) * lambda * deltaTime; | |||||
| // If no change was made between the old and new output, assume float granularity is too small and snap output to input | |||||
| if (out == y) | |||||
| out = in; | out = in; | ||||
| } | |||||
| else { | |||||
| float y = out + (in - out) * lambda * deltaTime; | |||||
| // If no change was detected, assume float granularity is too small and snap output to input | |||||
| if (out == y) | |||||
| out = in; | |||||
| else | |||||
| out = y; | |||||
| } | |||||
| else | |||||
| out = y; | |||||
| return out; | return out; | ||||
| } | } | ||||
| @@ -1,17 +0,0 @@ | |||||
| #pragma once | |||||
| #include "dsp/common.hpp" | |||||
| namespace rack { | |||||
| namespace dsp { | |||||
| /** Useful for storing arrays of samples in ring buffers and casting them to `float*` to be used by interleaved processors, like SampleRateConverter */ | |||||
| template <size_t CHANNELS> | |||||
| struct Frame { | |||||
| float samples[CHANNELS]; | |||||
| }; | |||||
| } // namespace dsp | |||||
| } // namespace rack | |||||
| @@ -15,7 +15,7 @@ https://www.cs.cmu.edu/~eli/papers/icmc01-hardsync.pdf | |||||
| void minBlepImpulse(int z, int o, float *output); | void minBlepImpulse(int z, int o, float *output); | ||||
| template<int Z, int O> | |||||
| template <int Z, int O> | |||||
| struct MinBlepGenerator { | struct MinBlepGenerator { | ||||
| float buf[2 * Z] = {}; | float buf[2 * Z] = {}; | ||||
| int pos = 0; | int pos = 0; | ||||
| @@ -26,7 +26,7 @@ For example, the following solves the system x''(t) = -x(t) using a fixed timest | |||||
| */ | */ | ||||
| /** Solves an ODE system using the 1st order Euler method */ | /** Solves an ODE system using the 1st order Euler method */ | ||||
| template<typename F> | |||||
| template <typename F> | |||||
| void stepEuler(float t, float dt, float x[], int len, F f) { | void stepEuler(float t, float dt, float x[], int len, F f) { | ||||
| float k[len]; | float k[len]; | ||||
| @@ -37,7 +37,7 @@ void stepEuler(float t, float dt, float x[], int len, F f) { | |||||
| } | } | ||||
| /** Solves an ODE system using the 2nd order Runge-Kutta method */ | /** Solves an ODE system using the 2nd order Runge-Kutta method */ | ||||
| template<typename F> | |||||
| template <typename F> | |||||
| void stepRK2(float t, float dt, float x[], int len, F f) { | void stepRK2(float t, float dt, float x[], int len, F f) { | ||||
| float k1[len]; | float k1[len]; | ||||
| float k2[len]; | float k2[len]; | ||||
| @@ -56,7 +56,7 @@ void stepRK2(float t, float dt, float x[], int len, F f) { | |||||
| } | } | ||||
| /** Solves an ODE system using the 4th order Runge-Kutta method */ | /** Solves an ODE system using the 4th order Runge-Kutta method */ | ||||
| template<typename F> | |||||
| template <typename F> | |||||
| void stepRK4(float t, float dt, float x[], int len, F f) { | void stepRK4(float t, float dt, float x[], int len, F f) { | ||||
| float k1[len]; | float k1[len]; | ||||
| float k2[len]; | float k2[len]; | ||||
| @@ -1,6 +1,5 @@ | |||||
| #pragma once | #pragma once | ||||
| #include "dsp/common.hpp" | #include "dsp/common.hpp" | ||||
| #include "dsp/frame.hpp" | |||||
| #include "dsp/ringbuffer.hpp" | #include "dsp/ringbuffer.hpp" | ||||
| #include "dsp/fir.hpp" | #include "dsp/fir.hpp" | ||||
| #include "dsp/window.hpp" | #include "dsp/window.hpp" | ||||
| @@ -14,10 +13,10 @@ namespace dsp { | |||||
| /** Resamples by a fixed rational factor. */ | /** Resamples by a fixed rational factor. */ | ||||
| template<int CHANNELS> | |||||
| template <int MAX_CHANNELS> | |||||
| struct SampleRateConverter { | struct SampleRateConverter { | ||||
| SpeexResamplerState *st = NULL; | SpeexResamplerState *st = NULL; | ||||
| int channels = CHANNELS; | |||||
| int channels = MAX_CHANNELS; | |||||
| int quality = SPEEX_RESAMPLER_QUALITY_DEFAULT; | int quality = SPEEX_RESAMPLER_QUALITY_DEFAULT; | ||||
| int inRate = 44100; | int inRate = 44100; | ||||
| int outRate = 44100; | int outRate = 44100; | ||||
| @@ -31,9 +30,9 @@ struct SampleRateConverter { | |||||
| } | } | ||||
| } | } | ||||
| /** Sets the number of channels to actually process. This can be at most CHANNELS. */ | |||||
| /** Sets the number of channels to actually process. This can be at most MAX_CHANNELS. */ | |||||
| void setChannels(int channels) { | void setChannels(int channels) { | ||||
| assert(channels <= CHANNELS); | |||||
| assert(channels <= MAX_CHANNELS); | |||||
| if (channels == this->channels) | if (channels == this->channels) | ||||
| return; | return; | ||||
| this->channels = channels; | this->channels = channels; | ||||
| @@ -68,13 +67,13 @@ struct SampleRateConverter { | |||||
| assert(st); | assert(st); | ||||
| assert(err == RESAMPLER_ERR_SUCCESS); | assert(err == RESAMPLER_ERR_SUCCESS); | ||||
| speex_resampler_set_input_stride(st, CHANNELS); | |||||
| speex_resampler_set_output_stride(st, CHANNELS); | |||||
| speex_resampler_set_input_stride(st, MAX_CHANNELS); | |||||
| speex_resampler_set_output_stride(st, MAX_CHANNELS); | |||||
| } | } | ||||
| } | } | ||||
| /** `in` and `out` are interlaced with the number of channels */ | /** `in` and `out` are interlaced with the number of channels */ | ||||
| void process(const Frame<CHANNELS> *in, int *inFrames, Frame<CHANNELS> *out, int *outFrames) { | |||||
| void process(const Frame<MAX_CHANNELS> *in, int *inFrames, Frame<MAX_CHANNELS> *out, int *outFrames) { | |||||
| assert(in); | assert(in); | ||||
| assert(inFrames); | assert(inFrames); | ||||
| assert(out); | assert(out); | ||||
| @@ -95,7 +94,7 @@ struct SampleRateConverter { | |||||
| else { | else { | ||||
| // Simply copy the buffer without conversion | // Simply copy the buffer without conversion | ||||
| int frames = std::min(*inFrames, *outFrames); | int frames = std::min(*inFrames, *outFrames); | ||||
| std::memcpy(out, in, frames * sizeof(Frame<CHANNELS>)); | |||||
| std::memcpy(out, in, frames * sizeof(Frame<MAX_CHANNELS>)); | |||||
| *inFrames = frames; | *inFrames = frames; | ||||
| *outFrames = frames; | *outFrames = frames; | ||||
| } | } | ||||
| @@ -104,7 +103,7 @@ struct SampleRateConverter { | |||||
| /** Downsamples by an integer factor. */ | /** Downsamples by an integer factor. */ | ||||
| template<int OVERSAMPLE, int QUALITY> | |||||
| template <int OVERSAMPLE, int QUALITY> | |||||
| struct Decimator { | struct Decimator { | ||||
| float inBuffer[OVERSAMPLE*QUALITY]; | float inBuffer[OVERSAMPLE*QUALITY]; | ||||
| float kernel[OVERSAMPLE*QUALITY]; | float kernel[OVERSAMPLE*QUALITY]; | ||||
| @@ -139,7 +138,7 @@ struct Decimator { | |||||
| /** Upsamples by an integer factor. */ | /** Upsamples by an integer factor. */ | ||||
| template<int OVERSAMPLE, int QUALITY> | |||||
| template <int OVERSAMPLE, int QUALITY> | |||||
| struct Upsampler { | struct Upsampler { | ||||
| float inBuffer[QUALITY]; | float inBuffer[QUALITY]; | ||||
| float kernel[OVERSAMPLE*QUALITY]; | float kernel[OVERSAMPLE*QUALITY]; | ||||
| @@ -54,14 +54,10 @@ struct VuMeter2 { | |||||
| }; | }; | ||||
| Mode mode = PEAK; | Mode mode = PEAK; | ||||
| /** Either the smoothed peak or the mean-square of the brightness, depending on the mode. */ | /** Either the smoothed peak or the mean-square of the brightness, depending on the mode. */ | ||||
| float v; | |||||
| float v = 0.f; | |||||
| /** Inverse time constant in 1/seconds */ | /** Inverse time constant in 1/seconds */ | ||||
| float lambda = 30.f; | float lambda = 30.f; | ||||
| VuMeter2() { | |||||
| reset(); | |||||
| } | |||||
| void reset() { | void reset() { | ||||
| v = 0.f; | v = 0.f; | ||||
| } | } | ||||
| @@ -14,7 +14,7 @@ inline float hann(float p) { | |||||
| return 0.5f * (1.f - std::cos(2*M_PI * p)); | return 0.5f * (1.f - std::cos(2*M_PI * p)); | ||||
| } | } | ||||
| /** Applies the Hann window to a signal `x`. */ | |||||
| /** Multiplies the Hann window by a signal `x` of length `len` in-place. */ | |||||
| inline void hannWindow(float *x, int len) { | inline void hannWindow(float *x, int len) { | ||||
| for (int i = 0; i < len; i++) { | for (int i = 0; i < len; i++) { | ||||
| x[i] *= hann((float) i / (len - 1)); | x[i] *= hann((float) i / (len - 1)); | ||||
| @@ -36,7 +36,7 @@ inline int clamp(int x, int a, int b) { | |||||
| If `b < a`, switches the two values. | If `b < a`, switches the two values. | ||||
| */ | */ | ||||
| inline int clampSafe(int x, int a, int b) { | inline int clampSafe(int x, int a, int b) { | ||||
| return clamp(x, std::min(a, b), std::max(a, b)); | |||||
| return (a <= b) ? clamp(x, a, b) : clamp(x, b, a); | |||||
| } | } | ||||
| /** Euclidean modulus. Always returns `0 <= mod < b`. | /** Euclidean modulus. Always returns `0 <= mod < b`. | ||||
| @@ -101,14 +101,14 @@ inline float clamp(float x, float a, float b) { | |||||
| If `b < a`, switches the two values. | If `b < a`, switches the two values. | ||||
| */ | */ | ||||
| inline float clampSafe(float x, float a, float b) { | inline float clampSafe(float x, float a, float b) { | ||||
| return clamp(x, std::fmin(a, b), std::fmax(a, b)); | |||||
| return (a <= b) ? clamp(x, a, b) : clamp(x, b, a); | |||||
| } | } | ||||
| /** Returns 1 for positive numbers, -1 for negative numbers, and 0 for zero. | /** Returns 1 for positive numbers, -1 for negative numbers, and 0 for zero. | ||||
| See https://en.wikipedia.org/wiki/Sign_function. | See https://en.wikipedia.org/wiki/Sign_function. | ||||
| */ | */ | ||||
| inline float sgn(float x) { | inline float sgn(float x) { | ||||
| return x > 0.f ? 1.f : x < 0.f ? -1.f : 0.f; | |||||
| return x > 0.f ? 1.f : (x < 0.f ? -1.f : 0.f); | |||||
| } | } | ||||
| /** Converts -0.f to 0.f. Leaves all other values unchanged. */ | /** Converts -0.f to 0.f. Leaves all other values unchanged. */ | ||||
| @@ -119,9 +119,12 @@ inline float normalizeZero(float x) { | |||||
| /** Euclidean modulus. Always returns `0 <= mod < b`. | /** Euclidean modulus. Always returns `0 <= mod < b`. | ||||
| See https://en.wikipedia.org/wiki/Euclidean_division. | See https://en.wikipedia.org/wiki/Euclidean_division. | ||||
| */ | */ | ||||
| inline float eucMod(float a, float base) { | |||||
| float mod = std::fmod(a, base); | |||||
| return (mod >= 0.f) ? mod : mod + base; | |||||
| inline float eucMod(float a, float b) { | |||||
| int mod = std::fmod(a, b); | |||||
| if (mod < 0.f) { | |||||
| mod += b; | |||||
| } | |||||
| return mod; | |||||
| } | } | ||||
| /** Returns whether `a` is within epsilon distance from `b`. */ | /** Returns whether `a` is within epsilon distance from `b`. */ | ||||
| @@ -131,7 +134,7 @@ inline bool isNear(float a, float b, float epsilon = 1e-6f) { | |||||
| /** If the magnitude of `x` if less than epsilon, return 0. */ | /** If the magnitude of `x` if less than epsilon, return 0. */ | ||||
| inline float chop(float x, float epsilon = 1e-6f) { | inline float chop(float x, float epsilon = 1e-6f) { | ||||
| return isNear(x, 0.f, epsilon) ? 0.f : x; | |||||
| return std::fabs(x) <= epsilon ? 0.f : x; | |||||
| } | } | ||||
| inline float rescale(float x, float xMin, float xMax, float yMin, float yMax) { | inline float rescale(float x, float xMin, float xMax, float yMin, float yMax) { | ||||
| @@ -155,9 +158,9 @@ inline float interpolateLinear(const float *p, float x) { | |||||
| Arguments may be the same pointers. | Arguments may be the same pointers. | ||||
| Example: | Example: | ||||
| cmultf(&ar, &ai, ar, ai, br, bi); | |||||
| cmultf(ar, ai, br, bi, &ar, &ai); | |||||
| */ | */ | ||||
| inline void complexMult(float *cr, float *ci, float ar, float ai, float br, float bi) { | |||||
| inline void complexMult(float ar, float ai, float br, float bi, float *cr, float *ci) { | |||||
| *cr = ar * br - ai * bi; | *cr = ar * br - ai * bi; | ||||
| *ci = ar * bi + ai * br; | *ci = ar * bi + ai * br; | ||||
| } | } | ||||
| @@ -202,6 +205,9 @@ struct Vec { | |||||
| float dot(Vec b) const { | float dot(Vec b) const { | ||||
| return x * b.x + y * b.y; | return x * b.x + y * b.y; | ||||
| } | } | ||||
| float arg() const { | |||||
| return std::atan2(y, x); | |||||
| } | |||||
| float norm() const { | float norm() const { | ||||
| return std::hypot(x, y); | return std::hypot(x, y); | ||||
| } | } | ||||
| @@ -229,6 +235,9 @@ struct Vec { | |||||
| Vec max(Vec b) const { | Vec max(Vec b) const { | ||||
| return Vec(std::fmax(x, b.x), std::fmax(y, b.y)); | return Vec(std::fmax(x, b.x), std::fmax(y, b.y)); | ||||
| } | } | ||||
| Vec abs() const { | |||||
| return Vec(std::fabs(x), std::fabs(y)); | |||||
| } | |||||
| Vec round() const { | Vec round() const { | ||||
| return Vec(std::round(x), std::round(y)); | return Vec(std::round(x), std::round(y)); | ||||
| } | } | ||||
| @@ -323,7 +332,7 @@ struct Rect { | |||||
| r.pos.y = math::clampSafe(pos.y, bound.pos.y, bound.pos.y + bound.size.y - size.y); | r.pos.y = math::clampSafe(pos.y, bound.pos.y, bound.pos.y + bound.size.y - size.y); | ||||
| return r; | return r; | ||||
| } | } | ||||
| /** Expands this Rect to contain `b`. */ | |||||
| /** Returns the bounding box of the union of `this` and `b`. */ | |||||
| Rect expand(Rect b) const { | Rect expand(Rect b) const { | ||||
| Rect r; | Rect r; | ||||
| r.pos.x = std::fmin(pos.x, b.pos.x); | r.pos.x = std::fmin(pos.x, b.pos.x); | ||||
| @@ -84,7 +84,6 @@ | |||||
| #include "dsp/fft.hpp" | #include "dsp/fft.hpp" | ||||
| #include "dsp/filter.hpp" | #include "dsp/filter.hpp" | ||||
| #include "dsp/fir.hpp" | #include "dsp/fir.hpp" | ||||
| #include "dsp/frame.hpp" | |||||
| #include "dsp/minblep.hpp" | #include "dsp/minblep.hpp" | ||||
| #include "dsp/ode.hpp" | #include "dsp/ode.hpp" | ||||
| #include "dsp/resampler.hpp" | #include "dsp/resampler.hpp" | ||||
| @@ -45,6 +45,7 @@ DEPRECATED inline float rescalef(float x, float a, float b, float yMin, float yM | |||||
| DEPRECATED inline float crossf(float a, float b, float frac) {return crossfade(a, b, frac);} | DEPRECATED inline float crossf(float a, float b, float frac) {return crossfade(a, b, frac);} | ||||
| DEPRECATED inline float interpf(const float *p, float x) {return interpolateLinear(p, x);} | DEPRECATED inline float interpf(const float *p, float x) {return interpolateLinear(p, x);} | ||||
| DEPRECATED inline void cmultf(float *cr, float *ci, float ar, float ai, float br, float bi) {return complexMult(cr, ci, ar, ai, br, bi);} | DEPRECATED inline void cmultf(float *cr, float *ci, float ar, float ai, float br, float bi) {return complexMult(cr, ci, ar, ai, br, bi);} | ||||
| DEPRECATED inline void complexMult(float *cr, float *ci, float ar, float ai, float br, float bi) {complexMult(ar, ai, br, bi, cr, ci);} | |||||
| //////////////////// | //////////////////// | ||||
| // random | // random | ||||
| @@ -10,7 +10,7 @@ namespace dsp { | |||||
| void minBlepImpulse(int z, int o, float *output) { | void minBlepImpulse(int z, int o, float *output) { | ||||
| // Symmetric sinc array with `z` zero-crossings on each side | // Symmetric sinc array with `z` zero-crossings on each side | ||||
| int n = 2 * z * o; | int n = 2 * z * o; | ||||
| float *x = alignedNew<float>(n); | |||||
| float *x = alignedMalloc<float>(n); | |||||
| for (int i = 0; i < n; i++) { | for (int i = 0; i < n; i++) { | ||||
| float p = math::rescale((float) i, 0.f, (float) (n - 1), (float) -z, (float) z); | float p = math::rescale((float) i, 0.f, (float) (n - 1), (float) -z, (float) z); | ||||
| x[i] = sinc(p); | x[i] = sinc(p); | ||||
| @@ -20,7 +20,7 @@ void minBlepImpulse(int z, int o, float *output) { | |||||
| blackmanHarrisWindow(x, n); | blackmanHarrisWindow(x, n); | ||||
| // Real cepstrum | // Real cepstrum | ||||
| float *fx = alignedNew<float>(2*n); | |||||
| float *fx = alignedMalloc<float>(2*n); | |||||
| RealFFT rfft(n); | RealFFT rfft(n); | ||||
| rfft.rfft(x, fx); | rfft.rfft(x, fx); | ||||
| // fx = log(abs(fx)) | // fx = log(abs(fx)) | ||||
| @@ -73,8 +73,8 @@ void minBlepImpulse(int z, int o, float *output) { | |||||
| std::memcpy(output, x, n * sizeof(float)); | std::memcpy(output, x, n * sizeof(float)); | ||||
| // Cleanup | // Cleanup | ||||
| alignedDelete(x); | |||||
| alignedDelete(fx); | |||||
| alignedFree(x); | |||||
| alignedFree(fx); | |||||
| } | } | ||||