Initial revision 6759
[qball-mpd.git] / src / replayGain.c
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
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.
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
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);
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);
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);
67 replayGainPreamp = pow(10, f / 20.0);
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;
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;
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;
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--;
165 break;
166 default:
167 ERROR("%i bits not supported by doReplaygain!\n", format->bits);