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