diff options
author | waker <wakeroid@gmail.com> | 2011-02-24 21:30:06 +0100 |
---|---|---|
committer | waker <wakeroid@gmail.com> | 2011-02-24 21:30:06 +0100 |
commit | f4b6e6a0aa2894025b6fe87a282a9988a1a9e341 (patch) | |
tree | 1f711b16a8f1f03d67d09257505b4005f831f6cc /replaygain.c | |
parent | c05c4393fc9bc38f73961afe67b0b950ccec328e (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.c | 265 |
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++; + } +} |