swresample/rematrix: fix update of channel matrix if input or output layout is undefined
[ffmpeg.git] / 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 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