189 lines
3.5 KiB
Racket
189 lines
3.5 KiB
Racket
#lang scribble/manual
|
|
@(require (for-label racket))
|
|
|
|
@title{AmpCompA}
|
|
Basic psychoacoustic amplitude compensation (ANSI A-weighting curve).@section{related}
|
|
Classes/AmpComp
|
|
@section{categories}
|
|
UGens>Analysis>Amplitude
|
|
|
|
|
|
@section{description}
|
|
|
|
|
|
Higher frequencies are normally perceived as louder, which AmpCompA
|
|
compensates. Following the measurements by Fletcher and Munson, the
|
|
ANSI standard describes a function for loudness vs. frequency.
|
|
|
|
Note that this curve is only valid for standardized amplitude.
|
|
@section{footnote}
|
|
|
|
Function freq → dB,
|
|
derived from http://www.beis.de/Elektronik/AudioMeasure/WeightingFilters.html
|
|
and modified to map freq → amp.
|
|
|
|
@racketblock[
|
|
(
|
|
var k = 3.5041384e16;
|
|
var c1 = 424.31867740601;
|
|
var c2 = 11589.093052022;
|
|
var c3 = 544440.67046057;
|
|
var c4 = 148698928.24309;
|
|
f = {|f|
|
|
var r = squared(f);
|
|
var m1 = pow(r,4);
|
|
var n1 = squared(c1 + r);
|
|
var n2 = c2 + r;
|
|
var n3 = c3 + r;
|
|
var n4 = squared(c4 + r);
|
|
var level = k * m1 / (n1 * n2 * n3 * n4);
|
|
sqrt(level)
|
|
};
|
|
)
|
|
::
|
|
|
|
::
|
|
|
|
|
|
For a simpler but more flexible curve, see link::Classes/AmpComp::
|
|
|
|
]
|
|
@section{classmethods}
|
|
|
|
|
|
@section{method}
|
|
ar, kr, ir
|
|
|
|
@section{argument}
|
|
freq
|
|
Input frequency value. For freq == root, the output is rootAmp.
|
|
|
|
@section{argument}
|
|
root
|
|
Root freq relative to which the curve is calculated (usually lowest freq).
|
|
|
|
@section{argument}
|
|
minAmp
|
|
Amplitude at the minimum point of the curve (around 2512 Hz).
|
|
|
|
@section{argument}
|
|
rootAmp
|
|
Amplitude at the root frequency.
|
|
|
|
@section{discussion}
|
|
|
|
Apart from
|
|
@racketblock[freq::, the values are not modulatable
|
|
|
|
]
|
|
@section{Examples}
|
|
|
|
|
|
|
|
@racketblock[
|
|
|
|
// compare a sine without compensation
|
|
|
|
{ SinOsc.ar(MouseX.kr(300, 15000, 1)) * 0.1 }.play;
|
|
|
|
// with one that uses amplitude compensation
|
|
(
|
|
{
|
|
var freq;
|
|
freq = MouseX.kr(300, 15000, 1);
|
|
SinOsc.ar(freq) * 0.3 * AmpCompA.kr(freq)
|
|
}.play;
|
|
)
|
|
|
|
|
|
// adjust the minimum and root amp
|
|
// (in this way one can flatten out the curve for higher amplitudes)
|
|
|
|
(
|
|
{
|
|
var freq;
|
|
freq = MouseX.kr(300, 18000, 1);
|
|
Formant.ar(300, freq, 20, 0.1) * AmpCompA.kr(freq, 300, 0.6, 0.3)
|
|
}.play;
|
|
)
|
|
|
|
// the curve:
|
|
|
|
{ AmpCompA.ar(Line.ar(48, 120, 1).midicps, 48.midicps) }.plot(1.0);
|
|
|
|
// freqs:
|
|
|
|
{ AmpCompA.ar(Line.ar(0, 20000, 1)) }.plot(1.0);
|
|
|
|
// compare with AmpComp (exponential decay)
|
|
|
|
{ AmpComp.ar(Line.ar(48, 120, 1).midicps, 48.midicps) }.plot(1.0);
|
|
|
|
// freqs:
|
|
|
|
{ AmpComp.ar(Line.ar(40, 20000, 1), 40) }.plot(1.0);
|
|
|
|
|
|
|
|
// amplitude compensation in frequency modulation (using Fletscher-Munson curve)
|
|
(
|
|
{
|
|
var freq;
|
|
freq = MouseX.kr(300, 15000, 1);
|
|
freq = freq * SinOsc.ar(MouseY.kr(3, 200, 1), 0, 0.5, 1);
|
|
SinOsc.ar(freq) * 0.1 * AmpCompA.ar(freq, 300)
|
|
}.play;
|
|
)
|
|
|
|
// amplitude compensation in frequency modulation (using AmpComp exponential decay)
|
|
(
|
|
{
|
|
var freq;
|
|
freq = MouseX.kr(300, 15000, 1);
|
|
freq = freq * SinOsc.ar(MouseY.kr(3, 200, 1), 0, 0.5, 1);
|
|
SinOsc.ar(freq) * 0.1 * AmpComp.ar(freq, 300)
|
|
}.play;
|
|
)
|
|
|
|
|
|
// without amplitude compensation
|
|
(
|
|
{
|
|
var freq;
|
|
freq = MouseX.kr(300, 15000, 1);
|
|
freq = freq * SinOsc.ar(MouseY.kr(3, 200, 1), 0, 0.5, 1);
|
|
SinOsc.ar(freq) * 0.1
|
|
}.play;
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
[1] Function freq -> dB,
|
|
derived from http://www.beis.de/Elektronik/AudioMeasure/WeightingFilters.html
|
|
and modified to map freq -> amp
|
|
|
|
(
|
|
var k = 3.5041384e16;
|
|
var c1 = 424.31867740601;
|
|
var c2 = 11589.093052022;
|
|
var c3 = 544440.67046057;
|
|
var c4 = 148698928.24309;
|
|
f = {|f|
|
|
var r = squared(f);
|
|
var m1 = pow(r,4);
|
|
var n1 = squared(c1 + r);
|
|
var n2 = c2 + r;
|
|
var n3 = c3 + r;
|
|
var n4 = squared(c4 + r);
|
|
var level = k * m1 / (n1 * n2 * n3 * n4);
|
|
sqrt(level)
|
|
};
|
|
)
|
|
|
|
::
|
|
|
|
]
|
|
|
|
|