aboutsummaryrefslogtreecommitdiffstats
path: root/lib/param.cpp
diff options
context:
space:
mode:
authorMarkus Mittendrein <maxmitti@maxmitti.tk>2022-11-28 20:16:46 +0100
committerMarkus Mittendrein <maxmitti@maxmitti.tk>2022-11-28 20:16:46 +0100
commit4cb83acddbe154312b74d2d63985ac1100bad7c5 (patch)
treed49dc904acc9af57acca8864fb6a40e340accacc /lib/param.cpp
downloadfresample-4cb83acddbe154312b74d2d63985ac1100bad7c5.tar.gz
fresample-4cb83acddbe154312b74d2d63985ac1100bad7c5.zip
InitialHEADmaster
Diffstat (limited to 'lib/param.cpp')
-rw-r--r--lib/param.cpp236
1 files changed, 236 insertions, 0 deletions
diff --git a/lib/param.cpp b/lib/param.cpp
new file mode 100644
index 0000000..58bcf5b
--- /dev/null
+++ b/lib/param.cpp
@@ -0,0 +1,236 @@
+/* Copyright 2012 Dietrich Epp <depp@zdome.net> */
+#include "param.h"
+
+void lfr_param::seti(lfr_param_t pname, int value)
+{
+ int n = pname;
+ if (n < 0 || n >= LFR_PARAM_COUNT)
+ return;
+ set |= 1u << n;
+ current = 0;
+ param[n] = (double) value;
+}
+
+void lfr_param::setf(lfr_param_t pname, double value)
+{
+ int n = pname;
+ if (n < 0 || n >= LFR_PARAM_COUNT)
+ return;
+ set |= 1u << n;
+ current = 0;
+ param[n] = value;
+}
+
+void lfr_param::geti(lfr_param_t pname, int *value)
+{
+ int n = pname;
+ if (n < 0 || n >= LFR_PARAM_COUNT)
+ return;
+ if (!current)
+ calculate();
+ *value = static_cast<int>(param[n] + 0.5);
+}
+
+void lfr_param::getf(lfr_param_t pname, double *value)
+{
+ int n = pname;
+ if (n < 0 || n >= LFR_PARAM_COUNT)
+ return;
+ if (!current)
+ calculate();
+ *value = param[n];
+}
+
+constexpr auto MAX_QUALITY = 10;
+
+struct lfr_quality {
+ unsigned short atten; /* dB */
+ unsigned short transition; /* out of 1000 */
+ unsigned short kind; /* 0 = loose, 2 = maxfreq=0 */
+ unsigned short minfpass; /* out of 1000 */
+};
+
+constexpr lfr_quality LFR_QUALITY[MAX_QUALITY + 1] = {
+ { 35, 350, 0, 500 },
+ { 35, 350, 0, 500 },
+ { 35, 350, 0, 500 }, /* low */
+ { 35, 350, 0, 500 },
+ { 50, 290, 0, 600 },
+ { 60, 230, 1, 700 }, /* medium */
+ { 80, 180, 1, 800 },
+ { 90, 140, 1, 850 },
+ { 96, 100, 1, 900 }, /* high */
+ { 108, 60, 2, 915 },
+ { 120, 30, 2, 930 } /* ultra */
+};
+
+constexpr auto MIN_OUTPUT = 1.0 / 128;
+constexpr auto MIN_ATTEN = 13;
+constexpr auto MAX_ATTEN = 144;
+constexpr auto MIN_TRANSITION = 1.0 / 256.0;
+constexpr auto MAX_MINPASS = 31.0 / 32.0;
+constexpr auto MIN_MINPASS = 8.0 / 32.0;
+
+#define ISSET(n) ((set & (1u << (LFR_PARAM_ ## n))) != 0)
+#define GETF(n) (param[LFR_PARAM_ ## n])
+#define GETI(n) (static_cast<int>(GETF(n) + 0.5))
+
+void lfr_param::calculate()
+{
+ int qual;
+ double rate;
+ double f_output, f_transition, f_maxfreq, f_minpass;
+ double atten, f_stop, f_pass;
+ double t;
+ int loose;
+
+ /* Quality */
+ if (ISSET(QUALITY)) {
+ qual = GETI(QUALITY);
+ if (qual < 0)
+ qual = 0;
+ else if (qual > MAX_QUALITY)
+ qual = MAX_QUALITY;
+ } else {
+ qual = 8;
+ }
+ GETF(QUALITY) = qual;
+
+ /* Input rate */
+ if (ISSET(INRATE)) {
+ rate = GETF(INRATE);
+ if (rate <= 0)
+ rate = -1.0;
+ } else {
+ rate = -1.0;
+ }
+ GETF(INRATE) = rate;
+
+ /* Output rate */
+ if (ISSET(OUTRATE)) {
+ t = GETF(OUTRATE);
+ if (rate > 0) {
+ if (t > rate) {
+ f_output = 1.0;
+ GETF(OUTRATE) = rate;
+ } else {
+ f_output = t / rate;
+ if (f_output < MIN_OUTPUT) {
+ f_output = MIN_OUTPUT;
+ GETF(OUTRATE) = MIN_OUTPUT * rate;
+ }
+ }
+ } else {
+ if (t >= 1.0) {
+ f_output = 1.0;
+ GETF(OUTRATE) = 1.0;
+ } else {
+ f_output = t;
+ if (f_output < MIN_OUTPUT) {
+ f_output = MIN_OUTPUT;
+ GETF(OUTRATE) = MIN_OUTPUT;
+ }
+ }
+ }
+ } else {
+ f_output = 1.0;
+ if (rate > 0)
+ GETF(OUTRATE) = 1.0;
+ else
+ GETF(OUTRATE) = rate;
+ }
+
+ /* Transition bandwidth */
+ if (ISSET(FTRANSITION)) {
+ f_transition = GETF(FTRANSITION);
+ if (f_transition < MIN_TRANSITION)
+ f_transition = 1.0/32;
+ if (f_transition > 1.0)
+ f_transition = 1.0;
+ } else {
+ f_transition = (0.5/1000) * (double) LFR_QUALITY[qual].transition;
+ }
+ GETF(FTRANSITION) = f_transition;
+
+ /* Maximum audible frequency */
+ if (ISSET(MAXFREQ)) {
+ f_maxfreq = GETF(MAXFREQ);
+ } else {
+ if (LFR_QUALITY[qual].kind < 2)
+ f_maxfreq = 20000.0;
+ else
+ f_maxfreq = -1;
+ GETF(MAXFREQ) = f_maxfreq;
+ }
+ if (rate > 0)
+ f_maxfreq = f_maxfreq / rate;
+ else
+ f_maxfreq = 1.0;
+
+ /* "Loose" flag */
+ if (ISSET(LOOSE)) {
+ loose = GETI(LOOSE) > 0;
+ } else {
+ loose = LFR_QUALITY[qual].kind < 1;
+ }
+ GETF(LOOSE) = (double) loose;
+
+ /* Minimum output bandwidth */
+ if (ISSET(MINFPASS)) {
+ f_minpass = GETF(MINFPASS);
+ if (f_minpass < MIN_MINPASS)
+ f_minpass = MIN_MINPASS;
+ else if (f_minpass > MAX_MINPASS)
+ f_minpass = MAX_MINPASS;
+ } else {
+ f_minpass = 0.001 * LFR_QUALITY[qual].minfpass;
+ }
+ GETF(MINFPASS) = f_minpass;
+
+ /* Stop band attenuation */
+ if (ISSET(ATTEN)) {
+ atten = GETF(ATTEN);
+ if (atten < MIN_ATTEN)
+ atten = MIN_ATTEN;
+ else if (atten > MAX_ATTEN)
+ atten = MAX_ATTEN;
+ } else {
+ atten = (double) LFR_QUALITY[qual].atten;
+ }
+ GETF(ATTEN) = atten;
+
+ /* Stop band frequency */
+ if (ISSET(FSTOP)) {
+ f_stop = GETF(FSTOP);
+ if (f_stop > 1.0)
+ f_stop = 1.0;
+ else if (f_stop < MIN_TRANSITION)
+ f_stop = MIN_TRANSITION;
+ } else {
+ f_stop = 0.5 * f_output;
+ if (loose && f_maxfreq > 0) {
+ t = f_output - f_maxfreq;
+ if (t > f_stop)
+ f_stop = t;
+ }
+ }
+ GETF(FSTOP) = f_stop;
+
+ /* Pass band frequency */
+ if (ISSET(ATTEN)) {
+ f_pass = GETF(FPASS);
+ } else {
+ f_pass = f_stop - f_transition;
+ t = 0.5 * f_output * f_minpass;
+ if (t > f_pass)
+ f_pass = t;
+ if (f_maxfreq > 0 && f_pass > f_maxfreq)
+ f_pass = f_maxfreq;
+ }
+ t = f_stop - MIN_TRANSITION;
+ if (t < 0)
+ t = 0;
+ if (t < f_pass)
+ f_pass = t;
+ GETF(FPASS) = f_pass;
+}