Merge branch 'master' of https://github.com/chrisherb/trnr-lib
This commit is contained in:
@@ -73,10 +73,10 @@ public:
|
|||||||
}
|
}
|
||||||
void processblock(t_sample** inputs, t_sample** outputs, int blockSize)
|
void processblock(t_sample** inputs, t_sample** outputs, int blockSize)
|
||||||
{
|
{
|
||||||
double* in1 = inputs[0];
|
t_sample* in1 = inputs[0];
|
||||||
double* in2 = inputs[1];
|
t_sample* in2 = inputs[1];
|
||||||
double* out1 = outputs[0];
|
t_sample* out1 = outputs[0];
|
||||||
double* out2 = outputs[1];
|
t_sample* out2 = outputs[1];
|
||||||
|
|
||||||
int inFramesToProcess = blockSize;
|
int inFramesToProcess = blockSize;
|
||||||
double overallscale = 1.0;
|
double overallscale = 1.0;
|
||||||
|
|||||||
@@ -73,10 +73,10 @@ public:
|
|||||||
}
|
}
|
||||||
void processblock(t_sample** inputs, t_sample** outputs, int blockSize)
|
void processblock(t_sample** inputs, t_sample** outputs, int blockSize)
|
||||||
{
|
{
|
||||||
double* in1 = inputs[0];
|
t_sample* in1 = inputs[0];
|
||||||
double* in2 = inputs[1];
|
t_sample* in2 = inputs[1];
|
||||||
double* out1 = outputs[0];
|
t_sample* out1 = outputs[0];
|
||||||
double* out2 = outputs[1];
|
t_sample* out2 = outputs[1];
|
||||||
|
|
||||||
int inFramesToProcess = blockSize;
|
int inFramesToProcess = blockSize;
|
||||||
double overallscale = 1.0;
|
double overallscale = 1.0;
|
||||||
|
|||||||
@@ -73,10 +73,10 @@ public:
|
|||||||
}
|
}
|
||||||
void processblock(t_sample** inputs, t_sample** outputs, int blockSize)
|
void processblock(t_sample** inputs, t_sample** outputs, int blockSize)
|
||||||
{
|
{
|
||||||
double* in1 = inputs[0];
|
t_sample* in1 = inputs[0];
|
||||||
double* in2 = inputs[1];
|
t_sample* in2 = inputs[1];
|
||||||
double* out1 = outputs[0];
|
t_sample* out1 = outputs[0];
|
||||||
double* out2 = outputs[1];
|
t_sample* out2 = outputs[1];
|
||||||
|
|
||||||
int inFramesToProcess = blockSize;
|
int inFramesToProcess = blockSize;
|
||||||
double overallscale = 1.0;
|
double overallscale = 1.0;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ enum filter_types {
|
|||||||
template <typename t_sample>
|
template <typename t_sample>
|
||||||
class ysvf {
|
class ysvf {
|
||||||
public:
|
public:
|
||||||
ysvf(double _samplerate)
|
ysvf(double _samplerate = 44100)
|
||||||
: lowpass { _samplerate }
|
: lowpass { _samplerate }
|
||||||
, highpass { _samplerate }
|
, highpass { _samplerate }
|
||||||
, bandpass { _samplerate }
|
, bandpass { _samplerate }
|
||||||
@@ -96,10 +96,10 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
filter_types filter_type;
|
filter_types filter_type;
|
||||||
ylowpass lowpass;
|
ylowpass<t_sample> lowpass;
|
||||||
yhighpass highpass;
|
yhighpass<t_sample> highpass;
|
||||||
ybandpass bandpass;
|
ybandpass<t_sample> bandpass;
|
||||||
ynotch notch;
|
ynotch<t_sample> notch;
|
||||||
|
|
||||||
double clamp(double& value, double min, double max) {
|
double clamp(double& value, double min, double max) {
|
||||||
if (value < min) {
|
if (value < min) {
|
||||||
|
|||||||
@@ -17,54 +17,45 @@ enum env_state {
|
|||||||
|
|
||||||
class tx_envelope {
|
class tx_envelope {
|
||||||
public:
|
public:
|
||||||
env_state state;
|
env_state state = idle;
|
||||||
float attack1_rate;
|
float attack1_rate = 0;
|
||||||
float attack1_level;
|
float attack1_level = 0;
|
||||||
float attack2_rate;
|
float attack2_rate = 0;
|
||||||
float hold_rate;
|
float hold_rate = 0;
|
||||||
float decay1_rate;
|
float decay1_rate = 0;
|
||||||
float decay1_level;
|
float decay1_level = 0;
|
||||||
float decay2_rate;
|
float decay2_rate = 0;
|
||||||
float sustain_level;
|
float sustain_level = 0;
|
||||||
float release1_rate;
|
float release1_rate = 0;
|
||||||
float release1_level;
|
float release1_level = 0;
|
||||||
float release2_rate;
|
float release2_rate = 0;
|
||||||
|
|
||||||
tx_envelope()
|
tx_envelope(bool _retrigger = false)
|
||||||
: samplerate { 44100. }
|
: retrigger { _retrigger }
|
||||||
, attack1_rate { 0 }
|
|
||||||
, attack1_level { 0 }
|
|
||||||
, attack2_rate { 0 }
|
|
||||||
, hold_rate { 0 }
|
|
||||||
, decay1_rate { 0 }
|
|
||||||
, decay1_level { 0 }
|
|
||||||
, decay2_rate { 0 }
|
|
||||||
, sustain_level { 0 }
|
|
||||||
, release1_rate { 0 }
|
|
||||||
, release1_level { 0 }
|
|
||||||
, release2_rate { 0 }
|
|
||||||
, level { 0.f }
|
|
||||||
, phase { 0 }
|
|
||||||
, state { idle }
|
|
||||||
, start_level { 0.f }
|
|
||||||
, h1 { 0. }
|
|
||||||
, h2 { 0. }
|
|
||||||
, h3 { 0. }
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
float process_sample(bool gate, bool trigger) {
|
float process_sample(bool gate, bool trigger) {
|
||||||
|
|
||||||
int attack_mid_x1 = ms_to_samples(attack1_rate);
|
return process_sample<float>(gate, trigger, 0, 0);
|
||||||
int attack_mid_x2 = ms_to_samples(attack2_rate);
|
}
|
||||||
int hold_samp = ms_to_samples(hold_rate);
|
|
||||||
int decay_mid_x1 = ms_to_samples(decay1_rate);
|
template <typename t_sample>
|
||||||
int decay_mid_x2 = ms_to_samples(decay2_rate);
|
float process_sample(bool gate, bool trigger, t_sample _attack_mod, t_sample _decay_mod) {
|
||||||
int release_mid_x1 = ms_to_samples(release1_rate);
|
|
||||||
int release_mid_x2 = ms_to_samples(release2_rate);
|
size_t attack_mid_x1 = ms_to_samples(attack1_rate + (float)_attack_mod);
|
||||||
|
size_t attack_mid_x2 = ms_to_samples(attack2_rate + (float)_attack_mod);
|
||||||
|
size_t hold_samp = ms_to_samples(hold_rate);
|
||||||
|
size_t decay_mid_x1 = ms_to_samples(decay1_rate + (float)_decay_mod);
|
||||||
|
size_t decay_mid_x2 = ms_to_samples(decay2_rate + (float)_decay_mod);
|
||||||
|
size_t release_mid_x1 = ms_to_samples(release1_rate + (float)_decay_mod);
|
||||||
|
size_t release_mid_x2 = ms_to_samples(release2_rate + (float)_decay_mod);
|
||||||
|
|
||||||
// if note on is triggered, transition to attack phase
|
// if note on is triggered, transition to attack phase
|
||||||
if (trigger) {
|
if (trigger) {
|
||||||
|
if (retrigger)
|
||||||
|
start_level = 0.f;
|
||||||
|
else
|
||||||
start_level = level;
|
start_level = level;
|
||||||
phase = 0;
|
phase = 0;
|
||||||
state = attack1;
|
state = attack1;
|
||||||
@@ -73,7 +64,7 @@ public:
|
|||||||
if (state == attack1) {
|
if (state == attack1) {
|
||||||
// while in attack phase
|
// while in attack phase
|
||||||
if (phase < attack_mid_x1) {
|
if (phase < attack_mid_x1) {
|
||||||
level = lerp(0, start_level, attack_mid_x1, attack1_level, phase);
|
level = lerp(0, start_level, (float)attack_mid_x1, attack1_level, (float)phase);
|
||||||
phase += 1;
|
phase += 1;
|
||||||
}
|
}
|
||||||
// reset phase if parameter was changed
|
// reset phase if parameter was changed
|
||||||
@@ -90,7 +81,7 @@ public:
|
|||||||
if (state == attack2) {
|
if (state == attack2) {
|
||||||
// while in attack phase
|
// while in attack phase
|
||||||
if (phase < attack_mid_x2) {
|
if (phase < attack_mid_x2) {
|
||||||
level = lerp(0, attack1_level, attack_mid_x2, 1, phase);
|
level = lerp(0, attack1_level, (float)attack_mid_x2, 1, (float)phase);
|
||||||
phase += 1;
|
phase += 1;
|
||||||
}
|
}
|
||||||
// reset phase if parameter was changed
|
// reset phase if parameter was changed
|
||||||
@@ -121,7 +112,7 @@ public:
|
|||||||
if (state == decay1) {
|
if (state == decay1) {
|
||||||
// while in decay phase
|
// while in decay phase
|
||||||
if (phase < decay_mid_x1) {
|
if (phase < decay_mid_x1) {
|
||||||
level = lerp(0, 1, decay_mid_x1, decay1_level, phase);
|
level = lerp(0, 1, (float)decay_mid_x1, decay1_level, (float)phase);
|
||||||
phase += 1;
|
phase += 1;
|
||||||
}
|
}
|
||||||
// reset phase if parameter was changed
|
// reset phase if parameter was changed
|
||||||
@@ -138,7 +129,7 @@ public:
|
|||||||
if (state == decay2) {
|
if (state == decay2) {
|
||||||
// while in decay phase
|
// while in decay phase
|
||||||
if (phase < decay_mid_x2) {
|
if (phase < decay_mid_x2) {
|
||||||
level = lerp(0, decay1_level, decay_mid_x2, sustain_level, phase);
|
level = lerp(0, decay1_level, (float)decay_mid_x2, sustain_level, (float)phase);
|
||||||
phase += 1;
|
phase += 1;
|
||||||
}
|
}
|
||||||
// reset phase if parameter was changed
|
// reset phase if parameter was changed
|
||||||
@@ -161,7 +152,7 @@ public:
|
|||||||
if (state == release1) {
|
if (state == release1) {
|
||||||
// while in release phase
|
// while in release phase
|
||||||
if (phase < release_mid_x1) {
|
if (phase < release_mid_x1) {
|
||||||
level = lerp(0, sustain_level, release_mid_x1, release1_level, phase);
|
level = lerp(0, sustain_level, (float)release_mid_x1, release1_level, (float)phase);
|
||||||
phase += 1;
|
phase += 1;
|
||||||
}
|
}
|
||||||
// reset phase if parameter was changed
|
// reset phase if parameter was changed
|
||||||
@@ -178,7 +169,7 @@ public:
|
|||||||
if (state == release2) {
|
if (state == release2) {
|
||||||
// while in release phase
|
// while in release phase
|
||||||
if (phase < release_mid_x2) {
|
if (phase < release_mid_x2) {
|
||||||
level = lerp(0, release1_level, release_mid_x2, 0, phase);
|
level = lerp(0, release1_level, (float)release_mid_x2, 0, (float)phase);
|
||||||
phase += 1;
|
phase += 1;
|
||||||
}
|
}
|
||||||
// reset phase if parameter was changed
|
// reset phase if parameter was changed
|
||||||
@@ -202,37 +193,41 @@ public:
|
|||||||
this->samplerate = sampleRate;
|
this->samplerate = sampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns the x/y coordinates of the envelope points as a list for graphical representation.
|
// converts the x/y coordinates of the envelope points as a list for graphical representation.
|
||||||
std::array<float, 18> calc_coordinates() {
|
std::array<float, 18> calc_coordinates(float _max_attack, float _max_decay, float _max_release) {
|
||||||
|
|
||||||
|
auto scale = [](float _value, float _max) {
|
||||||
|
return powf(_value / _max, 0.25) * _max;
|
||||||
|
};
|
||||||
|
|
||||||
float a_x = 0;
|
float a_x = 0;
|
||||||
float a_y = 0;
|
float a_y = 0;
|
||||||
|
|
||||||
float b_x = attack1_rate;
|
float b_x = scale(attack1_rate, _max_attack / 2);
|
||||||
float b_y = attack1_level;
|
float b_y = attack1_level;
|
||||||
|
|
||||||
float c_x = b_x + attack2_rate;
|
float c_x = b_x + scale(attack2_rate, _max_attack / 2);
|
||||||
float c_y = 1;
|
float c_y = 1;
|
||||||
|
|
||||||
float d_x = c_x + hold_rate;
|
float d_x = c_x + hold_rate;
|
||||||
float d_y = 1;
|
float d_y = 1;
|
||||||
|
|
||||||
float e_x = d_x + decay1_rate;
|
float e_x = d_x + scale(decay1_rate, _max_decay / 2);
|
||||||
float e_y = decay1_level;
|
float e_y = decay1_level;
|
||||||
|
|
||||||
float f_x = e_x + decay2_rate;
|
float f_x = e_x + scale(decay2_rate, _max_decay / 2);
|
||||||
float f_y = sustain_level;
|
float f_y = sustain_level;
|
||||||
|
|
||||||
float g_x = f_x + 125;
|
float g_x = _max_attack + _max_decay;
|
||||||
float g_y = sustain_level;
|
float g_y = sustain_level;
|
||||||
|
|
||||||
float h_x = g_x + release1_rate;
|
float h_x = g_x + scale(release1_rate, _max_decay / 2);
|
||||||
float h_y = release1_level;
|
float h_y = release1_level;
|
||||||
|
|
||||||
float i_x = h_x + release2_rate;
|
float i_x = h_x + scale(release2_rate, _max_decay / 2);
|
||||||
float i_y = 0;
|
float i_y = 0;
|
||||||
|
|
||||||
float total = i_x;
|
float total = _max_attack + _max_decay + _max_release;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
a_x,
|
a_x,
|
||||||
@@ -257,13 +252,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double samplerate;
|
double samplerate = 44100.;
|
||||||
int phase;
|
size_t phase = 0;
|
||||||
float level;
|
float level = 0.f;
|
||||||
float start_level;
|
float start_level = 0.f;
|
||||||
float h1;
|
float h1 = 0.f;
|
||||||
float h2;
|
float h2 = 0.f;
|
||||||
float h3;
|
float h3 = 0.f;
|
||||||
|
bool retrigger;
|
||||||
|
|
||||||
float lerp(float x1, float y1, float x2, float y2, float x) { return y1 + (((x - x1) * (y2 - y1)) / (x2 - x1)); }
|
float lerp(float x1, float y1, float x2, float y2, float x) { return y1 + (((x - x1) * (y2 - y1)) / (x2 - x1)); }
|
||||||
|
|
||||||
@@ -275,6 +271,8 @@ private:
|
|||||||
return (h1 + h2 + h3) / 3.f;
|
return (h1 + h2 + h3) / 3.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
float ms_to_samples(float ms) { return ms * samplerate / 1000.f; }
|
size_t ms_to_samples(float ms) {
|
||||||
|
return static_cast<size_t>(ms * samplerate / 1000.f);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,7 @@ public:
|
|||||||
std::vector<t_voice> voices;
|
std::vector<t_voice> voices;
|
||||||
|
|
||||||
voice_allocator()
|
voice_allocator()
|
||||||
: voices(8, t_voice())
|
: voices(4, t_voice())
|
||||||
{
|
{
|
||||||
// checks whether template derives from ivoice
|
// checks whether template derives from ivoice
|
||||||
typedef t_voice assert_at_compile_time[is_convertible<t_voice>::value ? 1 : -1];
|
typedef t_voice assert_at_compile_time[is_convertible<t_voice>::value ? 1 : -1];
|
||||||
@@ -92,6 +92,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<midi_event> input_queue;
|
std::vector<midi_event> input_queue;
|
||||||
|
int index_to_steal = 0;
|
||||||
|
|
||||||
t_voice* get_free_voice(float frequency)
|
t_voice* get_free_voice(float frequency)
|
||||||
{
|
{
|
||||||
@@ -118,7 +119,13 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (free_voice == nullptr) {
|
if (free_voice == nullptr) {
|
||||||
free_voice = &voices.at(0);
|
free_voice = &voices.at(index_to_steal);
|
||||||
|
|
||||||
|
if (index_to_steal < voices.size() - 1) {
|
||||||
|
index_to_steal++;
|
||||||
|
} else {
|
||||||
|
index_to_steal = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return free_voice;
|
return free_voice;
|
||||||
|
|||||||
38
util/demo_noise.h
Normal file
38
util/demo_noise.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
#define _USE_MATH_DEFINES
|
||||||
|
#include <math.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
namespace trnr {
|
||||||
|
template <typename t_sample>
|
||||||
|
class demo_noise {
|
||||||
|
public:
|
||||||
|
void set_samplerate(double _samplerate) {
|
||||||
|
samplerate = _samplerate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void process_block(t_sample** samples, long sample_frames) {
|
||||||
|
|
||||||
|
for (int s = 0; s < sample_frames; s++) {
|
||||||
|
demo_counter++;
|
||||||
|
|
||||||
|
if (demo_counter == samplerate * 20) {
|
||||||
|
demo_counter = 0;
|
||||||
|
}
|
||||||
|
if (demo_counter > samplerate * 17) {
|
||||||
|
t_sample r1 = static_cast<t_sample>(rand()) / static_cast<t_sample>(RAND_MAX);
|
||||||
|
t_sample r2 = static_cast<t_sample>(rand()) / static_cast<t_sample>(RAND_MAX);
|
||||||
|
|
||||||
|
t_sample noise = static_cast<t_sample>(sqrt(-2.0 * log(r1)) * cos(2.0 * M_PI * r2));
|
||||||
|
|
||||||
|
samples[0][s] = noise / 10.0;
|
||||||
|
samples[1][s] = noise / 10.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
double samplerate = 44100;
|
||||||
|
int demo_counter = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
156
util/retro_buf.h
Normal file
156
util/retro_buf.h
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../filter/chebyshev.h"
|
||||||
|
#include "../companding/ulaw.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace trnr {
|
||||||
|
|
||||||
|
struct retro_buf_modulation {
|
||||||
|
double midi_note;
|
||||||
|
double pitch_mod;
|
||||||
|
double samplerate; // the (re)samplerate
|
||||||
|
double bitrate;
|
||||||
|
size_t start; // sets the start point from which to play
|
||||||
|
size_t end; // sets the end point
|
||||||
|
bool looping; // sets whether the sample should loop
|
||||||
|
bool reset; // resets the phase
|
||||||
|
int jitter; // jitter amount
|
||||||
|
double deviation;
|
||||||
|
};
|
||||||
|
|
||||||
|
// base class for accessing a sample buffer with adjustable samplerate, bitrate and other options.
|
||||||
|
class retro_buf {
|
||||||
|
public:
|
||||||
|
void set_host_samplerate(double _samplerate) {
|
||||||
|
m_host_samplerate = _samplerate;
|
||||||
|
m_imaging_filter_l.set_samplerate(_samplerate);
|
||||||
|
m_imaging_filter_r.set_samplerate(_samplerate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_buf_samplerate(double _samplerate) {
|
||||||
|
m_buf_samplerate = _samplerate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_buffer_size(size_t _buffer_size) {
|
||||||
|
m_buffer_size = _buffer_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_channel_count(size_t _channel_count) {
|
||||||
|
m_channel_count = _channel_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void start_playback() {
|
||||||
|
if (m_modulation.reset || (!m_modulation.reset && m_playback_pos == -1)) {
|
||||||
|
m_playback_pos = (double)m_modulation.start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @return is active
|
||||||
|
bool process_block(double** _outputs, size_t _block_size, retro_buf_modulation _mod) {
|
||||||
|
|
||||||
|
m_modulation = _mod;
|
||||||
|
|
||||||
|
for (int i = 0; i < _block_size; ++i) {
|
||||||
|
double output_l = 0;
|
||||||
|
double output_r = 0;
|
||||||
|
|
||||||
|
// if within bounds
|
||||||
|
if (m_playback_pos > -1 && m_playback_pos <= _mod.end) {
|
||||||
|
|
||||||
|
// quantize index
|
||||||
|
double samplerate_divisor = m_host_samplerate / _mod.samplerate;
|
||||||
|
size_t quantized_index = static_cast<size_t>(static_cast<size_t>(m_playback_pos / samplerate_divisor) * samplerate_divisor);
|
||||||
|
|
||||||
|
// get sample for each channel
|
||||||
|
output_l = get_sample((size_t)wrap(quantized_index + jitterize(_mod.jitter), m_buffer_size), 0);
|
||||||
|
if (m_channel_count > 0) {
|
||||||
|
output_r = get_sample((size_t)wrap(quantized_index + jitterize(_mod.jitter), m_buffer_size), 1);
|
||||||
|
} else {
|
||||||
|
output_r = output_l;
|
||||||
|
}
|
||||||
|
|
||||||
|
// advance position
|
||||||
|
double note_ratio = midi_to_ratio(_mod.midi_note + _mod.pitch_mod);
|
||||||
|
m_playback_pos += note_ratio * (m_buf_samplerate / m_host_samplerate);
|
||||||
|
|
||||||
|
reduce_bitrate(output_l, output_r, _mod.bitrate);
|
||||||
|
|
||||||
|
// calculate imaging filter frequency + deviation
|
||||||
|
double filter_frequency = ((_mod.samplerate / 2) * note_ratio) * ((_mod.deviation * 9) + 1);
|
||||||
|
|
||||||
|
m_imaging_filter_l.process_sample(output_l, filter_frequency);
|
||||||
|
m_imaging_filter_r.process_sample(output_r, filter_frequency);
|
||||||
|
}
|
||||||
|
// else if loop
|
||||||
|
else if(_mod.looping) {
|
||||||
|
// loop
|
||||||
|
m_playback_pos = (double)_mod.start;
|
||||||
|
}
|
||||||
|
// else
|
||||||
|
else {
|
||||||
|
// stop
|
||||||
|
m_playback_pos = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_outputs[0][i] = output_l;
|
||||||
|
_outputs[1][i] = output_r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_playback_pos > -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual float get_sample(size_t _index, size_t _channel) = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t m_channel_count = 0;
|
||||||
|
size_t m_buffer_size = 0;
|
||||||
|
double m_buf_samplerate = 44100.0;
|
||||||
|
double m_host_samplerate = 44100.0;
|
||||||
|
double m_playback_pos = -1;
|
||||||
|
|
||||||
|
chebyshev m_imaging_filter_l;
|
||||||
|
chebyshev m_imaging_filter_r;
|
||||||
|
ulaw m_compander;
|
||||||
|
retro_buf_modulation m_modulation;
|
||||||
|
|
||||||
|
float midi_to_ratio(double midi_note) {
|
||||||
|
return powf(powf(2, (float)midi_note - 60.f), 1.f / 12.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T clamp(T& value, T min, T max) {
|
||||||
|
if (value < min) {
|
||||||
|
value = min;
|
||||||
|
} else if (value > max) {
|
||||||
|
value = max;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
double wrap(double value, double max) {
|
||||||
|
while (value > max) {
|
||||||
|
value =- max;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int jitterize(int jitter) {
|
||||||
|
if (jitter > 0) {
|
||||||
|
return static_cast<int>(rand() % jitter);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void reduce_bitrate(double& value1, double& value2, double bit) {
|
||||||
|
m_compander.encode_samples(value1, value2);
|
||||||
|
|
||||||
|
float resolution = powf(2, bit);
|
||||||
|
value1 = round(value1 * resolution) / resolution;
|
||||||
|
value2 = round(value2 * resolution) / resolution;
|
||||||
|
|
||||||
|
m_compander.decode_samples(value1, value2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user