[vlc-commits] [Git][videolan/vlc][master] 14 commits: aout: split aout_PrepareStereoMode
Jean-Baptiste Kempf
gitlab at videolan.org
Wed May 19 10:33:00 UTC 2021
Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC
Commits:
dd037e4a by Thomas Guillem at 2021-05-19T10:16:54+00:00
aout: split aout_PrepareStereoMode
- aout_PrepareStereoMode() prepares the "stereo-mode" var list and return the
default mode.
- aout_HasStereoMode() returns true if a mode is available (in "stereo-mode" var list)
- aout_UpdateStereo() does the actual changes.
No functional changes. This will be used by next commits.
- - - - -
9c67cd41 by Thomas Guillem at 2021-05-19T10:16:54+00:00
aout: add --mix-mode option
- - - - -
de2e530b by Thomas Guillem at 2021-05-19T10:16:54+00:00
aout: move headphones mode from stereo to mix mode
The aout->current_sink_info.headphones special case is handled after the
aout is started. At this point, only the filters need to be updated (via
filters_cfg).
- - - - -
d51f44af by Thomas Guillem at 2021-05-19T10:16:54+00:00
aout: print precise channels for the mix-mode menu
Example:
Original: Ambisonics
Original: 3F2M/LFE
5.1: 3F2R/LFE
7.1: 3F2M2R/LFE
- - - - -
483c3c7e by Thomas Guillem at 2021-05-19T10:16:54+00:00
aout: only propose original and binaural for ambisonics
- - - - -
72ee0103 by Thomas Guillem at 2021-05-19T10:16:54+00:00
aout: don't propose binaural mix mode if no module can handle it
- - - - -
de1e6c60 by Thomas Guillem at 2021-05-19T10:16:54+00:00
aout: use only stereo-mode for stereo
- - - - -
f54b115a by Thomas Guillem at 2021-05-19T10:16:54+00:00
aout: prepare the stereo-mode before starting the aout
This will allow to change aout->mixer_format before starting the aout,
cf. next commit.
- - - - -
3b32be66 by Thomas Guillem at 2021-05-19T10:16:54+00:00
aout: change LEFT/RIGHT fmt from aout_UpdateStereoMode
- - - - -
aa22f0f1 by Thomas Guillem at 2021-05-19T10:16:54+00:00
aout: assert than we can't apply both stereo and mix mode
- - - - -
1a4a91f9 by Thomas Guillem at 2021-05-19T10:16:54+00:00
aout: use a new chan_mode for binaural
Instead of using a custom cfg with an extra "audio filter".
i_chan_mode is already used by "audio converter" for dolbystereo.
The spatialaudio "audio filter" is converted to an "audio converter".
Such type of modules are loaded automatically when a conversion is needed
(the chan_mode conversion). Since this module is now an "audio
converter", don't override in/out fmt, but test for in/out fmt
compatibility.
- - - - -
ec53b544 by Thomas Guillem at 2021-05-19T10:16:54+00:00
spatialaudio: remove the "headphones" option
- - - - -
bdfc2a3b by Thomas Guillem at 2021-05-19T10:16:54+00:00
qt: add "mix-mode" menu
- - - - -
89cc76ca by Thomas Guillem at 2021-05-19T10:16:54+00:00
qt: display "mix-mode" or "stereo-mode" menu
But not both.
If one has entries, the other ones has 0 entries (and is disabled).
- - - - -
11 changed files:
- include/vlc_aout.h
- include/vlc_es.h
- modules/audio_filter/channel_mixer/spatialaudio.cpp
- modules/gui/qt/menus/menus.cpp
- modules/gui/qt/player/player_controller.cpp
- modules/gui/qt/player/player_controller.hpp
- modules/gui/qt/player/player_controller_p.hpp
- src/audio_output/aout_internal.h
- src/audio_output/filters.c
- src/audio_output/output.c
- src/libvlc-module.c
Changes:
=====================================
include/vlc_aout.h
=====================================
@@ -97,9 +97,16 @@
#define AOUT_VAR_CHAN_LEFT 3
#define AOUT_VAR_CHAN_RIGHT 4
#define AOUT_VAR_CHAN_DOLBYS 5
-#define AOUT_VAR_CHAN_HEADPHONES 6
+/* deprecated: AOUT_VAR_CHAN_HEADPHONES 6, use AOUT_MIX_MODE_BINAURAL */
#define AOUT_VAR_CHAN_MONO 7
+#define AOUT_MIX_MODE_UNSET 0
+#define AOUT_MIX_MODE_STEREO 1
+#define AOUT_MIX_MODE_BINAURAL 2
+#define AOUT_MIX_MODE_4_0 3
+#define AOUT_MIX_MODE_5_1 4
+#define AOUT_MIX_MODE_7_1 5
+
/*****************************************************************************
* Main audio output structures
*****************************************************************************/
=====================================
include/vlc_es.h
=====================================
@@ -170,6 +170,7 @@ static const uint16_t vlc_chan_maps[] =
/* Values available for i_chan_mode only */
#define AOUT_CHANMODE_DUALMONO 0x1
#define AOUT_CHANMODE_DOLBYSTEREO 0x2
+#define AOUT_CHANMODE_BINAURAL 0x4
/**
* Picture orientation.
=====================================
modules/audio_filter/channel_mixer/spatialaudio.cpp
=====================================
@@ -43,18 +43,12 @@
#include <spatialaudio/Ambisonics.h>
#include <spatialaudio/SpeakersBinauralizer.h>
-#define CFG_PREFIX "spatialaudio-"
-
#define DEFAULT_HRTF_PATH "hrtfs" DIR_SEP "dodeca_and_7channel_3DSL_HRTF.sofa"
#define HRTF_FILE_TEXT N_("HRTF file for the binauralization")
#define HRTF_FILE_LONGTEXT N_("Custom HRTF (Head-related transfer function) file " \
"in the SOFA format.")
-#define HEADPHONES_TEXT N_("Headphones mode (binaural)")
-#define HEADPHONES_LONGTEXT N_("If the output is stereo, render ambisonics " \
- "with the binaural decoder.")
-
static int OpenBinauralizer(vlc_object_t *p_this);
static int Open( vlc_object_t * );
static void Close( filter_t * );
@@ -67,14 +61,13 @@ vlc_module_begin()
set_category(CAT_AUDIO)
set_subcategory(SUBCAT_AUDIO_AFILTER)
set_callback(Open)
- add_bool(CFG_PREFIX "headphones", false,
- HEADPHONES_TEXT, HEADPHONES_LONGTEXT, true)
+ add_obsolete_bool("spatialaudio-headphones")
add_loadfile("hrtf-file", NULL, HRTF_FILE_TEXT, HRTF_FILE_LONGTEXT)
add_shortcut("ambisonics")
add_submodule()
set_shortname(N_("Binauralizer"))
- set_capability("audio filter", 0)
+ set_capability("audio converter", 30)
set_callback(OpenBinauralizer)
add_shortcut("binauralizer")
vlc_module_end()
@@ -332,8 +325,18 @@ static const struct FilterOperationInitializer {
static int OpenBinauralizer(vlc_object_t *p_this)
{
filter_t *p_filter = (filter_t *)p_this;
- audio_format_t *infmt = &p_filter->fmt_in.audio;
- audio_format_t *outfmt = &p_filter->fmt_out.audio;
+ const audio_format_t *infmt = &p_filter->fmt_in.audio;
+ const audio_format_t *outfmt = &p_filter->fmt_out.audio;
+
+ if (infmt->i_format != VLC_CODEC_FL32 || outfmt->i_format != VLC_CODEC_FL32)
+ return VLC_EGENERIC;
+
+ if (infmt->i_rate != outfmt->i_rate)
+ return VLC_EGENERIC;
+
+ if (infmt->i_channels <= 2 || outfmt->i_channels != 2
+ || outfmt->i_chan_mode != AOUT_CHANMODE_BINAURAL)
+ return VLC_EGENERIC;
filter_spatialaudio *p_sys = new(std::nothrow)filter_spatialaudio();
if (p_sys == NULL)
@@ -395,12 +398,6 @@ static int OpenBinauralizer(vlc_object_t *p_this)
}
p_sys->binauralizer.Reset();
- outfmt->i_format = infmt->i_format = VLC_CODEC_FL32;
- outfmt->i_rate = infmt->i_rate;
- outfmt->i_physical_channels = AOUT_CHANS_STEREO;
- aout_FormatPrepare(infmt);
- aout_FormatPrepare(outfmt);
-
p_filter->p_sys = p_sys;
p_filter->ops = &filter_ops.ops;
@@ -463,12 +460,9 @@ static int Open(vlc_object_t *p_this)
msg_Dbg(p_filter, "Order: %d %d %d", p_sys->i_order, p_sys->i_nondiegetic, infmt->i_channels);
- static const char *const options[] = { "headphones", NULL };
- config_ChainParse(p_filter, CFG_PREFIX, options, p_filter->p_cfg);
-
unsigned i_tailLength = 0;
if (p_filter->fmt_out.audio.i_channels == 2
- && var_InheritBool(p_filter, CFG_PREFIX "headphones"))
+ && p_filter->fmt_out.audio.i_chan_mode == AOUT_CHANMODE_BINAURAL)
{
p_sys->mode = filter_spatialaudio::AMBISONICS_BINAURAL_DECODER;
=====================================
modules/gui/qt/menus/menus.cpp
=====================================
@@ -452,7 +452,11 @@ QMenu *VLCMenuBar::AudioMenu( intf_thread_t *p_intf, QMenu * current )
updateAudioDevice( p_intf, audioDeviceSubmenu );
});
- current->addMenu( new CheckableListMenu(qtr( "&Stereo Mode" ), THEMIM->getAudioStereoMode(), CheckableListMenu::GROUPED, current) );
+ VLCVarChoiceModel *mix_mode = THEMIM->getAudioMixMode();
+ if (mix_mode->rowCount() == 0)
+ current->addMenu( new CheckableListMenu(qtr( "&Stereo Mode" ), THEMIM->getAudioStereoMode(), CheckableListMenu::GROUPED, current) );
+ else
+ current->addMenu( new CheckableListMenu(qtr( "&Mix Mode" ), mix_mode, CheckableListMenu::GROUPED, current) );
current->addSeparator();
current->addMenu( new CheckableListMenu(qtr( "&Visualizations" ), THEMIM->getAudioVisualizations(), CheckableListMenu::GROUPED, current) );
=====================================
modules/gui/qt/player/player_controller.cpp
=====================================
@@ -296,6 +296,7 @@ static void on_player_state_changed(vlc_player_t *, enum vlc_player_state state,
msg_Dbg( that->p_intf, "on_player_state_changed VLC_PLAYER_STATE_PLAYING");
PlayerController::AoutPtr aout = q->getAout();
that->m_audioStereoMode.resetObject( aout.get() );
+ that->m_audioMixMode.resetObject( aout.get() );
that->m_audioVisualization.resetObject( aout.get() );
break;
}
@@ -310,6 +311,7 @@ static void on_player_state_changed(vlc_player_t *, enum vlc_player_state state,
msg_Dbg( that->p_intf, "on_player_state_changed VLC_PLAYER_STATE_STOPPED");
that->m_audioStereoMode.resetObject((audio_output_t*)nullptr);
+ that->m_audioMixMode.resetObject((audio_output_t*)nullptr);
that->m_audioVisualization.resetObject((audio_output_t*)nullptr);
/* reset the state on stop */
@@ -1019,6 +1021,7 @@ PlayerControllerPrivate::PlayerControllerPrivate(PlayerController *playercontrol
, m_deinterlaceMode((vout_thread_t*)nullptr, "deinterlace-mode")
, m_autoscale((vout_thread_t*)nullptr, "autoscale")
, m_audioStereoMode((audio_output_t*)nullptr, "stereo-mode")
+ , m_audioMixMode((audio_output_t*)nullptr, "mix-mode")
, m_audioDeviceList(m_player)
, m_audioVisualization((audio_output_t*)nullptr, "visual")
{
@@ -1826,6 +1829,7 @@ QABSTRACTLIST_GETTER( VLCVarChoiceModel, getCrop, m_crop)
QABSTRACTLIST_GETTER( VLCVarChoiceModel, getDeinterlace, m_deinterlace)
QABSTRACTLIST_GETTER( VLCVarChoiceModel, getDeinterlaceMode, m_deinterlaceMode)
QABSTRACTLIST_GETTER( VLCVarChoiceModel, getAudioStereoMode, m_audioStereoMode)
+QABSTRACTLIST_GETTER( VLCVarChoiceModel, getAudioMixMode, m_audioMixMode)
QABSTRACTLIST_GETTER( VLCVarChoiceModel, getAudioVisualizations, m_audioVisualization)
=====================================
modules/gui/qt/player/player_controller.hpp
=====================================
@@ -176,6 +176,7 @@ public:
Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY soundMuteChanged)
Q_PROPERTY(AudioDeviceModel* audioDevices READ getAudioDevices CONSTANT)
Q_PROPERTY(VLCVarChoiceModel* audioStereoMode READ getAudioStereoMode CONSTANT)
+ Q_PROPERTY(VLCVarChoiceModel* audioMixMode READ getAudioMixMode CONSTANT)
Q_PROPERTY(VLCVarChoiceModel* audioVisualization READ getAudioVisualizations CONSTANT)
Q_PROPERTY(bool hasAudioVisualization READ hasAudioVisualization NOTIFY hasAudioVisualizationChanged)
@@ -347,6 +348,7 @@ public slots:
void setMuted( bool muted );
AudioDeviceModel* getAudioDevices();
VLCVarChoiceModel* getAudioStereoMode();
+ VLCVarChoiceModel* getAudioMixMode();
VLCVarChoiceModel* getAudioVisualizations();
bool hasAudioVisualization() const;
=====================================
modules/gui/qt/player/player_controller_p.hpp
=====================================
@@ -142,6 +142,7 @@ public:
//aout properties
VLCVarChoiceModel m_audioStereoMode;
+ VLCVarChoiceModel m_audioMixMode;
float m_volume = 0.f;
bool m_muted = false;
AudioDeviceModel m_audioDeviceList;
=====================================
src/audio_output/aout_internal.h
=====================================
@@ -78,6 +78,7 @@ typedef struct
vlc_tick_t original_pts;
int requested_stereo_mode; /**< Requested stereo mode set by the user */
+ int requested_mix_mode; /**< Requested mix mode set by the user */
/* Original input format and profile, won't change for the lifetime of a
* stream (between aout_DecNew() and aout_DecDelete()). */
=====================================
src/audio_output/filters.c
=====================================
@@ -152,8 +152,7 @@ static filter_t *TryFormat (vlc_object_t *obj, vlc_fourcc_t codec,
static int aout_FiltersPipelineCreate(vlc_object_t *obj, filter_t **filters,
unsigned *count, unsigned max,
const audio_sample_format_t *restrict infmt,
- const audio_sample_format_t *restrict outfmt,
- bool headphones)
+ const audio_sample_format_t *restrict outfmt)
{
aout_FormatsPrint (obj, "conversion:", infmt, outfmt);
max -= *count;
@@ -207,13 +206,8 @@ static int aout_FiltersPipelineCreate(vlc_object_t *obj, filter_t **filters,
infmt->channel_type != outfmt->channel_type ?
"audio renderer" : "audio converter";
- config_chain_t *cfg = NULL;
- if (headphones)
- config_ChainParseOptions(&cfg, "{headphones=true}");
filter_t *f = aout_filter_Create(obj, NULL, filter_type, NULL,
- &input, &output, cfg, true);
- if (cfg)
- config_ChainDestroy(cfg);
+ &input, &output, NULL, true);
if (f == NULL)
{
@@ -430,7 +424,7 @@ static int AppendFilter(vlc_object_t *obj, const char *type, const char *name,
/* convert to the filter input format if necessary */
if (aout_FiltersPipelineCreate (obj, filters->tab, &filters->count,
- max - 1, infmt, &filter->fmt_in.audio, false))
+ max - 1, infmt, &filter->fmt_in.audio))
{
msg_Err (filter, "cannot add user %s \"%s\" (skipped)", type, name);
filter_Close( filter );
@@ -552,8 +546,7 @@ aout_filters_t *aout_FiltersNewWithClock(vlc_object_t *obj, const vlc_clock_t *c
/* convert to the output format (minus resampling) if necessary */
output_format.i_rate = input_format.i_rate;
if (aout_FiltersPipelineCreate (obj, filters->tab, &filters->count,
- AOUT_MAX_FILTERS, &input_format, &output_format,
- cfg->headphones))
+ AOUT_MAX_FILTERS, &input_format, &output_format))
{
msg_Warn (obj, "cannot setup audio renderer pipeline");
/* Fallback to bitmap without any conversions */
@@ -597,15 +590,9 @@ aout_filters_t *aout_FiltersNewWithClock(vlc_object_t *obj, const vlc_clock_t *c
}
if (cfg != NULL)
- {
AppendRemapFilter(obj, filters, &input_format, &output_format,
cfg->remap);
- if (input_format.i_channels > 2 && cfg->headphones)
- AppendFilter(obj, "audio filter", "binauralizer", filters,
- &input_format, &output_format, NULL);
- }
-
/* Now add user filters */
char *str = var_InheritString (obj, "audio-filter");
if (str != NULL)
@@ -628,7 +615,7 @@ aout_filters_t *aout_FiltersNewWithClock(vlc_object_t *obj, const vlc_clock_t *c
/* convert to the output format (minus resampling) if necessary */
output_format.i_rate = input_format.i_rate;
if (aout_FiltersPipelineCreate (obj, filters->tab, &filters->count,
- AOUT_MAX_FILTERS, &input_format, &output_format, false))
+ AOUT_MAX_FILTERS, &input_format, &output_format))
{
msg_Err (obj, "cannot setup filtering pipeline");
goto error;
=====================================
src/audio_output/output.c
=====================================
@@ -193,6 +193,21 @@ static int StereoModeCallback (vlc_object_t *obj, const char *varname,
return 0;
}
+static int MixModeCallback (vlc_object_t *obj, const char *varname,
+ vlc_value_t oldval, vlc_value_t newval, void *data)
+{
+ audio_output_t *aout = (audio_output_t *)obj;
+ (void)varname; (void)oldval; (void)newval; (void)data;
+
+ aout_owner_t *owner = aout_owner (aout);
+ vlc_mutex_lock (&owner->lock);
+ owner->requested_mix_mode = newval.i_int;
+ vlc_mutex_unlock (&owner->lock);
+
+ aout_RestartRequest (aout, AOUT_RESTART_STEREOMODE);
+ return 0;
+}
+
static void aout_ChangeViewpoint(audio_output_t *, const vlc_viewpoint_t *);
static int ViewpointCallback (vlc_object_t *obj, const char *var,
@@ -335,6 +350,12 @@ audio_output_t *aout_New (vlc_object_t *parent)
var_AddCallback (aout, "stereo-mode", StereoModeCallback, NULL);
var_Change(aout, "stereo-mode", VLC_VAR_SETTEXT, _("Stereo audio mode"));
+ /* Mix mode */
+ var_Create (aout, "mix-mode", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
+ owner->requested_mix_mode = var_GetInteger (aout, "mix-mode");
+ var_AddCallback (aout, "mix-mode", MixModeCallback, NULL);
+ var_Change(aout, "mix-mode", VLC_VAR_SETTEXT, _("Audio mix mode"));
+
/* Equalizer */
var_Create (aout, "equalizer-preamp", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
var_Create (aout, "equalizer-bands", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
@@ -376,6 +397,7 @@ void aout_Destroy (audio_output_t *aout)
var_SetFloat (aout, "volume", -1.f);
var_DelCallback(aout, "volume", var_Copy, vlc_object_parent(aout));
var_DelCallback (aout, "stereo-mode", StereoModeCallback, NULL);
+ var_DelCallback (aout, "mix-mode", MixModeCallback, NULL);
aout_Release(aout);
}
@@ -397,34 +419,25 @@ void aout_Release(audio_output_t *aout)
vlc_object_delete(VLC_OBJECT(aout));
}
-static void aout_PrepareStereoMode (audio_output_t *aout,
- audio_sample_format_t *restrict fmt,
- aout_filters_cfg_t *filters_cfg,
- audio_channel_type_t input_chan_type,
- unsigned i_nb_input_channels)
+static int aout_PrepareStereoMode(audio_output_t *aout,
+ const audio_sample_format_t *restrict fmt,
+ unsigned i_nb_input_channels)
{
aout_owner_t *owner = aout_owner (aout);
/* Fill Stereo mode choices */
- var_Change(aout, "stereo-mode", VLC_VAR_CLEARCHOICES);
vlc_value_t val;
const char *txt;
val.i_int = 0;
- if (!AOUT_FMT_LINEAR(fmt) || i_nb_input_channels == 1)
- return;
+ if (!AOUT_FMT_LINEAR(fmt) || i_nb_input_channels != 2)
+ return AOUT_VAR_CHAN_UNSET;
- int i_output_mode = owner->requested_stereo_mode;
- int i_default_mode = AOUT_VAR_CHAN_UNSET;
+ int i_default_mode = owner->requested_stereo_mode;
val.i_int = AOUT_VAR_CHAN_MONO;
var_Change(aout, "stereo-mode", VLC_VAR_ADDCHOICE, val, _("Mono"));
- if (i_nb_input_channels != 2)
- {
- val.i_int = AOUT_VAR_CHAN_UNSET;
- var_Change(aout, "stereo-mode", VLC_VAR_ADDCHOICE, val, _("Original"));
- }
if (fmt->i_chan_mode & AOUT_CHANMODE_DOLBYSTEREO)
{
val.i_int = AOUT_VAR_CHAN_DOLBYS;
@@ -437,83 +450,204 @@ static void aout_PrepareStereoMode (audio_output_t *aout,
}
var_Change(aout, "stereo-mode", VLC_VAR_ADDCHOICE, val, txt);
- if (i_nb_input_channels == 2)
+ if (fmt->i_chan_mode & AOUT_CHANMODE_DUALMONO)
+ i_default_mode = AOUT_VAR_CHAN_LEFT;
+ else
+ i_default_mode = val.i_int; /* Stereo or Dolby Surround */
+
+ val.i_int = AOUT_VAR_CHAN_LEFT;
+ var_Change(aout, "stereo-mode", VLC_VAR_ADDCHOICE, val, _("Left"));
+ val.i_int = AOUT_VAR_CHAN_RIGHT;
+ var_Change(aout, "stereo-mode", VLC_VAR_ADDCHOICE, val, _("Right"));
+
+ val.i_int = AOUT_VAR_CHAN_RSTEREO;
+ var_Change(aout, "stereo-mode", VLC_VAR_ADDCHOICE, val,
+ _("Reverse stereo"));
+
+ return i_default_mode;
+}
+
+static void aout_UpdateStereoMode(audio_output_t *aout, int mode,
+ audio_sample_format_t *restrict fmt,
+ aout_filters_cfg_t *filters_cfg)
+{
+ /* The user may have selected a different channels configuration. */
+ switch (mode)
{
- if (fmt->i_chan_mode & AOUT_CHANMODE_DUALMONO)
- i_default_mode = AOUT_VAR_CHAN_LEFT;
- else
- i_default_mode = val.i_int; /* Stereo or Dolby Surround */
+ case AOUT_VAR_CHAN_RSTEREO:
+ filters_cfg->remap[AOUT_CHANIDX_LEFT] = AOUT_CHANIDX_RIGHT;
+ filters_cfg->remap[AOUT_CHANIDX_RIGHT] = AOUT_CHANIDX_LEFT;
+ break;
+ case AOUT_VAR_CHAN_STEREO:
+ break;
+ case AOUT_VAR_CHAN_LEFT:
+ filters_cfg->remap[AOUT_CHANIDX_RIGHT] = AOUT_CHANIDX_DISABLE;
+ fmt->i_physical_channels = AOUT_CHAN_CENTER;
+ aout_FormatPrepare (fmt);
+ break;
+ case AOUT_VAR_CHAN_RIGHT:
+ filters_cfg->remap[AOUT_CHANIDX_LEFT] = AOUT_CHANIDX_DISABLE;
+ fmt->i_physical_channels = AOUT_CHAN_CENTER;
+ aout_FormatPrepare (fmt);
+ break;
+ case AOUT_VAR_CHAN_DOLBYS:
+ fmt->i_chan_mode = AOUT_CHANMODE_DOLBYSTEREO;
+ break;
+ case AOUT_VAR_CHAN_MONO:
+ /* Remix all channels into one */
+ for (size_t i = 0; i < AOUT_CHANIDX_MAX; ++ i)
+ filters_cfg->remap[i] = AOUT_CHANIDX_LEFT;
+ break;
+ default:
+ break;
+ }
- val.i_int = AOUT_VAR_CHAN_LEFT;
- var_Change(aout, "stereo-mode", VLC_VAR_ADDCHOICE, val, _("Left"));
- val.i_int = AOUT_VAR_CHAN_RIGHT;
- var_Change(aout, "stereo-mode", VLC_VAR_ADDCHOICE, val, _("Right"));
+ var_Change(aout, "stereo-mode", VLC_VAR_SETVALUE,
+ (vlc_value_t) { .i_int = mode});
+}
- val.i_int = AOUT_VAR_CHAN_RSTEREO;
- var_Change(aout, "stereo-mode", VLC_VAR_ADDCHOICE, val,
- _("Reverse stereo"));
+static bool aout_HasStereoMode(audio_output_t *aout, int mode)
+{
+ bool mode_available = false;
+ vlc_value_t *vals;
+ size_t count;
+
+ if (!var_Change(aout, "stereo-mode", VLC_VAR_GETCHOICES,
+ &count, &vals, (char ***)NULL))
+ {
+ for (size_t i = 0; !mode_available && i < count; ++i)
+ {
+ if (vals[i].i_int == mode)
+ mode_available = true;
+ }
+ free(vals);
}
+ return mode_available;
+}
+
+static void aout_AddMixModeChoice(audio_output_t *aout, int mode,
+ const char *suffix,
+ const audio_sample_format_t *restrict fmt)
+{
+ assert(suffix);
+ const char *text;
+ char *buffer = NULL;
- if (input_chan_type == AUDIO_CHANNEL_TYPE_AMBISONICS
- || i_nb_input_channels > 2)
+ if (fmt == NULL)
+ text = suffix;
+ else
{
- val.i_int = AOUT_VAR_CHAN_HEADPHONES;
- var_Change(aout, "stereo-mode", VLC_VAR_ADDCHOICE, val,
- _("Headphones"));
+ const char *channels = aout_FormatPrintChannels(fmt);
+ if (asprintf(&buffer, "%s: %s", suffix, channels) < 0)
+ return;
+ text = buffer;
+ }
+
+ vlc_value_t val = { .i_int = mode };
+ var_Change(aout, "mix-mode", VLC_VAR_ADDCHOICE, val, text);
+
+ free(buffer);
+}
+
+static void aout_SetupMixModeChoices (audio_output_t *aout,
+ const audio_sample_format_t *restrict fmt)
+{
+ if (fmt->i_channels <= 2)
+ return;
- if (aout->current_sink_info.headphones)
- i_default_mode = AOUT_VAR_CHAN_HEADPHONES;
+ const bool has_spatialaudio = module_exists("spatialaudio");
+
+ aout_AddMixModeChoice(aout, AOUT_MIX_MODE_UNSET, _("Original"), fmt);
+
+ if (fmt->channel_type != AUDIO_CHANNEL_TYPE_AMBISONICS && has_spatialaudio)
+ aout_AddMixModeChoice(aout, AOUT_MIX_MODE_STEREO, _("Stereo"), NULL);
+
+ if (has_spatialaudio)
+ aout_AddMixModeChoice(aout, AOUT_MIX_MODE_BINAURAL, _("Binaural"), NULL);
+
+ /* Only propose Original and Binaural for Ambisonics content */
+ if (fmt->channel_type == AUDIO_CHANNEL_TYPE_AMBISONICS && has_spatialaudio)
+ return;
+
+ if (fmt->i_physical_channels != AOUT_CHANS_4_0)
+ {
+ static const audio_sample_format_t fmt_4_0 = {
+ .i_physical_channels = AOUT_CHANS_4_0,
+ .i_channels = 4,
+ };
+ aout_AddMixModeChoice(aout, AOUT_MIX_MODE_4_0, _("4.0"), &fmt_4_0);
}
+ if (fmt->i_physical_channels != AOUT_CHANS_5_1)
+ {
+ static const audio_sample_format_t fmt_5_1 = {
+ .i_physical_channels = AOUT_CHANS_5_1,
+ .i_channels = 6,
+ };
+ aout_AddMixModeChoice(aout, AOUT_MIX_MODE_5_1, _("5.1"), &fmt_5_1);
+ }
+
+ if (fmt->i_physical_channels != AOUT_CHANS_7_1)
+ {
+ static const audio_sample_format_t fmt_7_1 = {
+ .i_physical_channels = AOUT_CHANS_7_1,
+ .i_channels = 8,
+ };
+ aout_AddMixModeChoice(aout, AOUT_MIX_MODE_7_1, _("7.1"), &fmt_7_1);
+ }
+}
+
+static bool aout_HasMixModeChoice(audio_output_t *aout, int mode)
+{
bool mode_available = false;
vlc_value_t *vals;
size_t count;
- if (!var_Change(aout, "stereo-mode", VLC_VAR_GETCHOICES,
+ if (!var_Change(aout, "mix-mode", VLC_VAR_GETCHOICES,
&count, &vals, (char ***)NULL))
{
for (size_t i = 0; !mode_available && i < count; ++i)
{
- if (vals[i].i_int == i_output_mode)
+ if (vals[i].i_int == mode)
mode_available = true;
}
free(vals);
}
- if (!mode_available)
- i_output_mode = i_default_mode;
+ return mode_available;
+}
+
+static void aout_UpdateMixMode(audio_output_t *aout, int mode,
+ audio_sample_format_t *restrict fmt)
+{
/* The user may have selected a different channels configuration. */
- switch (i_output_mode)
+ switch (mode)
{
- case AOUT_VAR_CHAN_RSTEREO:
- filters_cfg->remap[AOUT_CHANIDX_LEFT] = AOUT_CHANIDX_RIGHT;
- filters_cfg->remap[AOUT_CHANIDX_RIGHT] = AOUT_CHANIDX_LEFT;
+ case AOUT_MIX_MODE_UNSET:
break;
- case AOUT_VAR_CHAN_STEREO:
+ case AOUT_MIX_MODE_BINAURAL:
+ fmt->i_physical_channels = AOUT_CHANS_STEREO;
+ fmt->i_chan_mode = AOUT_CHANMODE_BINAURAL;
break;
- case AOUT_VAR_CHAN_LEFT:
- filters_cfg->remap[AOUT_CHANIDX_RIGHT] = AOUT_CHANIDX_DISABLE;
+ case AOUT_MIX_MODE_STEREO:
+ fmt->i_physical_channels = AOUT_CHANS_STEREO;
break;
- case AOUT_VAR_CHAN_RIGHT:
- filters_cfg->remap[AOUT_CHANIDX_LEFT] = AOUT_CHANIDX_DISABLE;
- break;
- case AOUT_VAR_CHAN_DOLBYS:
- fmt->i_chan_mode = AOUT_CHANMODE_DOLBYSTEREO;
+ case AOUT_MIX_MODE_4_0:
+ fmt->i_physical_channels = AOUT_CHANS_4_0;
break;
- case AOUT_VAR_CHAN_HEADPHONES:
- filters_cfg->headphones = true;
+ case AOUT_MIX_MODE_5_1:
+ fmt->i_physical_channels = AOUT_CHANS_5_1;
break;
- case AOUT_VAR_CHAN_MONO:
- /* Remix all channels into one */
- for (size_t i = 0; i < AOUT_CHANIDX_MAX; ++ i)
- filters_cfg->remap[i] = AOUT_CHANIDX_LEFT;
+ case AOUT_MIX_MODE_7_1:
+ fmt->i_physical_channels = AOUT_CHANS_7_1;
break;
default:
break;
}
- var_Change(aout, "stereo-mode", VLC_VAR_SETVALUE,
- (vlc_value_t) { .i_int = i_output_mode });
+ assert(mode == AOUT_VAR_CHAN_UNSET || aout_HasMixModeChoice(aout, mode));
+
+ var_Change(aout, "mix-mode", VLC_VAR_SETVALUE, (vlc_value_t) { .i_int = mode});
}
/**
@@ -529,12 +663,14 @@ int aout_OutputNew (audio_output_t *aout)
audio_sample_format_t *filter_fmt = &owner->filter_format;
aout_filters_cfg_t *filters_cfg = &owner->filters_cfg;
- audio_channel_type_t input_chan_type = fmt->channel_type;
unsigned i_nb_input_channels = fmt->i_channels;
vlc_fourcc_t formats[] = {
fmt->i_format, 0, 0
};
+ var_Change(aout, "stereo-mode", VLC_VAR_CLEARCHOICES);
+ var_Change(aout, "mix-mode", VLC_VAR_CLEARCHOICES);
+
/* Ideally, the audio filters would be created before the audio output,
* and the ideal audio format would be the output of the filters chain.
* But that scheme would not really play well with digital pass-through. */
@@ -560,10 +696,12 @@ int aout_OutputNew (audio_output_t *aout)
fmt->i_format = (fmt->i_bitspersample > 16) ? VLC_CODEC_FL32
: VLC_CODEC_S16N;
- if (fmt->i_physical_channels == AOUT_CHANS_STEREO
- && (owner->requested_stereo_mode == AOUT_VAR_CHAN_LEFT
- || owner->requested_stereo_mode == AOUT_VAR_CHAN_RIGHT))
- fmt->i_physical_channels = AOUT_CHAN_CENTER;
+ aout_SetupMixModeChoices(aout, fmt);
+
+ /* Prefer the user requested mode if available, otherwise, use the
+ * default one */
+ if (aout_HasMixModeChoice(aout, owner->requested_mix_mode))
+ aout_UpdateMixMode(aout, owner->requested_mix_mode, fmt);
aout_FormatPrepare (fmt);
assert (aout_FormatNbChannels(fmt) > 0);
@@ -594,6 +732,13 @@ int aout_OutputNew (audio_output_t *aout)
}
}
+ int stereo_mode =
+ aout_PrepareStereoMode(aout, fmt, i_nb_input_channels);
+
+ if (stereo_mode != AOUT_VAR_CHAN_UNSET
+ && aout_HasStereoMode(aout, stereo_mode))
+ aout_UpdateStereoMode(aout, stereo_mode, fmt, filters_cfg);
+
aout->current_sink_info.headphones = false;
vlc_mutex_lock(&owner->lock);
@@ -615,8 +760,16 @@ int aout_OutputNew (audio_output_t *aout)
}
assert(aout->flush && aout->play && aout->time_get && aout->pause);
- aout_PrepareStereoMode (aout, fmt, filters_cfg, input_chan_type,
- i_nb_input_channels);
+ /* Autoselect the headphones mode if available and if the user didn't
+ * request any mode */
+ if (aout->current_sink_info.headphones
+ && owner->requested_mix_mode == AOUT_VAR_CHAN_UNSET
+ && aout_HasMixModeChoice(aout, AOUT_MIX_MODE_BINAURAL))
+ {
+ assert(fmt->i_physical_channels == AOUT_CHANS_STEREO);
+ assert(stereo_mode == AOUT_VAR_CHAN_UNSET);
+ aout_UpdateMixMode(aout, AOUT_MIX_MODE_BINAURAL, fmt);
+ }
aout_FormatPrepare (fmt);
assert (fmt->i_bytes_per_frame > 0 && fmt->i_frame_length > 0);
=====================================
src/libvlc-module.c
=====================================
@@ -190,12 +190,22 @@ static const char *const ppsz_force_dolby_descriptions[] = {
static const int pi_stereo_mode_values[] = { AOUT_VAR_CHAN_UNSET,
AOUT_VAR_CHAN_STEREO, AOUT_VAR_CHAN_RSTEREO,
AOUT_VAR_CHAN_LEFT, AOUT_VAR_CHAN_RIGHT, AOUT_VAR_CHAN_DOLBYS,
- AOUT_VAR_CHAN_HEADPHONES, AOUT_VAR_CHAN_MONO,
+ AOUT_VAR_CHAN_MONO,
};
static const char *const ppsz_stereo_mode_texts[] = { N_("Unset"),
N_("Stereo"), N_("Reverse stereo"),
N_("Left"), N_("Right"), N_("Dolby Surround"),
- N_("Headphones"), N_("Mono"),
+ N_("Mono"),
+};
+
+#define MIX_MODE_TEXT N_("Audio mix mode")
+static const int pi_mix_mode_values[] = {
+ AOUT_MIX_MODE_UNSET, AOUT_MIX_MODE_STEREO, AOUT_MIX_MODE_BINAURAL,
+ AOUT_MIX_MODE_4_0, AOUT_MIX_MODE_5_1, AOUT_MIX_MODE_7_1,
+};
+static const char *const ppsz_mix_mode_texts[] = {
+ N_("Unset"), N_("Stereo"), N_("Binaural"),
+ "4.0", "5.1", "7.1",
};
#define AUDIO_FILTER_TEXT N_("Audio filters")
@@ -1552,6 +1562,8 @@ vlc_module_begin ()
change_integer_list( pi_force_dolby_values, ppsz_force_dolby_descriptions )
add_integer( "stereo-mode", 0, STEREO_MODE_TEXT, NULL, true )
change_integer_list( pi_stereo_mode_values, ppsz_stereo_mode_texts )
+ add_integer( "mix-mode", NULL, MIX_MODE_TEXT, MIX_MODE_TEXT, true )
+ change_integer_list( pi_mix_mode_values, ppsz_mix_mode_texts )
add_integer( "audio-desync", 0, DESYNC_TEXT,
DESYNC_LONGTEXT, true )
change_safe ()
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/e97d492a8c886ad8a91da419daef088a5ff274fd...89cc76caa790f6d834b8e3c5ff40a2994b9a4a48
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/e97d492a8c886ad8a91da419daef088a5ff274fd...89cc76caa790f6d834b8e3c5ff40a2994b9a4a48
You're receiving this email because of your account on code.videolan.org.
More information about the vlc-commits
mailing list