parent
b610a89158
commit
c2c89b6aaa
@ -0,0 +1,26 @@ |
|||||||
|
#include "BerVibrato.h" |
||||||
|
|
||||||
|
BerVibrato::BerVibrato() |
||||||
|
: depth(0) |
||||||
|
, sampleRate(0) |
||||||
|
{ |
||||||
|
setFrequency(VIBRATO_FREQUENCY_DEFAULT_HZ); |
||||||
|
setDepth(VIBRATO_DEPTH_DEFAULT_PERCENT / 100); |
||||||
|
} |
||||||
|
|
||||||
|
void BerVibrato::initialize(float sr) |
||||||
|
{ |
||||||
|
sampleRate = sr; |
||||||
|
lfo.initialize(sampleRate, VIBRATO_FREQUENCY_DEFAULT_HZ); |
||||||
|
buffer.resize(BASE_DELAY_SEC * sampleRate * 2); |
||||||
|
} |
||||||
|
|
||||||
|
void BerVibrato::setFrequency(float frequency) |
||||||
|
{ |
||||||
|
lfo.setFrequency(frequency); |
||||||
|
} |
||||||
|
|
||||||
|
void BerVibrato::setDepth(float dt) |
||||||
|
{ |
||||||
|
depth = dt; |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
#ifndef VIBRATO_PROCESSOR_H |
||||||
|
#define VIBRATO_PROCESSOR_H |
||||||
|
|
||||||
|
#include "Lfo.h" |
||||||
|
#include "RingBuffer.h" |
||||||
|
|
||||||
|
const float BASE_DELAY_SEC = 0.002; // 2 ms
|
||||||
|
const float VIBRATO_FREQUENCY_DEFAULT_HZ = 2; |
||||||
|
const float VIBRATO_FREQUENCY_MAX_HZ = 14; |
||||||
|
const float VIBRATO_DEPTH_DEFAULT_PERCENT = 50; |
||||||
|
|
||||||
|
class BerVibrato |
||||||
|
{ |
||||||
|
public: |
||||||
|
BerVibrato(); |
||||||
|
|
||||||
|
public: |
||||||
|
void initialize(float sampleRate); |
||||||
|
void process(float* input, float*output, int numberOfSamples); |
||||||
|
void setFrequency(float frequency); |
||||||
|
void setDepth(float depth); |
||||||
|
|
||||||
|
public: |
||||||
|
INLINE float processOneSample(float input) |
||||||
|
{ |
||||||
|
float lfoValue = lfo.getValue(); |
||||||
|
int maxDelay = BASE_DELAY_SEC * sampleRate; |
||||||
|
|
||||||
|
float delay = lfoValue * depth * maxDelay; |
||||||
|
delay += additionalDelay; |
||||||
|
|
||||||
|
float value = buffer.getHermiteAt(delay); |
||||||
|
|
||||||
|
buffer.write_margined(input); |
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private: |
||||||
|
float sampleRate; |
||||||
|
Lfo lfo; |
||||||
|
RingBuffer buffer; |
||||||
|
float depth; |
||||||
|
|
||||||
|
static const int additionalDelay = 1; |
||||||
|
}; |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,39 @@ |
|||||||
|
#include "Lfo.h" |
||||||
|
#define _USE_MATH_DEFINES |
||||||
|
#include <math.h> /*sin*/ |
||||||
|
|
||||||
|
Lfo::Lfo()
|
||||||
|
: index(0), sampleRate(0), frequency(0), phase(0) |
||||||
|
{} |
||||||
|
|
||||||
|
Lfo::~Lfo(void) {} |
||||||
|
|
||||||
|
void Lfo::initialize(float sr, float freq)
|
||||||
|
{ |
||||||
|
sampleRate = sr; |
||||||
|
frequency = freq; |
||||||
|
} |
||||||
|
|
||||||
|
void Lfo::setFrequency(float freq)
|
||||||
|
{ |
||||||
|
frequency = freq; |
||||||
|
} |
||||||
|
|
||||||
|
void Lfo::setPhase(float ph) |
||||||
|
{ |
||||||
|
phase = ph; |
||||||
|
} |
||||||
|
|
||||||
|
float Lfo::getValue() |
||||||
|
{ |
||||||
|
const float dp = 2 * M_PI * frequency / sampleRate; // phase step
|
||||||
|
|
||||||
|
float value = sin(phase); |
||||||
|
value = (value + 1) * 0.5; // transform from [-1; 1] to [0; 1]
|
||||||
|
|
||||||
|
phase += dp; |
||||||
|
while(phase > 2 * M_PI) |
||||||
|
phase -= 2 * M_PI; |
||||||
|
|
||||||
|
return value;
|
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
#ifndef LFO_H_ |
||||||
|
#define LFO_H_ |
||||||
|
|
||||||
|
class Lfo
|
||||||
|
{ |
||||||
|
public: |
||||||
|
Lfo(); |
||||||
|
~Lfo(); |
||||||
|
|
||||||
|
void initialize(float sampleRate, float freq); |
||||||
|
void setFrequency(float freq); |
||||||
|
void setPhase(float phase); |
||||||
|
|
||||||
|
public: |
||||||
|
float getValue(); |
||||||
|
|
||||||
|
private: |
||||||
|
float sampleRate; |
||||||
|
float frequency; |
||||||
|
float phase; |
||||||
|
float index; |
||||||
|
}; |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,43 @@ |
|||||||
|
#include "RingBuffer.h" |
||||||
|
|
||||||
|
RingBuffer::RingBuffer() |
||||||
|
: size(0), writeIndex(0) |
||||||
|
{} |
||||||
|
|
||||||
|
void RingBuffer::resize(int sz) |
||||||
|
{ |
||||||
|
size = sz; |
||||||
|
buffer.resize(size + interpolatorMargin); |
||||||
|
} |
||||||
|
|
||||||
|
void RingBuffer::write(float sample) |
||||||
|
{ |
||||||
|
buffer[writeIndex] = sample; |
||||||
|
writeIndex++; |
||||||
|
if(writeIndex == size){ |
||||||
|
writeIndex = 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void RingBuffer::write_margined(float sample) |
||||||
|
{ |
||||||
|
buffer[writeIndex] = sample; |
||||||
|
|
||||||
|
if( writeIndex < interpolatorMargin ) |
||||||
|
{ |
||||||
|
buffer[size + writeIndex] = sample; |
||||||
|
} |
||||||
|
|
||||||
|
writeIndex++; |
||||||
|
if(writeIndex == size){ |
||||||
|
writeIndex = 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
float RingBuffer::readWithDelay(int delay){ |
||||||
|
int readIndex = writeIndex - delay; |
||||||
|
if (readIndex < 0){ |
||||||
|
readIndex += size; |
||||||
|
} |
||||||
|
return buffer[readIndex]; |
||||||
|
} |
@ -0,0 +1,58 @@ |
|||||||
|
#ifndef __RINGBUFFER_H |
||||||
|
#define __RINGBUFFER_H |
||||||
|
|
||||||
|
#ifdef _MSC_VER |
||||||
|
#define INLINE __forceinline |
||||||
|
#else |
||||||
|
#define INLINE inline |
||||||
|
#endif |
||||||
|
|
||||||
|
#include <vector> |
||||||
|
|
||||||
|
// Hermite polynomial interpolation
|
||||||
|
INLINE float getSampleHermite4p3o(float x, float *y) |
||||||
|
{ |
||||||
|
static float c0, c1, c2, c3; |
||||||
|
|
||||||
|
// 4-point, 3rd-order Hermite (x-form)
|
||||||
|
c0 = y[1]; |
||||||
|
c1 = (1.0/2.0)*(y[2]-y[0]); |
||||||
|
c2 = (y[0] - (5.0/2.0)*y[1]) + (2.0*y[2] - (1.0/2.0)*y[3]); |
||||||
|
c3 = (1.0/2.0)*(y[3]-y[0]) + (3.0/2.0)*(y[1]-y[2]); |
||||||
|
return ((c3*x+c2)*x+c1)*x+c0; |
||||||
|
} |
||||||
|
|
||||||
|
class RingBuffer |
||||||
|
{ |
||||||
|
public: |
||||||
|
RingBuffer(); |
||||||
|
|
||||||
|
void write(float sample); |
||||||
|
void write_margined(float sample); |
||||||
|
float readWithDelay(int delay); |
||||||
|
void resize(int size); |
||||||
|
|
||||||
|
public: |
||||||
|
INLINE float getHermiteAt(float delay) |
||||||
|
{ |
||||||
|
float fReadIndex = writeIndex - 1 - delay; |
||||||
|
while(fReadIndex < 0) |
||||||
|
fReadIndex += size; |
||||||
|
while(fReadIndex >= size) |
||||||
|
fReadIndex -= size; |
||||||
|
|
||||||
|
int iPart = (int)fReadIndex; // integer part of the delay
|
||||||
|
float fPart = fReadIndex - iPart; // fractional part of the delay
|
||||||
|
|
||||||
|
return getSampleHermite4p3o(fPart, &(buffer[iPart])); |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
std::vector<float> buffer; |
||||||
|
int writeIndex; |
||||||
|
int size; |
||||||
|
|
||||||
|
static const int interpolatorMargin = 3; |
||||||
|
}; |
||||||
|
|
||||||
|
#endif |
Loading…
Reference in new issue