Skip to content

Commit

Permalink
+ warmth param
Browse files Browse the repository at this point in the history
  • Loading branch information
psemiletov committed Oct 14, 2023
1 parent 4b91139 commit c607e3d
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 124 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ A set of LV2 plugins for bedroom music studio :) The idea is to provide simple,

Current plugins list:

Metalluga - the distortion effect
**Metalluga** - the distortion effect

## Build and install

Expand Down
100 changes: 77 additions & 23 deletions source/dsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,39 @@ void init_db()
#endif
*/


db_scale = log (10.0) * 0.05;
}



/*************** SATURATION/DIST/OVERDRIVE *******************/


// Функция для более "хриплого" гитарного искажения
float gritty_guitar_distortion (float input_sample, float distortion_level)
{
// Шаг 1: Усиление с более высоким коэффициентом
float amplified_sample = input_sample * (1.5f + 4.0f * distortion_level);

// Шаг 2: Операционный усилитель с более высокой нелинейностью
float op_amp_output = tanh (2.0f * amplified_sample);

// Шаг 3: Клиппер/ограничитель с более сильным искажением
float clipped_sample = tanh (2.0f * op_amp_output);

// Ограничиваем значения в диапазоне от 0 до 1
clipped_sample = std::min (1.0f, std::max (0.0f, clipped_sample));

return clipped_sample;
}



//analog
float warmify(float x, float warmth)
float warmify (float x, float warmth)
{
// Проверяем, что "warmth" находится в пределах от 0 до 1
warmth = std::min(1.0f, std::max(0.0f, warmth));
warmth = std::min (1.0f, std::max(0.0f, warmth));

// Применяем теплое, аналоговое воздействие на сигнал
float warm_x = x * (1.0f - warmth) + std::sin(x * M_PI) * warmth;
Expand All @@ -52,38 +73,71 @@ float warmify(float x, float warmth)
}


/*
/*************** FILTERS *******************/


float hp_filter (float input, float samplerate, float fc)
{
// Рассчитываем константу времени T из частоты среза
float T = 1.0f / (2.0f * M_PI * fc);

// Рассчитываем коэффициент для фильтра
float alpha = T / (T + 1.0f);

// Инициализируем предыдущее значение (первоначальное условие)
static float prev_output = 0.0f;

// Применяем фильтр к входному сигналу
float output = alpha * (prev_output + input - prev_output);

// Обновляем предыдущее значение для следующего вызова
prev_output = output;

return output;
}


/*************** MISC *******************/


// Функция для мягкого понижения уровня сигнала, если он превышает порог в 18 дБ (выше нуля)
float softLimit(float input, float threshold_dB)

const float thresholdLevel18db = pow (10.0f, 18.0f / 20.0f); // Значение, соответствующее +18 дБ


float soft_limit (float input)
{
// Проверяем, превышает ли входной сигнал порог
if (input > 0.0f && 20.0f * log10f(input) > threshold_dB)
if (input > thresholdLevel18db)
{
// Рассчитываем множитель для понижения уровня
float reductionFactor = pow(10.0f, (threshold_dB - 20.0f * log10f(input)) / 20.0f);
// Применяем мягкое понижение уровня
return input * reductionFactor;
float reduction_factor = thresholdLevel18db / input;

// Применяем мягкое понижение уровня
return input * reduction_factor;
}

// Если сигнал не превышает порог, возвращаем его без изменений
// Если сигнал не превышает порог, возвращаем его без изменений
return input;
}
*/

const float thresholdLevel = pow(10.0f, 18.0f / 20.0f); // Значение, соответствующее +18 дБ


float softLimit(float input) {
float apply_resonance (float input, float resonance_amount)
{
// Вычисляем коэффициент для изменения резонанса
float resonance_factor = 1.0f + resonance_amount;

// Проверяем, превышает ли входной сигнал порог
if (input > thresholdLevel) {
// Рассчитываем множитель для понижения уровня
float reductionFactor = thresholdLevel / input;
// Применяем резонансное изменение
float resonant_signal = input * resonance_factor;

// Применяем мягкое понижение уровня
return input * reductionFactor;
}
// Ограничиваем результат в пределах от -1 до 1 (клиппинг)
if (resonant_signal > 1.0f)
resonant_signal = 1.0f;
else
if (resonant_signal < -1.0f)
resonant_signal = -1.0f;

// Если сигнал не превышает порог, возвращаем его без изменений
return input;
}

return resonant_signal;
}
20 changes: 18 additions & 2 deletions source/dsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,24 @@ inline void pan_equal_power3 (float &l, float& r, float p)
}


float warmify(float x, float warmth);
float softLimit(float input);

/*************** SATURATION/DIST/OVERDRIVE *******************/

float gritty_guitar_distortion (float input_sample, float distortion_level);
float warmify (float x, float warmth);



/*************** FILTERS *******************/

float hp_filter (float input, float samplerate, float fc);


/*************** MISC *******************/


float soft_limit (float input);
float apply_resonance (float input, float resonance_amount);


#endif
138 changes: 49 additions & 89 deletions source/metalluga.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

#define METALLUGA_URI "https://github.com/psemiletov/metalluga"

