avfilter/af_sidechaincompress: implement mode option
This commit is contained in:
		
							parent
							
								
									2a50f1d9e4
								
							
						
					
					
						commit
						a0559fcd81
					
				@ -390,6 +390,10 @@ The filter accepts the following options:
 | 
				
			|||||||
@item level_in
 | 
					@item level_in
 | 
				
			||||||
Set input gain. Default is 1. Range is between 0.015625 and 64.
 | 
					Set input gain. Default is 1. Range is between 0.015625 and 64.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@item mode
 | 
				
			||||||
 | 
					Set mode of compressor operation. Can be @code{upward} or @code{downward}.
 | 
				
			||||||
 | 
					Default is @code{downward}.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@item threshold
 | 
					@item threshold
 | 
				
			||||||
If a signal of stream rises above this level it will affect the gain
 | 
					If a signal of stream rises above this level it will affect the gain
 | 
				
			||||||
reduction.
 | 
					reduction.
 | 
				
			||||||
@ -4247,6 +4251,10 @@ The filter accepts the following options:
 | 
				
			|||||||
@item level_in
 | 
					@item level_in
 | 
				
			||||||
Set input gain. Default is 1. Range is between 0.015625 and 64.
 | 
					Set input gain. Default is 1. Range is between 0.015625 and 64.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@item mode
 | 
				
			||||||
 | 
					Set mode of compressor operation. Can be @code{upward} or @code{downward}.
 | 
				
			||||||
 | 
					Default is @code{downward}.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@item threshold
 | 
					@item threshold
 | 
				
			||||||
If a signal of second stream raises above this level it will affect the gain
 | 
					If a signal of second stream raises above this level it will affect the gain
 | 
				
			||||||
reduction of first stream.
 | 
					reduction of first stream.
 | 
				
			||||||
 | 
				
			|||||||
