Justin's version has more features but is otherwise equivalent from the point of view of the syntax.tags/n1.1
| @@ -829,56 +829,6 @@ out | |||||
| Convert the audio sample format, sample rate and channel layout. This filter is | Convert the audio sample format, sample rate and channel layout. This filter is | ||||
| not meant to be used directly. | not meant to be used directly. | ||||
| @section volume | |||||
| Adjust the input audio volume. | |||||
| The filter accepts exactly one parameter @var{vol}, which expresses | |||||
| how the audio volume will be increased or decreased. | |||||
| Output values are clipped to the maximum value. | |||||
| If @var{vol} is expressed as a decimal number, the output audio | |||||
| volume is given by the relation: | |||||
| @example | |||||
| @var{output_volume} = @var{vol} * @var{input_volume} | |||||
| @end example | |||||
| If @var{vol} is expressed as a decimal number followed by the string | |||||
| "dB", the value represents the requested change in decibels of the | |||||
| input audio power, and the output audio volume is given by the | |||||
| relation: | |||||
| @example | |||||
| @var{output_volume} = 10^(@var{vol}/20) * @var{input_volume} | |||||
| @end example | |||||
| Otherwise @var{vol} is considered an expression and its evaluated | |||||
| value is used for computing the output audio volume according to the | |||||
| first relation. | |||||
| Default value for @var{vol} is 1.0. | |||||
| @subsection Examples | |||||
| @itemize | |||||
| @item | |||||
| Half the input audio volume: | |||||
| @example | |||||
| volume=0.5 | |||||
| @end example | |||||
| The above example is equivalent to: | |||||
| @example | |||||
| volume=1/2 | |||||
| @end example | |||||
| @item | |||||
| Decrease input audio power by 12 decibels: | |||||
| @example | |||||
| volume=-12dB | |||||
| @end example | |||||
| @end itemize | |||||
| @section volumedetect | @section volumedetect | ||||
| Detect the volume of the input video. | Detect the volume of the input video. | ||||
| @@ -919,7 +869,7 @@ There are 6 samples at -4 dB, 62 at -5 dB, 286 at -6 dB, etc. | |||||
| In other words, raising the volume by +4 dB does not cause any clipping, | In other words, raising the volume by +4 dB does not cause any clipping, | ||||
| raising it by +5 dB causes clipping for 6 samples, etc. | raising it by +5 dB causes clipping for 6 samples, etc. | ||||
| @section volume_justin | |||||
| @section volume | |||||
| Adjust the input audio volume. | Adjust the input audio volume. | ||||
| @@ -966,15 +916,21 @@ precision of the volume scaling. | |||||
| @item | @item | ||||
| Halve the input audio volume: | Halve the input audio volume: | ||||
| @example | @example | ||||
| volume_justin=volume=0.5 | |||||
| volume_justin=volume=1/2 | |||||
| volume_justin=volume=-6.0206dB | |||||
| volume=volume=0.5 | |||||
| volume=volume=1/2 | |||||
| volume=volume=-6.0206dB | |||||
| @end example | |||||
| In all the above example the named key for @option{volume} can be | |||||
| omitted, for example like in: | |||||
| @example | |||||
| volume=0.5 | |||||
| @end example | @end example | ||||
| @item | @item | ||||
| Increase input audio power by 6 decibels using fixed-point precision: | Increase input audio power by 6 decibels using fixed-point precision: | ||||
| @example | @example | ||||
| volume_justin=volume=6dB:precision=fixed | |||||
| volume=volume=6dB:precision=fixed | |||||
| @end example | @end example | ||||
| @end itemize | @end itemize | ||||
| @@ -71,8 +71,7 @@ OBJS-$(CONFIG_JOIN_FILTER) += af_join.o | |||||
| OBJS-$(CONFIG_PAN_FILTER) += af_pan.o | OBJS-$(CONFIG_PAN_FILTER) += af_pan.o | ||||
| OBJS-$(CONFIG_RESAMPLE_FILTER) += af_resample.o | OBJS-$(CONFIG_RESAMPLE_FILTER) += af_resample.o | ||||
| OBJS-$(CONFIG_SILENCEDETECT_FILTER) += af_silencedetect.o | OBJS-$(CONFIG_SILENCEDETECT_FILTER) += af_silencedetect.o | ||||
| OBJS-$(CONFIG_VOLUME_FILTER) += af_volume_stefano.o | |||||
| OBJS-$(CONFIG_VOLUME_JUSTIN_FILTER) += af_volume_justin.o | |||||
| OBJS-$(CONFIG_VOLUME_FILTER) += af_volume.o | |||||
| OBJS-$(CONFIG_VOLUMEDETECT_FILTER) += af_volumedetect.o | OBJS-$(CONFIG_VOLUMEDETECT_FILTER) += af_volumedetect.o | ||||
| OBJS-$(CONFIG_AEVALSRC_FILTER) += asrc_aevalsrc.o | OBJS-$(CONFIG_AEVALSRC_FILTER) += asrc_aevalsrc.o | ||||
| @@ -299,8 +299,8 @@ static const AVFilterPad avfilter_af_volume_outputs[] = { | |||||
| { NULL } | { NULL } | ||||
| }; | }; | ||||
| AVFilter avfilter_af_volume_justin = { | |||||
| .name = "volume_justin", | |||||
| AVFilter avfilter_af_volume = { | |||||
| .name = "volume", | |||||
| .description = NULL_IF_CONFIG_SMALL("Change input volume."), | .description = NULL_IF_CONFIG_SMALL("Change input volume."), | ||||
| .query_formats = query_formats, | .query_formats = query_formats, | ||||
| .priv_size = sizeof(VolumeContext), | .priv_size = sizeof(VolumeContext), | ||||
| @@ -1,201 +0,0 @@ | |||||
| /* | |||||
| * Copyright (c) 2011 Stefano Sabatini | |||||
| * | |||||
| * This file is part of FFmpeg. | |||||
| * | |||||
| * FFmpeg is free software; you can redistribute it and/or | |||||
| * modify it under the terms of the GNU Lesser General Public | |||||
| * License as published by the Free Software Foundation; either | |||||
| * version 2.1 of the License, or (at your option) any later version. | |||||
| * | |||||
| * FFmpeg is distributed in the hope that it will be useful, | |||||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||||
| * Lesser General Public License for more details. | |||||
| * | |||||
| * You should have received a copy of the GNU Lesser General Public | |||||
| * License along with FFmpeg; if not, write to the Free Software | |||||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||||
| */ | |||||
| /** | |||||
| * @file | |||||
| * audio volume filter | |||||
| * based on ffmpeg.c code | |||||
| */ | |||||
| #include "libavutil/channel_layout.h" | |||||
| #include "libavutil/eval.h" | |||||
| #include "audio.h" | |||||
| #include "avfilter.h" | |||||
| #include "formats.h" | |||||
| typedef struct { | |||||
| double volume; | |||||
| int volume_i; | |||||
| } VolumeContext; | |||||
| static av_cold int init(AVFilterContext *ctx, const char *args) | |||||
| { | |||||
| VolumeContext *vol = ctx->priv; | |||||
| char *tail; | |||||
| int ret = 0; | |||||
| vol->volume = 1.0; | |||||
| if (args) { | |||||
| /* parse the number as a decimal number */ | |||||
| double d = strtod(args, &tail); | |||||
| if (*tail) { | |||||
| if (!strcmp(tail, "dB")) { | |||||
| /* consider the argument an adjustement in decibels */ | |||||
| d = pow(10, d/20); | |||||
| } else { | |||||
| /* parse the argument as an expression */ | |||||
| ret = av_expr_parse_and_eval(&d, args, NULL, NULL, | |||||
| NULL, NULL, NULL, NULL, | |||||
| NULL, 0, ctx); | |||||
| } | |||||
| } | |||||
| if (ret < 0) { | |||||
| av_log(ctx, AV_LOG_ERROR, | |||||
| "Invalid volume argument '%s'\n", args); | |||||
| return AVERROR(EINVAL); | |||||
| } | |||||
| if (d < 0 || d > 65536) { /* 65536 = INT_MIN / (128 * 256) */ | |||||
| av_log(ctx, AV_LOG_ERROR, | |||||
| "Negative or too big volume value %f\n", d); | |||||
| return AVERROR(EINVAL); | |||||
| } | |||||
| vol->volume = d; | |||||
| } | |||||
| vol->volume_i = (int)(vol->volume * 256 + 0.5); | |||||
| av_log(ctx, AV_LOG_VERBOSE, "volume=%f\n", vol->volume); | |||||
| return 0; | |||||
| } | |||||
| static int query_formats(AVFilterContext *ctx) | |||||
| { | |||||
| AVFilterFormats *formats = NULL; | |||||
| AVFilterChannelLayouts *layouts; | |||||
| enum AVSampleFormat sample_fmts[] = { | |||||
| AV_SAMPLE_FMT_U8, | |||||
| AV_SAMPLE_FMT_S16, | |||||
| AV_SAMPLE_FMT_S32, | |||||
| AV_SAMPLE_FMT_FLT, | |||||
| AV_SAMPLE_FMT_DBL, | |||||
| AV_SAMPLE_FMT_NONE | |||||
| }; | |||||
| layouts = ff_all_channel_layouts(); | |||||
| if (!layouts) | |||||
| return AVERROR(ENOMEM); | |||||
| ff_set_common_channel_layouts(ctx, layouts); | |||||
| formats = ff_make_format_list(sample_fmts); | |||||
| if (!formats) | |||||
| return AVERROR(ENOMEM); | |||||
| ff_set_common_formats(ctx, formats); | |||||
| formats = ff_all_samplerates(); | |||||
| if (!formats) | |||||
| return AVERROR(ENOMEM); | |||||
| ff_set_common_samplerates(ctx, formats); | |||||
| return 0; | |||||
| } | |||||
| static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *insamples) | |||||
| { | |||||
| VolumeContext *vol = inlink->dst->priv; | |||||
| AVFilterLink *outlink = inlink->dst->outputs[0]; | |||||
| const int nb_samples = insamples->audio->nb_samples * | |||||
| av_get_channel_layout_nb_channels(insamples->audio->channel_layout); | |||||
| const double volume = vol->volume; | |||||
| const int volume_i = vol->volume_i; | |||||
| int i; | |||||
| if (volume_i != 256) { | |||||
| switch (insamples->format) { | |||||
| case AV_SAMPLE_FMT_U8: | |||||
| { | |||||
| uint8_t *p = (void *)insamples->data[0]; | |||||
| for (i = 0; i < nb_samples; i++) { | |||||
| int v = (((*p - 128) * volume_i + 128) >> 8) + 128; | |||||
| *p++ = av_clip_uint8(v); | |||||
| } | |||||
| break; | |||||
| } | |||||
| case AV_SAMPLE_FMT_S16: | |||||
| { | |||||
| int16_t *p = (void *)insamples->data[0]; | |||||
| for (i = 0; i < nb_samples; i++) { | |||||
| int v = ((int64_t)*p * volume_i + 128) >> 8; | |||||
| *p++ = av_clip_int16(v); | |||||
| } | |||||
| break; | |||||
| } | |||||
| case AV_SAMPLE_FMT_S32: | |||||
| { | |||||
| int32_t *p = (void *)insamples->data[0]; | |||||
| for (i = 0; i < nb_samples; i++) { | |||||
| int64_t v = (((int64_t)*p * volume_i + 128) >> 8); | |||||
| *p++ = av_clipl_int32(v); | |||||
| } | |||||
| break; | |||||
| } | |||||
| case AV_SAMPLE_FMT_FLT: | |||||
| { | |||||
| float *p = (void *)insamples->data[0]; | |||||
| float scale = (float)volume; | |||||
| for (i = 0; i < nb_samples; i++) { | |||||
| *p++ *= scale; | |||||
| } | |||||
| break; | |||||
| } | |||||
| case AV_SAMPLE_FMT_DBL: | |||||
| { | |||||
| double *p = (void *)insamples->data[0]; | |||||
| for (i = 0; i < nb_samples; i++) { | |||||
| *p *= volume; | |||||
| p++; | |||||
| } | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| return ff_filter_frame(outlink, insamples); | |||||
| } | |||||
| static const AVFilterPad volume_inputs[] = { | |||||
| { | |||||
| .name = "default", | |||||
| .type = AVMEDIA_TYPE_AUDIO, | |||||
| .filter_frame = filter_frame, | |||||
| .min_perms = AV_PERM_READ | AV_PERM_WRITE, | |||||
| }, | |||||
| { NULL }, | |||||
| }; | |||||
| static const AVFilterPad volume_outputs[] = { | |||||
| { | |||||
| .name = "default", | |||||
| .type = AVMEDIA_TYPE_AUDIO, | |||||
| }, | |||||
| { NULL }, | |||||
| }; | |||||
| AVFilter avfilter_af_volume = { | |||||
| .name = "volume", | |||||
| .description = NULL_IF_CONFIG_SMALL("Change input volume."), | |||||
| .query_formats = query_formats, | |||||
| .priv_size = sizeof(VolumeContext), | |||||
| .init = init, | |||||
| .inputs = volume_inputs, | |||||
| .outputs = volume_outputs, | |||||
| }; | |||||
| @@ -64,7 +64,6 @@ void avfilter_register_all(void) | |||||
| REGISTER_FILTER (RESAMPLE, resample, af); | REGISTER_FILTER (RESAMPLE, resample, af); | ||||
| REGISTER_FILTER (SILENCEDETECT, silencedetect, af); | REGISTER_FILTER (SILENCEDETECT, silencedetect, af); | ||||
| REGISTER_FILTER (VOLUME, volume, af); | REGISTER_FILTER (VOLUME, volume, af); | ||||
| REGISTER_FILTER (VOLUME_JUSTIN, volume_justin, af); | |||||
| REGISTER_FILTER (VOLUMEDETECT,volumedetect,af); | REGISTER_FILTER (VOLUMEDETECT,volumedetect,af); | ||||
| REGISTER_FILTER (AEVALSRC, aevalsrc, asrc); | REGISTER_FILTER (AEVALSRC, aevalsrc, asrc); | ||||
| @@ -29,8 +29,8 @@ | |||||
| #include "libavutil/avutil.h" | #include "libavutil/avutil.h" | ||||
| #define LIBAVFILTER_VERSION_MAJOR 3 | #define LIBAVFILTER_VERSION_MAJOR 3 | ||||
| #define LIBAVFILTER_VERSION_MINOR 25 | |||||
| #define LIBAVFILTER_VERSION_MICRO 102 | |||||
| #define LIBAVFILTER_VERSION_MINOR 26 | |||||
| #define LIBAVFILTER_VERSION_MICRO 100 | |||||
| #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ | #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ | ||||
| LIBAVFILTER_VERSION_MINOR, \ | LIBAVFILTER_VERSION_MINOR, \ | ||||