]> git.sesse.net Git - ffmpeg/blob - libswresample/resample_template.c
Merge commit 'cdab9db2adeec46b3984309c8c651bdd737d2b6b'
[ffmpeg] / libswresample / resample_template.c
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 OUT(d, v) d = v
36
37 #elif    defined(TEMPLATE_RESAMPLE_FLT)
38
39 #    define RENAME(N) N ## _float
40 #    define FILTER_SHIFT 0
41 #    define DELEM  float
42 #    define FELEM  float
43 #    define FELEM2 float
44 #    define OUT(d, v) d = v
45
46 #elif defined(TEMPLATE_RESAMPLE_S32)
47
48 #    define RENAME(N) N ## _int32
49 #    define FILTER_SHIFT 30
50 #    define DELEM  int32_t
51 #    define FELEM  int32_t
52 #    define FELEM2 int64_t
53 #    define FELEM_MAX INT32_MAX
54 #    define FELEM_MIN INT32_MIN
55 #    define OUT(d, v) v = (v + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT;\
56                       d = (uint64_t)(v + 0x80000000) > 0xFFFFFFFF ? (v>>63) ^ 0x7FFFFFFF : v
57
58 #elif    defined(TEMPLATE_RESAMPLE_S16)
59
60 #    define RENAME(N) N ## _int16
61 #    define FILTER_SHIFT 15
62 #    define DELEM  int16_t
63 #    define FELEM  int16_t
64 #    define FELEM2 int32_t
65 #    define FELEML int64_t
66 #    define FELEM_MAX INT16_MAX
67 #    define FELEM_MIN INT16_MIN
68 #    define OUT(d, v) v = (v + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT;\
69                       d = (unsigned)(v + 32768) > 65535 ? (v>>31) ^ 32767 : v
70
71 #endif
72
73 static void RENAME(resample_one)(DELEM *dst, const DELEM *src,
74                                  int dst_size, int64_t index2, int64_t incr)
75 {
76     int dst_index;
77
78     for (dst_index = 0; dst_index < dst_size; dst_index++) {
79         dst[dst_index] = src[index2 >> 32];
80         index2 += incr;
81     }
82 }
83
84 static int RENAME(resample_common)(ResampleContext *c,
85                                    DELEM *dst, const DELEM *src,
86                                    int n, int update_ctx)
87 {
88     int dst_index;
89     int index= c->index;
90     int frac= c->frac;
91     int sample_index = index >> c->phase_shift;
92
93     index &= c->phase_mask;
94     for (dst_index = 0; dst_index < n; dst_index++) {
95         FELEM *filter = ((FELEM *) c->filter_bank) + c->filter_alloc * index;
96
97         FELEM2 val=0;
98         int i;
99         for (i = 0; i < c->filter_length; i++) {
100             val += src[sample_index + i] * (FELEM2)filter[i];
101         }
102         OUT(dst[dst_index], val);
103
104         frac  += c->dst_incr_mod;
105         index += c->dst_incr_div;
106         if (frac >= c->src_incr) {
107             frac -= c->src_incr;
108             index++;
109         }
110         sample_index += index >> c->phase_shift;
111         index &= c->phase_mask;
112     }
113
114     if(update_ctx){
115         c->frac= frac;
116         c->index= index;
117     }
118
119     return sample_index;
120 }
121
122 static int RENAME(resample_linear)(ResampleContext *c,
123                                    DELEM *dst, const DELEM *src,
124                                    int n, int update_ctx)
125 {
126     int dst_index;
127     int index= c->index;
128     int frac= c->frac;
129     int sample_index = index >> c->phase_shift;
130 #if FILTER_SHIFT == 0
131     double inv_src_incr = 1.0 / c->src_incr;
132 #endif
133
134     index &= c->phase_mask;
135     for (dst_index = 0; dst_index < n; dst_index++) {
136         FELEM *filter = ((FELEM *) c->filter_bank) + c->filter_alloc * index;
137         FELEM2 val=0, v2 = 0;
138
139         int i;
140         for (i = 0; i < c->filter_length; i++) {
141             val += src[sample_index + i] * (FELEM2)filter[i];
142             v2  += src[sample_index + i] * (FELEM2)filter[i + c->filter_alloc];
143         }
144 #ifdef FELEML
145         val += (v2 - val) * (FELEML) frac / c->src_incr;
146 #else
147 #    if FILTER_SHIFT == 0
148         val += (v2 - val) * inv_src_incr * frac;
149 #    else
150         val += (v2 - val) / c->src_incr * frac;
151 #    endif
152 #endif
153         OUT(dst[dst_index], val);
154
155         frac += c->dst_incr_mod;
156         index += c->dst_incr_div;
157         if (frac >= c->src_incr) {
158             frac -= c->src_incr;
159             index++;
160         }
161         sample_index += index >> c->phase_shift;
162         index &= c->phase_mask;
163     }
164
165     if(update_ctx){
166         c->frac= frac;
167         c->index= index;
168     }
169
170     return sample_index;
171 }
172
173 #undef RENAME
174 #undef FILTER_SHIFT
175 #undef DELEM
176 #undef FELEM
177 #undef FELEM2
178 #undef FELEML
179 #undef FELEM_MAX
180 #undef FELEM_MIN
181 #undef OUT