2 * Copyright (C) 2012-2013 Michael Niedermayer (michaelni@gmx.at)
4 * This file is part of libswresample
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.
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.
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
21 #include "libavutil/avassert.h"
22 #include "swresample_internal.h"
24 #include "noise_shaping_data.c"
26 void swri_get_dither(SwrContext
*s
, void *dst
, int len
, unsigned seed
, enum AVSampleFormat noise_fmt
) {
27 double scale
= s
->dither
.noise_scale
;
29 double *tmp
= av_malloc_array(len
+ TMP_EXTRA
, sizeof(double));
32 for(i
=0; i
<len
+ TMP_EXTRA
; i
++){
34 seed
= seed
* 1664525 + 1013904223;
36 switch(s
->dither
.method
){
37 case SWR_DITHER_RECTANGULAR
: v
= ((double)seed
) / UINT_MAX
- 0.5; break;
39 av_assert0(s
->dither
.method
< SWR_DITHER_NB
);
40 v
= ((double)seed
) / UINT_MAX
;
41 seed
= seed
*1664525 + 1013904223;
42 v
-= ((double)seed
) / UINT_MAX
;
51 switch(s
->dither
.method
){
53 av_assert0(s
->dither
.method
< SWR_DITHER_NB
);
56 case SWR_DITHER_TRIANGULAR_HIGHPASS
:
57 v
= (- tmp
[i
] + 2*tmp
[i
+1] - tmp
[i
+2]) / sqrt(6);
64 case AV_SAMPLE_FMT_S16P
: ((int16_t*)dst
)[i
] = v
; break;
65 case AV_SAMPLE_FMT_S32P
: ((int32_t*)dst
)[i
] = v
; break;
66 case AV_SAMPLE_FMT_FLTP
: ((float *)dst
)[i
] = v
; break;
67 case AV_SAMPLE_FMT_DBLP
: ((double *)dst
)[i
] = v
; break;
68 default: av_assert0(0);
75 int swri_dither_init(SwrContext
*s
, enum AVSampleFormat out_fmt
, enum AVSampleFormat in_fmt
)
80 if (s
->dither
.method
> SWR_DITHER_TRIANGULAR_HIGHPASS
&& s
->dither
.method
<= SWR_DITHER_NS
)
81 return AVERROR(EINVAL
);
83 out_fmt
= av_get_packed_sample_fmt(out_fmt
);
84 in_fmt
= av_get_packed_sample_fmt( in_fmt
);
86 if(in_fmt
== AV_SAMPLE_FMT_FLT
|| in_fmt
== AV_SAMPLE_FMT_DBL
){
87 if(out_fmt
== AV_SAMPLE_FMT_S32
) scale
= 1.0/(1L<<31);
88 if(out_fmt
== AV_SAMPLE_FMT_S16
) scale
= 1.0/(1L<<15);
89 if(out_fmt
== AV_SAMPLE_FMT_U8
) scale
= 1.0/(1L<< 7);
91 if(in_fmt
== AV_SAMPLE_FMT_S32
&& out_fmt
== AV_SAMPLE_FMT_S32
&& (s
->dither
.output_sample_bits
&31)) scale
= 1;
92 if(in_fmt
== AV_SAMPLE_FMT_S32
&& out_fmt
== AV_SAMPLE_FMT_S16
) scale
= 1L<<16;
93 if(in_fmt
== AV_SAMPLE_FMT_S32
&& out_fmt
== AV_SAMPLE_FMT_U8
) scale
= 1L<<24;
94 if(in_fmt
== AV_SAMPLE_FMT_S16
&& out_fmt
== AV_SAMPLE_FMT_U8
) scale
= 1L<<8;
96 scale
*= s
->dither
.scale
;
98 if (out_fmt
== AV_SAMPLE_FMT_S32
&& s
->dither
.output_sample_bits
)
99 scale
*= 1<<(32-s
->dither
.output_sample_bits
);
101 s
->dither
.ns_pos
= 0;
102 s
->dither
.noise_scale
= scale
;
103 s
->dither
.ns_scale
= scale
;
104 s
->dither
.ns_scale_1
= scale
? 1/scale
: 0;
105 memset(s
->dither
.ns_errors
, 0, sizeof(s
->dither
.ns_errors
));
106 for (i
=0; filters
[i
].coefs
; i
++) {
107 const filter_t
*f
= &filters
[i
];
108 if (fabs(s
->out_sample_rate
- f
->rate
) / f
->rate
<= .05 && f
->name
== s
->dither
.method
) {
110 s
->dither
.ns_taps
= f
->len
;
111 for (j
=0; j
<f
->len
; j
++)
112 s
->dither
.ns_coeffs
[j
] = f
->coefs
[j
];
113 s
->dither
.ns_scale_1
*= 1 - exp(f
->gain_cB
* M_LN10
* 0.005) * 2 / (1<<(8*av_get_bytes_per_sample(out_fmt
)));
117 if (!filters
[i
].coefs
&& s
->dither
.method
> SWR_DITHER_NS
) {
118 av_log(s
, AV_LOG_WARNING
, "Requested noise shaping dither not available at this sampling rate, using triangular hp dither\n");
119 s
->dither
.method
= SWR_DITHER_TRIANGULAR_HIGHPASS
;
122 av_assert0(!s
->preout
.count
);
123 s
->dither
.noise
= s
->preout
;
124 s
->dither
.temp
= s
->preout
;
125 if (s
->dither
.method
> SWR_DITHER_NS
) {
126 s
->dither
.noise
.bps
= 4;
127 s
->dither
.noise
.fmt
= AV_SAMPLE_FMT_FLTP
;
128 s
->dither
.noise_scale
= 1;
134 #define TEMPLATE_DITHER_S16
135 #include "dither_template.c"
136 #undef TEMPLATE_DITHER_S16
138 #define TEMPLATE_DITHER_S32
139 #include "dither_template.c"
140 #undef TEMPLATE_DITHER_S32
142 #define TEMPLATE_DITHER_FLT
143 #include "dither_template.c"
144 #undef TEMPLATE_DITHER_FLT
146 #define TEMPLATE_DITHER_DBL
147 #include "dither_template.c"
148 #undef TEMPLATE_DITHER_DBL