Fix the software-volume control dither algorithm, which was (a) broken [by me] and (b) not best practice anyway.

This commit is contained in:
Mike Brady
2015-11-26 17:32:08 +00:00
parent 223d52144e
commit c15c49fd2e
2 changed files with 53 additions and 2 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.50])
AC_INIT([shairport-sync], [2.7.2], [mikebrady@eircom.net])
AC_INIT([shairport-sync], [2.7.3], [mikebrady@eircom.net])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([shairport.c])
AC_CONFIG_HEADERS([config.h])
+52 -1
View File
@@ -373,18 +373,68 @@ void player_put_packet(seq_t seqno, uint32_t timestamp, uint8_t *data, int len)
pthread_mutex_unlock(&ab_mutex);
}
int32_t rand_in_range(int32_t exclusive_range_limit) {
static uint32_t lcg_prev = 12345;
// returns a pseudo random integer in the range 0 to (exclusive_range_limit-1) inclusive
int64_t sp = lcg_prev;
int64_t rl = exclusive_range_limit;
lcg_prev = lcg_prev * 69069 + 3; // crappy psrg
sp = sp*rl; // 64 bit calculation. INtersting part if above the 32 rightmost bits;
return sp >> 32;
}
static inline short dithered_vol(short sample) {
int32_t out;
out = (int32_t)sample * fix_volume;
if (fix_volume < 0x10000) {
// add a TPDF dither -- see http://www.users.qwest.net/%7Evolt42/cadenzarecording/DitherExplained.pdf
// and the discussion around https://www.hydrogenaud.io/forums/index.php?showtopic=16963&st=25
// I think, for a 32 --> 16 bits, the range of
// random numbers needs to be from -2^16 to 2^16, i.e. from -65536 to 65536 inclusive, not from -32768 to +32767
// See the original paper at http://www.ece.rochester.edu/courses/ECE472/resources/Papers/Lipshitz_1992.pdf
// by Lipshitz, Wannamaker and Vanderkooy, 1992.
int32_t tpdf = rand_in_range(65536+1) - rand_in_range(65536+1);
// Check there's no clipping -- if there is,
if (tpdf>=0) {
if (LONG_MAX-tpdf>=out)
out += tpdf;
else
out = LONG_MAX;
} else {
if (LONG_MIN-tpdf<=out)
out += tpdf;
else
out = LONG_MIN;
}
}
return out >> 16;
}
/*
static inline short lcg_rand(void) {
static unsigned long lcg_prev = 12345;
lcg_prev = lcg_prev * 69069 + 3;
return lcg_prev & 0xffff;
}
static inline short dithered_vol(short sample) {
short rand_a, rand_b;
static short rand_a;
short rand_b;
long out;
out = (long)sample * fix_volume;
if (fix_volume < 0x10000) {
// add a TPDF dither -- see http://www.users.qwest.net/%7Evolt42/cadenzarecording/DitherExplained.pdf
// and the discussion around https://www.hydrogenaud.io/forums/index.php?showtopic=16963&st=25
// I think it's wrong. I think, for a 32 --> 16 bits, the range of
// random numbers needs to be from 0 to 2^16, i.e. from 0 to 65536, not from -32768bto +32767
rand_b = rand_a;
rand_a = lcg_rand();
out += rand_a;
@@ -392,6 +442,7 @@ static inline short dithered_vol(short sample) {
}
return out >> 16;
}
*/
// get the next frame, when available. return 0 if underrun/stream reset.
static abuf_t *buffer_get_frame(void) {