History

swr: add dither support.

Michael Niedermayer committed 14 years ago

Commit db2eadb1 parent 5c1f3126 files · +98 −11Browse files

Unified · Split

6 files
  1. libswresample/Makefile +1 −1
  2. libswresample/dither.c +56 −0
  3. libswresample/rematrix.c +10 −9
  4. libswresample/swresample.c +20 −0
  5. libswresample/swresample.h +6 −1
  6. libswresample/swresample_internal.h +5 −0
libswresample/Makefile+1−1
@@ -5,6 +5,6 @@ FFLIBS = avutil · 4 unmodified lines
55
66 HEADERS = swresample.h
77
8−OBJS = swresample.o audioconvert.o resample.o rematrix.o
8+OBJS = swresample.o audioconvert.o resample.o rematrix.o dither.o
99
1010 TESTPROGS = swresample_test
libswresample/dither.c+56−0
@@ -0,0 +1,56 @@
1+/*
2+ * Copyright (C) 2012 Michael Niedermayer (michaelni@gmx.at)
3+ *
4+ * This file is part of libswresample
5+ *
6+ * libswresample is free software; you can redistribute it and/or
7+ * modify it under the terms of the GNU Lesser General Public
8+ * License as published by the Free Software Foundation; either
9+ * version 2.1 of the License, or (at your option) any later version.
10+ *
11+ * libswresample is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+ * Lesser General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU Lesser General Public
17+ * License along with libswresample; if not, write to the Free Software
18+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19+ */
20+
21+#include "libavutil/avassert.h"
22+#include "swresample_internal.h"
23+
24+void swri_get_dither(void *dst, int len, unsigned seed, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, enum SwrDitherType method) {
25+ double scale = 0;
26+ int i;
27+
28+ if(in_fmt == AV_SAMPLE_FMT_FLT || in_fmt == AV_SAMPLE_FMT_DBL){
29+ if(out_fmt == AV_SAMPLE_FMT_S32) scale = 1.0/(1L<<31);
30+ if(out_fmt == AV_SAMPLE_FMT_S16) scale = 1.0/(1L<<15);
31+ if(out_fmt == AV_SAMPLE_FMT_U8 ) scale = 1.0/(1L<< 7);
32+ }
33+ if(in_fmt == AV_SAMPLE_FMT_S32 && out_fmt == AV_SAMPLE_FMT_S16) scale = 1L<<16;
34+ if(in_fmt == AV_SAMPLE_FMT_S32 && out_fmt == AV_SAMPLE_FMT_U8 ) scale = 1L<<24;
35+ if(in_fmt == AV_SAMPLE_FMT_S16 && out_fmt == AV_SAMPLE_FMT_U8 ) scale = 1L<<8;
36+
37+ for(i=0; i<len; i++){
38+ double v;
39+ seed = seed* 1664525 + 1013904223;
40+
41+ switch(method){
42+ case SWR_DITHER_RECTANGULAR: v= ((double)seed) / UINT_MAX - 0.5; break;
43+ default: av_assert0(0);
44+ }
45+
46+ v*= scale;
47+
48+ switch(in_fmt){
49+ case AV_SAMPLE_FMT_S16: ((int16_t*)dst)[i] = v; break;
50+ case AV_SAMPLE_FMT_S32: ((int32_t*)dst)[i] = v; break;
51+ case AV_SAMPLE_FMT_FLT: ((float *)dst)[i] = v; break;
52+ case AV_SAMPLE_FMT_DBL: ((double *)dst)[i] = v; break;
53+ default: av_assert0(0);
54+ }
55+ }
56+}
libswresample/rematrix.c+10−9
@@ -272,6 +272,14 @@ int swri_rematrix_init(SwrContext *s){ · 271 unmodified lines
272272 return 0;
273273 }
274274
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+
275283 int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy){
276284 int out_i, in_i, i, j;
277285
@@ -295,15 +303,8 @@ int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mus · 17 unmodified lines
295303 }
296304 break;
297305 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− }
306+ 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] ],
307+ s->matrix[out_i][ s->matrix_ch[out_i][1] ], s->matrix[out_i][ s->matrix_ch[out_i][2] ], len);
307308 break;
308309 default:
309310 if(s->int_sample_fmt == AV_SAMPLE_FMT_FLT){
libswresample/swresample.c+20−0
@@ -53,6 +53,7 @@ static const AVOption options[]={ · 52 unmodified lines
5353 {"rmvol", "rematrix volume" , OFFSET(rematrix_volume), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, -1000, 1000, 0},
5454 {"flags", NULL , OFFSET(flags) , AV_OPT_TYPE_FLAGS, {.dbl=0}, 0, UINT_MAX, 0, "flags"},
5555 {"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},
5657
5758 {0}
5859 };
@@ -139,6 +140,7 @@ void swr_free(SwrContext **ss){ · 80 unmodified lines
139140 free_temp(&s->midbuf);
140141 free_temp(&s->preout);
141142 free_temp(&s->in_buffer);
143+ free_temp(&s->dither);
142144 swri_audio_convert_free(&s-> in_convert);
143145 swri_audio_convert_free(&s->out_convert);
144146 swri_audio_convert_free(&s->full_convert);
@@ -156,6 +158,7 @@ int swr_init(struct SwrContext *s){ · 11 unmodified lines
156158 free_temp(&s->midbuf);
157159 free_temp(&s->preout);
158160 free_temp(&s->in_buffer);
161+ free_temp(&s->dither);
159162 swri_audio_convert_free(&s-> in_convert);
160163 swri_audio_convert_free(&s->out_convert);
161164 swri_audio_convert_free(&s->full_convert);
@@ -281,6 +284,8 @@ av_assert0(s->out.ch_count); · 119 unmodified lines
281284 s->in_buffer.planar = 1;
282285 }
283286
287+ s->dither = s->preout;
288+
284289 if(s->rematrix)
285290 return swri_rematrix_init(s);
286291
@@ -505,6 +510,21 @@ static int swr_convert_internal(struct SwrContext *s, AudioData *out, int out_co · 218 unmodified lines
505510 }
506511
507512 if(preout != out && out_count){
513+ if(s->dither_method){
514+ int ch, i;
515+ av_assert0(preout != in);
516+
517+ if((ret=realloc_audio(&s->dither, out_count))<0)
518+ return ret;
519+ if(ret)
520+ for(ch=0; ch<s->dither.ch_count; ch++)
521+ swri_get_dither(s->dither.ch[ch], s->dither.count, 12345678913579<<ch, s->out_sample_fmt, s->int_sample_fmt, s->dither_method);
522+ av_assert0(s->dither.ch_count == preout->ch_count);
523+
524+ for(ch=0; ch<preout->ch_count; ch++){
525+ swri_sum2(s->int_sample_fmt, preout->ch[ch], preout->ch[ch], s->dither.ch[ch], 1, 1, out_count);
526+ }
527+ }
508528 //FIXME packed doesnt need more than 1 chan here!
509529 swri_audio_convert(s->out_convert, out, preout, out_count);
510530 }
libswresample/swresample.h+6−1
@@ -30,7 +30,7 @@ · 29 unmodified lines
3030 #include "libavutil/samplefmt.h"
3131
3232 #define LIBSWRESAMPLE_VERSION_MAJOR 0
33−#define LIBSWRESAMPLE_VERSION_MINOR 10
33+#define LIBSWRESAMPLE_VERSION_MINOR 11
3434 #define LIBSWRESAMPLE_VERSION_MICRO 100
3535
3636 #define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \
@@ -45,6 +45,11 @@ · 8 unmodified lines
4545 //TODO use int resample ?
4646 //long term TODO can we enable this dynamically?
4747
48+enum SwrDitherType {
49+ SWR_DITHER_NONE = 0,
50+ SWR_DITHER_RECTANGULAR,
51+ SWR_DITHER_NB, ///< not part of API/ABI
52+};
4853
4954 typedef struct SwrContext SwrContext;
5055
libswresample/swresample_internal.h+5−0
@@ -49,6 +49,7 @@ struct SwrContext { · 48 unmodified lines
4949 float rematrix_volume; ///< rematrixing volume coefficient
5050 const int *channel_map; ///< channel index (or -1 if muted channel) map
5151 int used_ch_count; ///< number of used input channels (mapped channel count if channel_map, otherwise in.ch_count)
52+ enum SwrDitherType dither_method;
5253
5354 int int_bps; ///< internal bytes per sample
5455 int resample_first; ///< 1 if resampling must come first, 0 if rematrixing
@@ -61,6 +62,7 @@ struct SwrContext { · 6 unmodified lines
6162 AudioData preout; ///< pre-output audio data: used for rematrix/resample
6263 AudioData out; ///< converted output audio data
6364 AudioData in_buffer; ///< cached audio data (convert and resample purpose)
65+ AudioData dither; ///< cached audio data (convert and resample purpose)
6466 int in_buffer_index; ///< cached buffer position
6567 int in_buffer_count; ///< cached buffer length
6668 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 * · 22 unmodified lines
8991
9092 int swri_rematrix_init(SwrContext *s);
9193 int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy);
94+void swri_sum2(enum AVSampleFormat format, void *dst, const void *src0, const void *src1, float coef0, float coef1, int len);
95+
96+void swri_get_dither(void *dst, int len, unsigned seed, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, enum SwrDitherType type);
9297
9398 #endif

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t