PR #20697 opened by kupix URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20697 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20697.patch
This adds an audio filter using the [Bungee](https://github.com/bungee-audio-stretch/bungee) open source audio timescale manipulation library. It also adds support for the proprietary "Bungee Pro" variant. >From 135787f1a1b3ab51b3b5d9f290ac4575891848f8 Mon Sep 17 00:00:00 2001 From: John Funnell <[email protected]> Date: Sun, 23 Feb 2025 20:46:22 +0000 Subject: [PATCH 1/4] avfilter: add Bungee wrapper --- Changelog | 1 + configure | 8 ++ doc/filters.texi | 24 ++++ libavfilter/Makefile | 2 + libavfilter/af_bungee.c | 26 ++++ libavfilter/af_bungeepro.c | 26 ++++ libavfilter/allfilters.c | 2 + libavfilter/bungee.h | 280 +++++++++++++++++++++++++++++++++++++ 8 files changed, 369 insertions(+) create mode 100644 libavfilter/af_bungee.c create mode 100644 libavfilter/af_bungeepro.c create mode 100644 libavfilter/bungee.h diff --git a/Changelog b/Changelog index 6fd95c9136..9986e89452 100644 --- a/Changelog +++ b/Changelog @@ -45,6 +45,7 @@ version 8.0: - ffprobe -codec option - HDR10+ metadata passthrough when decoding/encoding with libaom-av1 +- Bungee audio stretch and pitch shift filter version 7.1: - Raw Captions with Time (RCWT) closed caption demuxer diff --git a/configure b/configure index 7828381b5d..897b3e8d23 100755 --- a/configure +++ b/configure @@ -220,6 +220,8 @@ External library support: needed for subtitles and ass filter [no] --enable-libbluray enable BluRay reading using libbluray [no] --enable-libbs2b enable bs2b DSP library [no] + --enable-libbungee enable enable Bungee audio stretch [no] + --enable-libbungeepro enable enable Bungee Pro audio stretch [no] --enable-libcaca enable textual display using libcaca [no] --enable-libcelt enable CELT decoding via libcelt [no] --enable-libcdio enable audio CD grabbing with libcdio [no] @@ -1962,6 +1964,8 @@ EXTERNAL_LIBRARY_LIST=" libass libbluray libbs2b + libbungee + libbungeepro libcaca libcelt libcodec2 @@ -3978,6 +3982,8 @@ blend_vulkan_filter_deps="vulkan spirv_compiler" boxblur_filter_deps="gpl" boxblur_opencl_filter_deps="opencl gpl" bs2b_filter_deps="libbs2b" +bungee_filter_deps="libbungee" +bungeepro_filter_deps="libbungeepro" bwdif_cuda_filter_deps="ffnvcodec" bwdif_cuda_filter_deps_any="cuda_nvcc cuda_llvm" bwdif_vulkan_filter_deps="vulkan spirv_compiler" @@ -7107,6 +7113,8 @@ enabled libiec61883 && require libiec61883 libiec61883/iec61883.h iec61883 enabled libass && require_pkg_config libass "libass >= 0.11.0" ass/ass.h ass_library_init enabled libbluray && require_pkg_config libbluray libbluray libbluray/bluray.h bd_open enabled libbs2b && require_pkg_config libbs2b libbs2b bs2b.h bs2b_open +enabled libbungee && require_pkg_config libbungee "libbungee >= 0.0.0" bungee/Bungee.h getFunctionsBungeeBasic +enabled libbungeepro && require_pkg_config libbungeepro "libbungeepro >= 0.0.0" bungee/Bungee.h getFunctionsBungeePro enabled libcelt && require libcelt celt/celt.h celt_decode -lcelt0 && { check_lib libcelt celt/celt.h celt_decoder_create_custom -lcelt0 || die "ERROR: libcelt must be installed and version must be >= 0.11.0."; } diff --git a/doc/filters.texi b/doc/filters.texi index 5863041d1a..69afa5fc29 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -4292,6 +4292,30 @@ Feed level (in Hz). @end table +@section bungee + +Stretch audio timescale and/or modify pitch using Bungee Basic. + +This filter accepts the following parameters: +@table @option +@item speed +Controls the speed or tempo of the output audio. The default value 1 will not change speed. +@item pitch +Sets a pitch adjustment as a frequency multiplier. The default value 1 will have no effect on pitch. +@end table + + +To enable compilation of this filter, you need to configure FFmpeg with +@code{--enable-libbungee}. + +@section bungeepro + +Stretch audio timescale and/or modify pitch using Bungee Pro. This filter accepts +the same options as @ref{bungee}. + +To enable compilation of this filter, you need to configure FFmpeg with +@code{--enable-libbungeepron }. + @section channelmap Remap input channels to new locations. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 1f5de29ba2..d02dbe841e 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -126,6 +126,8 @@ OBJS-$(CONFIG_BANDREJECT_FILTER) += af_biquads.o OBJS-$(CONFIG_BASS_FILTER) += af_biquads.o OBJS-$(CONFIG_BIQUAD_FILTER) += af_biquads.o OBJS-$(CONFIG_BS2B_FILTER) += af_bs2b.o +OBJS-$(CONFIG_BUNGEE_FILTER) += af_bungee.o +OBJS-$(CONFIG_BUNGEEPRO_FILTER) += af_bungeepro.o OBJS-$(CONFIG_CHANNELMAP_FILTER) += af_channelmap.o OBJS-$(CONFIG_CHANNELSPLIT_FILTER) += af_channelsplit.o OBJS-$(CONFIG_CHORUS_FILTER) += af_chorus.o generate_wave_table.o diff --git a/libavfilter/af_bungee.c b/libavfilter/af_bungee.c new file mode 100644 index 0000000000..cfcb1c3e58 --- /dev/null +++ b/libavfilter/af_bungee.c @@ -0,0 +1,26 @@ +/* + * 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 + */ + +#define BUNGEE bungee +#define BUNGEE_CLASS bungee_class +#define BUNGEE_AF ff_af_bungee +#define BUNGEE_name "bungee" +#define BUNGEE_Name "Bungee" +#define BUNGEE_GET_FUNCTIONS getFunctionsBungeeBasic + +#include "bungee.h" diff --git a/libavfilter/af_bungeepro.c b/libavfilter/af_bungeepro.c new file mode 100644 index 0000000000..f625e64481 --- /dev/null +++ b/libavfilter/af_bungeepro.c @@ -0,0 +1,26 @@ +/* + * 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 + */ + +#define BUNGEE bungeepro +#define BUNGEE_CLASS bungeepro_class +#define BUNGEE_AF ff_af_bungeepro +#define BUNGEE_name "bungeepro" +#define BUNGEE_Name "Bungee Pro" +#define BUNGEE_GET_FUNCTIONS getFunctionsBungeePro + +#include "bungee.h" \ No newline at end of file diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 84f15f85c5..90409e814d 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -112,6 +112,8 @@ extern const FFFilter ff_af_bandreject; extern const FFFilter ff_af_bass; extern const FFFilter ff_af_biquad; extern const FFFilter ff_af_bs2b; +extern const FFFilter ff_af_bungee; +extern const FFFilter ff_af_bungeepro; extern const FFFilter ff_af_channelmap; extern const FFFilter ff_af_channelsplit; extern const FFFilter ff_af_chorus; diff --git a/libavfilter/bungee.h b/libavfilter/bungee.h new file mode 100644 index 0000000000..9fad792421 --- /dev/null +++ b/libavfilter/bungee.h @@ -0,0 +1,280 @@ +/* + * 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 + */ + +#include "bungee/Bungee.h" + +#include "libavutil/avassert.h" +#include "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" + +#include "audio.h" +#include "avfilter.h" +#include "filters.h" + +typedef struct BungeeContext +{ + const AVClass *class; + + const struct Functions *functions; + + void *stretcher; + int debug; + + struct SampleRates sampleRates; + int channelCount; + + float *inputBuffer; + int inputBufferSampleCount; + + int64_t inputBufferBeginPosition; + int64_t inputBufferEndPosition; + int64_t inputStartPosition; + int64_t inputFinishPosition; + + int64_t ptsOriginPosition; + + struct Request request; + struct InputChunk inputChunk; + + int64_t start_pts; + int64_t last_pts; + + int64_t outputSampleCount; + int eof; // end of input +} BungeeContext; + +static int samplesNeeded(const BungeeContext *s) +{ + return s->inputChunk.end - s->inputBufferEndPosition; +} + +static void appendToInputBuffer(BungeeContext *s, const AVFrame *in) +{ + int moveOffset = s->inputBufferBeginPosition - s->inputChunk.begin; + int moveCount = s->inputBufferEndPosition - s->inputChunk.begin; + + av_assert1(!in || in->nb_samples <= samplesNeeded(s)); + + if (moveCount < 0) + moveCount = 0; + + for (int c = 0; c < s->channelCount; ++c) + memmove( + &s->inputBuffer[c * s->inputBufferSampleCount], + &s->inputBuffer[c * s->inputBufferSampleCount - moveOffset], + moveCount * sizeof(float)); + + s->inputBufferBeginPosition = s->inputChunk.begin; + + if (in) { + const float *const *source = (const float *const *)in->extended_data; + + for (int c = 0; c < s->channelCount; ++c) + memcpy( + &s->inputBuffer[moveCount + c * s->inputBufferSampleCount], + source[c], + in->nb_samples * sizeof(float)); + + s->inputBufferEndPosition += in->nb_samples; + } +} + +#define BUNGEE_OPTIONS BUNGEE##_options + +static const AVOption BUNGEE_OPTIONS[] = { + {"speed", "set speed as a tempo multiplier", offsetof(BungeeContext, request.speed), AV_OPT_TYPE_DOUBLE, {.dbl = 1}, 0.01, 100, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM}, + {"pitch", "set pitch as a frequency multiplier", offsetof(BungeeContext, request.pitch), AV_OPT_TYPE_DOUBLE, {.dbl = 1}, 0.25, 2, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM}, + {"debug", "verbose debug checks", offsetof(BungeeContext, debug), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_AUDIO_PARAM}, + {NULL}, +}; + +AVFILTER_DEFINE_CLASS(BUNGEE); + +static av_cold int init(AVFilterContext *ctx) +{ + BungeeContext *s = ctx->priv; + s->functions = BUNGEE_GET_FUNCTIONS(); + if (!s->functions) + { + av_log(ctx, AV_LOG_ERROR, "No functions found for " BUNGEE_Name "\n"); + return AVERROR_INVALIDDATA; + } + s->stretcher = NULL; + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + BungeeContext *s = ctx->priv; + if (s->stretcher) + s->functions->destroy(s->stretcher); +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + BungeeContext *s = ctx->priv; + s->sampleRates.input = inlink->sample_rate; + s->sampleRates.output = inlink->sample_rate; + s->channelCount = inlink->ch_layout.nb_channels; + + if (s->stretcher) + s->functions->destroy(s->stretcher); + s->stretcher = NULL; + + s->stretcher = s->functions->create(s->sampleRates, s->channelCount, 0); + s->functions->enableInstrumentation(s->stretcher, s->debug); + + s->request.position = 0; + s->functions->next(s->stretcher, &s->request); + s->request.reset = 1; + s->inputChunk = s->functions->specifyGrain(s->stretcher, &s->request, 0.); + + s->inputBufferSampleCount = s->inputChunk.end - s->inputChunk.begin; + s->inputStartPosition = s->inputBufferSampleCount / 2; + s->inputBufferBeginPosition = s->inputStartPosition - s->inputBufferSampleCount; + s->inputBufferEndPosition = s->inputStartPosition; + + s->inputBuffer = av_calloc(s->inputBufferSampleCount * s->channelCount, sizeof(float)); + if (!s->inputBuffer) + return AVERROR(ENOMEM); + + s->outputSampleCount = 0; + + s->ptsOriginPosition = AV_NOPTS_VALUE; + s->eof = 0; + + return 0; +} + +static int activate(AVFilterContext *ctx) +{ + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + BungeeContext *s = ctx->priv; + struct OutputChunk outputChunk; + int64_t pts; + int status, ret = 0, endOfOutput = 0; + + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + + if (!s->eof) + { + AVFrame *in; + ret = ff_inlink_consume_samples(inlink, 1, samplesNeeded(s), &in); + + if (ff_inlink_acknowledge_status(inlink, &status, &pts)) + s->eof = status == AVERROR_EOF; + + if (in) + { + if (s->start_pts == AV_NOPTS_VALUE) + s->start_pts = av_rescale_q(in->pts, inlink->time_base, outlink->time_base); + + appendToInputBuffer(s, in); + av_frame_free(&in); + } + + if (s->eof) + s->inputFinishPosition = s->inputBufferEndPosition; + } + else + appendToInputBuffer(s, NULL); + + av_assert1(s->inputBufferEndPosition == s->inputChunk.end); + + if (samplesNeeded(s) == 0 || s->eof) + { + s->functions->next(s->stretcher, &s->request); + s->functions->analyseGrain(s->stretcher, s->inputBuffer, s->inputBufferSampleCount, 0, samplesNeeded(s)); + s->functions->synthesiseGrain(s->stretcher, &outputChunk); + s->inputChunk = s->functions->specifyGrain(s->stretcher, &s->request, 0); + + endOfOutput = s->eof && outputChunk.request[1]->position >= s->inputFinishPosition; + + if (outputChunk.request[0]->position >= s->inputStartPosition) + { + AVRational outputTimebase = {1, s->sampleRates.output}; + AVFrame *out = ff_get_audio_buffer(outlink, outputChunk.frameCount); + float *const *p = (float *const *)out->extended_data; + + if (!out) + return AVERROR(ENOMEM); + + if (endOfOutput) + { + const double fraction = (s->inputFinishPosition - outputChunk.request[0]->position) / (outputChunk.request[1]->position - outputChunk.request[0]->position); + int frameCount = round(outputChunk.frameCount * fraction); + if (frameCount < 0) + frameCount = 0; + if (frameCount > outputChunk.frameCount) + frameCount = outputChunk.frameCount; + outputChunk.frameCount = frameCount; + } + + for (int c = 0; c < s->channelCount; ++c) + memcpy(p[c], &outputChunk.data[c * outputChunk.channelStride], sizeof(float) * outputChunk.frameCount); + + out->pts = s->start_pts + av_rescale_q(s->outputSampleCount, outputTimebase, outlink->time_base); + s->last_pts = out->pts; + + out->nb_samples = outputChunk.frameCount; + s->outputSampleCount += outputChunk.frameCount; + + ret = ff_filter_frame(outlink, out); + if (ret < 0) + return ret; + } + } + + if (ff_inlink_queued_samples(inlink) >= samplesNeeded(s)) + ff_filter_set_ready(ctx, 100); + + if (endOfOutput) + { + ff_outlink_set_status(outlink, AVERROR_EOF, s->last_pts); + return 0; + } + + FF_FILTER_FORWARD_WANTED(outlink, inlink); + + return FFERROR_NOT_READY; +} + +static const AVFilterPad bungee_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .config_props = config_input, + }, +}; + +const FFFilter BUNGEE_AF = { + .p.name = BUNGEE_name, + .p.description = NULL_IF_CONFIG_SMALL("Adjust audio speed and pitch using " BUNGEE_Name "."), + .p.priv_class = &BUNGEE_CLASS, + .priv_size = sizeof(BungeeContext), + .init = init, + .uninit = uninit, + .activate = activate, + FILTER_INPUTS(bungee_inputs), + FILTER_OUTPUTS(ff_audio_default_filterpad), + FILTER_SINGLE_SAMPLEFMT(AV_SAMPLE_FMT_FLTP), +}; -- 2.49.1 >From ac8a018d6b17a6a9965d272684e4ff3a5fcd9029 Mon Sep 17 00:00:00 2001 From: John Funnell <[email protected]> Date: Sun, 12 Oct 2025 11:35:13 +0100 Subject: [PATCH 2/4] use semitones for pitch parameters; add resample parameter --- libavfilter/bungee.h | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/libavfilter/bungee.h b/libavfilter/bungee.h index 9fad792421..e4cc105de7 100644 --- a/libavfilter/bungee.h +++ b/libavfilter/bungee.h @@ -50,6 +50,8 @@ typedef struct BungeeContext int64_t ptsOriginPosition; + double semitones; + struct Request request; struct InputChunk inputChunk; @@ -98,10 +100,35 @@ static void appendToInputBuffer(BungeeContext *s, const AVFrame *in) #define BUNGEE_OPTIONS BUNGEE##_options + +enum BungeeModeCounts { + +#define X_BEGIN(Type, type) count##Type = 0 +#define X_ITEM(Type, type, mode, description) + 1 +#define X_END(Type, type) , +BUNGEE_MODES +#undef X_BEGIN +#undef X_ITEM +#undef X_END + +}; + + +static const int flags = AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM; + static const AVOption BUNGEE_OPTIONS[] = { - {"speed", "set speed as a tempo multiplier", offsetof(BungeeContext, request.speed), AV_OPT_TYPE_DOUBLE, {.dbl = 1}, 0.01, 100, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM}, - {"pitch", "set pitch as a frequency multiplier", offsetof(BungeeContext, request.pitch), AV_OPT_TYPE_DOUBLE, {.dbl = 1}, 0.25, 2, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM}, - {"debug", "verbose debug checks", offsetof(BungeeContext, debug), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_AUDIO_PARAM}, + {"speed", "set speed as a tempo multiplier", offsetof(BungeeContext, request.speed), AV_OPT_TYPE_DOUBLE, {.dbl = 1}, 0.01, 100, flags}, + {"pitch", "set pitch as a semitone offset", offsetof(BungeeContext, semitones), AV_OPT_TYPE_DOUBLE, {.dbl = 0}, -24, 24, flags}, + {"debug", "verbose debug checks", offsetof(BungeeContext, debug), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 0, AV_OPT_FLAG_AUDIO_PARAM}, + +#define X_BEGIN(Type, type) { #type, "set " #type " mode", offsetof(BungeeContext, request.type##Mode), AV_OPT_TYPE_INT, {.i64=0}, 0, count##Type - 1, flags, .unit = #type }, +#define X_ITEM(Type, type, mode, description) {#mode, description, 0, AV_OPT_TYPE_CONST, {.i64=type##Mode_##mode}, 0, 0, flags, .unit = #type }, +#define X_END(Type, type) +BUNGEE_MODES +#undef X_BEGIN +#undef X_ITEM +#undef X_END + {NULL}, }; @@ -143,6 +170,7 @@ static int config_input(AVFilterLink *inlink) s->functions->enableInstrumentation(s->stretcher, s->debug); s->request.position = 0; + s->request.pitch = pow(2., s->semitones * (1. / 12)); s->functions->next(s->stretcher, &s->request); s->request.reset = 1; s->inputChunk = s->functions->specifyGrain(s->stretcher, &s->request, 0.); @@ -202,6 +230,8 @@ static int activate(AVFilterContext *ctx) if (samplesNeeded(s) == 0 || s->eof) { + s->request.pitch = pow(2., s->semitones * (1. / 12)); + s->functions->next(s->stretcher, &s->request); s->functions->analyseGrain(s->stretcher, s->inputBuffer, s->inputBufferSampleCount, 0, samplesNeeded(s)); s->functions->synthesiseGrain(s->stretcher, &outputChunk); -- 2.49.1 >From b95aeb32ba210d3c982f27ac6cd57c36f514d5c7 Mon Sep 17 00:00:00 2001 From: John Funnell <[email protected]> Date: Sun, 12 Oct 2025 17:28:15 +0100 Subject: [PATCH 3/4] require libbungee v2.4 --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 897b3e8d23..a76e83c709 100755 --- a/configure +++ b/configure @@ -7113,7 +7113,7 @@ enabled libiec61883 && require libiec61883 libiec61883/iec61883.h iec61883 enabled libass && require_pkg_config libass "libass >= 0.11.0" ass/ass.h ass_library_init enabled libbluray && require_pkg_config libbluray libbluray libbluray/bluray.h bd_open enabled libbs2b && require_pkg_config libbs2b libbs2b bs2b.h bs2b_open -enabled libbungee && require_pkg_config libbungee "libbungee >= 0.0.0" bungee/Bungee.h getFunctionsBungeeBasic +enabled libbungee && require_pkg_config libbungee "libbungee >= 2.4.0 libbungee < 3.0.0" bungee/Bungee.h getFunctionsBungeeBasic enabled libbungeepro && require_pkg_config libbungeepro "libbungeepro >= 0.0.0" bungee/Bungee.h getFunctionsBungeePro enabled libcelt && require libcelt celt/celt.h celt_decode -lcelt0 && { check_lib libcelt celt/celt.h celt_decoder_create_custom -lcelt0 || -- 2.49.1 >From 529304750258cac5055b0766d70db6f50a34f413 Mon Sep 17 00:00:00 2001 From: John Funnell <[email protected]> Date: Mon, 13 Oct 2025 05:48:51 +0100 Subject: [PATCH 4/4] tidying before push --- Changelog | 2 +- doc/filters.texi | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Changelog b/Changelog index 9986e89452..42bfa1cd1d 100644 --- a/Changelog +++ b/Changelog @@ -7,6 +7,7 @@ version <next>: - gfxcapture: Windows.Graphics.Capture based window/monitor capture - hxvs demuxer for HXVS/HXVT IP camera format - MPEG-H 3D Audio decoding via mpeghdec +- Bungee and Bungee Pro audio stretch filters version 8.0: @@ -45,7 +46,6 @@ version 8.0: - ffprobe -codec option - HDR10+ metadata passthrough when decoding/encoding with libaom-av1 -- Bungee audio stretch and pitch shift filter version 7.1: - Raw Captions with Time (RCWT) closed caption demuxer diff --git a/doc/filters.texi b/doc/filters.texi index 69afa5fc29..00189d41bf 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -4294,7 +4294,7 @@ Feed level (in Hz). @section bungee -Stretch audio timescale and/or modify pitch using Bungee Basic. +Stretch audio timescale and/or modify pitch using Bungee. This filter accepts the following parameters: @table @option @@ -4302,6 +4302,8 @@ This filter accepts the following parameters: Controls the speed or tempo of the output audio. The default value 1 will not change speed. @item pitch Sets a pitch adjustment as a frequency multiplier. The default value 1 will have no effect on pitch. +@item resample +Controls whether Bungee should apply any resampling necessary to change pitch on the input or output of the filter. @end table -- 2.49.1 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
