Credit Andrew - fix vorbis audio which was scratchy and ensure aging plugin does...
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / interp.h
1 /*
2  * This program is free software; you can redistribute it and/or modify it
3  * under the terms of the GNU General Public License as published
4  * by the Free Software Foundation; either version 2 of the License, or
5  * (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful, but
8  * WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10  * General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public
13  * License along with this program; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
15  * USA
16  */
17
18
19 #ifndef __INTERP__
20 #define __INTERP__
21
22 /* fractional input interpolation
23  interp = nearest, bi_linear, bi_cubic
24  typical use:
25
26  type **in_rows = (type**)in->get_rows();
27  type **out_rows = (type**)out->get_rows();
28  int ow = out->get_w(), oh = out->get_h();
29  type offset[4] = { 0, chroma, chroma, 0 };
30  type bkgrnd[4] = { 0, chroma, chroma, 0 };
31  INTERP_SETUP(in_rows, max, 0,0, width,height); 
32
33  for( int oy=0; oy<oh; ++oy ) {
34    type *out_row = out_rows[y];
35    for( ox=0; ox<ow; ++ox ) {
36      float x_in = remap_x(ox,oy), y_in = remap_y(ox,oy);
37      interp##_SETUP(type, components, x_in, y_in); \
38      *out_row++ = interp##_interp(offset[i], bkgrnd[i]); \
39      for( int i=1; i<components; ++i ) {
40        interp##_next();
41        *out_row++ = interp##_interp(offset[i], bkgrnd[i]); \
42      }
43    }
44  }
45 */
46
47 static inline float in_clip(float v, float mx)
48 {
49         return v < 0 ? 0 : v > mx ? mx : v;
50 }
51
52 static inline float interp_linear(float dx, float p1, float p2)
53 {
54         return p1 * (1-dx) + p2 * dx;
55 }
56
57 static inline float interp_cubic(float dx, float p0, float p1, float p2, float p3)
58 { /* Catmull-Rom - not bad */
59         return ((( (- p0 + 3*p1 - 3*p2 + p3) * dx +
60                 ( 2*p0 - 5*p1 + 4*p2 - p3 ) ) * dx +
61                 ( - p0 + p2 ) ) * dx + (p1 + p1)) / 2;
62 }
63
64
65 #define INTERP_SETUP(rows, max, x_in_min,y_in_min, x_in_max,y_in_max) \
66         void **interp_rows = (void **)(rows);  float in_max = (max);  \
67         int in_min_x = (x_in_min), in_max_x = (x_in_max); \
68         int in_min_y = (y_in_min), in_max_y = (y_in_max)
69
70
71 #define nearest_SETUP(typ, components, tx, ty) \
72         int itx = (tx), ity = (ty), in_comps = (components); \
73         int c0 = itx+0, r0 = ity+0; \
74         typ *r0p = r0>=in_min_y && r0<in_max_y ? ((typ**)interp_rows)[r0] : 0
75
76 #define NEAREST_ROW(in_row, ofs, bg) (!in_row ? bg - ofs : ( \
77         (c0>=in_min_x && c0<in_max_x ? in_row[c0*in_comps] : bg) - ofs))
78
79 #define nearest_interp(ofs, bg) in_clip(NEAREST_ROW(r0p, ofs, bg) + ofs, in_max)
80
81 #define nearest_next(s) { if(r0p) ++r0p; }
82
83
84 #define bi_linear_SETUP(typ, components, tx, ty) \
85         const int in_comps = components; \
86         float fx = (tx), fy = (ty); \
87         int c0 = floorf(fx), r0 = floorf(fy); \
88         float dx = fx-c0, dy = fy-r0; \
89         int c1 = c0+1, r1 = r0+1; \
90         typ *r0p = r0>=in_min_y && r0<in_max_y ? ((typ**)interp_rows)[r0] : 0; \
91         typ *r1p = r1>=in_min_y && r1<in_max_y ? ((typ**)interp_rows)[r1] : 0
92
93 #define LINEAR_ROW(in_row, ofs, bg) (!in_row ? bg - ofs : interp_linear(dx, \
94         (c0>=in_min_x && c0<in_max_x ? in_row[c0*in_comps] : bg) - ofs, \
95         (c1>=in_min_x && c1<in_max_x ? in_row[c1*in_comps] : bg) - ofs))
96
97 #define bi_linear_interp(ofs, bg) in_clip(interp_linear(dy, \
98         LINEAR_ROW(r0p, ofs, bg), LINEAR_ROW(r1p, ofs, bg)) + ofs, in_max)
99
100 #define bi_linear_next(s) { if(r0p) ++r0p;  if(r1p) ++r1p; }
101
102
103 #define bi_cubic_SETUP(typ, components, tx, ty) \
104         const int in_comps = components; \
105         float fx = (tx), fy = (ty); \
106         int c0 = floorf(fx), r0 = floorf(fy); \
107         float dx = fx-c0, dy = fy-r0; \
108         int cp = c0-1, c1 = c0+1, c2 = c0+2; \
109         int rp = r0-1, r1 = r0+1, r2 = r0+2; \
110         typ *rpp = rp>=in_min_y && rp<in_max_y ? ((typ**)interp_rows)[rp] : 0; \
111         typ *r0p = r0>=in_min_y && r0<in_max_y ? ((typ**)interp_rows)[r0] : 0; \
112         typ *r1p = r1>=in_min_y && r1<in_max_y ? ((typ**)interp_rows)[r1] : 0; \
113         typ *r2p = r2>=in_min_y && r2<in_max_y ? ((typ**)interp_rows)[r2] : 0
114
115 #define CUBIC_ROW(in_row, ofs, bg) (!in_row ? bg - ofs : interp_cubic(dx, \
116         (cp>=in_min_x && cp<in_max_x ? in_row[cp*in_comps] : bg) - ofs, \
117         (c0>=in_min_x && c0<in_max_x ? in_row[c0*in_comps] : bg) - ofs, \
118         (c1>=in_min_x && c1<in_max_x ? in_row[c1*in_comps] : bg) - ofs, \
119         (c2>=in_min_x && c2<in_max_x ? in_row[c2*in_comps] : bg) - ofs))
120
121 #define bi_cubic_interp(ofs, bg) in_clip(interp_cubic(dy, \
122         CUBIC_ROW(rpp, ofs, bg), CUBIC_ROW(r0p, ofs, bg), \
123         CUBIC_ROW(r1p, ofs, bg), CUBIC_ROW(r2p, ofs, bg)) + ofs, in_max)
124
125 #define bi_cubic_next(s) { if(rpp) ++rpp;  if(r0p) ++r0p;  if(r1p) ++r1p;  if(r2p) ++r2p; }
126
127 #endif