1 /*****************************************************************************
2 * volume.c : audio output volume operations
3 *****************************************************************************
4 * Copyright (C) 2002-2004 VLC authors and VideoLAN
5 * Copyright (C) 2011-2012 RĂ©mi Denis-Courmont
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
20 *****************************************************************************/
29 #include <vlc_common.h>
31 #include <vlc_modules.h>
33 #include <vlc_aout_volume.h>
34 #include "aout_internal.h"
38 audio_volume_t object
;
39 audio_replay_gain_t replay_gain
;
40 vlc_atomic_float gain_factor
;
45 static int ReplayGainCallback (vlc_object_t
*, char const *,
46 vlc_value_t
, vlc_value_t
, void *);
48 #undef aout_volume_New
50 * Creates a software amplifier.
52 aout_volume_t
*aout_volume_New(vlc_object_t
*parent
,
53 const audio_replay_gain_t
*gain
)
55 aout_volume_t
*vol
= vlc_custom_create(parent
, sizeof (aout_volume_t
),
57 if (unlikely(vol
== NULL
))
60 vol
->output_factor
= 1.f
;
62 //audio_volume_t *obj = &vol->object;
66 memcpy(&vol
->replay_gain
, gain
, sizeof (vol
->replay_gain
));
68 memset(&vol
->replay_gain
, 0, sizeof (vol
->replay_gain
));
70 var_AddCallback(parent
, "audio-replay-gain-mode",
71 ReplayGainCallback
, vol
);
72 var_TriggerCallback(parent
, "audio-replay-gain-mode");
78 * Selects the current sample format for software amplification.
80 int aout_volume_SetFormat(aout_volume_t
*vol
, vlc_fourcc_t format
)
82 if (unlikely(vol
== NULL
))
85 audio_volume_t
*obj
= &vol
->object
;
86 if (vol
->module
!= NULL
)
88 if (obj
->format
== format
)
90 msg_Dbg (obj
, "retaining sample format");
93 msg_Dbg (obj
, "changing sample format");
94 module_unneed(obj
, vol
->module
);
98 vol
->module
= module_need(obj
, "audio volume", NULL
, false);
99 if (vol
->module
== NULL
)
105 * Destroys a software amplifier.
107 void aout_volume_Delete(aout_volume_t
*vol
)
112 audio_volume_t
*obj
= &vol
->object
;
114 if (vol
->module
!= NULL
)
115 module_unneed(obj
, vol
->module
);
116 var_DelCallback(obj
->obj
.parent
, "audio-replay-gain-mode",
117 ReplayGainCallback
, vol
);
118 vlc_object_release(obj
);
121 void aout_volume_SetVolume(aout_volume_t
*vol
, float factor
)
123 if (unlikely(vol
== NULL
))
126 vol
->output_factor
= factor
;
130 * Applies replay gain and software volume to an audio buffer.
132 int aout_volume_Amplify(aout_volume_t
*vol
, block_t
*block
)
134 if (unlikely(vol
== NULL
) || vol
->module
== NULL
)
137 float amp
= vol
->output_factor
138 * vlc_atomic_load_float (&vol
->gain_factor
);
140 vol
->object
.amplify(&vol
->object
, block
, amp
);
144 /*** Replay gain ***/
145 static float aout_ReplayGainSelect(vlc_object_t
*obj
, const char *str
,
146 const audio_replay_gain_t
*replay_gain
)
148 unsigned mode
= AUDIO_REPLAY_GAIN_MAX
;
150 if (likely(str
!= NULL
))
151 { /* Find selectrf mode */
152 if (!strcmp (str
, "track"))
153 mode
= AUDIO_REPLAY_GAIN_TRACK
;
155 if (!strcmp (str
, "album"))
156 mode
= AUDIO_REPLAY_GAIN_ALBUM
;
162 if (mode
== AUDIO_REPLAY_GAIN_MAX
)
170 /* If the selectrf mode is not available, prefer the other one */
171 if (!replay_gain
->pb_gain
[mode
] && replay_gain
->pb_gain
[!mode
])
174 if (replay_gain
->pb_gain
[mode
])
175 gain
= replay_gain
->pf_gain
[mode
]
176 + var_InheritFloat (obj
, "audio-replay-gain-preamp");
178 gain
= var_InheritFloat (obj
, "audio-replay-gain-default");
180 multiplier
= powf (10.f
, gain
/ 20.f
);
182 if (var_InheritBool (obj
, "audio-replay-gain-peak-protection"))
183 multiplier
= fminf (multiplier
, replay_gain
->pb_peak
[mode
]
184 ? 1.f
/ replay_gain
->pf_peak
[mode
]
188 /* Command line / configuration gain */
189 multiplier
*= var_InheritFloat (obj
, "gain");
194 static int ReplayGainCallback (vlc_object_t
*obj
, char const *var
,
195 vlc_value_t oldval
, vlc_value_t val
, void *data
)
197 aout_volume_t
*vol
= data
;
198 float multiplier
= aout_ReplayGainSelect(obj
, val
.psz_string
,
200 vlc_atomic_store_float (&vol
->gain_factor
, multiplier
);
201 VLC_UNUSED(var
); VLC_UNUSED(oldval
);