浏览代码

LibAudio: Correctly rescale 8-bit PCM samples

8-bit PCM samples are unsigned, at least in WAV, so after rescaling them
to the correct range we also need to center them around 0. This fix
should make 8-bit WAVs have the correct volume of double of what it was
before, and also future-proof for all other unsigned PCM sample formats
we may encounter.
kleines Filmröllchen 2 年之前
父节点
当前提交
5f71c81e1b
共有 1 个文件被更改,包括 9 次插入1 次删除
  1. 9 1
      Userland/Libraries/LibAudio/WavLoader.cpp

+ 9 - 1
Userland/Libraries/LibAudio/WavLoader.cpp

@@ -83,8 +83,16 @@ static ErrorOr<double> read_sample(Core::Stream::Stream& stream)
 {
     T sample { 0 };
     TRY(stream.read(Bytes { &sample, sizeof(T) }));
+    // Remap integer samples to normalized floating-point range of -1 to 1.
     if constexpr (IsIntegral<T>) {
-        return static_cast<double>(AK::convert_between_host_and_little_endian(sample)) / static_cast<double>(NumericLimits<T>::max());
+        if constexpr (NumericLimits<T>::is_signed()) {
+            // Signed integer samples are centered around zero, so this division is enough.
+            return static_cast<double>(AK::convert_between_host_and_little_endian(sample)) / static_cast<double>(NumericLimits<T>::max());
+        } else {
+            // Unsigned integer samples, on the other hand, need to be shifted to center them around zero.
+            // The first division therefore remaps to the range 0 to 2.
+            return static_cast<double>(AK::convert_between_host_and_little_endian(sample)) / (static_cast<double>(NumericLimits<T>::max()) / 2.0) - 1.0;
+        }
     } else {
         return static_cast<double>(AK::convert_between_host_and_little_endian(sample));
     }