typedef enum { MTL_INPUT = 0, MTL_OUTPUT = 1, MTL_DRIVE = 2, MTL_LEVEL = 3, MTL_TONE = 4, MTL_RESO = 5} PortIndex;
typedef enum { MTL_INPUT = 0, MTL_OUTPUT = 1, MTL_DRIVE = 2, MTL_LEVEL = 3, MTL_WEIGHT = 4, MTL_RESO = 5, MTL_WARMTH = 6} PortIndex;



Expand All @@ -25,13 +25,17 @@ class CMetalluga

int samplerate;

//CResoFilter hp_pre;


CResoFilter lp;
CResoFilter hp;

const float* drive;
const float* level;
const float* tone;
const float* weight;
const float* reso;
const float* warmth;

const float* input;
float *output;
Expand All @@ -45,67 +49,9 @@ CMetalluga::CMetalluga()
hp.mode = FILTER_MODE_HIGHPASS;
lp.reset();
hp.reset();
}


//hp_pre.mode = FILTER_MODE_HIGHPASS;

float applyResonance(float input, float resonanceAmount)
{
// Вычисляем коэффициент для изменения резонанса
float resonanceFactor = 1.0f + resonanceAmount;

// Применяем резонансное изменение
float resonantSignal = input * resonanceFactor;

// Ограничиваем результат в пределах от -1 до 1 (клиппинг)
if (resonantSignal > 1.0f) {
resonantSignal = 1.0f;
} else if (resonantSignal < -1.0f) {
resonantSignal = -1.0f;
}

return resonantSignal;
}


float highPassFilter(float input, float sampleRate, float fc) {
// Рассчитываем константу времени T из частоты среза
float T = 1.0f / (2.0f * M_PI * fc);

// Рассчитываем коэффициент для фильтра
float alpha = T / (T + 1.0f);

// Инициализируем предыдущее значение (первоначальное условие)
static float prevOutput = 0.0f;

// Применяем фильтр к входному сигналу
float output = alpha * (prevOutput + input - prevOutput);

// Обновляем предыдущее значение для следующего вызова
prevOutput = output;

return output;
}




// Функция для более "хриплого" гитарного искажения
float grittyGuitarDistortion(float inputSample, float distortionLevel)
{
// Шаг 1: Усиление с более высоким коэффициентом
float amplifiedSample = inputSample * (1.5f + 4.0f * distortionLevel);

// Шаг 2: Операционный усилитель с более высокой нелинейностью
float opAmpOutput = tanh(2.0f * amplifiedSample);

// Шаг 3: Клиппер/ограничитель с более сильным искажением
float clippedSample = tanh(2.0f * opAmpOutput);

// Ограничиваем значения в диапазоне от 0 до 1
clippedSample = std::min(1.0f, std::max(0.0f, clippedSample));

return clippedSample;
// hp_pre.reset();
}


Expand All @@ -123,6 +69,7 @@ instantiate(const LV2_Descriptor* descriptor,
init_db();
CMetalluga *instance = new CMetalluga;
instance->samplerate = rate;
// instance->hp_pre.set_cutoff ((float) 7.2f / rate);

return (LV2_Handle)instance;
}
Expand All @@ -133,29 +80,38 @@ connect_port(LV2_Handle instance, uint32_t port, void* data)
{
CMetalluga *inst = (CMetalluga*)instance;

switch ((PortIndex)port) {
case MTL_INPUT:
inst->input = (const float*)data;
break;
case MTL_OUTPUT:
inst->output = (float*)data;
break;
case MTL_DRIVE:
inst->drive = (const float*)data;
break;
case MTL_LEVEL:
inst->level = (const float*)data;
break;
case MTL_TONE:
inst->tone = (const float*)data;
break;
case MTL_RESO:
inst->reso = (const float*)data;
break;

}
}
switch ((PortIndex)port)
{
case MTL_INPUT:
inst->input = (const float*)data;
break;

case MTL_OUTPUT:
inst->output = (float*)data;
break;

case MTL_DRIVE:
inst->drive = (const float*)data;
break;

case MTL_LEVEL:
inst->level = (const float*)data;
break;

case MTL_WEIGHT:
inst->weight = (const float*)data;
break;

case MTL_RESO:
inst->reso = (const float*)data;
break;

case MTL_WARMTH:
inst->warmth = (const float*)data;
break;

}
}


static void
Expand All @@ -171,21 +127,25 @@ run(LV2_Handle instance, uint32_t n_samples)

float f = input[pos];

// f = highPassFilter(f, inst->tone_filter.samplerate, 7.2f);

// f = inst->hp_pre.process (f);
//f = hp_filter (f, inst->samplerate, 7.2f);

f *= db2lin (*(inst->level));

// f = highPassFilter(f, inst->session_samplerate, 11.0f);

f = grittyGuitarDistortion(f, *(inst->drive));
f = gritty_guitar_distortion(f, *(inst->drive));

inst->lp.set_cutoff (1 - *(inst->tone));
inst->hp.set_cutoff (1 - *(inst->tone));
inst->lp.set_cutoff (1 - *(inst->weight));
inst->hp.set_cutoff (1 - *(inst->weight));

f = inst->lp.process (f);
f = inst->hp.process (f);

f = applyResonance(f, *(inst->reso));
f = apply_resonance (f, *(inst->reso));

f = warmify (f, *(inst->warmth));

output[pos] = f;
}
Expand Down
Loading

0 comments on commit c607e3d

Please sign in to comment.