summaryrefslogtreecommitdiff
path: root/streamer.c
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <wakeroid@gmail.com>2009-09-23 23:14:17 +0200
committerGravatar Alexey Yakovenko <wakeroid@gmail.com>2009-09-23 23:14:17 +0200
commit90459ab8f2d1086fd2f164fd8a3f161708febb8a (patch)
treeeffd2bdb51bcda7c2364a24bd0f629c54eaa5c98 /streamer.c
parentf91d372e4c3d08d59b6633560af491d56608cfcc (diff)
replaygain (experimental)
Diffstat (limited to 'streamer.c')
-rw-r--r--streamer.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/streamer.c b/streamer.c
index dd53fa6b..ceba12d7 100644
--- a/streamer.c
+++ b/streamer.c
@@ -34,6 +34,7 @@
#include "conf.h"
#include "plugins.h"
#include "optmath.h"
+#include "volume.h"
static intptr_t streamer_tid;
static SRC_STATE *src;
@@ -371,6 +372,52 @@ streamer_reset (int full) { // must be called when current song changes by exter
src_reset (src);
}
+int replaygain = 0;
+
+static void
+apply_replay_gain_int16 (playItem_t *it, char *bytes, int size) {
+ if (!replaygain) {
+ return;
+ }
+ if (it->replaygain_track_gain != 0) {
+ int vol = db_to_amp (str_streaming_song.replaygain_track_gain) * 1000;
+ 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) {
+ return;
+ }
+ if (it->replaygain_track_gain != 0) {
+ float vol = db_to_amp (str_streaming_song.replaygain_track_gain);
+ 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++;
+ }
+ }
+}
+
// returns number of bytes been read
static int
streamer_read_async (char *bytes, int size) {
@@ -393,10 +440,12 @@ streamer_read_async (char *bytes, int size) {
if (decoder->info.channels == 2) {
bytesread = decoder->read_int16 (bytes, size);
codec_unlock ();
+ apply_replay_gain_int16 (&str_streaming_song, bytes, size);
}
else {
bytesread = decoder->read_int16 (g_readbuffer, size/2);
codec_unlock ();
+ apply_replay_gain_int16 (&str_streaming_song, g_readbuffer, size/2);
for (i = 0; i < size/4; i++) {
int16_t sample = (int16_t)(((int32_t)(((int16_t*)g_readbuffer)[i])));
((int16_t*)bytes)[i*2+0] = sample;
@@ -426,6 +475,7 @@ streamer_read_async (char *bytes, int size) {
// }
if (!decoder->read_float32) {
bytesread = decoder->read_int16 (g_readbuffer, nbytes);
+ apply_replay_gain_int16 (&str_streaming_song, g_readbuffer, nbytes/2);
}
else {
samplesize = 4;
@@ -457,6 +507,7 @@ streamer_read_async (char *bytes, int size) {
codec_lock ();
bytesread = decoder->read_float32 (g_readbuffer, nbytes*2);
codec_unlock ();
+ apply_replay_gain_float32 (&str_streaming_song, g_readbuffer, nbytes*2);
nsamples = bytesread / (samplesize * nchannels) + codecleft;
for (i = 0; i < (nsamples - codecleft); i++) {
fbuffer[i*2+0] = ((float *)g_readbuffer)[i];
@@ -467,6 +518,7 @@ streamer_read_async (char *bytes, int size) {
codec_lock ();
bytesread = decoder->read_float32 ((char *)fbuffer, nbytes*2);
codec_unlock ();
+ apply_replay_gain_float32 (&str_streaming_song, (char *)fbuffer, nbytes*2);
nsamples = bytesread / (samplesize * nchannels) + codecleft;
}
}