LGPL
[vlc.git] / src / audio_output / mixer.c
1 /*****************************************************************************
2  * mixer.c : audio output mixing operations
3  *****************************************************************************
4  * Copyright (C) 2002-2004 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <stddef.h>
32 #include <math.h>
33
34 #include <vlc_common.h>
35 #include <libvlc.h>
36 #include <vlc_modules.h>
37 #include <vlc_aout.h>
38 #include <vlc_aout_mixer.h>
39 #include "aout_internal.h"
40
41 #undef aout_MixerNew
42 /**
43  * Creates a software amplifier.
44  */
45 audio_mixer_t *aout_MixerNew(vlc_object_t *obj, vlc_fourcc_t format)
46 {
47     audio_mixer_t *mixer = vlc_custom_create(obj, sizeof (*mixer), "mixer");
48     if (unlikely(mixer == NULL))
49         return NULL;
50
51     mixer->format = format;
52     mixer->mix = NULL;
53     mixer->module = module_need(mixer, "audio mixer", NULL, false);
54     if (mixer->module == NULL)
55     {
56         vlc_object_release(mixer);
57         mixer = NULL;
58     }
59     return mixer;
60 }
61
62 /**
63  * Destroys a software amplifier.
64  */
65 void aout_MixerDelete(audio_mixer_t *mixer)
66 {
67     if (mixer == NULL)
68         return;
69
70     module_unneed(mixer, mixer->module);
71     vlc_object_release(mixer);
72 }
73
74 /**
75  * Applies replay gain and software volume to an audio buffer.
76  */
77 void aout_MixerRun(audio_mixer_t *mixer, block_t *block, float amp)
78 {
79     mixer->mix(mixer, block, amp);
80 }
81
82 /*** Replay gain ***/
83 float (aout_ReplayGainSelect)(vlc_object_t *obj, const char *str,
84                               const audio_replay_gain_t *replay_gain)
85 {
86     float gain = 0.;
87     unsigned mode = AUDIO_REPLAY_GAIN_MAX;
88
89     if (likely(str != NULL))
90     {   /* Find selectrf mode */
91         if (!strcmp (str, "track"))
92             mode = AUDIO_REPLAY_GAIN_TRACK;
93         else
94         if (!strcmp (str, "album"))
95             mode = AUDIO_REPLAY_GAIN_ALBUM;
96
97         /* If the selectrf mode is not available, prefer the other one */
98         if (mode != AUDIO_REPLAY_GAIN_MAX && !replay_gain->pb_gain[mode])
99         {
100             if (replay_gain->pb_gain[!mode])
101                 mode = !mode;
102         }
103     }
104
105     /* */
106     if (mode == AUDIO_REPLAY_GAIN_MAX)
107         return 1.;
108
109     if (replay_gain->pb_gain[mode])
110         gain = replay_gain->pf_gain[mode]
111              + var_InheritFloat (obj, "audio-replay-gain-preamp");
112     else
113         gain = var_InheritFloat (obj, "audio-replay-gain-default");
114
115     float multiplier = pow (10., gain / 20.);
116
117     if (replay_gain->pb_peak[mode]
118      && var_InheritBool (obj, "audio-replay-gain-peak-protection")
119      && replay_gain->pf_peak[mode] * multiplier > 1.0)
120         multiplier = 1.0f / replay_gain->pf_peak[mode];
121
122     return multiplier;
123 }