aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2009-01-03 14:51:47 +0100
committerMax Kellermann <max@duempel.org>2009-01-13 23:09:19 +0100
commita0141dbe4f868413d78c94737846279124415479 (patch)
treee917b22e3eced7f9a8d9a4fa9e1121b899246a86
parentd93477d1369e55d76476952f30463461e47af443 (diff)
downloadmpd-a0141dbe4f868413d78c94737846279124415479.tar.gz
mpd-a0141dbe4f868413d78c94737846279124415479.tar.xz
mpd-a0141dbe4f868413d78c94737846279124415479.zip
pcm_utils: use the custom PRNG for volume dithering
Don't use libc's rand() function, because it is slow. Our own trivial linear congruential generator is good enough for dithering.
-rw-r--r--NEWS1
-rw-r--r--src/Makefile.am1
-rw-r--r--src/pcm_dither.c6
-rw-r--r--src/pcm_prng.h31
-rw-r--r--src/pcm_utils.c8
5 files changed, 41 insertions, 6 deletions
diff --git a/NEWS b/NEWS
index 8d3a37f1c..e9959c157 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,7 @@ MPD 0.14.1 - not yet released
* fix minor memory leak in decoder_tag()
* fix cross-fading bug: it used to play some chunks of the new song twice
* playlist: fix assertion failure during playlist load
+* use custom PRNG for volume dithering (speedup)
* detect libid3tag without pkg-config
diff --git a/src/Makefile.am b/src/Makefile.am
index ad4ad99f3..0699be50e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -53,6 +53,7 @@ mpd_headers = \
pcm_channels.h \
pcm_resample.h \
pcm_dither.h \
+ pcm_prng.h \
permission.h \
player_thread.h \
player_control.h \
diff --git a/src/pcm_dither.c b/src/pcm_dither.c
index 1296d0926..984949685 100644
--- a/src/pcm_dither.c
+++ b/src/pcm_dither.c
@@ -17,11 +17,7 @@
*/
#include "pcm_dither.h"
-
-static unsigned long prng(unsigned long state)
-{
- return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
-}
+#include "pcm_prng.h"
static int16_t
pcm_dither_sample_24_to_16(int32_t sample, struct pcm_dither_24 *dither)
diff --git a/src/pcm_prng.h b/src/pcm_prng.h
new file mode 100644
index 000000000..e961baacd
--- /dev/null
+++ b/src/pcm_prng.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2003-2009 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PCM_PRNG_H
+#define PCM_PRNG_H
+
+/**
+ * A very simple linear congruential PRNG. It's good enough for PCM
+ * dithering.
+ */
+static unsigned long prng(unsigned long state)
+{
+ return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
+}
+
+#endif
diff --git a/src/pcm_utils.c b/src/pcm_utils.c
index f73df8aef..3ce9b5fd0 100644
--- a/src/pcm_utils.c
+++ b/src/pcm_utils.c
@@ -18,6 +18,7 @@
#include "pcm_utils.h"
#include "pcm_channels.h"
+#include "pcm_prng.h"
#include "log.h"
#include "utils.h"
#include "conf.h"
@@ -31,7 +32,12 @@
static inline int
pcm_dither(void)
{
- return (rand() & 511) - (rand() & 511);
+ static unsigned long state;
+ uint32_t r;
+
+ r = state = prng(state);
+
+ return (r & 511) - ((r >> 9) & 511);
}
/**