1 /*
2 This file is part of Deadbeef Player source code
3 http://deadbeef.sourceforge.net
4
5 replaygain support
6
7 Copyright (C) 2009-2013 Alexey Yakovenko
8
9 This software is provided 'as-is', without any express or implied
10 warranty. In no event will the authors be held liable for any damages
11 arising from the use of this software.
12
13 Permission is granted to anyone to use this software for any purpose,
14 including commercial applications, and to alter it and redistribute it
15 freely, subject to the following restrictions:
16
17 1. The origin of this software must not be misrepresented; you must not
18 claim that you wrote the original software. If you use this software
19 in a product, an acknowledgment in the product documentation would be
20 appreciated but is not required.
21 2. Altered source versions must be plainly marked as such, and must not be
22 misrepresented as being the original software.
23 3. This notice may not be removed or altered from any source distribution.
24
25 Alexey Yakovenko waker@users.sourceforge.net
26 */
27 #include "playlist.h"
28 #include "volume.h"
29 #include "replaygain.h"
30
31 static int conf_replaygain_mode = 0;
32 static int conf_replaygain_scale = 1;
33 static float conf_replaygain_preamp = 0;
34 static float conf_global_preamp = 0;
35
36 static float rg_albumgain = 1;
37 static float rg_albumpeak = 1;
38 static float rg_trackgain = 1;
39 static float rg_trackpeak = 1;
40 static float rg_albumgain_full_preamp = 1;
41 static float rg_trackgain_full_preamp = 1;
42 static float rg_albumgain_global_preamp = 1;
43 static float rg_trackgain_global_preamp = 1;
44
45 void
replaygain_apply(ddb_waveformat_t * fmt,playItem_t * it,char * bytes,int bytesread)46 replaygain_apply (ddb_waveformat_t *fmt, playItem_t *it, char *bytes, int bytesread) {
47 // FIXME: separate replaygain DSP plugin?
48 if (fmt->bps == 16) {
49 apply_replay_gain_int16 (it, bytes, bytesread);
50 }
51 else if (fmt->bps == 24) {
52 apply_replay_gain_int24 (it, bytes, bytesread);
53 }
54 else if (fmt->bps == 8) {
55 apply_replay_gain_int16 (it, bytes, bytesread);
56 }
57 else if (fmt->bps == 32 && !fmt->is_float) {
58 apply_replay_gain_int32 (it, bytes, bytesread);
59 }
60 else if (fmt->bps == 32 && fmt->is_float) {
61 apply_replay_gain_float32 (it, bytes, bytesread);
62 }
63 }
64
65 void
replaygain_set(int mode,int scale,float preamp,float global_preamp)66 replaygain_set (int mode, int scale, float preamp, float global_preamp) {
67 conf_replaygain_mode = mode;
68 conf_replaygain_scale = scale;
69 conf_replaygain_preamp = db_to_amp (preamp);
70 conf_global_preamp = db_to_amp (global_preamp);
71 rg_albumgain_full_preamp = rg_albumgain * conf_replaygain_preamp * conf_global_preamp;
72 rg_trackgain_full_preamp = rg_trackgain * conf_replaygain_preamp * conf_global_preamp;
73 rg_albumgain_global_preamp = rg_albumgain * conf_global_preamp;
74 rg_trackgain_global_preamp = rg_trackgain * conf_global_preamp;
75 }
76
77 void
replaygain_set_values(float albumgain,float albumpeak,float trackgain,float trackpeak)78 replaygain_set_values (float albumgain, float albumpeak, float trackgain, float trackpeak) {
79 if (albumgain > 100 && trackgain <= 100) {
80 albumgain = trackgain;
81 albumpeak = trackpeak;
82 }
83 else if (albumgain <= 100 && trackgain > 100) {
84 trackgain = albumgain;
85 trackpeak = albumpeak;
86 }
87 else if (albumgain > 100 && trackgain > 100) {
88 trackgain = albumgain = 0;
89 }
90 rg_albumgain = db_to_amp (albumgain);
91 rg_trackgain = db_to_amp (trackgain);
92 rg_albumgain_full_preamp = rg_albumgain * conf_replaygain_preamp * conf_global_preamp;
93 rg_trackgain_full_preamp = rg_trackgain * conf_replaygain_preamp * conf_global_preamp;
94 rg_albumgain_global_preamp = rg_albumgain * conf_global_preamp;
95 rg_trackgain_global_preamp = rg_trackgain * conf_global_preamp;
96 rg_albumpeak = albumpeak;
97 rg_trackpeak = trackpeak;
98 }
99
100 static inline int
get_int_volume(void)101 get_int_volume (void) {
102 int vol = 1000;
103 if (conf_replaygain_mode == 1) {
104 if (rg_trackgain == 1) {
105 vol = rg_trackgain_global_preamp * 1000;
106 } else {
107 vol = rg_trackgain_full_preamp * 1000;
108 }
109 if (conf_replaygain_scale) {
110 if (vol * rg_trackpeak > 1000) {
111 vol = 1000 / rg_trackpeak;
112 }
113 }
114 }
115 else if (conf_replaygain_mode == 2) {
116 if (rg_albumgain == 1) {
117 vol = rg_albumgain_global_preamp * 1000;
118 } else {
119 vol = rg_albumgain_full_preamp * 1000;
120 }
121 if (conf_replaygain_scale) {
122 if (vol * rg_albumpeak > 1000) {
123 vol = 1000 / rg_albumpeak;
124 }
125 }
126 }
127 return vol;
128 }
129
130 void
apply_replay_gain_int8(playItem_t * it,char * bytes,int size)131 apply_replay_gain_int8 (playItem_t *it, char *bytes, int size) {
132 if (!conf_replaygain_mode) {
133 return;
134 }
135 int vol = get_int_volume ();
136 if (vol < 0) {
137 return;
138 }
139 int8_t *s = (int8_t*)bytes;
140 for (int j = 0; j < size; j++) {
141 int32_t sample = ((int8_t)(*s)) * vol / 1000;
142 if (sample > 0x7f) {
143 sample = 0x7f;
144 }
145 else if (sample < -0x80) {
146 sample = -0x80;
147 }
148 *s = (int8_t)sample;
149 s++;
150 }
151 }
152
153 void
apply_replay_gain_int16(playItem_t * it,char * bytes,int size)154 apply_replay_gain_int16 (playItem_t *it, char *bytes, int size) {
155 if (!conf_replaygain_mode) {
156 return;
157 }
158 int vol = get_int_volume ();
159 if (vol < 0) {
160 return;
161 }
162 int16_t *s = (int16_t*)bytes;
163 for (int j = 0; j < size/2; j++) {
164 int32_t sample = ((int32_t)(*s)) * vol / 1000;
165 if (sample > 0x7fff) {
166 sample = 0x7fff;
167 }
168 else if (sample < -0x8000) {
169 sample = -0x8000;
170 }
171 *s = (int16_t)sample;
172 s++;
173 }
174 }
175
176 void
apply_replay_gain_int24(playItem_t * it,char * bytes,int size)177 apply_replay_gain_int24 (playItem_t *it, char *bytes, int size) {
178 if (!conf_replaygain_mode) {
179 return;
180 }
181 int64_t vol = get_int_volume ();
182 if (vol < 0) {
183 return;
184 }
185 char *s = (char*)bytes;
186 for (int j = 0; j < size/3; j++) {
187 int32_t sample = ((unsigned char)s[0]) | ((unsigned char)s[1]<<8) | (s[2]<<16);
188 sample = sample * vol / 1000;
189 if (sample > 0x7fffff) {
190 sample = 0x7fffff;
191 }
192 else if (sample < -0x800000) {
193 sample = -0x800000;
194 }
195 s[0] = (sample&0x0000ff);
196 s[1] = (sample&0x00ff00)>>8;
197 s[2] = (sample&0xff0000)>>16;
198 s += 3;
199 }
200 }
201
202 void
apply_replay_gain_int32(playItem_t * it,char * bytes,int size)203 apply_replay_gain_int32 (playItem_t *it, char *bytes, int size) {
204 if (!conf_replaygain_mode) {
205 return;
206 }
207 int64_t vol = get_int_volume ();
208 if (vol < 0) {
209 return;
210 }
211 int32_t *s = (int32_t*)bytes;
212 for (int j = 0; j < size/4; j++) {
213 int64_t sample = ((int32_t)(*s)) * vol / 1000;
214 *s = (int32_t)sample;
215 s++;
216 }
217 }
218
219 void
apply_replay_gain_float32(playItem_t * it,char * bytes,int size)220 apply_replay_gain_float32 (playItem_t *it, char *bytes, int size) {
221 if (!conf_replaygain_mode) {
222 return;
223 }
224 float vol = 1.f;
225 if (conf_replaygain_mode == 1) {
226 if (rg_trackgain == 1) {
227 vol = rg_trackgain_global_preamp;
228 } else {
229 vol = rg_trackgain_full_preamp;
230 }
231 if (conf_replaygain_scale) {
232 if (vol * rg_trackpeak > 1.f) {
233 vol = 1.f / rg_trackpeak;
234 }
235 }
236 }
237 else if (conf_replaygain_mode == 2) {
238 if (rg_albumgain == 1) {
239 vol = rg_albumgain_global_preamp;
240 } else {
241 vol = rg_albumgain_full_preamp;
242 }
243 if (conf_replaygain_scale) {
244 if (vol * rg_albumpeak > 1.f) {
245 vol = 1.f / rg_albumpeak;
246 }
247 }
248 }
249 float *s = (float*)bytes;
250 for (int j = 0; j < size/4; j++) {
251 float sample = ((float)*s) * vol;
252 if (sample > 1.f) {
253 sample = 1.f;
254 }
255 else if (sample < -1.f) {
256 sample = -1.f;
257 }
258 *s = sample;
259 s++;
260 }
261 }
262