@@ -3,6 +3,11 @@ | |||||
namespace rack { | namespace rack { | ||||
namespace dsp { | |||||
static const float FREQ_C4 = 261.6256f; | |||||
static const float FREQ_A4 = 440.0000f; | |||||
/** The normalized sinc function. https://en.wikipedia.org/wiki/Sinc_function */ | /** The normalized sinc function. https://en.wikipedia.org/wiki/Sinc_function */ | ||||
@@ -42,13 +47,14 @@ inline float exponentialBipolar(float b, float x) { | |||||
return (std::pow(b, x) - std::pow(b, -x)) / a; | return (std::pow(b, x) - std::pow(b, -x)) / a; | ||||
} | } | ||||
inline float gainToDb(float gain) { | |||||
return std::log10(gain) * 20.f; | |||||
inline float amplitudeToDb(float amp) { | |||||
return std::log10(amp) * 20.f; | |||||
} | } | ||||
inline float dbToGain(float db) { | |||||
inline float dbToAmplitude(float db) { | |||||
return std::pow(10.f, db / 20.f); | return std::pow(10.f, db / 20.f); | ||||
} | } | ||||
} // namespace dsp | |||||
} // namespace rack | } // namespace rack |
@@ -1,2 +0,0 @@ | |||||
#pragma once | |||||
#include "resampler.hpp" |
@@ -1,8 +1,9 @@ | |||||
#pragma once | #pragma once | ||||
#include "math.hpp" | |||||
#include "dsp/common.hpp" | |||||
namespace rack { | namespace rack { | ||||
namespace dsp { | |||||
/** 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. */ | ||||
@@ -102,4 +103,5 @@ struct PulseGenerator { | |||||
}; | }; | ||||
} // namespace dsp | |||||
} // namespace rack | } // namespace rack |
@@ -1,8 +1,10 @@ | |||||
#pragma once | #pragma once | ||||
#include "math.hpp" | |||||
#include "dsp/common.hpp" | |||||
namespace rack { | namespace rack { | ||||
namespace dsp { | |||||
struct RCFilter { | struct RCFilter { | ||||
float c = 0.f; | float c = 0.f; | ||||
@@ -81,4 +83,5 @@ struct ExponentialFilter { | |||||
}; | }; | ||||
} // namespace dsp | |||||
} // namespace rack | } // namespace rack |
@@ -1,9 +1,11 @@ | |||||
#pragma once | #pragma once | ||||
#include "dsp/functions.hpp" | |||||
#include "dsp/common.hpp" | |||||
#include <pffft.h> | #include <pffft.h> | ||||
namespace rack { | namespace rack { | ||||
namespace dsp { | |||||
/** Performs a direct sum convolution */ | /** Performs a direct sum convolution */ | ||||
inline float convolveNaive(const float *in, const float *kernel, int len) { | inline float convolveNaive(const float *in, const float *kernel, int len) { | ||||
@@ -145,4 +147,5 @@ struct RealTimeConvolver { | |||||
}; | }; | ||||
} // namespace dsp | |||||
} // namespace rack | } // namespace rack |
@@ -1,8 +1,10 @@ | |||||
#pragma once | #pragma once | ||||
#include <stdlib.h> | |||||
#include "dsp/common.hpp" | |||||
namespace rack { | 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 */ | /** 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> | template <size_t CHANNELS> | ||||
@@ -10,4 +12,6 @@ struct Frame { | |||||
float samples[CHANNELS]; | float samples[CHANNELS]; | ||||
}; | }; | ||||
} // namespace dsp | |||||
} // namespace rack | } // namespace rack |
@@ -1,8 +1,10 @@ | |||||
#pragma once | #pragma once | ||||
#include "math.hpp" | |||||
#include "dsp/common.hpp" | |||||
namespace rack { | namespace rack { | ||||
namespace dsp { | |||||
// Pre-made minBLEP samples in minBLEP.cpp | // Pre-made minBLEP samples in minBLEP.cpp | ||||
extern const float minblep_16_32[]; | extern const float minblep_16_32[]; | ||||
@@ -33,4 +35,6 @@ struct MinBLEP { | |||||
} | } | ||||
}; | }; | ||||
} // namespace dsp | |||||
} // namespace rack | } // namespace rack |
@@ -1,8 +1,10 @@ | |||||
#pragma once | #pragma once | ||||
#include "dsp/common.hpp" | |||||
namespace rack { | namespace rack { | ||||
namespace ode { | |||||
namespace dsp { | |||||
/** The callback function `f` in each of these stepping functions must have the signature | /** The callback function `f` in each of these stepping functions must have the signature | ||||
@@ -84,5 +86,6 @@ void stepRK4(float t, float dt, float x[], int len, F f) { | |||||
} | } | ||||
} | } | ||||
} // namespace ode | |||||
} // namespace dsp | |||||
} // namespace rack | } // namespace rack |
@@ -1,13 +1,16 @@ | |||||
#pragma once | #pragma once | ||||
#include "frame.hpp" | |||||
#include "ringbuffer.hpp" | |||||
#include "fir.hpp" | |||||
#include "dsp/common.hpp" | |||||
#include "dsp/frame.hpp" | |||||
#include "dsp/ringbuffer.hpp" | |||||
#include "dsp/fir.hpp" | |||||
#include <assert.h> | #include <assert.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <speex/speex_resampler.h> | #include <speex/speex_resampler.h> | ||||
namespace rack { | namespace rack { | ||||
namespace dsp { | |||||
template<int CHANNELS> | template<int CHANNELS> | ||||
struct SampleRateConverter { | struct SampleRateConverter { | ||||
@@ -170,4 +173,5 @@ struct Upsampler { | |||||
}; | }; | ||||
} // namespace dsp | |||||
} // namespace rack | } // namespace rack |
@@ -1,9 +1,11 @@ | |||||
#pragma once | #pragma once | ||||
#include "common.hpp" | |||||
#include "dsp/common.hpp" | |||||
#include <string.h> | #include <string.h> | ||||
namespace rack { | namespace rack { | ||||
namespace dsp { | |||||
/** A simple cyclic buffer. | /** A simple cyclic buffer. | ||||
S must be a power of 2. | S must be a power of 2. | ||||
@@ -196,4 +198,6 @@ struct AppleRingBuffer { | |||||
} | } | ||||
}; | }; | ||||
} // namespace dsp | |||||
} // namespace rack | } // namespace rack |
@@ -1,2 +0,0 @@ | |||||
#pragma once | |||||
#include "resampler.hpp" |
@@ -1,8 +1,9 @@ | |||||
#pragma once | #pragma once | ||||
#include "math.hpp" | |||||
#include "dsp/common.hpp" | |||||
namespace rack { | namespace rack { | ||||
namespace dsp { | |||||
struct VUMeter { | struct VUMeter { | ||||
@@ -28,4 +29,5 @@ struct VUMeter { | |||||
}; | }; | ||||
} // namespace dsp | |||||
} // namespace rack | } // namespace rack |
@@ -80,6 +80,16 @@ | |||||
#include "plugin/Model.hpp" | #include "plugin/Model.hpp" | ||||
#include "plugin/callbacks.hpp" | #include "plugin/callbacks.hpp" | ||||
#include "dsp/common.hpp" | |||||
#include "dsp/digital.hpp" | |||||
#include "dsp/filter.hpp" | |||||
#include "dsp/fir.hpp" | |||||
#include "dsp/frame.hpp" | |||||
#include "dsp/minblep.hpp" | |||||
#include "dsp/ode.hpp" | |||||
#include "dsp/resampler.hpp" | |||||
#include "dsp/ringbuffer.hpp" | |||||
#include "dsp/vumeter.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -147,4 +147,19 @@ DEPRECATED inline float engineGetSampleTime() { | |||||
return context()->engine->getSampleTime(); | return context()->engine->getSampleTime(); | ||||
} | } | ||||
//////////////////// | |||||
// dsp | |||||
//////////////////// | |||||
using namespace dsp; | |||||
inline float gainToDb(float gain) { | |||||
return dsp::amplitudeToDb(gain); | |||||
} | |||||
inline float dbToGain(float db) { | |||||
return dsp::dbToAmplitude(db); | |||||
} | |||||
} // namespace rack | } // namespace rack |
@@ -1,7 +1,5 @@ | |||||
#include "Core.hpp" | #include "Core.hpp" | ||||
#include "audio.hpp" | #include "audio.hpp" | ||||
#include "dsp/resampler.hpp" | |||||
#include "dsp/ringbuffer.hpp" | |||||
#include <mutex> | #include <mutex> | ||||
#include <chrono> | #include <chrono> | ||||
#include <thread> | #include <thread> | ||||
@@ -23,9 +21,9 @@ struct AudioInterfaceIO : audio::IO { | |||||
std::mutex audioMutex; | std::mutex audioMutex; | ||||
std::condition_variable audioCv; | std::condition_variable audioCv; | ||||
// Audio thread produces, engine thread consumes | // Audio thread produces, engine thread consumes | ||||
DoubleRingBuffer<Frame<AUDIO_INPUTS>, (1<<15)> inputBuffer; | |||||
dsp::DoubleRingBuffer<dsp::Frame<AUDIO_INPUTS>, (1<<15)> inputBuffer; | |||||
// Audio thread consumes, engine thread produces | // Audio thread consumes, engine thread produces | ||||
DoubleRingBuffer<Frame<AUDIO_OUTPUTS>, (1<<15)> outputBuffer; | |||||
dsp::DoubleRingBuffer<dsp::Frame<AUDIO_OUTPUTS>, (1<<15)> outputBuffer; | |||||
bool active = false; | bool active = false; | ||||
~AudioInterfaceIO() { | ~AudioInterfaceIO() { | ||||
@@ -46,7 +44,7 @@ struct AudioInterfaceIO : audio::IO { | |||||
for (int i = 0; i < frames; i++) { | for (int i = 0; i < frames; i++) { | ||||
if (inputBuffer.full()) | if (inputBuffer.full()) | ||||
break; | break; | ||||
Frame<AUDIO_INPUTS> inputFrame; | |||||
dsp::Frame<AUDIO_INPUTS> inputFrame; | |||||
memset(&inputFrame, 0, sizeof(inputFrame)); | memset(&inputFrame, 0, sizeof(inputFrame)); | ||||
memcpy(&inputFrame, &input[numInputs * i], numInputs * sizeof(float)); | memcpy(&inputFrame, &input[numInputs * i], numInputs * sizeof(float)); | ||||
inputBuffer.push(inputFrame); | inputBuffer.push(inputFrame); | ||||
@@ -62,7 +60,7 @@ struct AudioInterfaceIO : audio::IO { | |||||
if (audioCv.wait_for(lock, timeout, cond)) { | if (audioCv.wait_for(lock, timeout, cond)) { | ||||
// Consume audio block | // Consume audio block | ||||
for (int i = 0; i < frames; i++) { | for (int i = 0; i < frames; i++) { | ||||
Frame<AUDIO_OUTPUTS> f = outputBuffer.shift(); | |||||
dsp::Frame<AUDIO_OUTPUTS> f = outputBuffer.shift(); | |||||
for (int j = 0; j < numOutputs; j++) { | for (int j = 0; j < numOutputs; j++) { | ||||
output[numOutputs*i + j] = clamp(f.samples[j], -1.f, 1.f); | output[numOutputs*i + j] = clamp(f.samples[j], -1.f, 1.f); | ||||
} | } | ||||
@@ -112,12 +110,12 @@ struct AudioInterface : Module { | |||||
int lastNumOutputs = -1; | int lastNumOutputs = -1; | ||||
int lastNumInputs = -1; | int lastNumInputs = -1; | ||||
SampleRateConverter<AUDIO_INPUTS> inputSrc; | |||||
SampleRateConverter<AUDIO_OUTPUTS> outputSrc; | |||||
dsp::SampleRateConverter<AUDIO_INPUTS> inputSrc; | |||||
dsp::SampleRateConverter<AUDIO_OUTPUTS> outputSrc; | |||||
// in rack's sample rate | // in rack's sample rate | ||||
DoubleRingBuffer<Frame<AUDIO_INPUTS>, 16> inputBuffer; | |||||
DoubleRingBuffer<Frame<AUDIO_OUTPUTS>, 16> outputBuffer; | |||||
dsp::DoubleRingBuffer<dsp::Frame<AUDIO_INPUTS>, 16> inputBuffer; | |||||
dsp::DoubleRingBuffer<dsp::Frame<AUDIO_OUTPUTS>, 16> outputBuffer; | |||||
AudioInterface() { | AudioInterface() { | ||||
setup(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | setup(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | ||||
@@ -177,7 +175,7 @@ void AudioInterface::step() { | |||||
} | } | ||||
// Take input from buffer | // Take input from buffer | ||||
Frame<AUDIO_INPUTS> inputFrame; | |||||
dsp::Frame<AUDIO_INPUTS> inputFrame; | |||||
if (!inputBuffer.empty()) { | if (!inputBuffer.empty()) { | ||||
inputFrame = inputBuffer.shift(); | inputFrame = inputBuffer.shift(); | ||||
} | } | ||||
@@ -195,7 +193,7 @@ void AudioInterface::step() { | |||||
if (audioIO.active && audioIO.numOutputs > 0) { | if (audioIO.active && audioIO.numOutputs > 0) { | ||||
// Get and push output SRC frame | // Get and push output SRC frame | ||||
if (!outputBuffer.full()) { | if (!outputBuffer.full()) { | ||||
Frame<AUDIO_OUTPUTS> outputFrame; | |||||
dsp::Frame<AUDIO_OUTPUTS> outputFrame; | |||||
for (int i = 0; i < AUDIO_OUTPUTS; i++) { | for (int i = 0; i < AUDIO_OUTPUTS; i++) { | ||||
outputFrame.samples[i] = inputs[AUDIO_INPUT + i].getVoltage() / 10.f; | outputFrame.samples[i] = inputs[AUDIO_INPUT + i].getVoltage() / 10.f; | ||||
} | } | ||||
@@ -1,6 +1,5 @@ | |||||
#include "Core.hpp" | #include "Core.hpp" | ||||
#include "midi.hpp" | #include "midi.hpp" | ||||
#include "dsp/filter.hpp" | |||||
struct MIDICCToCVInterface : Module { | struct MIDICCToCVInterface : Module { | ||||
@@ -20,7 +19,7 @@ struct MIDICCToCVInterface : Module { | |||||
midi::InputQueue midiInput; | midi::InputQueue midiInput; | ||||
int8_t ccs[128]; | int8_t ccs[128]; | ||||
ExponentialFilter ccFilters[16]; | |||||
dsp::ExponentialFilter ccFilters[16]; | |||||
int learningId = -1; | int learningId = -1; | ||||
int learnedCcs[16] = {}; | int learnedCcs[16] = {}; | ||||
@@ -1,7 +1,5 @@ | |||||
#include "Core.hpp" | #include "Core.hpp" | ||||
#include "midi.hpp" | #include "midi.hpp" | ||||
#include "dsp/digital.hpp" | |||||
#include "dsp/filter.hpp" | |||||
#include <algorithm> | #include <algorithm> | ||||
@@ -35,14 +33,14 @@ struct MIDIToCVInterface : Module { | |||||
midi::InputQueue midiInput; | midi::InputQueue midiInput; | ||||
uint8_t mod = 0; | uint8_t mod = 0; | ||||
ExponentialFilter modFilter; | |||||
dsp::ExponentialFilter modFilter; | |||||
uint16_t pitch = 8192; | uint16_t pitch = 8192; | ||||
ExponentialFilter pitchFilter; | |||||
PulseGenerator retriggerPulse; | |||||
PulseGenerator clockPulses[2]; | |||||
PulseGenerator startPulse; | |||||
PulseGenerator stopPulse; | |||||
PulseGenerator continuePulse; | |||||
dsp::ExponentialFilter pitchFilter; | |||||
dsp::PulseGenerator retriggerPulse; | |||||
dsp::PulseGenerator clockPulses[2]; | |||||
dsp::PulseGenerator startPulse; | |||||
dsp::PulseGenerator stopPulse; | |||||
dsp::PulseGenerator continuePulse; | |||||
int clock = 0; | int clock = 0; | ||||
int divisions[2]; | int divisions[2]; | ||||
@@ -1,6 +1,5 @@ | |||||
#include "Core.hpp" | #include "Core.hpp" | ||||
#include "midi.hpp" | #include "midi.hpp" | ||||
#include "dsp/digital.hpp" | |||||
#include <algorithm> | #include <algorithm> | ||||