diff options
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | replaygain.c | 265 | ||||
-rw-r--r-- | replaygain.h | 45 | ||||
-rw-r--r-- | streamer.c | 105 |
4 files changed, 316 insertions, 102 deletions
diff --git a/Makefile.am b/Makefile.am index 8977b4b5..e6ed3fd1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -33,7 +33,8 @@ deadbeef_SOURCES =\ metacache.c metacache.h\ gettext.h\ ringbuf.c ringbuf.h\ - dsppreset.c dsppreset.h + dsppreset.c dsppreset.h\ + replaygain.c replaygain.h sdkdir = $(pkgincludedir) sdk_HEADERS = deadbeef.h 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++; + } +} diff --git a/replaygain.h b/replaygain.h new file mode 100644 index 00000000..5169c99c --- /dev/null +++ b/replaygain.h @@ -0,0 +1,45 @@ +/* + 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. +*/ +#ifndef __REPLAYGAIN_H +#define __REPLAYGAIN_H + +#include "deadbeef.h" + +void +replaygain_apply (ddb_waveformat_t *fmt, playItem_t *it, char *bytes, int bytesread); + +void +replaygain_set (int mode, int scale); + +void +apply_replay_gain_int8 (playItem_t *it, char *bytes, int size); + +void +apply_replay_gain_int16 (playItem_t *it, char *bytes, int size); + +void +apply_replay_gain_int24 (playItem_t *it, char *bytes, int size); + +void +apply_replay_gain_int32 (playItem_t *it, char *bytes, int size); + +void +apply_replay_gain_float32 (playItem_t *it, char *bytes, int size); + +#endif @@ -36,6 +36,7 @@ #include "vfs.h" #include "premix.h" #include "ringbuf.h" +#include "replaygain.h" //#define trace(...) { fprintf(stderr, __VA_ARGS__); } #define trace(fmt,...) @@ -62,9 +63,6 @@ static ddb_dsp_context_t *eq; static int dsp_on = 0; -static int conf_replaygain_mode = 0; -static int conf_replaygain_scale = 1; - static int streaming_terminate; // buffer up to 3 seconds at 44100Hz stereo @@ -1377,8 +1375,7 @@ streamer_init (void) { streamer_dsp_init (); - conf_replaygain_mode = conf_get_int ("replaygain_mode", 0); - conf_replaygain_scale = conf_get_int ("replaygain_scale", 1); + replaygain_set (conf_get_int ("replaygain_mode", 0), conf_get_int ("replaygain_scale", 1)); streamer_tid = thread_start (streamer_thread, NULL); return 0; } @@ -1442,93 +1439,6 @@ streamer_reset (int full) { // must be called when current song changes by exter } } -int replaygain = 1; -int replaygain_scale = 1; - -static void -apply_replay_gain_int16 (playItem_t *it, char *bytes, int size) { - if (!replaygain || !conf_replaygain_mode) { - return; - } - int vol = 1000; - if (conf_replaygain_mode == 1) { - if (it->replaygain_track_gain == 0) { - return; - } - vol = db_to_amp (streaming_track->replaygain_track_gain) * 1000; - if (conf_replaygain_scale && replaygain_scale) { - if (vol * streaming_track->replaygain_track_peak > 1000) { - vol = 1000 / streaming_track->replaygain_track_peak; - } - } - } - else if (conf_replaygain_mode == 2) { - if (it->replaygain_album_gain == 0) { - return; - } - vol = db_to_amp (streaming_track->replaygain_album_gain) * 1000; - if (conf_replaygain_scale && replaygain_scale) { - if (vol * streaming_track->replaygain_album_peak > 1000) { - vol = 1000 / streaming_track->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++; - } -} - -static void -apply_replay_gain_float32 (playItem_t *it, char *bytes, int size) { - if (!replaygain || !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 && 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 && 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++; - } -} - static int streamer_set_output_format (void) { DB_output_t *output = plug_get_output (); @@ -1653,13 +1563,7 @@ streamer_read_async (char *bytes, int size) { } #endif - // FIXME: separate replaygain DSP plugin? - if (output->fmt.bps == 16) { - apply_replay_gain_int16 (streaming_track, bytes, bytesread); - } - else if (output->fmt.bps == 32 && output->fmt.is_float) { - apply_replay_gain_float32 (streaming_track, bytes, bytesread); - } + replaygain_apply (&output->fmt, streaming_track, bytes, bytesread); } mutex_unlock (decodemutex); if (!is_eof) { @@ -1814,8 +1718,7 @@ streamer_ok_to_read (int len) { void streamer_configchanged (void) { - conf_replaygain_mode = conf_get_int ("replaygain_mode", 0); - conf_replaygain_scale = conf_get_int ("replaygain_scale", 1); + replaygain_set (conf_get_int ("replaygain_mode", 0), conf_get_int ("replaygain_scale", 1)); pl_set_order (conf_get_int ("playback.order", 0)); if (playing_track) { playing_track->played = 1; |