Replies: 3 comments
-
There was a cut and paste error in the above. Corrections: Function declaration line should be: The call to it should be: |
Beta Was this translation helpful? Give feedback.
-
Extra info that may be relevant... Output of println(library_version()) is KFR 6.0.3 avx2 64-bit (clang-15.0.0/macos) +in +ve I use Xcode 15.4 running on MacOS Sonoma. |
Beta Was this translation helpful? Give feedback.
-
Hi Dan, I’ve made some progress… Definition of dynamic range compression expression: Implementation of expression traits… Samples are held in a univector so I’ve used shape<1>. Size is not known at compile time as CoreAudio sometimes provides samples in buffers of less than the configured size. template I can instantiate and evaluate the expression as follows: Seems that I need to do 2 more things…
template <typename T, index_t Axis, size_t N>
Also, I can contribute by preparing documentation if this would be helpful. Just let me know. Thanks in advance, |
Beta Was this translation helpful? Give feedback.
-
Hi again Dan,
Following our previous discussion on splitting audio, I’m working on a means of managing LFE level after redirecting the bass from the 7 main channels. Rather than just attenuate the LFE samples by a fixed number of dB, I’m implementing dynamic range compression. I use a Mac Mini 2018 and my KFR processing is all double precision floating point. I have plenty of amplifier power and subs to deliver high sound pressure levels at low frequencies. :)
The compression algorithm I’m using (for better or worse), is based on a circular arc. For a sample s, the function drc(s) is:
if abs(s) <= threshold (say 0.9), drc(s) = s.
if threshold < abs(s) < upper limit, drc(s) = point on a circular arc centred such that drc() is differentiable at all values of s. Upper limit is set at the point where the arc has zero slope. Soft clip.
if abs(s) > upper limit, drc(s) = 1.0. Hard clip.
Sorry if this is a bit cryptic.
The function’s code looks like this (NB calculation of some constants is not shown):
double grc(double apply_circular_arc_drc(double s)
if (abs(s) <= threshold)
return s; // Sample is below threshold; no compression.
else if (abs(s) < s_input_max) {
// Sample is above threshold and below upper limit
const double w = s_input_max - abs(s); // Find width of triangle for sample
// Calculate height of point on circular arc on which the sample lies using Pythagoras
const double h = std::pow((std::pow(r, 2) - std::pow(w, 2)), 0.5);
// Calculate sample as height of triangle in circle plus height of centre of circle above 0.0
const double t = (h + c) * sign(s); // Retain sign of original sample
return t;
} else {
// Sample is above upper limit; hard clip.
double t = 1.0 * sign(s); // Retain sign of original sample
return t;
}
I apply the compression to univector samples using:
std::transform(samples.begin(), samples.end(), samples.begin(), g);
This runs the function against every sample in univector and does not leverage simd intrinsics. It runs fine, but I'm looking for a more efficient solution.
Question: How could this be implemented more efficiently using KFR?
I’ve tried to work out whether I can use KFR template expressions (and read the example) and the existing sqr and sqrt functions but haven’t found a solution.
Appreciate your help with this.
PS Pls let me know if this approach is nonsense and should be done another way!
Beta Was this translation helpful? Give feedback.
All reactions