You've already forked FFmpeg
							
							
				mirror of
				https://github.com/FFmpeg/FFmpeg.git
				synced 2025-10-30 23:18:11 +02:00 
			
		
		
		
	avfilter/af_aiir: add polar zeros/poles format variant
Signed-off-by: Paul B Mahol <onemda@gmail.com>
This commit is contained in:
		| @@ -1084,8 +1084,17 @@ Set output gain. | ||||
|  | ||||
| @item f | ||||
| Set coefficients format. | ||||
| Can be @code{tf} - transfer function or @code{zp} - Z-plane zeros/poles. | ||||
| Default is @code{zp}. | ||||
|  | ||||
| @table @samp | ||||
| @item tf | ||||
| transfer function | ||||
| @item zp | ||||
| Z-plane zeros/poles, cartesian (default) | ||||
| @item zpr | ||||
| Z-plane zeros/poles, polar radians | ||||
| @item zpd | ||||
| Z-plane zeros/poles, polar degrees | ||||
| @end table | ||||
|  | ||||
| @item r | ||||
| Set kind of processing. | ||||
| @@ -1094,7 +1103,7 @@ Can be @code{d} - direct or @code{s} - serial cascading. Defauls is @code{s}. | ||||
| @item e | ||||
| Set filtering precision. | ||||
|  | ||||
| @table @option | ||||
| @table @samp | ||||
| @item dbl | ||||
| double-precision floating-point (default) | ||||
| @item flt | ||||
|   | ||||
| @@ -283,7 +283,7 @@ static int read_tf_coefficients(AVFilterContext *ctx, char *item_str, int nb_ite | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int read_zp_coefficients(AVFilterContext *ctx, char *item_str, int nb_items, double *dst) | ||||
| static int read_zp_coefficients(AVFilterContext *ctx, char *item_str, int nb_items, double *dst, const char *format) | ||||
| { | ||||
|     char *p, *arg, *old_str, *saveptr = NULL; | ||||
|     int i; | ||||
| @@ -296,7 +296,7 @@ static int read_zp_coefficients(AVFilterContext *ctx, char *item_str, int nb_ite | ||||
|             break; | ||||
|  | ||||
|         p = NULL; | ||||
|         if (sscanf(arg, "%lf %lfi", &dst[i*2], &dst[i*2+1]) != 2) { | ||||
|         if (sscanf(arg, format, &dst[i*2], &dst[i*2+1]) != 2) { | ||||
|             av_log(ctx, AV_LOG_ERROR, "Invalid coefficients supplied: %s\n", arg); | ||||
|             av_freep(&old_str); | ||||
|             return AVERROR(EINVAL); | ||||
| @@ -308,6 +308,8 @@ static int read_zp_coefficients(AVFilterContext *ctx, char *item_str, int nb_ite | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static const char *format[] = { "%lf", "%lf %lfi", "%lf %lfr", "%lf %lfd" }; | ||||
|  | ||||
| static int read_channels(AVFilterContext *ctx, int channels, uint8_t *item_str, int ab) | ||||
| { | ||||
|     AudioIIRContext *s = ctx->priv; | ||||
| @@ -332,14 +334,14 @@ static int read_channels(AVFilterContext *ctx, int channels, uint8_t *item_str, | ||||
|  | ||||
|         p = NULL; | ||||
|         iir->cache[ab] = av_calloc(iir->nb_ab[ab] + 1, sizeof(double)); | ||||
|         iir->ab[ab] = av_calloc(iir->nb_ab[ab] * (s->format + 1), sizeof(double)); | ||||
|         iir->ab[ab] = av_calloc(iir->nb_ab[ab] * (!!s->format + 1), sizeof(double)); | ||||
|         if (!iir->ab[ab] || !iir->cache[ab]) { | ||||
|             av_freep(&old_str); | ||||
|             return AVERROR(ENOMEM); | ||||
|         } | ||||
|  | ||||
|         if (s->format) { | ||||
|             ret = read_zp_coefficients(ctx, arg, iir->nb_ab[ab], iir->ab[ab]); | ||||
|             ret = read_zp_coefficients(ctx, arg, iir->nb_ab[ab], iir->ab[ab], format[s->format]); | ||||
|         } else { | ||||
|             ret = read_tf_coefficients(ctx, arg, iir->nb_ab[ab], iir->ab[ab]); | ||||
|         } | ||||
| @@ -586,6 +588,60 @@ static int decompose_zp2biquads(AVFilterContext *ctx, int channels) | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static void convert_pr2zp(AVFilterContext *ctx, int channels) | ||||
| { | ||||
|     AudioIIRContext *s = ctx->priv; | ||||
|     int ch; | ||||
|  | ||||
|     for (ch = 0; ch < channels; ch++) { | ||||
|         IIRChannel *iir = &s->iir[ch]; | ||||
|         int n; | ||||
|  | ||||
|         for (n = 0; n < iir->nb_ab[0]; n++) { | ||||
|             double r = iir->ab[0][2*n]; | ||||
|             double angle = iir->ab[0][2*n+1]; | ||||
|  | ||||
|             iir->ab[0][2*n]   = r * cos(angle); | ||||
|             iir->ab[0][2*n+1] = r * sin(angle); | ||||
|         } | ||||
|  | ||||
|         for (n = 0; n < iir->nb_ab[1]; n++) { | ||||
|             double r = iir->ab[1][2*n]; | ||||
|             double angle = iir->ab[1][2*n+1]; | ||||
|  | ||||
|             iir->ab[1][2*n]   = r * cos(angle); | ||||
|             iir->ab[1][2*n+1] = r * sin(angle); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void convert_pd2zp(AVFilterContext *ctx, int channels) | ||||
| { | ||||
|     AudioIIRContext *s = ctx->priv; | ||||
|     int ch; | ||||
|  | ||||
|     for (ch = 0; ch < channels; ch++) { | ||||
|         IIRChannel *iir = &s->iir[ch]; | ||||
|         int n; | ||||
|  | ||||
|         for (n = 0; n < iir->nb_ab[0]; n++) { | ||||
|             double r = iir->ab[0][2*n]; | ||||
|             double angle = M_PI*iir->ab[0][2*n+1]/180.; | ||||
|  | ||||
|             iir->ab[0][2*n]   = r * cos(angle); | ||||
|             iir->ab[0][2*n+1] = r * sin(angle); | ||||
|         } | ||||
|  | ||||
|         for (n = 0; n < iir->nb_ab[1]; n++) { | ||||
|             double r = iir->ab[1][2*n]; | ||||
|             double angle = M_PI*iir->ab[1][2*n+1]/180.; | ||||
|  | ||||
|             iir->ab[1][2*n]   = r * cos(angle); | ||||
|             iir->ab[1][2*n+1] = r * sin(angle); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static int config_output(AVFilterLink *outlink) | ||||
| { | ||||
|     AVFilterContext *ctx = outlink->src; | ||||
| @@ -610,10 +666,16 @@ static int config_output(AVFilterLink *outlink) | ||||
|     if (ret < 0) | ||||
|         return ret; | ||||
|  | ||||
|     if (s->format == 2) { | ||||
|         convert_pr2zp(ctx, inlink->channels); | ||||
|     } else if (s->format == 3) { | ||||
|         convert_pd2zp(ctx, inlink->channels); | ||||
|     } | ||||
|  | ||||
|     if (s->format == 0) | ||||
|         av_log(ctx, AV_LOG_WARNING, "tf coefficients format is not recommended for too high number of zeros/poles.\n"); | ||||
|  | ||||
|     if (s->format == 1 && s->process == 0) { | ||||
|     if (s->format > 0 && s->process == 0) { | ||||
|         av_log(ctx, AV_LOG_WARNING, "Direct processsing is not recommended for zp coefficients format.\n"); | ||||
|  | ||||
|         ret = convert_zp2tf(ctx, inlink->channels); | ||||
| @@ -622,7 +684,7 @@ static int config_output(AVFilterLink *outlink) | ||||
|     } else if (s->format == 0 && s->process == 1) { | ||||
|         av_log(ctx, AV_LOG_ERROR, "Serial cascading is not implemented for transfer function.\n"); | ||||
|         return AVERROR_PATCHWELCOME; | ||||
|     } else if (s->format == 1 && s->process == 1) { | ||||
|     } else if (s->format > 0 && s->process == 1) { | ||||
|         if (inlink->format == AV_SAMPLE_FMT_S16P) | ||||
|             av_log(ctx, AV_LOG_WARNING, "Serial cascading is not recommended for i16 precision.\n"); | ||||
|  | ||||
| @@ -755,9 +817,11 @@ static const AVOption aiir_options[] = { | ||||
|     { "k", "set channels gains",                   OFFSET(g_str),    AV_OPT_TYPE_STRING, {.str="1|1"}, 0, 0, AF }, | ||||
|     { "dry", "set dry gain",                       OFFSET(dry_gain), AV_OPT_TYPE_DOUBLE, {.dbl=1},     0, 1, AF }, | ||||
|     { "wet", "set wet gain",                       OFFSET(wet_gain), AV_OPT_TYPE_DOUBLE, {.dbl=1},     0, 1, AF }, | ||||
|     { "f", "set coefficients format",              OFFSET(format),   AV_OPT_TYPE_INT,    {.i64=1},     0, 1, AF, "format" }, | ||||
|     { "f", "set coefficients format",              OFFSET(format),   AV_OPT_TYPE_INT,    {.i64=1},     0, 3, AF, "format" }, | ||||
|     { "tf", "transfer function",                   0,                AV_OPT_TYPE_CONST,  {.i64=0},     0, 0, AF, "format" }, | ||||
|     { "zp", "Z-plane zeros/poles",                 0,                AV_OPT_TYPE_CONST,  {.i64=1},     0, 0, AF, "format" }, | ||||
|     { "pr", "Z-plane zeros/poles (polar radians)", 0,                AV_OPT_TYPE_CONST,  {.i64=2},     0, 0, AF, "format" }, | ||||
|     { "pd", "Z-plane zeros/poles (polar degrees)", 0,                AV_OPT_TYPE_CONST,  {.i64=3},     0, 0, AF, "format" }, | ||||
|     { "r", "set kind of processing",               OFFSET(process),  AV_OPT_TYPE_INT,    {.i64=1},     0, 1, AF, "process" }, | ||||
|     { "d", "direct",                               0,                AV_OPT_TYPE_CONST,  {.i64=0},     0, 0, AF, "process" }, | ||||
|     { "s", "serial cascading",                     0,                AV_OPT_TYPE_CONST,  {.i64=1},     0, 0, AF, "process" }, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user