vlc | branch: master | Valentin Deniaud <[email protected]> | Mon Sep 4 14:56:13 2017 +0200| [d3e1f1455f85f39c383896318987c4bc9a169102] | committer: Thomas Guillem
scaletempo: add pitch shifting submodule The idea is to load a resampler in order to change the tempo along with the pitch, then use scaletempo to get back to the initial tempo while keeping the adjusted pitch. Fixes #8396 Signed-off-by: Thomas Guillem <[email protected]> > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=d3e1f1455f85f39c383896318987c4bc9a169102 --- modules/MODULES_LIST | 2 +- modules/audio_filter/Makefile.am | 1 + modules/audio_filter/scaletempo.c | 113 +++++++++++++++++++++++++++++++++++++- 3 files changed, 114 insertions(+), 2 deletions(-) diff --git a/modules/MODULES_LIST b/modules/MODULES_LIST index 698118fe5e..28dac0289f 100644 --- a/modules/MODULES_LIST +++ b/modules/MODULES_LIST @@ -339,7 +339,7 @@ $Id$ * sapi: Windows Text to Speech Synthetizer using the SAPI 5.1 API * satip: SES Astra SAT>IP access module * scale: Images rescaler - * scaletempo: Scale audio tempo in sync with playback rate + * scaletempo: Scale audio tempo in sync with playback rate, or adjust pitch without changing tempo * scene: scene video filter * schroedinger: Schroedinger video decoder * screen: a input module that takes screenshots of the primary monitor diff --git a/modules/audio_filter/Makefile.am b/modules/audio_filter/Makefile.am index 1b8a2aba38..bcff753948 100644 --- a/modules/audio_filter/Makefile.am +++ b/modules/audio_filter/Makefile.am @@ -16,6 +16,7 @@ libgain_plugin_la_SOURCES = audio_filter/gain.c libparam_eq_plugin_la_SOURCES = audio_filter/param_eq.c libparam_eq_plugin_la_LIBADD = $(LIBM) libscaletempo_plugin_la_SOURCES = audio_filter/scaletempo.c +libscaletempo_plugin_la_LIBADD = $(LIBM) libstereo_widen_plugin_la_SOURCES = audio_filter/stereo_widen.c libspatializer_plugin_la_SOURCES = \ audio_filter/spatializer/allpass.cpp \ diff --git a/modules/audio_filter/scaletempo.c b/modules/audio_filter/scaletempo.c index 39ded6fc44..2ba51b7eea 100644 --- a/modules/audio_filter/scaletempo.c +++ b/modules/audio_filter/scaletempo.c @@ -32,6 +32,8 @@ #include <vlc_plugin.h> #include <vlc_aout.h> #include <vlc_filter.h> +#include <vlc_modules.h> +#include <vlc_atomic.h> #include <string.h> /* for memset */ #include <limits.h> /* form INT_MIN */ @@ -40,8 +42,11 @@ * Module descriptor *****************************************************************************/ static int Open( vlc_object_t * ); +static int OpenPitch( vlc_object_t * ); static void Close( vlc_object_t * ); +static void ClosePitch( vlc_object_t * ); static block_t *DoWork( filter_t *, block_t * ); +static block_t *DoPitchWork( filter_t *, block_t * ); vlc_module_begin () set_description( N_("Audio tempo scaler synched with rate") ) @@ -56,8 +61,15 @@ vlc_module_begin () N_("Overlap Length"), N_("Percentage of stride to overlap"), true ) add_integer_with_range( "scaletempo-search", 14, 0, 200, N_("Search Length"), N_("Length in milliseconds to search for best overlap position"), true ) - set_callbacks( Open, Close ) + + add_submodule () + set_shortname( N_("Pitch Shifter") ) + set_description( N_("Audio pitch changer") ) + set_callbacks( OpenPitch, ClosePitch ) + add_shortcut( "pitch" ) + add_float_with_range( "pitch-shift", 0, -12, 12, + N_("Pitch Shift"), N_("Pitch shift in semitones"), false ) vlc_module_end () /* @@ -111,6 +123,9 @@ struct filter_sys_t void *buf_pre_corr; void *table_window; unsigned(*best_overlap_offset)( filter_t *p_filter ); + /* pitch */ + filter_t * resampler; + vlc_atomic_float rate_shift; }; /***************************************************************************** @@ -431,6 +446,73 @@ static int Open( vlc_object_t *p_this ) aout_FormatPrepare(&p_filter->fmt_in.audio); p_filter->fmt_out.audio = p_filter->fmt_in.audio; p_filter->pf_audio_filter = DoWork; + + return VLC_SUCCESS; +} + +static inline void PitchSetRateShift( filter_sys_t *p_sys, float pitch_shift ) +{ + vlc_atomic_store_float( &p_sys->rate_shift, + p_sys->sample_rate / powf(2, pitch_shift / 12) ); +} + +static int PitchCallback( vlc_object_t *p_this, char const *psz_var, + vlc_value_t oldval, vlc_value_t newval, void *p_data ) +{ + VLC_UNUSED( p_this ); + VLC_UNUSED( oldval ); + VLC_UNUSED( psz_var ); + + PitchSetRateShift( p_data, newval.f_float ); + + return VLC_SUCCESS; +} + +static filter_t *ResamplerCreate(filter_t *p_filter) +{ + filter_t *p_resampler = vlc_object_create( p_filter, sizeof (filter_t) ); + if( unlikely( p_resampler == NULL ) ) + return NULL; + + p_resampler->owner.sys = NULL; + p_resampler->p_cfg = NULL; + p_resampler->fmt_in = p_filter->fmt_in; + p_resampler->fmt_out = p_filter->fmt_in; + p_resampler->fmt_out.audio.i_rate = + vlc_atomic_load_float( &p_filter->p_sys->rate_shift ); + aout_FormatPrepare( &p_resampler->fmt_out.audio ); + p_resampler->p_module = module_need( p_resampler, "audio resampler", NULL, + false ); + + if( p_resampler->p_module == NULL ) + { + msg_Err( p_filter, "Could not load resampler" ); + vlc_object_release( p_resampler ); + return NULL; + } + return p_resampler; +} + +static int OpenPitch( vlc_object_t *p_this ) +{ + int err = Open( p_this ); + if( err ) + return err; + + filter_t *p_filter = (filter_t *)p_this; + vlc_object_t *p_aout = p_filter->obj.parent; + filter_sys_t *p_sys = p_filter->p_sys; + + float pitch_shift = var_CreateGetFloat( p_aout, "pitch-shift" ); + var_AddCallback( p_aout, "pitch-shift", PitchCallback, p_sys ); + PitchSetRateShift( p_sys, pitch_shift ); + + p_sys->resampler = ResamplerCreate(p_filter); + if( !p_sys->resampler ) + return VLC_EGENERIC; + + p_filter->pf_audio_filter = DoPitchWork; + return VLC_SUCCESS; } @@ -446,6 +528,18 @@ static void Close( vlc_object_t *p_this ) free( p_sys ); } +static void ClosePitch( vlc_object_t *p_this ) +{ + filter_t *p_filter = (filter_t *)p_this; + filter_sys_t *p_sys = p_filter->p_sys; + vlc_object_t *p_aout = p_filter->obj.parent; + var_DelCallback( p_aout, "pitch-shift", PitchCallback, p_sys ); + var_Destroy( p_aout, "pitch-shift" ); + module_unneed( p_sys->resampler, p_sys->resampler->p_module ); + vlc_object_release( p_sys->resampler ); + Close( p_this ); +} + /***************************************************************************** * DoWork: filter wrapper for transform_buffer *****************************************************************************/ @@ -486,3 +580,20 @@ static block_t *DoWork( filter_t * p_filter, block_t * p_in_buf ) block_Release( p_in_buf ); return p_out_buf; } + +static block_t *DoPitchWork( filter_t * p_filter, block_t * p_in_buf ) +{ + filter_sys_t *p = p_filter->p_sys; + + float rate_shift = vlc_atomic_load_float( &p->rate_shift ); + + /* Set matching rates for resampler's output and scaletempo's input */ + p->resampler->fmt_out.audio.i_rate = rate_shift; + p_filter->fmt_in.audio.i_rate = rate_shift; + + /* Change rate, thus changing pitch */ + p_in_buf = p->resampler->pf_audio_filter( p->resampler, p_in_buf ); + + /* Change tempo while preserving shifted pitch */ + return DoWork( p_filter, p_in_buf ); +} _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
