skins2: simplify playlist title
[vlc.git] / src / audio_output / volume.c
blobb16cc832c71b299a9f40269bae5d779a96c6f0a9
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 *****************************************************************************/
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
26 #include <stddef.h>
27 #include <math.h>
29 #include <vlc_common.h>
30 #include <libvlc.h>
31 #include <vlc_modules.h>
32 #include <vlc_aout.h>
33 #include <vlc_aout_volume.h>
34 #include "aout_internal.h"
36 struct aout_volume
38 audio_volume_t object;
39 audio_replay_gain_t replay_gain;
40 vlc_atomic_float gain_factor;
41 float output_factor;
42 module_t *module;
45 static int ReplayGainCallback (vlc_object_t *, char const *,
46 vlc_value_t, vlc_value_t, void *);
48 #undef aout_volume_New
49 /**
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),
56 "volume");
57 if (unlikely(vol == NULL))
58 return NULL;
59 vol->module = NULL;
60 vol->output_factor = 1.f;
62 //audio_volume_t *obj = &vol->object;
64 /* Gain */
65 if (gain != NULL)
66 memcpy(&vol->replay_gain, gain, sizeof (vol->replay_gain));
67 else
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");
74 return vol;
77 /**
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))
83 return -1;
85 audio_volume_t *obj = &vol->object;
86 if (vol->module != NULL)
88 if (obj->format == format)
90 msg_Dbg (obj, "retaining sample format");
91 return 0;
93 msg_Dbg (obj, "changing sample format");
94 module_unneed(obj, vol->module);
97 obj->format = format;
98 vol->module = module_need(obj, "audio volume", NULL, false);
99 if (vol->module == NULL)
100 return -1;
101 return 0;
105 * Destroys a software amplifier.
107 void aout_volume_Delete(aout_volume_t *vol)
109 if (vol == NULL)
110 return;
112 audio_volume_t *obj = &vol->object;
114 if (vol->module != NULL)
115 module_unneed(obj, vol->module);
116 var_DelCallback(obj->p_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))
124 return;
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)
135 return -1;
137 float amp = vol->output_factor
138 * vlc_atomic_loadf (&vol->gain_factor);
140 vol->object.amplify(&vol->object, block, amp);
141 return 0;
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;
154 else
155 if (!strcmp (str, "album"))
156 mode = AUDIO_REPLAY_GAIN_ALBUM;
159 /* */
160 float multiplier;
162 if (mode == AUDIO_REPLAY_GAIN_MAX)
164 multiplier = 1.f;
166 else
168 float gain;
170 /* If the selectrf mode is not available, prefer the other one */
171 if (!replay_gain->pb_gain[mode] && replay_gain->pb_gain[!mode])
172 mode = !mode;
174 if (replay_gain->pb_gain[mode])
175 gain = replay_gain->pf_gain[mode]
176 + var_InheritFloat (obj, "audio-replay-gain-preamp");
177 else
178 gain = var_InheritFloat (obj, "audio-replay-gain-default");
180 multiplier = pow (10., gain / 20.);
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]
185 : 1.f);
188 /* Command line / configuration gain */
189 multiplier *= var_InheritFloat (obj, "gain");
191 return multiplier;
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,
199 &vol->replay_gain);
200 vlc_atomic_storef (&vol->gain_factor, multiplier);
201 VLC_UNUSED(var); VLC_UNUSED(oldval);
202 return VLC_SUCCESS;