@ -54,10 +54,14 @@ typedef struct SidechainCompressContext {
 | 
				
			|||||||
    double knee_start;
 | 
					    double knee_start;
 | 
				
			||||||
    double knee_stop;
 | 
					    double knee_stop;
 | 
				
			||||||
    double lin_knee_start;
 | 
					    double lin_knee_start;
 | 
				
			||||||
 | 
					    double lin_knee_stop;
 | 
				
			||||||
    double adj_knee_start;
 | 
					    double adj_knee_start;
 | 
				
			||||||
 | 
					    double adj_knee_stop;
 | 
				
			||||||
 | 
					    double compressed_knee_start;
 | 
				
			||||||
    double compressed_knee_stop;
 | 
					    double compressed_knee_stop;
 | 
				
			||||||
    int link;
 | 
					    int link;
 | 
				
			||||||
    int detection;
 | 
					    int detection;
 | 
				
			||||||
 | 
					    int mode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    AVAudioFifo *fifo[2];
 | 
					    AVAudioFifo *fifo[2];
 | 
				
			||||||
    int64_t pts;
 | 
					    int64_t pts;
 | 
				
			||||||
@ -69,6 +73,9 @@ typedef struct SidechainCompressContext {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static const AVOption options[] = {
 | 
					static const AVOption options[] = {
 | 
				
			||||||
    { "level_in",  "set input gain",     OFFSET(level_in),  AV_OPT_TYPE_DOUBLE, {.dbl=1},        0.015625,   64, A|F },
 | 
					    { "level_in",  "set input gain",     OFFSET(level_in),  AV_OPT_TYPE_DOUBLE, {.dbl=1},        0.015625,   64, A|F },
 | 
				
			||||||
 | 
					    { "mode",      "set mode",           OFFSET(mode),      AV_OPT_TYPE_INT,    {.i64=0},               0,    1, A|F, "mode" },
 | 
				
			||||||
 | 
					    {   "downward",0,                    0,                 AV_OPT_TYPE_CONST,  {.i64=0},               0,    0, A|F, "mode" },
 | 
				
			||||||
 | 
					    {   "upward",  0,                    0,                 AV_OPT_TYPE_CONST,  {.i64=1},               0,    0, A|F, "mode" },
 | 
				
			||||||
    { "threshold", "set threshold",      OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl=0.125}, 0.000976563,    1, A|F },
 | 
					    { "threshold", "set threshold",      OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl=0.125}, 0.000976563,    1, A|F },
 | 
				
			||||||
    { "ratio",     "set ratio",          OFFSET(ratio),     AV_OPT_TYPE_DOUBLE, {.dbl=2},               1,   20, A|F },
 | 
					    { "ratio",     "set ratio",          OFFSET(ratio),     AV_OPT_TYPE_DOUBLE, {.dbl=2},               1,   20, A|F },
 | 
				
			||||||
    { "attack",    "set attack",         OFFSET(attack),    AV_OPT_TYPE_DOUBLE, {.dbl=20},           0.01, 2000, A|F },
 | 
					    { "attack",    "set attack",         OFFSET(attack),    AV_OPT_TYPE_DOUBLE, {.dbl=20},           0.01, 2000, A|F },
 | 
				
			||||||
@ -97,7 +104,9 @@ AVFILTER_DEFINE_CLASS(sidechaincompress);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static double output_gain(double lin_slope, double ratio, double thres,
 | 
					static double output_gain(double lin_slope, double ratio, double thres,
 | 
				
			||||||
                          double knee, double knee_start, double knee_stop,
 | 
					                          double knee, double knee_start, double knee_stop,
 | 
				
			||||||
                          double compressed_knee_stop, int detection)
 | 
					                          double compressed_knee_start,
 | 
				
			||||||
 | 
					                          double compressed_knee_stop,
 | 
				
			||||||
 | 
					                          int detection, int mode)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    double slope = log(lin_slope);
 | 
					    double slope = log(lin_slope);
 | 
				
			||||||
    double gain = 0.0;
 | 
					    double gain = 0.0;
 | 
				
			||||||
@ -114,10 +123,17 @@ static double output_gain(double lin_slope, double ratio, double thres,
 | 
				
			|||||||
        delta = 1.0 / ratio;
 | 
					        delta = 1.0 / ratio;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (mode) {
 | 
				
			||||||
 | 
					        if (knee > 1.0 && slope > knee_start)
 | 
				
			||||||
 | 
					            gain = hermite_interpolation(slope, knee_stop, knee_start,
 | 
				
			||||||
 | 
					                                         knee_stop, compressed_knee_start,
 | 
				
			||||||
 | 
					                                         1.0, delta);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
        if (knee > 1.0 && slope < knee_stop)
 | 
					        if (knee > 1.0 && slope < knee_stop)
 | 
				
			||||||
            gain = hermite_interpolation(slope, knee_start, knee_stop,
 | 
					            gain = hermite_interpolation(slope, knee_start, knee_stop,
 | 
				
			||||||
                                         knee_start, compressed_knee_stop,
 | 
					                                         knee_start, compressed_knee_stop,
 | 
				
			||||||
                                         1.0, delta);
 | 
					                                         1.0, delta);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return exp(gain - slope);
 | 
					    return exp(gain - slope);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -129,9 +145,12 @@ static int compressor_config_output(AVFilterLink *outlink)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    s->thres = log(s->threshold);
 | 
					    s->thres = log(s->threshold);
 | 
				
			||||||
    s->lin_knee_start = s->threshold / sqrt(s->knee);
 | 
					    s->lin_knee_start = s->threshold / sqrt(s->knee);
 | 
				
			||||||
 | 
					    s->lin_knee_stop = s->threshold * sqrt(s->knee);
 | 
				
			||||||
    s->adj_knee_start = s->lin_knee_start * s->lin_knee_start;
 | 
					    s->adj_knee_start = s->lin_knee_start * s->lin_knee_start;
 | 
				
			||||||
 | 
					    s->adj_knee_stop = s->lin_knee_stop * s->lin_knee_stop;
 | 
				
			||||||
    s->knee_start = log(s->lin_knee_start);
 | 
					    s->knee_start = log(s->lin_knee_start);
 | 
				
			||||||
    s->knee_stop = log(s->threshold * sqrt(s->knee));
 | 
					    s->knee_stop = log(s->lin_knee_stop);
 | 
				
			||||||
 | 
					    s->compressed_knee_start = (s->knee_start - s->thres) / s->ratio + s->thres;
 | 
				
			||||||
    s->compressed_knee_stop = (s->knee_stop - s->thres) / s->ratio + s->thres;
 | 
					    s->compressed_knee_stop = (s->knee_stop - s->thres) / s->ratio + s->thres;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->attack_coeff = FFMIN(1., 1. / (s->attack * outlink->sample_rate / 4000.));
 | 
					    s->attack_coeff = FFMIN(1., 1. / (s->attack * outlink->sample_rate / 4000.));
 | 
				
			||||||
@ -151,6 +170,8 @@ static void compressor(SidechainCompressContext *s,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < nb_samples; i++) {
 | 
					    for (i = 0; i < nb_samples; i++) {
 | 
				
			||||||
        double abs_sample, gain = 1.0;
 | 
					        double abs_sample, gain = 1.0;
 | 
				
			||||||
 | 
					        double detector;
 | 
				
			||||||
 | 
					        int detected;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        abs_sample = fabs(scsrc[0] * level_sc);
 | 
					        abs_sample = fabs(scsrc[0] * level_sc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -169,10 +190,20 @@ static void compressor(SidechainCompressContext *s,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        s->lin_slope += (abs_sample - s->lin_slope) * (abs_sample > s->lin_slope ? s->attack_coeff : s->release_coeff);
 | 
					        s->lin_slope += (abs_sample - s->lin_slope) * (abs_sample > s->lin_slope ? s->attack_coeff : s->release_coeff);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (s->lin_slope > 0.0 && s->lin_slope > (s->detection ? s->adj_knee_start : s->lin_knee_start))
 | 
					        if (s->mode) {
 | 
				
			||||||
 | 
					            detector = (s->detection ? s->adj_knee_stop : s->lin_knee_stop);
 | 
				
			||||||
 | 
					            detected = s->lin_slope < detector;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            detector = (s->detection ? s->adj_knee_start : s->lin_knee_start);
 | 
				
			||||||
 | 
					            detected = s->lin_slope > detector;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (s->lin_slope > 0.0 && detected)
 | 
				
			||||||
            gain = output_gain(s->lin_slope, s->ratio, s->thres, s->knee,
 | 
					            gain = output_gain(s->lin_slope, s->ratio, s->thres, s->knee,
 | 
				
			||||||
                               s->knee_start, s->knee_stop,
 | 
					                               s->knee_start, s->knee_stop,
 | 
				
			||||||
                               s->compressed_knee_stop, s->detection);
 | 
					                               s->compressed_knee_start,
 | 
				
			||||||
 | 
					                               s->compressed_knee_stop,
 | 
				
			||||||
 | 
					                               s->detection, s->mode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (c = 0; c < inlink->channels; c++)
 | 
					        for (c = 0; c < inlink->channels; c++)
 | 
				
			||||||
            dst[c] = src[c] * level_in * (gain * makeup * mix + (1. - mix));
 | 
					            dst[c] = src[c] * level_in * (gain * makeup * mix + (1. - mix));
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user