[FFmpeg-devel] [PATCH] audio conversion clipping/overflows
Ronald S. Bultje
rsbultje
Mon Mar 1 15:18:58 CET 2010
Hi,
float 1.0 rounds to int INT_MIN (whatever int size). This leads to
considerable audio clipping artifacts.
Attached patch is a lame attempt of mine to fix this. It probably
makes the code slower, so sue me. :-).
Ronald
-------------- next part --------------
Index: libavcodec/audioconvert.c
===================================================================
--- libavcodec/audioconvert.c (revision 22027)
+++ libavcodec/audioconvert.c (working copy)
@@ -226,14 +226,20 @@
else CONV(SAMPLE_FMT_S32, int32_t, SAMPLE_FMT_S32, *(const int32_t*)pi)
else CONV(SAMPLE_FMT_FLT, float , SAMPLE_FMT_S32, *(const int32_t*)pi*(1.0 / (1<<31)))
else CONV(SAMPLE_FMT_DBL, double , SAMPLE_FMT_S32, *(const int32_t*)pi*(1.0 / (1<<31)))
- else CONV(SAMPLE_FMT_U8 , uint8_t, SAMPLE_FMT_FLT, lrintf(*(const float*)pi * (1<<7)) + 0x80)
- else CONV(SAMPLE_FMT_S16, int16_t, SAMPLE_FMT_FLT, lrintf(*(const float*)pi * (1<<15)))
- else CONV(SAMPLE_FMT_S32, int32_t, SAMPLE_FMT_FLT, lrintf(*(const float*)pi * (1<<31)))
+ else CONV(SAMPLE_FMT_U8 , uint8_t, SAMPLE_FMT_FLT,
+ av_clip_uint8(lrintf(*(const float*)pi * (1<<7)) + 0x80))
+ else CONV(SAMPLE_FMT_S16, int16_t, SAMPLE_FMT_FLT,
+ av_clip_int16(lrintf(*(const float*)pi * (1<<15))))
+ else CONV(SAMPLE_FMT_S32, int32_t, SAMPLE_FMT_FLT,
+ av_clipl_int32(llrintf(*(const float*)pi * (1<<31))))
else CONV(SAMPLE_FMT_FLT, float , SAMPLE_FMT_FLT, *(const float*)pi)
else CONV(SAMPLE_FMT_DBL, double , SAMPLE_FMT_FLT, *(const float*)pi)
- else CONV(SAMPLE_FMT_U8 , uint8_t, SAMPLE_FMT_DBL, lrint(*(const double*)pi * (1<<7)) + 0x80)
- else CONV(SAMPLE_FMT_S16, int16_t, SAMPLE_FMT_DBL, lrint(*(const double*)pi * (1<<15)))
- else CONV(SAMPLE_FMT_S32, int32_t, SAMPLE_FMT_DBL, lrint(*(const double*)pi * (1<<31)))
+ else CONV(SAMPLE_FMT_U8 , uint8_t, SAMPLE_FMT_DBL,
+ av_clip_uint8(lrint(*(const double*)pi * (1<<7)) + 0x80))
+ else CONV(SAMPLE_FMT_S16, int16_t, SAMPLE_FMT_DBL,
+ av_clip_int16(lrint(*(const double*)pi * (1<<15))))
+ else CONV(SAMPLE_FMT_S32, int32_t, SAMPLE_FMT_DBL,
+ av_clipl_int32(llrint(*(const double*)pi * (1<<31))))
else CONV(SAMPLE_FMT_FLT, float , SAMPLE_FMT_DBL, *(const double*)pi)
else CONV(SAMPLE_FMT_DBL, double , SAMPLE_FMT_DBL, *(const double*)pi)
else return -1;
Index: libavutil/common.h
===================================================================
--- libavutil/common.h (revision 22030)
+++ libavutil/common.h (working copy)
@@ -222,6 +222,17 @@
}
/**
+ * Clips a signed 64-bit integer value into the -2147483648,2147483647 range.
+ * @param a value to clip
+ * @return clipped value
+ */
+static inline av_const int32_t av_clipl_int32(int64_t a)
+{
+ if ((a+2147483648) & ~2147483647) return (a>>63) ^ 2147483647;
+ else return a;
+}
+
+/**
* Clips a float value into the amin-amax range.
* @param a value to clip
* @param amin minimum value of the clip range
More information about the ffmpeg-devel
mailing list