From f4b6e6a0aa2894025b6fe87a282a9988a1a9e341 Mon Sep 17 00:00:00 2001 From: waker Date: Thu, 24 Feb 2011 21:30:06 +0100 Subject: moved replaygain code to separate file; added support for applying replaygain to 8, 24 and 32 bit int streams --- replaygain.c | 265 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 265 insertions(+) create mode 100644 replaygain.c (limited to 'replaygain.c') 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 + + 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++; + } +} -- cgit v1.2.3