aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/audio.c9
-rw-r--r--src/pcm_utils.c92
-rw-r--r--src/player.c2
-rw-r--r--src/playerData.c2
-rw-r--r--src/replayGain.c47
-rw-r--r--src/replayGain.h2
-rw-r--r--src/volume.c4
7 files changed, 90 insertions, 68 deletions
diff --git a/src/audio.c b/src/audio.c
index 1bcd24de6..d622d45df 100644
--- a/src/audio.c
+++ b/src/audio.c
@@ -107,16 +107,11 @@ void initAudioDriver() {
void getInternalAudioFormat(AudioFormat * inAudioFormat,
AudioFormat * outAudioFormat)
{
- /*TODO add #define for integer version */
-
/* take the input format... */
copyAudioFormat(outAudioFormat,inAudioFormat);
- /* .. change to 32 bit integers with 28 bit resolution */
+ /* .. change to 32 bit integers with 28 bit fractional part */
outAudioFormat->bits = 32;
outAudioFormat->fracBits = 28;
- /* if forced output sample rate - use that as internal sample rate */
- if(audio_configFormat && (audio_configFormat->sampleRate != 0))
- outAudioFormat->sampleRate = audio_configFormat->sampleRate;
}
void getOutputAudioFormat(AudioFormat * inAudioFormat,
@@ -208,7 +203,7 @@ int parseAudioConfig(AudioFormat * audioFormat, char * conf) {
return -1;
}
- /* audioFormat is never shifted */
+ /* The output audio format is never shifted */
audioFormat->fracBits = 0;
return 0;
diff --git a/src/pcm_utils.c b/src/pcm_utils.c
index e92089f31..8454c8871 100644
--- a/src/pcm_utils.c
+++ b/src/pcm_utils.c
@@ -78,12 +78,16 @@ void pcm_convertToIntWithDither(int bits,
const mpd_fixed_t max = (1L << (fracBits)) - 1;
const mpd_fixed_t min = ~0L << (fracBits);
mpd_fixed_t sample;
+
/* need to split in two cases to avoid negative shifting */
if(bits>fracBits) {
/* left shift - no need to dither */
while(samples--) {
sample = *buffer;
- sample = sample>max ? max : (sample<min ? min : sample);
+ if(sample>max)
+ sample = max;
+ else if(sample<min)
+ sample = min;
*buffer++ = sample << (bits - fracBits - 1);
}
}
@@ -92,7 +96,10 @@ void pcm_convertToIntWithDither(int bits,
while(samples--) {
sample = *buffer + half + (ditherRandom[0] & mask) -
(ditherRandom[1] & mask);
- sample = sample>max ? max : (sample<min ? min : sample);
+ if(sample>max)
+ sample = max;
+ else if(sample<min)
+ sample = min;
*buffer++ = sample >> (fracBits - bits + 1);
ditherRandom[1] = ditherRandom[0] >> 1;
ditherRandom[0] = prng(ditherRandom[0]);
@@ -232,47 +239,52 @@ void pcm_volumeChange(char * buffer, int bufferSize, AudioFormat * format,
int volume)
{
mpd_fixed_t * buffer32 = (mpd_fixed_t *)buffer;
- int iScale;
- int samples;
- int shift;
+ int samples = bufferSize >> 2;
+ static int iScale;
+ static int shift;
+ static int currentVolume = -1;
if(format->bits!=32 || format->fracBits == 0) {
- ERROR("Only 32 bit mpd_fixed_t samples are supported in pcm_volumeChange!\n");
+ ERROR("Only 32 bit mpd_fixed_t samples are supported in"
+ " pcm_volumeChange!\n");
exit(EXIT_FAILURE);
}
/* take care of full and no volume cases */
- if(volume>=1000) return;
+ if(volume>=1024) return;
if(volume<=0) {
memset(buffer,0,bufferSize);
return;
}
- /****** change volume ******/
- samples = bufferSize >> 2;
- iScale = (mpd_uint32)(volume * 256) / 1000;
- shift = 8;
-
- /* lower shifting value as much as possible */
- while(!(iScale & 1) && shift) {
- iScale >>= 1;
- shift--;
+ /* recalculate if volume has changed */
+ if(volume != currentVolume) {
+ currentVolume = volume;
+ iScale = volume;
+ shift = 10;
+
+ /* Minimize values to get the precision loss as small as
+ * possible in the integer calculations. Make iScale less
+ * then 5 bits. This results in a volume change precision
+ * of approx. 0.5dB */
+ while((iScale>31 || !(iScale & 1)) && shift) {
+ iScale >>= 1;
+ shift--;
+ }
}
- /* change */
- if(iScale == 1) {
+
+ /* change the volume */
+ if(iScale == 1)
while(samples--) {
*buffer32 = *buffer32 >> shift;
buffer32++;
}
- }
- else {
+ else
while(samples--) {
*buffer32 = (*buffer32 >> shift) * iScale;
buffer32++;
}
- }
-
}
void pcm_add(char * buffer1, char * buffer2, size_t bufferSize1,
@@ -281,29 +293,33 @@ void pcm_add(char * buffer1, char * buffer2, size_t bufferSize1,
mpd_fixed_t * buffer32_1 = (mpd_fixed_t *)buffer1;
mpd_fixed_t * buffer32_2 = (mpd_fixed_t *)buffer2;
mpd_fixed_t temp;
- int samples1;
- int samples2;
- int iScale1;
- int iScale2;
- int shift;
+ int samples1 = bufferSize1 >> 2;
+ int samples2 = bufferSize2 >> 2;
+ int iScale1 = vol1 >> 2;
+ int iScale2 = vol2 >> 2;
+ int shift = 8;
if(format->bits!=32 || format->fracBits==0 ) {
- ERROR("Only 32 bit mpd_fixed_t samples are supported in pcm_add!\n");
+ ERROR("Only 32 bit mpd_fixed_t samples are supported in"
+ " pcm_add!\n");
exit(EXIT_FAILURE);
}
- samples1 = bufferSize1 >> 2;
- samples2 = bufferSize1 >> 2;
- iScale1 = (mpd_uint32)(vol1 * 256) / 1000;
- iScale2 = (mpd_uint32)(vol2 * 256) / 1000;
- shift = 8;
-
+ /* lower iScale to minimize audio resolution loss */
+ /* as long as it can be done without loss */
+ while(!(iScale1 & 1) && !(iScale2 & 1) && shift) {
+ iScale1 >>= 1;
+ iScale2 >>= 1;
+ shift--;
+ }
+
/* scale and add samples */
/* no check for overflow needed - we trust our headroom is enough */
while(samples1 && samples2) {
temp = (*buffer32_1 >> shift) * iScale1 +
(*buffer32_2 >> shift) * iScale2;
- *buffer32_1++ = temp;
+ *buffer32_1 = temp;
+ buffer32_1++;
buffer32_2++;
}
/* take care of case where buffer2 > buffer1 */
@@ -319,10 +335,10 @@ void pcm_mix(char * buffer1, char * buffer2, size_t bufferSize1,
float s = sin(M_PI_2*portion1);
s*=s;
- vol1 = s*1000+0.5;
- vol1 = vol1>1000 ? 1000 : ( vol1<0 ? 0 : vol1 );
+ vol1 = s*1024+0.5;
+ vol1 = vol1>1024 ? 1024 : ( vol1<0 ? 0 : vol1 );
- pcm_add(buffer1,buffer2,bufferSize1,bufferSize2,vol1,1000-vol1,format);
+ pcm_add(buffer1,buffer2,bufferSize1,bufferSize2,vol1,1024-vol1,format);
}
diff --git a/src/player.c b/src/player.c
index e398323e8..d0d9a2764 100644
--- a/src/player.c
+++ b/src/player.c
@@ -417,7 +417,7 @@ void setPlayerCrossFade(float crossFadeInSeconds) {
void setPlayerSoftwareVolume(int volume) {
PlayerControl * pc;
- volume = (volume>1000) ? 1000 : (volume<0 ? 0 : volume);
+ volume = (volume>1024) ? 1024 : (volume<0 ? 0 : volume);
pc = &(getPlayerData()->playerControl);
diff --git a/src/playerData.c b/src/playerData.c
index 281453548..c9472a5bd 100644
--- a/src/playerData.c
+++ b/src/playerData.c
@@ -129,7 +129,7 @@ void initPlayerData() {
memset(playerData_pd->playerControl.erroredUrl, 0, MAXPATHLEN+1);
memset(playerData_pd->playerControl.currentUrl, 0, MAXPATHLEN+1);
playerData_pd->playerControl.crossFade = crossfade;
- playerData_pd->playerControl.softwareVolume = 1000;
+ playerData_pd->playerControl.softwareVolume = 1024;
playerData_pd->playerControl.totalPlayTime = 0;
playerData_pd->playerControl.decode_pid = 0;
playerData_pd->playerControl.metadataState =
diff --git a/src/replayGain.c b/src/replayGain.c
index ace70b0e5..308ea7054 100644
--- a/src/replayGain.c
+++ b/src/replayGain.c
@@ -108,17 +108,18 @@ void doReplayGain(ReplayGainInfo * info, char * buffer, int bufferSize,
AudioFormat * format)
{
mpd_sint32 * buffer32 = (mpd_sint32 *)buffer;
- int samples;
- int shift;
- int iScale;
+ int samples = bufferSize >> 2;
+ int iScale = info->iScale;
+ int shift = info->shift;
- if(format->bits!=32 || format->channels!=2 ) {
- ERROR("Only 32 bit stereo is supported for doReplayGain!\n");
+ if(replayGainState == REPLAYGAIN_OFF || !info) return;
+
+ if(format->bits!=32 || format->fracBits==0 ) {
+ ERROR("Only 32 bit mpd_fixed_t samples are supported in"
+ " doReplayGain!\n");
exit(EXIT_FAILURE);
return;
}
-
- if(replayGainState == REPLAYGAIN_OFF || !info) return;
if(info->scale < 0) {
switch(replayGainState) {
@@ -131,13 +132,26 @@ void doReplayGain(ReplayGainInfo * info, char * buffer, int bufferSize,
info->albumPeak);
break;
}
- }
+
+ /* Calculate integer scale and shift to use in
+ * integer calculations. Make iScale as small as
+ * possible and no more then 5 bits. This gives a
+ * precision of approx. 0.5 dB */
+ iScale = info->scale * 1024;
+ shift = 10;
- samples = bufferSize >> 2;
- /* 64 steps is enough - gives 0.13db resolution at 0dB and 2.5dB at -25dB*/
- iScale = info->scale * 64;
- shift = 6;
+ while((iScale>31 || !(iScale & 1)) && shift) {
+ iScale >>= 1;
+ shift--;
+ }
+ info->iScale = iScale;
+ info->shift = shift;
+
+ /*ERROR("Info: ReplayGain scale %f gives iScale=%i and shift=%i"
+ " resulting in %f\n",
+ info->scale, iScale, shift, (float)iScale / (1<<shift));*/
+ }
/* handle negative or zero scale */
if(iScale<=0) {
@@ -145,14 +159,9 @@ void doReplayGain(ReplayGainInfo * info, char * buffer, int bufferSize,
return;
}
- /* lower shift value as much as possible */
- while(!(iScale & 1) && shift) {
- iScale >>= 1;
- shift--;
- }
-
+
/* change samples */
- /* no check for overflow needed - replaygain peak info prevent
+ /* no overflow check needed - replaygain peak info prevent
* clipping and we have 3 headroom bits in our 32 bit samples */
if(iScale == 1) {
while(samples--) {
diff --git a/src/replayGain.h b/src/replayGain.h
index 112034fbe..22728ef2d 100644
--- a/src/replayGain.h
+++ b/src/replayGain.h
@@ -34,6 +34,8 @@ typedef struct _ReplayGainInfo {
/* used internally by mpd, to mess with it*/
float scale;
+ int iScale;
+ int shift;
} ReplayGainInfo;
ReplayGainInfo * newReplayGainInfo();
diff --git a/src/volume.c b/src/volume.c
index c16938042..b99bd9156 100644
--- a/src/volume.c
+++ b/src/volume.c
@@ -433,9 +433,9 @@ int changeSoftwareVolume(FILE * fp, int change, int rel) {
volume_softwareSet = new;
/*new = 100.0*(exp(new/50.0)-1)/(M_E*M_E-1)+0.5;*/
- if(new>=100) new = 1000;
+ if(new>=100) new = 1024;
else if(new<=0) new = 0;
- else new = 1000.0*(exp(new/25.0)-1)/(54.5981500331F-1)+0.5;
+ else new = 1024.0*(exp(new/25.0)-1)/(54.5981500331F-1)+0.5;
setPlayerSoftwareVolume(new);