Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
52868 views
1
/*
2
* Copyright (C) 2012-2013 Michael Niedermayer ([email protected])
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
#include "noise_shaping_data.c"
25
26
int swri_get_dither(SwrContext *s, void *dst, int len, unsigned seed, enum AVSampleFormat noise_fmt) {
27
double scale = s->dither.noise_scale;
28
#define TMP_EXTRA 2
29
double *tmp = av_malloc_array(len + TMP_EXTRA, sizeof(double));
30
int i;
31
32
if (!tmp)
33
return AVERROR(ENOMEM);
34
35
for(i=0; i<len + TMP_EXTRA; i++){
36
double v;
37
seed = seed* 1664525 + 1013904223;
38
39
switch(s->dither.method){
40
case SWR_DITHER_RECTANGULAR: v= ((double)seed) / UINT_MAX - 0.5; break;
41
default:
42
av_assert0(s->dither.method < SWR_DITHER_NB);
43
v = ((double)seed) / UINT_MAX;
44
seed = seed*1664525 + 1013904223;
45
v-= ((double)seed) / UINT_MAX;
46
break;
47
}
48
tmp[i] = v;
49
}
50
51
for(i=0; i<len; i++){
52
double v;
53
54
switch(s->dither.method){
55
default:
56
av_assert0(s->dither.method < SWR_DITHER_NB);
57
v = tmp[i];
58
break;
59
case SWR_DITHER_TRIANGULAR_HIGHPASS :
60
v = (- tmp[i] + 2*tmp[i+1] - tmp[i+2]) / sqrt(6);
61
break;
62
}
63
64
v*= scale;
65
66
switch(noise_fmt){
67
case AV_SAMPLE_FMT_S16P: ((int16_t*)dst)[i] = v; break;
68
case AV_SAMPLE_FMT_S32P: ((int32_t*)dst)[i] = v; break;
69
case AV_SAMPLE_FMT_FLTP: ((float *)dst)[i] = v; break;
70
case AV_SAMPLE_FMT_DBLP: ((double *)dst)[i] = v; break;
71
default: av_assert0(0);
72
}
73
}
74
75
av_free(tmp);
76
return 0;
77
}
78
79
av_cold int swri_dither_init(SwrContext *s, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt)
80
{
81
int i;
82
double scale = 0;
83
84
if (s->dither.method > SWR_DITHER_TRIANGULAR_HIGHPASS && s->dither.method <= SWR_DITHER_NS)
85
return AVERROR(EINVAL);
86
87
out_fmt = av_get_packed_sample_fmt(out_fmt);
88
in_fmt = av_get_packed_sample_fmt( in_fmt);
89
90
if(in_fmt == AV_SAMPLE_FMT_FLT || in_fmt == AV_SAMPLE_FMT_DBL){
91
if(out_fmt == AV_SAMPLE_FMT_S32) scale = 1.0/(1LL<<31);
92
if(out_fmt == AV_SAMPLE_FMT_S16) scale = 1.0/(1LL<<15);
93
if(out_fmt == AV_SAMPLE_FMT_U8 ) scale = 1.0/(1LL<< 7);
94
}
95
if(in_fmt == AV_SAMPLE_FMT_S32 && out_fmt == AV_SAMPLE_FMT_S32 && (s->dither.output_sample_bits&31)) scale = 1;
96
if(in_fmt == AV_SAMPLE_FMT_S32 && out_fmt == AV_SAMPLE_FMT_S16) scale = 1<<16;
97
if(in_fmt == AV_SAMPLE_FMT_S32 && out_fmt == AV_SAMPLE_FMT_U8 ) scale = 1<<24;
98
if(in_fmt == AV_SAMPLE_FMT_S16 && out_fmt == AV_SAMPLE_FMT_U8 ) scale = 1<<8;
99
100
scale *= s->dither.scale;
101
102
if (out_fmt == AV_SAMPLE_FMT_S32 && s->dither.output_sample_bits)
103
scale *= 1<<(32-s->dither.output_sample_bits);
104
105
s->dither.ns_pos = 0;
106
s->dither.noise_scale= scale;
107
s->dither.ns_scale = scale;
108
s->dither.ns_scale_1 = scale ? 1/scale : 0;
109
memset(s->dither.ns_errors, 0, sizeof(s->dither.ns_errors));
110
for (i=0; filters[i].coefs; i++) {
111
const filter_t *f = &filters[i];
112
if (llabs(s->out_sample_rate - f->rate)*20 <= f->rate && f->name == s->dither.method) {
113
int j;
114
s->dither.ns_taps = f->len;
115
for (j=0; j<f->len; j++)
116
s->dither.ns_coeffs[j] = f->coefs[j];
117
s->dither.ns_scale_1 *= 1 - exp(f->gain_cB * M_LN10 * 0.005) * 2 / (1<<(8*av_get_bytes_per_sample(out_fmt)));
118
break;
119
}
120
}
121
if (!filters[i].coefs && s->dither.method > SWR_DITHER_NS) {
122
av_log(s, AV_LOG_WARNING, "Requested noise shaping dither not available at this sampling rate, using triangular hp dither\n");
123
s->dither.method = SWR_DITHER_TRIANGULAR_HIGHPASS;
124
}
125
126
av_assert0(!s->preout.count);
127
s->dither.noise = s->preout;
128
s->dither.temp = s->preout;
129
if (s->dither.method > SWR_DITHER_NS) {
130
s->dither.noise.bps = 4;
131
s->dither.noise.fmt = AV_SAMPLE_FMT_FLTP;
132
s->dither.noise_scale = 1;
133
}
134
135
return 0;
136
}
137
138
#define TEMPLATE_DITHER_S16
139
#include "dither_template.c"
140
#undef TEMPLATE_DITHER_S16
141
142
#define TEMPLATE_DITHER_S32
143
#include "dither_template.c"
144
#undef TEMPLATE_DITHER_S32
145
146
#define TEMPLATE_DITHER_FLT
147
#include "dither_template.c"
148
#undef TEMPLATE_DITHER_FLT
149
150
#define TEMPLATE_DITHER_DBL
151
#include "dither_template.c"
152
#undef TEMPLATE_DITHER_DBL
153
154