// Exponential curve for the knee. // It is 1st derivative matched at m_linearThreshold and asymptotically // approaches the value m_linearThreshold + 1 / k. float DynamicsCompressorKernel::kneeCurve(float x, float k) { // Linear up to threshold. if (x < m_linearThreshold) return x;
// Full compression curve with constant ratio after knee. float DynamicsCompressorKernel::saturate(float x, float k) { float y;
if (x < m_kneeThreshold)
y = kneeCurve(x, k); else { // Constant ratio after knee. float xDb = WebAudioUtils::ConvertLinearToDecibels(x, -1000.0f); float yDb = m_ykneeThresholdDb + m_slope * (xDb - m_kneeThresholdDb);
y = WebAudioUtils::ConvertDecibelsToLinear(yDb);
}
return y;
}
// Approximate 1st derivative with input and output expressed in dB. // This slope is equal to the inverse of the compression "ratio". // In other words, a compression ratio of 20 would be a slope of 1/20. float DynamicsCompressorKernel::slopeAt(float x, float k) { if (x < m_linearThreshold) return1;
unsigned frameIndex = 0; for (int i = 0; i < nDivisions; ++i) { // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Calculate desired gain // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Fix gremlins. if (std::isnan(m_detectorAverage)) m_detectorAverage = 1; if (std::isinf(m_detectorAverage)) m_detectorAverage = 1;
float desiredGain = m_detectorAverage;
// Pre-warp so we get desiredGain after sin() warp below. float scaledDesiredGain = fdlibm_asinf(desiredGain) / (0.5f * M_PI);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Deal with envelopes // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// envelopeRate is the rate we slew from current compressor level to the // desired level. The exact rate depends on if we're attacking or releasing // and by how much. float envelopeRate;
// compressionDiffDb is the difference between current compression level and // the desired level. float compressionDiffDb; if (scaledDesiredGain == 0.0) {
compressionDiffDb = PositiveInfinity<float>();
} else {
compressionDiffDb = WebAudioUtils::ConvertLinearToDecibels(
m_compressorGain / scaledDesiredGain, -1000.0f);
}
if (isReleasing) { // Release mode - compressionDiffDb should be negative dB
m_maxAttackCompressionDiffDb = -1;
// Fix gremlins. if (std::isnan(compressionDiffDb)) compressionDiffDb = -1; if (std::isinf(compressionDiffDb)) compressionDiffDb = -1;
// Contain within range: -12 -> 0 then scale to go from 0 -> 3 float x = compressionDiffDb;
x = std::max(-12.0f, x);
x = std::min(0.0f, x);
x = 0.25f * (x + 12);
// Compute adaptive release curve using 4th order polynomial. // Normal values for the polynomial coefficients would create a // monotonically increasing function. float x2 = x * x; float x3 = x2 * x; float x4 = x2 * x2; float releaseFrames = kA + kB * x + kC * x2 + kD * x3 + kE * x4;
envelopeRate = WebAudioUtils::ConvertDecibelsToLinear(dbPerFrame);
} else { // Attack mode - compressionDiffDb should be positive dB
// Fix gremlins. if (std::isnan(compressionDiffDb)) compressionDiffDb = 1; if (std::isinf(compressionDiffDb)) compressionDiffDb = 1;
// As long as we're still in attack mode, use a rate based off // the largest compressionDiffDb we've encountered so far. if (m_maxAttackCompressionDiffDb == -1 ||
m_maxAttackCompressionDiffDb < compressionDiffDb)
m_maxAttackCompressionDiffDb = compressionDiffDb;
// Put through shaping curve. // This is linear up to the threshold, then enters a "knee" portion // followed by the "ratio" portion. The transition from the threshold to // the knee is smooth (1st derivative matched). The transition from the // knee to the ratio portion is smooth (1st derivative matched). float shapedInput = saturate(absInput, k);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.