-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
1,041 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// # compressor | ||
// | ||
// Author: shensley, AvAars | ||
// | ||
|
||
#include <cmath> | ||
#include <stdlib.h> | ||
#include <stdint.h> | ||
#include "compressor.h" | ||
|
||
using namespace daisysp; | ||
|
||
#ifndef max | ||
#define max(a, b) ((a < b) ? b : a) | ||
#endif | ||
|
||
#ifndef min | ||
#define min(a, b) ((a < b) ? a : b) | ||
#endif | ||
|
||
void Compressor::Init(float sample_rate) | ||
{ | ||
sample_rate_ = min(192000, max(1, sample_rate)); | ||
sample_rate_inv_ = 1.0f / (float)sample_rate_; | ||
sample_rate_inv2_ = 2.0f / (float)sample_rate_; | ||
|
||
// Initializing the params in this order to avoid dividing by zero | ||
|
||
SetRatio(2.0f); | ||
SetAttack(0.1f); | ||
SetRelease(0.1f); | ||
SetThreshold(-12.0f); | ||
AutoMakeup(true); | ||
|
||
gain_rec_ = 0.1f; | ||
slope_rec_ = 0.1f; | ||
} | ||
|
||
float Compressor::Process(float in) | ||
{ | ||
float inAbs = fabsf(in); | ||
float cur_slo = ((slope_rec_ > inAbs) ? rel_slo_ : atk_slo_); | ||
slope_rec_ = ((slope_rec_ * cur_slo) + ((1.0f - cur_slo) * inAbs)); | ||
gain_rec_ = ((atk_slo2_ * gain_rec_) | ||
+ (ratio_mul_ | ||
* fmax(((20.f * fastlog10f(slope_rec_)) - thresh_), 0.f))); | ||
gain_ = pow10f(0.05f * (gain_rec_ + makeup_gain_)); | ||
|
||
return gain_ * in; | ||
} | ||
|
||
void Compressor::ProcessBlock(float *in, float *out, float *key, size_t size) | ||
{ | ||
for(size_t i = 0; i < size; i++) | ||
{ | ||
Process(key[i]); | ||
out[i] = Apply(in[i]); | ||
} | ||
} | ||
|
||
// Multi-channel block processing | ||
void Compressor::ProcessBlock(float **in, | ||
float **out, | ||
float * key, | ||
size_t channels, | ||
size_t size) | ||
{ | ||
for(size_t i = 0; i < size; i++) | ||
{ | ||
Process(key[i]); | ||
for(size_t c = 0; c < channels; c++) | ||
{ | ||
out[c][i] = Apply(in[c][i]); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,207 @@ | ||
/* | ||
Copyright (c) 2023 Electrosmith, Corp, GRAME, Centre National de Creation Musicale. | ||
Use of this source code is governed by the LGPL V2.1 | ||
license that can be found in the LICENSE file or at | ||
https://opensource.org/license/lgpl-2-1/ | ||
*/ | ||
|
||
#pragma once | ||
#ifndef DSY_COMPRESSOR_H | ||
#define DSY_COMPRESSOR_H | ||
|
||
#include "Utility/dsp.h" | ||
|
||
namespace daisysp | ||
{ | ||
/** dynamics compressor | ||
influenced by compressor in soundpipe (from faust). | ||
Modifications made to do: | ||
- Less calculations during each process loop (coefficients recalculated on parameter change). | ||
- C++-ified | ||
- added sidechain support | ||
- pulled gain apart for monitoring and multichannel support | ||
- improved readability | ||
- improved makeup-gain calculations | ||
- changing controls now costs a lot less | ||
- a lot less expensive | ||
by: shensley, improved upon by AvAars | ||
\todo Add soft/hard knee settings | ||
*/ | ||
class Compressor | ||
{ | ||
public: | ||
Compressor() {} | ||
~Compressor() {} | ||
/** Initializes compressor | ||
\param sample_rate rate at which samples will be produced by the audio engine. | ||
*/ | ||
void Init(float sample_rate); | ||
|
||
/** Compress the audio input signal, saves the calculated gain | ||
\param in audio input signal | ||
*/ | ||
float Process(float in); | ||
|
||
/** Compresses the audio input signal, keyed by a secondary input. | ||
\param in audio input signal (to be compressed) | ||
\param key audio input that will be used to side-chain the compressor | ||
*/ | ||
float Process(float in, float key) | ||
{ | ||
Process(key); | ||
return Apply(in); | ||
} | ||
|
||
/** Apply compression to the audio signal, based on the previously calculated gain | ||
\param in audio input signal | ||
*/ | ||
float Apply(float in) { return gain_ * in; } | ||
|
||
/** Compresses a block of audio | ||
\param in audio input signal | ||
\param out audio output signal | ||
\param size the size of the block | ||
*/ | ||
void ProcessBlock(float *in, float *out, size_t size) | ||
{ | ||
ProcessBlock(in, out, in, size); | ||
} | ||
|
||
/** Compresses a block of audio, keyed by a secondary input | ||
\param in audio input signal (to be compressed) | ||
\param out audio output signal | ||
\param key audio input that will be used to side-chain the compressor | ||
\param size the size of the block | ||
*/ | ||
void ProcessBlock(float *in, float *out, float *key, size_t size); | ||
|
||
/** Compresses a block of multiple channels of audio, keyed by a secondary input | ||
\param in audio input signals (to be compressed) | ||
\param out audio output signals | ||
\param key audio input that will be used to side-chain the compressor | ||
\param channels the number of audio channels | ||
\param size the size of the block | ||
*/ | ||
void ProcessBlock(float **in, | ||
float **out, | ||
float * key, | ||
size_t channels, | ||
size_t size); | ||
|
||
/** Gets the amount of gain reduction */ | ||
float GetRatio() { return ratio_; } | ||
|
||
/** Sets the amount of gain reduction applied to compressed signals | ||
\param ratio Expects 1.0 -> 40. (untested with values < 1.0) | ||
*/ | ||
void SetRatio(float ratio) | ||
{ | ||
ratio_ = ratio; | ||
RecalculateRatio(); | ||
} | ||
|
||
/** Gets the threshold in dB */ | ||
float GetThreshold() { return thresh_; } | ||
|
||
/** Sets the threshold in dB at which compression will be applied | ||
\param threshold Expects 0.0 -> -80. | ||
*/ | ||
void SetThreshold(float threshold) | ||
{ | ||
thresh_ = threshold; | ||
RecalculateMakeup(); | ||
} | ||
|
||
/** Gets the envelope time for onset of compression */ | ||
float GetAttack() { return atk_; } | ||
|
||
/** Sets the envelope time for onset of compression for signals above the threshold. | ||
\param attack Expects 0.001 -> 10 | ||
*/ | ||
void SetAttack(float attack) | ||
{ | ||
atk_ = attack; | ||
RecalculateAttack(); | ||
} | ||
|
||
/** Gets the envelope time for release of compression */ | ||
float GetRelease() { return rel_; } | ||
|
||
/** Sets the envelope time for release of compression as input signal falls below threshold. | ||
\param release Expects 0.001 -> 10 | ||
*/ | ||
void SetRelease(float release) | ||
{ | ||
rel_ = release; | ||
RecalculateRelease(); | ||
} | ||
|
||
/** Gets the additional gain to make up for the compression */ | ||
float GetMakeup() { return makeup_gain_; } | ||
|
||
/** Manually sets the additional gain to make up for the compression | ||
\param gain Expects 0.0 -> 80 | ||
*/ | ||
void SetMakeup(float gain) { makeup_gain_ = gain; } | ||
|
||
/** Enables or disables the automatic makeup gain. Disabling sets the makeup gain to 0.0 | ||
\param enable true to enable, false to disable | ||
*/ | ||
void AutoMakeup(bool enable) | ||
{ | ||
makeup_auto_ = enable; | ||
makeup_gain_ = 0.0f; | ||
RecalculateMakeup(); | ||
} | ||
|
||
/** Gets the gain reduction in dB | ||
*/ | ||
float GetGain() { return fastlog10f(gain_) * 20.0f; } | ||
|
||
private: | ||
float ratio_, thresh_, atk_, rel_; | ||
float makeup_gain_; | ||
float gain_; | ||
|
||
// Recorded slope and gain, used in next sample | ||
float slope_rec_, gain_rec_; | ||
|
||
// Internals from faust | ||
float atk_slo2_, ratio_mul_, atk_slo_, rel_slo_; | ||
|
||
int sample_rate_; | ||
float sample_rate_inv2_, sample_rate_inv_; | ||
|
||
// Auto makeup gain enable | ||
bool makeup_auto_; | ||
|
||
// Methods for recalculating internals | ||
void RecalculateRatio() | ||
{ | ||
ratio_mul_ = ((1.0f - atk_slo2_) * ((1.0f / ratio_) - 1.0f)); | ||
} | ||
|
||
void RecalculateAttack() | ||
{ | ||
atk_slo_ = expf(-(sample_rate_inv_ / atk_)); | ||
atk_slo2_ = expf(-(sample_rate_inv2_ / atk_)); | ||
|
||
RecalculateRatio(); | ||
} | ||
|
||
void RecalculateRelease() { rel_slo_ = expf((-(sample_rate_inv_ / rel_))); } | ||
|
||
void RecalculateMakeup() | ||
{ | ||
if(makeup_auto_) | ||
makeup_gain_ = fabsf(thresh_ - thresh_ / ratio_) * 0.5f; | ||
} | ||
}; | ||
|
||
} // namespace daisysp | ||
|
||
#endif // DSY_COMPRESSOR_H |
Oops, something went wrong.