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
5 5
6HEADERS = swresample.h6HEADERS = swresample.h
7 7
8OBJS = swresample.o audioconvert.o resample.o rematrix.o8OBJS = swresample.o audioconvert.o resample.o rematrix.o dither.o
9 9
10TESTPROGS = swresample_test10TESTPROGS = 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
24void 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
272 return 0;272 return 0;
273}273}
274 274
275void 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
275int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy){283int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy){
276 int out_i, in_i, i, j;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 · 17 unmodified lines
295 }303 }
296 break;304 break;
297 case 2:305 case 2:
298 if(s->int_sample_fmt == AV_SAMPLE_FMT_FLT){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] ],
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] ],307 s->matrix[out_i][ s->matrix_ch[out_i][1] ], s->matrix[out_i][ s->matrix_ch[out_i][2] ], len);
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 }
307 break;308 break;
308 default:309 default:
309 if(s->int_sample_fmt == AV_SAMPLE_FMT_FLT){310 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
53{"rmvol", "rematrix volume" , OFFSET(rematrix_volume), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, -1000, 1000, 0},53{"rmvol", "rematrix volume" , OFFSET(rematrix_volume), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, -1000, 1000, 0},
54{"flags", NULL , OFFSET(flags) , AV_OPT_TYPE_FLAGS, {.dbl=0}, 0, UINT_MAX, 0, "flags"},54{"flags", NULL , OFFSET(flags) , AV_OPT_TYPE_FLAGS, {.dbl=0}, 0, UINT_MAX, 0, "flags"},
55{"res", "force resampling", 0, AV_OPT_TYPE_CONST, {.dbl=SWR_FLAG_RESAMPLE}, INT_MIN, INT_MAX, 0, "flags"},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{0}58{0}
58};59};
@@ -139,6 +140,7 @@ void swr_free(SwrContext **ss){ · 80 unmodified lines
139 free_temp(&s->midbuf);140 free_temp(&s->midbuf);
140 free_temp(&s->preout);141 free_temp(&s->preout);
141 free_temp(&s->in_buffer);142 free_temp(&s->in_buffer);
143 free_temp(&s->dither);
142 swri_audio_convert_free(&s-> in_convert);144 swri_audio_convert_free(&s-> in_convert);
143 swri_audio_convert_free(&s->out_convert);145 swri_audio_convert_free(&s->out_convert);
144 swri_audio_convert_free(&s->full_convert);146 swri_audio_convert_free(&s->full_convert);
@@ -156,6 +158,7 @@ int swr_init(struct SwrContext *s){ · 11 unmodified lines
156 free_temp(&s->midbuf);158 free_temp(&s->midbuf);
157 free_temp(&s->preout);159 free_temp(&s->preout);
158 free_temp(&s->in_buffer);160 free_temp(&s->in_buffer);
161 free_temp(&s->dither);
159 swri_audio_convert_free(&s-> in_convert);162 swri_audio_convert_free(&s-> in_convert);
160 swri_audio_convert_free(&s->out_convert);163 swri_audio_convert_free(&s->out_convert);
161 swri_audio_convert_free(&s->full_convert);164 swri_audio_convert_free(&s->full_convert);
@@ -281,6 +284,8 @@ av_assert0(s->out.ch_count); · 119 unmodified lines
281 s->in_buffer.planar = 1;284 s->in_buffer.planar = 1;
282 }285 }
283 286
287 s->dither = s->preout;
288
284 if(s->rematrix)289 if(s->rematrix)
285 return swri_rematrix_init(s);290 return swri_rematrix_init(s);
286 291
@@ -505,6 +510,21 @@ static int swr_convert_internal(struct SwrContext *s, AudioData *out, int out_co · 218 unmodified lines
505 }510 }
506 511
507 if(preout != out && out_count){512 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 }
508//FIXME packed doesnt need more than 1 chan here!528//FIXME packed doesnt need more than 1 chan here!
509 swri_audio_convert(s->out_convert, out, preout, out_count);529 swri_audio_convert(s->out_convert, out, preout, out_count);
510 }530 }
libswresample/swresample.h+6−1
@@ -30,7 +30,7 @@ · 29 unmodified lines
30#include "libavutil/samplefmt.h"30#include "libavutil/samplefmt.h"
31 31
32#define LIBSWRESAMPLE_VERSION_MAJOR 032#define LIBSWRESAMPLE_VERSION_MAJOR 0
33#define LIBSWRESAMPLE_VERSION_MINOR 1033#define LIBSWRESAMPLE_VERSION_MINOR 11
34#define LIBSWRESAMPLE_VERSION_MICRO 10034#define LIBSWRESAMPLE_VERSION_MICRO 100
35 35
36#define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \36#define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \
@@ -45,6 +45,11 @@ · 8 unmodified lines
45//TODO use int resample ?45//TODO use int resample ?
46//long term TODO can we enable this dynamically?46//long term TODO can we enable this dynamically?
47 47
48enum SwrDitherType {
49 SWR_DITHER_NONE = 0,
50 SWR_DITHER_RECTANGULAR,
51 SWR_DITHER_NB, ///< not part of API/ABI
52};
48 53
49typedef struct SwrContext SwrContext;54typedef struct SwrContext SwrContext;
50 55
libswresample/swresample_internal.h+5−0
@@ -49,6 +49,7 @@ struct SwrContext { · 48 unmodified lines
49 float rematrix_volume; ///< rematrixing volume coefficient49 float rematrix_volume; ///< rematrixing volume coefficient
50 const int *channel_map; ///< channel index (or -1 if muted channel) map50 const int *channel_map; ///< channel index (or -1 if muted channel) map
51 int used_ch_count; ///< number of used input channels (mapped channel count if channel_map, otherwise in.ch_count)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 int int_bps; ///< internal bytes per sample54 int int_bps; ///< internal bytes per sample
54 int resample_first; ///< 1 if resampling must come first, 0 if rematrixing55 int resample_first; ///< 1 if resampling must come first, 0 if rematrixing
@@ -61,6 +62,7 @@ struct SwrContext { · 6 unmodified lines
61 AudioData preout; ///< pre-output audio data: used for rematrix/resample62 AudioData preout; ///< pre-output audio data: used for rematrix/resample
62 AudioData out; ///< converted output audio data63 AudioData out; ///< converted output audio data
63 AudioData in_buffer; ///< cached audio data (convert and resample purpose)64 AudioData in_buffer; ///< cached audio data (convert and resample purpose)
65 AudioData dither; ///< cached audio data (convert and resample purpose)
64 int in_buffer_index; ///< cached buffer position66 int in_buffer_index; ///< cached buffer position
65 int in_buffer_count; ///< cached buffer length67 int in_buffer_count; ///< cached buffer length
66 int resample_in_constraint; ///< 1 if the input end was reach before the output end, 0 otherwise68 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
89 91
90int swri_rematrix_init(SwrContext *s);92int swri_rematrix_init(SwrContext *s);
91int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy);93int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy);
94void swri_sum2(enum AVSampleFormat format, void *dst, const void *src0, const void *src1, float coef0, float coef1, int len);
95
96void swri_get_dither(void *dst, int len, unsigned seed, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, enum SwrDitherType type);
92 97
93#endif98#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