aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2023-07-30 17:36:50 +0200
committerPaul B Mahol <onemda@gmail.com>2023-07-30 18:14:16 +0200
commitbd23b1d0acb7664e76734ea3b2a07eb5029764b8 (patch)
tree5d607269170d814ebaa040e00157def1058c88f6
parent6f552b9c5eb0c8c37a5c636ff1daa4ce3d45ebe4 (diff)
downloadffmpeg-bd23b1d0acb7664e76734ea3b2a07eb5029764b8.tar.gz
avfilter/avf_showcwt: add iscale option
-rw-r--r--doc/filters.texi12
-rw-r--r--libavfilter/avf_showcwt.c55
2 files changed, 58 insertions, 9 deletions
diff --git a/doc/filters.texi b/doc/filters.texi
index 6f47428aa0..4c2ce6a44c 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -30793,6 +30793,18 @@ Set the frequency scale used. Allowed values are:
@end table
Default value is @code{linear}.
+@item iscale
+Set the intensity scale used. Allowed values are:
+
+@table @option
+@item linear
+@item log
+@item sqrt
+@item cbrt
+@item qdrt
+@end table
+Default value is @code{log}.
+
@item min
Set the minimum frequency that will be used in output.
Default is @code{20} Hz.
diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c
index ea78a83d3e..51a89706ab 100644
--- a/libavfilter/avf_showcwt.c
+++ b/libavfilter/avf_showcwt.c
@@ -47,6 +47,15 @@ enum FrequencyScale {
NB_FSCALE
};
+enum IntensityScale {
+ ISCALE_LOG,
+ ISCALE_LINEAR,
+ ISCALE_SQRT,
+ ISCALE_CBRT,
+ ISCALE_QDRT,
+ NB_ISCALE
+};
+
enum DirectionMode {
DIRECTION_LR,
DIRECTION_RL,
@@ -106,6 +115,7 @@ typedef struct ShowCWTContext {
int input_sample_count, output_sample_count;
int frequency_band_count;
float logarithmic_basis;
+ int intensity_scale;
int frequency_scale;
float minimum_frequency, maximum_frequency;
float deviation;
@@ -133,6 +143,12 @@ static const AVOption showcwt_options[] = {
{ "sqrt", "sqrt", 0, AV_OPT_TYPE_CONST,{.i64=FSCALE_SQRT}, 0, 0, FLAGS, "scale" },
{ "cbrt", "cbrt", 0, AV_OPT_TYPE_CONST,{.i64=FSCALE_CBRT}, 0, 0, FLAGS, "scale" },
{ "qdrt", "qdrt", 0, AV_OPT_TYPE_CONST,{.i64=FSCALE_QDRT}, 0, 0, FLAGS, "scale" },
+ { "iscale", "set intensity scale", OFFSET(intensity_scale),AV_OPT_TYPE_INT, {.i64=0}, 0, NB_ISCALE-1, FLAGS, "iscale" },
+ { "linear", "linear", 0, AV_OPT_TYPE_CONST,{.i64=ISCALE_LINEAR}, 0, 0, FLAGS, "iscale" },
+ { "log", "logarithmic", 0, AV_OPT_TYPE_CONST,{.i64=ISCALE_LOG}, 0, 0, FLAGS, "iscale" },
+ { "sqrt", "sqrt", 0, AV_OPT_TYPE_CONST,{.i64=ISCALE_SQRT}, 0, 0, FLAGS, "iscale" },
+ { "cbrt", "cbrt", 0, AV_OPT_TYPE_CONST,{.i64=ISCALE_CBRT}, 0, 0, FLAGS, "iscale" },
+ { "qdrt", "qdrt", 0, AV_OPT_TYPE_CONST,{.i64=ISCALE_QDRT}, 0, 0, FLAGS, "iscale" },
{ "min", "set minimum frequency", OFFSET(minimum_frequency), AV_OPT_TYPE_FLOAT, {.dbl = 20.}, 1, 192000, FLAGS },
{ "max", "set maximum frequency", OFFSET(maximum_frequency), AV_OPT_TYPE_FLOAT, {.dbl = 20000.}, 1, 192000, FLAGS },
{ "logb", "set logarithmic basis", OFFSET(logarithmic_basis), AV_OPT_TYPE_FLOAT, {.dbl = 0.0001}, 0, 1, FLAGS },
@@ -278,11 +294,31 @@ static void frequency_band(float *frequency_band,
}
}
-static float remap_log(float value, float log_factor)
+static float remap_log(float value, int iscale, float log_factor)
{
- value = logf(value) * log_factor;
+ float ret;
+
+ switch (iscale) {
+ case ISCALE_LINEAR:
+ ret = value * 20.f*expf(log_factor);
+ break;
+ case ISCALE_LOG:
+ value = logf(value) * log_factor;
- return 1.f - av_clipf(value, 0.f, 1.f);
+ ret = 1.f - av_clipf(value, 0.f, 1.f);
+ break;
+ case ISCALE_SQRT:
+ ret = sqrtf(value * 20.f*expf(log_factor));
+ break;
+ case ISCALE_CBRT:
+ ret = cbrtf(value * 20.f*expf(log_factor));
+ break;
+ case ISCALE_QDRT:
+ ret = powf(value * 20.f*expf(log_factor), 0.25f);
+ break;
+ }
+
+ return ret;
}
static int run_channel_cwt_prepare(AVFilterContext *ctx, void *arg, int jobnr, int ch)
@@ -403,6 +439,7 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
const int start = (count * jobnr) / nb_jobs;
const int end = (count * (jobnr+1)) / nb_jobs;
const int nb_channels = s->nb_channels;
+ const int iscale = s->intensity_scale;
const int ihop_index = s->ihop_index;
const int ihop_size = s->ihop_size;
const float rotation = s->rotation;
@@ -479,9 +516,9 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
u = hypotf(src[0].re, src[0].im);
v = hypotf(src2[0].re, src2[0].im);
- z = remap_log(z, log_factor);
- u = remap_log(u, log_factor);
- v = remap_log(v, log_factor);
+ z = remap_log(z, iscale, log_factor);
+ u = remap_log(u, iscale, log_factor);
+ v = remap_log(v, iscale, log_factor);
Y = z;
U = sinf((v - u) * M_PI_2);
@@ -515,7 +552,7 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
float z;
z = hypotf(srcn[0].re, srcn[0].im);
- z = remap_log(z, log_factor);
+ z = remap_log(z, iscale, log_factor);
Y += z * yf;
U += z * yf * sinf(2.f * M_PI * (ch * yf + rotation));
@@ -534,7 +571,7 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
break;
case 2:
Y = hypotf(src[0].re, src[0].im);
- Y = remap_log(Y, log_factor);
+ Y = remap_log(Y, iscale, log_factor);
U = atan2f(src[0].im, src[0].re);
U = 0.5f + 0.5f * U * Y / M_PI;
V = 1.f - U;
@@ -559,7 +596,7 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
break;
case 0:
Y = hypotf(src[0].re, src[0].im);
- Y = remap_log(Y, log_factor);
+ Y = remap_log(Y, iscale, log_factor);
dstY[0] = av_clip_uint8(lrintf(Y * 255.f));
if (dstA)