Browse code

swr: add dither support.

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>

Michael Niedermayer authored on 2012/04/11 02:52:42
Showing 6 changed files
... ...
@@ -5,6 +5,6 @@ FFLIBS = avutil
5 5
 
6 6
 HEADERS = swresample.h
7 7
 
8
-OBJS = swresample.o audioconvert.o resample.o rematrix.o
8
+OBJS = swresample.o audioconvert.o resample.o rematrix.o dither.o
9 9
 
10 10
 TESTPROGS = swresample_test
11 11
new file mode 100644
... ...
@@ -0,0 +1,56 @@
0
+/*
1
+ * Copyright (C) 2012 Michael Niedermayer (michaelni@gmx.at)
2
+ *
3
+ * This file is part of libswresample
4
+ *
5
+ * libswresample is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * libswresample is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with libswresample; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+#include "libavutil/avassert.h"
21
+#include "swresample_internal.h"
22
+
23
+void swri_get_dither(void *dst, int len, unsigned seed, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, enum SwrDitherType method) {
24
+    double scale = 0;
25
+    int i;
26
+
27
+    if(in_fmt == AV_SAMPLE_FMT_FLT || in_fmt == AV_SAMPLE_FMT_DBL){
28
+        if(out_fmt == AV_SAMPLE_FMT_S32) scale = 1.0/(1L<<31);
29
+        if(out_fmt == AV_SAMPLE_FMT_S16) scale = 1.0/(1L<<15);
30
+        if(out_fmt == AV_SAMPLE_FMT_U8 ) scale = 1.0/(1L<< 7);
31
+    }
32
+    if(in_fmt == AV_SAMPLE_FMT_S32 && out_fmt == AV_SAMPLE_FMT_S16) scale = 1L<<16;
33
+    if(in_fmt == AV_SAMPLE_FMT_S32 && out_fmt == AV_SAMPLE_FMT_U8 ) scale = 1L<<24;
34
+    if(in_fmt == AV_SAMPLE_FMT_S16 && out_fmt == AV_SAMPLE_FMT_U8 ) scale = 1L<<8;
35
+
36
+    for(i=0; i<len; i++){
37
+        double v;
38
+        seed = seed* 1664525 + 1013904223;
39
+
40
+        switch(method){
41
+            case SWR_DITHER_RECTANGULAR: v= ((double)seed) / UINT_MAX - 0.5; break;
42
+            default: av_assert0(0);
43
+        }
44
+
45
+        v*= scale;
46
+
47
+        switch(in_fmt){
48
+            case AV_SAMPLE_FMT_S16: ((int16_t*)dst)[i] = v; break;
49
+            case AV_SAMPLE_FMT_S32: ((int32_t*)dst)[i] = v; break;
50
+            case AV_SAMPLE_FMT_FLT: ((float  *)dst)[i] = v; break;
51
+            case AV_SAMPLE_FMT_DBL: ((double *)dst)[i] = v; break;
52
+            default: av_assert0(0);
53
+        }
54
+    }
55
+}
... ...
@@ -272,6 +272,14 @@ int swri_rematrix_init(SwrContext *s){
272 272
     return 0;
273 273
 }
274 274
 
275
+void swri_sum2(enum AVSampleFormat format, void *dst, const void *src0, const void *src1, float coef0, float coef1, int len){
276
+    if(format == AV_SAMPLE_FMT_FLT){
277
+        sum2_float((float  *)dst, (const float  *)src0, (const float  *)src1, coef0, coef1, len);
278
+    }else{
279
+        sum2_s16  ((int16_t*)dst, (const int16_t*)src0, (const int16_t*)src1, lrintf(coef0 * 32768), lrintf(coef1 * 32768), len);
280
+    }
281
+}
282
+
275 283
 int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy){
276 284
     int out_i, in_i, i, j;
277 285
 
... ...
@@ -295,15 +303,8 @@ int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mus
295 295
             }
296 296
             break;
297 297
         case 2:
298
-            if(s->int_sample_fmt == AV_SAMPLE_FMT_FLT){
299
-                sum2_float((float  *)out->ch[out_i], (const float  *)in->ch[ s->matrix_ch[out_i][1] ],           (const float  *)in->ch[ s->matrix_ch[out_i][2] ],
300
-                                 s->matrix[out_i][ s->matrix_ch[out_i][1] ], s->matrix[out_i][ s->matrix_ch[out_i][2] ],
301
-                           len);
302
-            }else{
303
-                sum2_s16  ((int16_t*)out->ch[out_i], (const int16_t*)in->ch[ s->matrix_ch[out_i][1] ],           (const int16_t*)in->ch[ s->matrix_ch[out_i][2] ],
304
-                                 s->matrix32[out_i][ s->matrix_ch[out_i][1] ], s->matrix32[out_i][ s->matrix_ch[out_i][2] ],
305
-                           len);
306
-            }
298
+            swri_sum2(s->int_sample_fmt, out->ch[out_i], in->ch[ s->matrix_ch[out_i][1] ],           in->ch[ s->matrix_ch[out_i][2] ],
299
+                        s->matrix[out_i][ s->matrix_ch[out_i][1] ], s->matrix[out_i][ s->matrix_ch[out_i][2] ], len);
307 300
             break;
308 301
         default:
309 302
             if(s->int_sample_fmt == AV_SAMPLE_FMT_FLT){
... ...
@@ -53,6 +53,7 @@ static const AVOption options[]={
53 53
 {"rmvol", "rematrix volume"     , OFFSET(rematrix_volume), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, -1000, 1000, 0},
54 54
 {"flags", NULL                  , OFFSET(flags)        , AV_OPT_TYPE_FLAGS, {.dbl=0}, 0,  UINT_MAX, 0, "flags"},
55 55
 {"res", "force resampling", 0, AV_OPT_TYPE_CONST, {.dbl=SWR_FLAG_RESAMPLE}, INT_MIN, INT_MAX, 0, "flags"},
56
+{"dither", "dither method"      , OFFSET(dither_method), AV_OPT_TYPE_INT, {.dbl=0}, 0, SWR_DITHER_NB-1, 0},
56 57
 
57 58
 {0}
58 59
 };
... ...
@@ -139,6 +140,7 @@ void swr_free(SwrContext **ss){
139 139
         free_temp(&s->midbuf);
140 140
         free_temp(&s->preout);
141 141
         free_temp(&s->in_buffer);
142
+        free_temp(&s->dither);
142 143
         swri_audio_convert_free(&s-> in_convert);
143 144
         swri_audio_convert_free(&s->out_convert);
144 145
         swri_audio_convert_free(&s->full_convert);
... ...
@@ -156,6 +158,7 @@ int swr_init(struct SwrContext *s){
156 156
     free_temp(&s->midbuf);
157 157
     free_temp(&s->preout);
158 158
     free_temp(&s->in_buffer);
159
+    free_temp(&s->dither);
159 160
     swri_audio_convert_free(&s-> in_convert);
160 161
     swri_audio_convert_free(&s->out_convert);
161 162
     swri_audio_convert_free(&s->full_convert);
... ...
@@ -281,6 +284,8 @@ av_assert0(s->out.ch_count);
281 281
         s->in_buffer.planar = 1;
282 282
     }
283 283
 
284
+    s->dither = s->preout;
285
+
284 286
     if(s->rematrix)
285 287
         return swri_rematrix_init(s);
286 288
 
... ...
@@ -505,6 +510,21 @@ static int swr_convert_internal(struct SwrContext *s, AudioData *out, int out_co
505 505
     }
506 506
 
507 507
     if(preout != out && out_count){
508
+        if(s->dither_method){
509
+            int ch, i;
510
+            av_assert0(preout != in);
511
+
512
+            if((ret=realloc_audio(&s->dither, out_count))<0)
513
+                return ret;
514
+            if(ret)
515
+                for(ch=0; ch<s->dither.ch_count; ch++)
516
+                    swri_get_dither(s->dither.ch[ch], s->dither.count, 12345678913579<<ch, s->out_sample_fmt, s->int_sample_fmt, s->dither_method);
517
+            av_assert0(s->dither.ch_count == preout->ch_count);
518
+
519
+            for(ch=0; ch<preout->ch_count; ch++){
520
+                swri_sum2(s->int_sample_fmt, preout->ch[ch], preout->ch[ch], s->dither.ch[ch], 1, 1, out_count);
521
+            }
522
+        }
508 523
 //FIXME packed doesnt need more than 1 chan here!
509 524
         swri_audio_convert(s->out_convert, out, preout, out_count);
510 525
     }
... ...
@@ -30,7 +30,7 @@
30 30
 #include "libavutil/samplefmt.h"
31 31
 
32 32
 #define LIBSWRESAMPLE_VERSION_MAJOR 0
33
-#define LIBSWRESAMPLE_VERSION_MINOR 10
33
+#define LIBSWRESAMPLE_VERSION_MINOR 11
34 34
 #define LIBSWRESAMPLE_VERSION_MICRO 100
35 35
 
36 36
 #define LIBSWRESAMPLE_VERSION_INT  AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \
... ...
@@ -45,6 +45,11 @@
45 45
 //TODO use int resample ?
46 46
 //long term TODO can we enable this dynamically?
47 47
 
48
+enum SwrDitherType {
49
+    SWR_DITHER_NONE = 0,
50
+    SWR_DITHER_RECTANGULAR,
51
+    SWR_DITHER_NB,              ///< not part of API/ABI
52
+};
48 53
 
49 54
 typedef struct SwrContext SwrContext;
50 55
 
... ...
@@ -49,6 +49,7 @@ struct SwrContext {
49 49
     float rematrix_volume;                          ///< rematrixing volume coefficient
50 50
     const int *channel_map;                         ///< channel index (or -1 if muted channel) map
51 51
     int used_ch_count;                              ///< number of used input channels (mapped channel count if channel_map, otherwise in.ch_count)
52
+    enum SwrDitherType dither_method;
52 53
 
53 54
     int int_bps;                                    ///< internal bytes per sample
54 55
     int resample_first;                             ///< 1 if resampling must come first, 0 if rematrixing
... ...
@@ -61,6 +62,7 @@ struct SwrContext {
61 61
     AudioData preout;                               ///< pre-output audio data: used for rematrix/resample
62 62
     AudioData out;                                  ///< converted output audio data
63 63
     AudioData in_buffer;                            ///< cached audio data (convert and resample purpose)
64
+    AudioData dither;                               ///< cached audio data (convert and resample purpose)
64 65
     int in_buffer_index;                            ///< cached buffer position
65 66
     int in_buffer_count;                            ///< cached buffer length
66 67
     int resample_in_constraint;                     ///< 1 if the input end was reach before the output end, 0 otherwise
... ...
@@ -89,5 +91,8 @@ int swri_resample_double(struct ResampleContext *c,double  *dst, const double  *
89 89
 
90 90
 int swri_rematrix_init(SwrContext *s);
91 91
 int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy);
92
+void swri_sum2(enum AVSampleFormat format, void *dst, const void *src0, const void *src1, float coef0, float coef1, int len);
93
+
94
+void swri_get_dither(void *dst, int len, unsigned seed, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, enum SwrDitherType type);
92 95
 
93 96
 #endif