Initial revision 6759
[qball-mpd.git] / src / .svn / text-base / replayGain.c.svn-base
blobce9d48085e630c1ce92a713a9401c5188a5be51f
1 /* the Music Player Daemon (MPD)
2  * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
3  * (c)2004 replayGain code by AliasMrJones
4  * This project's homepage is: http://www.musicpd.org
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
20 #include "replayGain.h"
21 #include "utils.h"
23 #include "log.h"
24 #include "conf.h"
26 #include <string.h>
27 #include <math.h>
28 #include <stdlib.h>
30 /* Added 4/14/2004 by AliasMrJones */
31 int replayGainState = REPLAYGAIN_OFF;
33 static float replayGainPreamp = 1.0;
35 void initReplayGainState(void)
37         ConfigParam *param = getConfigParam(CONF_REPLAYGAIN);
39         if (!param)
40                 return;
42         if (strcmp(param->value, "track") == 0) {
43                 replayGainState = REPLAYGAIN_TRACK;
44         } else if (strcmp(param->value, "album") == 0) {
45                 replayGainState = REPLAYGAIN_ALBUM;
46         } else {
47                 FATAL("replaygain value \"%s\" at line %i is invalid\n",
48                       param->value, param->line);
49         }
51         param = getConfigParam(CONF_REPLAYGAIN_PREAMP);
53         if (param) {
54                 char *test;
55                 float f = strtod(param->value, &test);
57                 if (*test != '\0') {
58                         FATAL("Replaygain preamp \"%s\" is not a number at "
59                               "line %i\n", param->value, param->line);
60                 }
62                 if (f < -15 || f > 15) {
63                         FATAL("Replaygain preamp \"%s\" is not between -15 and"
64                               "15 at line %i\n", param->value, param->line);
65                 }
67                 replayGainPreamp = pow(10, f / 20.0);
68         }
71 static float computeReplayGainScale(float gain, float peak)
73         float scale;
75         if (gain == 0.0)
76                 return (1);
77         scale = pow(10.0, gain / 20.0);
78         scale *= replayGainPreamp;
79         if (scale > 15.0)
80                 scale = 15.0;
82         if (scale * peak > 1.0) {
83                 scale = 1.0 / peak;
84         }
85         return (scale);
88 ReplayGainInfo *newReplayGainInfo(void)
90         ReplayGainInfo *ret = xmalloc(sizeof(ReplayGainInfo));
92         ret->albumGain = 0.0;
93         ret->albumPeak = 0.0;
95         ret->trackGain = 0.0;
96         ret->trackPeak = 0.0;
98         /* set to -1 so that we know in doReplayGain to compute the scale */
99         ret->scale = -1.0;
101         return ret;
104 void freeReplayGainInfo(ReplayGainInfo * info)
106         free(info);
109 void doReplayGain(ReplayGainInfo * info, char *buffer, int bufferSize,
110                   AudioFormat * format)
112         mpd_sint16 *buffer16;
113         mpd_sint8 *buffer8;
114         mpd_sint32 temp32;
115         float scale;
117         if (replayGainState == REPLAYGAIN_OFF || !info)
118                 return;
120         if (info->scale < 0) {
121                 switch (replayGainState) {
122                 case REPLAYGAIN_TRACK:
123                         DEBUG("computing ReplayGain track scale with gain %f, "
124                               "peak %f\n", info->trackGain, info->trackPeak);
125                         info->scale = computeReplayGainScale(info->trackGain,
126                                                              info->trackPeak);
127                         break;
128                 default:
129                         DEBUG("computing ReplayGain album scale with gain %f, "
130                               "peak %f\n", info->albumGain, info->albumPeak);
131                         info->scale = computeReplayGainScale(info->albumGain,
132                                                              info->albumPeak);
133                         break;
134                 }
135         }
137         if (info->scale <= 1.01 && info->scale >= 0.99)
138                 return;
140         buffer16 = (mpd_sint16 *) buffer;
141         buffer8 = (mpd_sint8 *) buffer;
143         scale = info->scale;
145         switch (format->bits) {
146         case 16:
147                 while (bufferSize > 0) {
148                         temp32 = *buffer16;
149                         temp32 *= scale;
150                         *buffer16 = temp32 > 32767 ? 32767 :
151                             (temp32 < -32768 ? -32768 : temp32);
152                         buffer16++;
153                         bufferSize -= 2;
154                 }
155                 break;
156         case 8:
157                 while (bufferSize > 0) {
158                         temp32 = *buffer8;
159                         temp32 *= scale;
160                         *buffer8 = temp32 > 127 ? 127 :
161                             (temp32 < -128 ? -128 : temp32);
162                         buffer8++;
163                         bufferSize--;
164                 }
165                 break;
166         default:
167                 ERROR("%i bits not supported by doReplaygain!\n", format->bits);
168         }