blob: 4c227b9940150543c52c11a7db6aafb56ca3cd06
1 | /* |
2 | * audio resampling |
3 | * Copyright (c) 2004-2012 Michael Niedermayer <michaelni@gmx.at> |
4 | * |
5 | * This file is part of FFmpeg. |
6 | * |
7 | * FFmpeg is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either |
10 | * version 2.1 of the License, or (at your option) any later version. |
11 | * |
12 | * FFmpeg is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * Lesser General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU Lesser General Public |
18 | * License along with FFmpeg; if not, write to the Free Software |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | */ |
21 | |
22 | /** |
23 | * @file |
24 | * audio resampling |
25 | * @author Michael Niedermayer <michaelni@gmx.at> |
26 | */ |
27 | |
28 | #if defined(TEMPLATE_RESAMPLE_DBL) |
29 | |
30 | # define RENAME(N) N ## _double |
31 | # define FILTER_SHIFT 0 |
32 | # define DELEM double |
33 | # define FELEM double |
34 | # define FELEM2 double |
35 | # define FOFFSET 0 |
36 | # define OUT(d, v) d = v |
37 | |
38 | #elif defined(TEMPLATE_RESAMPLE_FLT) |
39 | |
40 | # define RENAME(N) N ## _float |
41 | # define FILTER_SHIFT 0 |
42 | # define DELEM float |
43 | # define FELEM float |
44 | # define FELEM2 float |
45 | # define FOFFSET 0 |
46 | # define OUT(d, v) d = v |
47 | |
48 | #elif defined(TEMPLATE_RESAMPLE_S32) |
49 | |
50 | # define RENAME(N) N ## _int32 |
51 | # define FILTER_SHIFT 30 |
52 | # define DELEM int32_t |
53 | # define FELEM int32_t |
54 | # define FELEM2 int64_t |
55 | # define FELEM_MAX INT32_MAX |
56 | # define FELEM_MIN INT32_MIN |
57 | # define FOFFSET (1<<(FILTER_SHIFT-1)) |
58 | # define OUT(d, v) (d) = av_clipl_int32((v)>>FILTER_SHIFT) |
59 | |
60 | #elif defined(TEMPLATE_RESAMPLE_S16) |
61 | |
62 | # define RENAME(N) N ## _int16 |
63 | # define FILTER_SHIFT 15 |
64 | # define DELEM int16_t |
65 | # define FELEM int16_t |
66 | # define FELEM2 int32_t |
67 | # define FELEML int64_t |
68 | # define FELEM_MAX INT16_MAX |
69 | # define FELEM_MIN INT16_MIN |
70 | # define FOFFSET (1<<(FILTER_SHIFT-1)) |
71 | # define OUT(d, v) (d) = av_clip_int16((v)>>FILTER_SHIFT) |
72 | |
73 | #endif |
74 | |
75 | static void RENAME(resample_one)(void *dest, const void *source, |
76 | int dst_size, int64_t index2, int64_t incr) |
77 | { |
78 | DELEM *dst = dest; |
79 | const DELEM *src = source; |
80 | int dst_index; |
81 | |
82 | for (dst_index = 0; dst_index < dst_size; dst_index++) { |
83 | dst[dst_index] = src[index2 >> 32]; |
84 | index2 += incr; |
85 | } |
86 | } |
87 | |
88 | static int RENAME(resample_common)(ResampleContext *c, |
89 | void *dest, const void *source, |
90 | int n, int update_ctx) |
91 | { |
92 | DELEM *dst = dest; |
93 | const DELEM *src = source; |
94 | int dst_index; |
95 | int index= c->index; |
96 | int frac= c->frac; |
97 | int sample_index = 0; |
98 | |
99 | while (index >= c->phase_count) { |
100 | sample_index++; |
101 | index -= c->phase_count; |
102 | } |
103 | |
104 | for (dst_index = 0; dst_index < n; dst_index++) { |
105 | FELEM *filter = ((FELEM *) c->filter_bank) + c->filter_alloc * index; |
106 | |
107 | FELEM2 val = FOFFSET; |
108 | FELEM2 val2= 0; |
109 | int i; |
110 | for (i = 0; i + 1 < c->filter_length; i+=2) { |
111 | val += src[sample_index + i ] * (FELEM2)filter[i ]; |
112 | val2 += src[sample_index + i + 1] * (FELEM2)filter[i + 1]; |
113 | } |
114 | if (i < c->filter_length) |
115 | val += src[sample_index + i ] * (FELEM2)filter[i ]; |
116 | #ifdef FELEML |
117 | OUT(dst[dst_index], val + (FELEML)val2); |
118 | #else |
119 | OUT(dst[dst_index], val + val2); |
120 | #endif |
121 | |
122 | frac += c->dst_incr_mod; |
123 | index += c->dst_incr_div; |
124 | if (frac >= c->src_incr) { |
125 | frac -= c->src_incr; |
126 | index++; |
127 | } |
128 | |
129 | while (index >= c->phase_count) { |
130 | sample_index++; |
131 | index -= c->phase_count; |
132 | } |
133 | } |
134 | |
135 | if(update_ctx){ |
136 | c->frac= frac; |
137 | c->index= index; |
138 | } |
139 | |
140 | return sample_index; |
141 | } |
142 | |
143 | static int RENAME(resample_linear)(ResampleContext *c, |
144 | void *dest, const void *source, |
145 | int n, int update_ctx) |
146 | { |
147 | DELEM *dst = dest; |
148 | const DELEM *src = source; |
149 | int dst_index; |
150 | int index= c->index; |
151 | int frac= c->frac; |
152 | int sample_index = 0; |
153 | #if FILTER_SHIFT == 0 |
154 | double inv_src_incr = 1.0 / c->src_incr; |
155 | #endif |
156 | |
157 | while (index >= c->phase_count) { |
158 | sample_index++; |
159 | index -= c->phase_count; |
160 | } |
161 | |
162 | for (dst_index = 0; dst_index < n; dst_index++) { |
163 | FELEM *filter = ((FELEM *) c->filter_bank) + c->filter_alloc * index; |
164 | FELEM2 val = FOFFSET, v2 = FOFFSET; |
165 | |
166 | int i; |
167 | for (i = 0; i < c->filter_length; i++) { |
168 | val += src[sample_index + i] * (FELEM2)filter[i]; |
169 | v2 += src[sample_index + i] * (FELEM2)filter[i + c->filter_alloc]; |
170 | } |
171 | #ifdef FELEML |
172 | val += (v2 - val) * (FELEML) frac / c->src_incr; |
173 | #else |
174 | # if FILTER_SHIFT == 0 |
175 | val += (v2 - val) * inv_src_incr * frac; |
176 | # else |
177 | val += (v2 - val) / c->src_incr * frac; |
178 | # endif |
179 | #endif |
180 | OUT(dst[dst_index], val); |
181 | |
182 | frac += c->dst_incr_mod; |
183 | index += c->dst_incr_div; |
184 | if (frac >= c->src_incr) { |
185 | frac -= c->src_incr; |
186 | index++; |
187 | } |
188 | |
189 | while (index >= c->phase_count) { |
190 | sample_index++; |
191 | index -= c->phase_count; |
192 | } |
193 | } |
194 | |
195 | if(update_ctx){ |
196 | c->frac= frac; |
197 | c->index= index; |
198 | } |
199 | |
200 | return sample_index; |
201 | } |
202 | |
203 | #undef RENAME |
204 | #undef FILTER_SHIFT |
205 | #undef DELEM |
206 | #undef FELEM |
207 | #undef FELEM2 |
208 | #undef FELEML |
209 | #undef FELEM_MAX |
210 | #undef FELEM_MIN |
211 | #undef OUT |
212 | #undef FOFFSET |
213 |