Avoid wrapping when shifting down the audio after scaling by a 20-bit value. Fixes #9967

This commit is contained in:
Henrik Rydgård 2017-11-30 18:22:25 +01:00
parent d884eeda99
commit 407812916d
3 changed files with 31 additions and 7 deletions

View File

@ -37,7 +37,10 @@ void AdjustVolumeBlockStandard(s16 *out, s16 *in, size_t size, int leftVol, int
out += 16;
size -= 16;
}
} else {
}
#if 0
// This path wraps instead of clamps in _mm_slli_epi16. Needs fixing.
else {
// We have to shift inside the loop to avoid the signed 16-bit multiply issue.
int leftShift = 0;
int leftVol16 = leftVol;
@ -63,9 +66,17 @@ void AdjustVolumeBlockStandard(s16 *out, s16 *in, size_t size, int leftVol, int
}
}
#endif
for (size_t i = 0; i < size; i += 2) {
out[i] = ApplySampleVolume(in[i], leftVol);
out[i + 1] = ApplySampleVolume(in[i + 1], rightVol);
#endif
if (leftVol <= 0x7fff && -leftVol <= 0x8000 && rightVol <= 0x7fff && -rightVol <= 0x8000) {
for (size_t i = 0; i < size; i += 2) {
out[i] = ApplySampleVolume(in[i], leftVol);
out[i + 1] = ApplySampleVolume(in[i + 1], rightVol);
}
} else {
for (size_t i = 0; i < size; i += 2) {
out[i] = ApplySampleVolume20Bit(in[i], leftVol);
out[i + 1] = ApplySampleVolume20Bit(in[i + 1], rightVol);
}
}
}

View File

@ -59,6 +59,12 @@ static inline s16 ApplySampleVolume(s16 sample, int vol) {
#endif
}
// We sacrifice a little volume precision to fit in 32 bits, for speed.
// Probably not worth it to make a special path for 64-bit CPUs.
static inline s16 ApplySampleVolume20Bit(s16 sample, int vol20) {
return clamp_s16((sample * (vol20 >> 4)) >> 12);
}
void SetupAudioFormats();
void AdjustVolumeBlockStandard(s16 *out, s16 *in, size_t size, int leftVol, int rightVol);
void ConvertS16ToF32(float *ou, const s16 *in, size_t size);

View File

@ -58,9 +58,16 @@ void AdjustVolumeBlockNEON(s16 *out, s16 *in, size_t size, int leftVol, int righ
}
}
for (size_t i = 0; i < size; i += 2) {
out[i] = ApplySampleVolume(in[i], leftVol);
out[i + 1] = ApplySampleVolume(in[i + 1], rightVol);
if (leftVol <= 0x7fff && -leftVol <= 0x8000 && rightVol <= 0x7fff && -rightVol <= 0x8000) {
for (size_t i = 0; i < size; i += 2) {
out[i] = ApplySampleVolume(in[i], leftVol);
out[i + 1] = ApplySampleVolume(in[i + 1], rightVol);
}
} else {
for (size_t i = 0; i < size; i += 2) {
out[i] = ApplySampleVolume20Bit(in[i], leftVol);
out[i + 1] = ApplySampleVolume20Bit(in[i + 1], rightVol);
}
}
}