summaryrefslogtreecommitdiff
path: root/replaygain.c
diff options
context:
space:
mode:
authorGravatar waker <wakeroid@gmail.com>2011-02-24 21:30:06 +0100
committerGravatar waker <wakeroid@gmail.com>2011-02-24 21:30:06 +0100
commitf4b6e6a0aa2894025b6fe87a282a9988a1a9e341 (patch)
tree1f711b16a8f1f03d67d09257505b4005f831f6cc /replaygain.c
parentc05c4393fc9bc38f73961afe67b0b950ccec328e (diff)
moved replaygain code to separate file; added support for applying replaygain to 8, 24 and 32 bit int streams
Diffstat (limited to 'replaygain.c')
-rw-r--r--replaygain.c265
1 files changed, 265 insertions, 0 deletions
diff --git a/replaygain.c b/replaygain.c
new file mode 100644
index 00000000..335cd8b0
--- /dev/null
+++ b/replaygain.c
@@ -0,0 +1,265 @@
+
+/*
+ DeaDBeeF - ultimate music player for GNU/Linux systems with X11
+ Copyright (C) 2009-2011 Alexey Yakovenko <waker@users.sourceforge.net>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+#include "playlist.h"
+#include "volume.h"
+#include "replaygain.h"
+
+static int conf_replaygain_mode = 0;
+static int conf_replaygain_scale = 1;
+
+
+void
+replaygain_apply (ddb_waveformat_t *fmt, playItem_t *it, char *bytes, int bytesread) {
+ // FIXME: separate replaygain DSP plugin?
+ if (fmt->bps == 16) {
+ apply_replay_gain_int16 (it, bytes, bytesread);
+ }
+ else if (fmt->bps == 24) {
+ apply_replay_gain_int24 (it, bytes, bytesread);
+ }
+ else if (fmt->bps == 8) {
+ apply_replay_gain_int16 (it, bytes, bytesread);
+ }
+ else if (fmt->bps == 32 && !fmt->is_float) {
+ apply_replay_gain_int32 (it, bytes, bytesread);
+ }
+ else if (fmt->bps == 32 && fmt->is_float) {
+ apply_replay_gain_float32 (it, bytes, bytesread);
+ }
+}
+
+void
+replaygain_set (int mode, int scale) {
+ conf_replaygain_mode = mode;
+ conf_replaygain_scale = scale;
+}
+
+void
+apply_replay_gain_int8 (playItem_t *it, char *bytes, int size) {
+ if (!conf_replaygain_mode) {
+ return;
+ }
+ int vol = 1000;
+ if (conf_replaygain_mode == 1) {
+ if (it->replaygain_track_gain == 0) {
+ return;
+ }
+ vol = db_to_amp (it->replaygain_track_gain) * 1000;
+ if (conf_replaygain_scale) {
+ if (vol * it->replaygain_track_peak > 1000) {
+ vol = 1000 / it->replaygain_track_peak;
+ }
+ }
+ }
+ else if (conf_replaygain_mode == 2) {
+ if (it->replaygain_album_gain == 0) {
+ return;
+ }
+ vol = db_to_amp (it->replaygain_album_gain) * 1000;
+ if (conf_replaygain_scale) {
+ if (vol * it->replaygain_album_peak > 1000) {
+ vol = 1000 / it->replaygain_album_peak;
+ }
+ }
+ }
+ int8_t *s = (int8_t*)bytes;
+ for (int j = 0; j < size; j++) {
+ int32_t sample = ((int8_t)(*s)) * vol / 1000;
+ if (sample > 0x7f) {
+ sample = 0x7f;
+ }
+ else if (sample < -0x80) {
+ sample = -0x80;
+ }
+ *s = (int8_t)sample;
+ s++;
+ }
+}
+
+void
+apply_replay_gain_int16 (playItem_t *it, char *bytes, int size) {
+ if (!conf_replaygain_mode) {
+ return;
+ }
+ int vol = 1000;
+ if (conf_replaygain_mode == 1) {
+ if (it->replaygain_track_gain == 0) {
+ return;
+ }
+ vol = db_to_amp (it->replaygain_track_gain) * 1000;
+ if (conf_replaygain_scale) {
+ if (vol * it->replaygain_track_peak > 1000) {
+ vol = 1000 / it->replaygain_track_peak;
+ }
+ }
+ }
+ else if (conf_replaygain_mode == 2) {
+ if (it->replaygain_album_gain == 0) {
+ return;
+ }
+ vol = db_to_amp (it->replaygain_album_gain) * 1000;
+ if (conf_replaygain_scale) {
+ if (vol * it->replaygain_album_peak > 1000) {
+ vol = 1000 / it->replaygain_album_peak;
+ }
+ }
+ }
+ int16_t *s = (int16_t*)bytes;
+ for (int j = 0; j < size/2; j++) {
+ int32_t sample = ((int32_t)(*s)) * vol / 1000;
+ if (sample > 0x7fff) {
+ sample = 0x7fff;
+ }
+ else if (sample < -0x8000) {
+ sample = -0x8000;
+ }
+ *s = (int16_t)sample;
+ s++;
+ }
+}
+
+void
+apply_replay_gain_int24 (playItem_t *it, char *bytes, int size) {
+ if (!conf_replaygain_mode) {
+ return;
+ }
+ int64_t vol = 1000;
+ if (conf_replaygain_mode == 1) {
+ if (it->replaygain_track_gain == 0) {
+ return;
+ }
+ vol = db_to_amp (it->replaygain_track_gain) * 1000;
+ if (conf_replaygain_scale) {
+ if (vol * it->replaygain_track_peak > 1000) {
+ vol = 1000 / it->replaygain_track_peak;
+ }
+ }
+ }
+ else if (conf_replaygain_mode == 2) {
+ if (it->replaygain_album_gain == 0) {
+ return;
+ }
+ vol = db_to_amp (it->replaygain_album_gain) * 1000;
+ if (conf_replaygain_scale) {
+ if (vol * it->replaygain_album_peak > 1000) {
+ vol = 1000 / it->replaygain_album_peak;
+ }
+ }
+ }
+ char *s = (char*)bytes;
+ for (int j = 0; j < size/3; j++) {
+ int32_t sample = ((unsigned char)s[0]) | ((unsigned char)s[1]<<8) | (s[2]<<16);
+ sample = sample * vol / 1000;
+ if (sample > 0x7fffff) {
+ sample = 0x7fffff;
+ }
+ else if (sample < -0x800000) {
+ sample = -0x800000;
+ }
+ s[0] = (sample&0x0000ff);
+ s[1] = (sample&0x00ff00)>>8;
+ s[2] = (sample&0xff0000)>>16;
+ s += 3;
+ }
+}
+
+void
+apply_replay_gain_int32 (playItem_t *it, char *bytes, int size) {
+ if (!conf_replaygain_mode) {
+ return;
+ }
+ int64_t vol = 1000;
+ if (conf_replaygain_mode == 1) {
+ if (it->replaygain_track_gain == 0) {
+ return;
+ }
+ vol = db_to_amp (it->replaygain_track_gain) * 1000;
+ if (conf_replaygain_scale) {
+ if (vol * it->replaygain_track_peak > 1000) {
+ vol = 1000 / it->replaygain_track_peak;
+ }
+ }
+ }
+ else if (conf_replaygain_mode == 2) {
+ if (it->replaygain_album_gain == 0) {
+ return;
+ }
+ vol = db_to_amp (it->replaygain_album_gain) * 1000;
+ if (conf_replaygain_scale) {
+ if (vol * it->replaygain_album_peak > 1000) {
+ vol = 1000 / it->replaygain_album_peak;
+ }
+ }
+ }
+ int32_t *s = (int32_t*)bytes;
+ for (int j = 0; j < size/4; j++) {
+ int64_t sample = ((int32_t)(*s)) * vol / 1000;
+ if (sample > 0x7fffffff) {
+ sample = 0x7fffffff;
+ }
+ else if (sample < -0x80000000) {
+ sample = -0x80000000;
+ }
+ *s = (int32_t)sample;
+ s++;
+ }
+}
+
+void
+apply_replay_gain_float32 (playItem_t *it, char *bytes, int size) {
+ if (!conf_replaygain_mode) {
+ return;
+ }
+ float vol = 1.f;
+ if (conf_replaygain_mode == 1) {
+ if (it->replaygain_track_gain == 0) {
+ return;
+ }
+ vol = db_to_amp (it->replaygain_track_gain);
+ if (conf_replaygain_scale) {
+ if (vol * it->replaygain_track_peak > 1.f) {
+ vol = 1.f / it->replaygain_track_peak;
+ }
+ }
+ }
+ else if (conf_replaygain_mode == 2) {
+ if (it->replaygain_album_gain == 0) {
+ return;
+ }
+ vol = db_to_amp (it->replaygain_album_gain);
+ if (conf_replaygain_scale) {
+ if (vol * it->replaygain_album_peak > 1.f) {
+ vol = 1.f / it->replaygain_album_peak;
+ }
+ }
+ }
+ float *s = (float*)bytes;
+ for (int j = 0; j < size/4; j++) {
+ float sample = ((float)*s) * vol;
+ if (sample > 1.f) {
+ sample = 1.f;
+ }
+ else if (sample < -1.f) {
+ sample = -1.f;
+ }
+ *s = sample;
+ s++;
+ }
+}