annotate src/filters/interp.h @ 437:20a9d5faf47c

now I can play two voices at once!
author Robert McIntyre <rlm@mit.edu>
date Wed, 25 Apr 2012 13:09:06 -0500
parents f9f4f1b99eed
children
rev   line source
rlm@1 1 /*
rlm@1 2 * This file is part of the Advance project.
rlm@1 3 *
rlm@1 4 * Copyright (C) 2003 Andrea Mazzoleni
rlm@1 5 *
rlm@1 6 * This program is free software; you can redistribute it and/or modify
rlm@1 7 * it under the terms of the GNU General Public License as published by
rlm@1 8 * the Free Software Foundation; either version 2 of the License, or
rlm@1 9 * (at your option) any later version.
rlm@1 10 *
rlm@1 11 * This program is distributed in the hope that it will be useful,
rlm@1 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
rlm@1 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
rlm@1 14 * GNU General Public License for more details.
rlm@1 15 *
rlm@1 16 * You should have received a copy of the GNU General Public License
rlm@1 17 * along with this program; if not, write to the Free Software
rlm@1 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
rlm@1 19 *
rlm@1 20 * In addition, as a special exception, Andrea Mazzoleni
rlm@1 21 * gives permission to link the code of this program with
rlm@1 22 * the MAME library (or with modified versions of MAME that use the
rlm@1 23 * same license as MAME), and distribute linked combinations including
rlm@1 24 * the two. You must obey the GNU General Public License in all
rlm@1 25 * respects for all of the code used other than MAME. If you modify
rlm@1 26 * this file, you may extend this exception to your version of the
rlm@1 27 * file, but you are not obligated to do so. If you do not wish to
rlm@1 28 * do so, delete this exception statement from your version.
rlm@1 29 */
rlm@1 30
rlm@1 31 #ifndef __INTERP_H
rlm@1 32 #define __INTERP_H
rlm@1 33
rlm@1 34 /***************************************************************************/
rlm@1 35 /* Basic types */
rlm@1 36
rlm@1 37 /***************************************************************************/
rlm@1 38 /* interpolation */
rlm@1 39
rlm@1 40 extern unsigned interp_mask[2];
rlm@1 41 extern unsigned interp_bits_per_pixel;
rlm@1 42
rlm@1 43 #define INTERP_16_MASK_1(v) (v & interp_mask[0])
rlm@1 44 #define INTERP_16_MASK_2(v) (v & interp_mask[1])
rlm@1 45
rlm@1 46 static inline u16 interp_16_521(u16 p1, u16 p2, u16 p3)
rlm@1 47 {
rlm@1 48 return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*5 + INTERP_16_MASK_1(p2)*2 + INTERP_16_MASK_1(p3)*1) / 8)
rlm@1 49 | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*5 + INTERP_16_MASK_2(p2)*2 + INTERP_16_MASK_2(p3)*1) / 8);
rlm@1 50 }
rlm@1 51
rlm@1 52 static inline u16 interp_16_332(u16 p1, u16 p2, u16 p3)
rlm@1 53 {
rlm@1 54 return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*3 + INTERP_16_MASK_1(p2)*3 + INTERP_16_MASK_1(p3)*2) / 8)
rlm@1 55 | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*3 + INTERP_16_MASK_2(p2)*3 + INTERP_16_MASK_2(p3)*2) / 8);
rlm@1 56 }
rlm@1 57
rlm@1 58 static inline u16 interp_16_611(u16 p1, u16 p2, u16 p3)
rlm@1 59 {
rlm@1 60 return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*6 + INTERP_16_MASK_1(p2) + INTERP_16_MASK_1(p3)) / 8)
rlm@1 61 | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*6 + INTERP_16_MASK_2(p2) + INTERP_16_MASK_2(p3)) / 8);
rlm@1 62 }
rlm@1 63
rlm@1 64 static inline u16 interp_16_71(u16 p1, u16 p2)
rlm@1 65 {
rlm@1 66 return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*7 + INTERP_16_MASK_1(p2)) / 8)
rlm@1 67 | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*7 + INTERP_16_MASK_2(p2)) / 8);
rlm@1 68 }
rlm@1 69
rlm@1 70 static inline u16 interp_16_211(u16 p1, u16 p2, u16 p3)
rlm@1 71 {
rlm@1 72 return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*2 + INTERP_16_MASK_1(p2) + INTERP_16_MASK_1(p3)) / 4)
rlm@1 73 | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*2 + INTERP_16_MASK_2(p2) + INTERP_16_MASK_2(p3)) / 4);
rlm@1 74 }
rlm@1 75
rlm@1 76 static inline u16 interp_16_772(u16 p1, u16 p2, u16 p3)
rlm@1 77 {
rlm@1 78 return INTERP_16_MASK_1(((INTERP_16_MASK_1(p1) + INTERP_16_MASK_1(p2))*7 + INTERP_16_MASK_1(p3)*2) / 16)
rlm@1 79 | INTERP_16_MASK_2(((INTERP_16_MASK_2(p1) + INTERP_16_MASK_2(p2))*7 + INTERP_16_MASK_2(p3)*2) / 16);
rlm@1 80 }
rlm@1 81
rlm@1 82 static inline u16 interp_16_11(u16 p1, u16 p2)
rlm@1 83 {
rlm@1 84 return INTERP_16_MASK_1((INTERP_16_MASK_1(p1) + INTERP_16_MASK_1(p2)) / 2)
rlm@1 85 | INTERP_16_MASK_2((INTERP_16_MASK_2(p1) + INTERP_16_MASK_2(p2)) / 2);
rlm@1 86 }
rlm@1 87
rlm@1 88 static inline u16 interp_16_31(u16 p1, u16 p2)
rlm@1 89 {
rlm@1 90 return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*3 + INTERP_16_MASK_1(p2)) / 4)
rlm@1 91 | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*3 + INTERP_16_MASK_2(p2)) / 4);
rlm@1 92 }
rlm@1 93
rlm@1 94 static inline u16 interp_16_1411(u16 p1, u16 p2, u16 p3)
rlm@1 95 {
rlm@1 96 return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*14 + INTERP_16_MASK_1(p2) + INTERP_16_MASK_1(p3)) / 16)
rlm@1 97 | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*14 + INTERP_16_MASK_2(p2) + INTERP_16_MASK_2(p3)) / 16);
rlm@1 98 }
rlm@1 99
rlm@1 100 static inline u16 interp_16_431(u16 p1, u16 p2, u16 p3)
rlm@1 101 {
rlm@1 102 return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*4 + INTERP_16_MASK_1(p2)*3 + INTERP_16_MASK_1(p3)) / 8)
rlm@1 103 | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*4 + INTERP_16_MASK_2(p2)*3 + INTERP_16_MASK_2(p3)) / 8);
rlm@1 104 }
rlm@1 105
rlm@1 106 static inline u16 interp_16_53(u16 p1, u16 p2)
rlm@1 107 {
rlm@1 108 return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*5 + INTERP_16_MASK_1(p2)*3) / 8)
rlm@1 109 | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*5 + INTERP_16_MASK_2(p2)*3) / 8);
rlm@1 110 }
rlm@1 111
rlm@1 112 static inline u16 interp_16_151(u16 p1, u16 p2)
rlm@1 113 {
rlm@1 114 return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*15 + INTERP_16_MASK_1(p2)) / 16)
rlm@1 115 | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*15 + INTERP_16_MASK_2(p2)) / 16);
rlm@1 116 }
rlm@1 117
rlm@1 118 static inline u16 interp_16_97(u16 p1, u16 p2)
rlm@1 119 {
rlm@1 120 return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*9 + INTERP_16_MASK_1(p2)*7) / 16)
rlm@1 121 | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*9 + INTERP_16_MASK_2(p2)*7) / 16);
rlm@1 122 }
rlm@1 123
rlm@1 124 #define INTERP_32_MASK_1(v) (v & 0xFF00FF)
rlm@1 125 #define INTERP_32_MASK_2(v) (v & 0x00FF00)
rlm@1 126
rlm@1 127 static inline u32 interp_32_521(u32 p1, u32 p2, u32 p3)
rlm@1 128 {
rlm@1 129 return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*5 + INTERP_32_MASK_1(p2)*2 + INTERP_32_MASK_1(p3)*1) / 8)
rlm@1 130 | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*5 + INTERP_32_MASK_2(p2)*2 + INTERP_32_MASK_2(p3)*1) / 8);
rlm@1 131 }
rlm@1 132
rlm@1 133 static inline u32 interp_32_332(u32 p1, u32 p2, u32 p3)
rlm@1 134 {
rlm@1 135 return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*3 + INTERP_32_MASK_1(p2)*3 + INTERP_32_MASK_1(p3)*2) / 8)
rlm@1 136 | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*3 + INTERP_32_MASK_2(p2)*3 + INTERP_32_MASK_2(p3)*2) / 8);
rlm@1 137 }
rlm@1 138
rlm@1 139 static inline u32 interp_32_211(u32 p1, u32 p2, u32 p3)
rlm@1 140 {
rlm@1 141 return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*2 + INTERP_32_MASK_1(p2) + INTERP_32_MASK_1(p3)) / 4)
rlm@1 142 | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*2 + INTERP_32_MASK_2(p2) + INTERP_32_MASK_2(p3)) / 4);
rlm@1 143 }
rlm@1 144
rlm@1 145 static inline u32 interp_32_611(u32 p1, u32 p2, u32 p3)
rlm@1 146 {
rlm@1 147 return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*6 + INTERP_32_MASK_1(p2) + INTERP_32_MASK_1(p3)) / 8)
rlm@1 148 | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*6 + INTERP_32_MASK_2(p2) + INTERP_32_MASK_2(p3)) / 8);
rlm@1 149 }
rlm@1 150
rlm@1 151 static inline u32 interp_32_71(u32 p1, u32 p2)
rlm@1 152 {
rlm@1 153 return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*7 + INTERP_32_MASK_1(p2)) / 8)
rlm@1 154 | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*7 + INTERP_32_MASK_2(p2)) / 8);
rlm@1 155 }
rlm@1 156
rlm@1 157 static inline u32 interp_32_772(u32 p1, u32 p2, u32 p3)
rlm@1 158 {
rlm@1 159 return INTERP_32_MASK_1(((INTERP_32_MASK_1(p1) + INTERP_32_MASK_1(p2))*7 + INTERP_32_MASK_1(p3)*2) / 16)
rlm@1 160 | INTERP_32_MASK_2(((INTERP_32_MASK_2(p1) + INTERP_32_MASK_2(p2))*7 + INTERP_32_MASK_2(p3)*2) / 16);
rlm@1 161 }
rlm@1 162
rlm@1 163 static inline u32 interp_32_11(u32 p1, u32 p2)
rlm@1 164 {
rlm@1 165 return INTERP_32_MASK_1((INTERP_32_MASK_1(p1) + INTERP_32_MASK_1(p2)) / 2)
rlm@1 166 | INTERP_32_MASK_2((INTERP_32_MASK_2(p1) + INTERP_32_MASK_2(p2)) / 2);
rlm@1 167 }
rlm@1 168
rlm@1 169 static inline u32 interp_32_31(u32 p1, u32 p2)
rlm@1 170 {
rlm@1 171 return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*3 + INTERP_32_MASK_1(p2)) / 4)
rlm@1 172 | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*3 + INTERP_32_MASK_2(p2)) / 4);
rlm@1 173 }
rlm@1 174
rlm@1 175 static inline u32 interp_32_1411(u32 p1, u32 p2, u32 p3)
rlm@1 176 {
rlm@1 177 return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*14 + INTERP_32_MASK_1(p2) + INTERP_32_MASK_1(p3)) / 16)
rlm@1 178 | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*14 + INTERP_32_MASK_2(p2) + INTERP_32_MASK_2(p3)) / 16);
rlm@1 179 }
rlm@1 180
rlm@1 181 static inline u32 interp_32_431(u32 p1, u32 p2, u32 p3)
rlm@1 182 {
rlm@1 183 return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*4 + INTERP_32_MASK_1(p2)*3 + INTERP_32_MASK_1(p3)) / 8)
rlm@1 184 | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*4 + INTERP_32_MASK_2(p2)*3 + INTERP_32_MASK_2(p3)) / 8);
rlm@1 185 }
rlm@1 186
rlm@1 187 static inline u32 interp_32_53(u32 p1, u32 p2)
rlm@1 188 {
rlm@1 189 return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*5 + INTERP_32_MASK_1(p2)*3) / 8)
rlm@1 190 | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*5 + INTERP_32_MASK_2(p2)*3) / 8);
rlm@1 191 }
rlm@1 192
rlm@1 193 static inline u32 interp_32_151(u32 p1, u32 p2)
rlm@1 194 {
rlm@1 195 return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*15 + INTERP_32_MASK_1(p2)) / 16)
rlm@1 196 | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*15 + INTERP_32_MASK_2(p2)) / 16);
rlm@1 197 }
rlm@1 198
rlm@1 199 static inline u32 interp_32_97(u32 p1, u32 p2)
rlm@1 200 {
rlm@1 201 return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*9 + INTERP_32_MASK_1(p2)*7) / 16)
rlm@1 202 | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*9 + INTERP_32_MASK_2(p2)*7) / 16);
rlm@1 203 }
rlm@1 204
rlm@1 205 /***************************************************************************/
rlm@1 206 /* diff */
rlm@1 207
rlm@1 208 #define INTERP_Y_LIMIT (0x30*4)
rlm@1 209 #define INTERP_U_LIMIT (0x07*4)
rlm@1 210 #define INTERP_V_LIMIT (0x06*8)
rlm@1 211
rlm@1 212 static int interp_16_diff(u16 p1, u16 p2)
rlm@1 213 {
rlm@1 214 int r, g, b;
rlm@1 215 int y, u, v;
rlm@1 216
rlm@1 217 if (p1 == p2)
rlm@1 218 return 0;
rlm@1 219
rlm@1 220 if (interp_bits_per_pixel == 16) {
rlm@1 221 b = (int)((p1 & 0x1F) - (p2 & 0x1F)) << 3;
rlm@1 222 g = (int)((p1 & 0x7E0) - (p2 & 0x7E0)) >> 3;
rlm@1 223 r = (int)((p1 & 0xF800) - (p2 & 0xF800)) >> 8;
rlm@1 224 } else {
rlm@1 225 b = (int)((p1 & 0x1F) - (p2 & 0x1F)) << 3;
rlm@1 226 g = (int)((p1 & 0x3E0) - (p2 & 0x3E0)) >> 2;
rlm@1 227 r = (int)((p1 & 0x7C00) - (p2 & 0x7C00)) >> 7;
rlm@1 228 }
rlm@1 229
rlm@1 230 y = r + g + b;
rlm@1 231 u = r - b;
rlm@1 232 v = -r + 2*g - b;
rlm@1 233
rlm@1 234 if (y < -INTERP_Y_LIMIT || y > INTERP_Y_LIMIT)
rlm@1 235 return 1;
rlm@1 236
rlm@1 237 if (u < -INTERP_U_LIMIT || u > INTERP_U_LIMIT)
rlm@1 238 return 1;
rlm@1 239
rlm@1 240 if (v < -INTERP_V_LIMIT || v > INTERP_V_LIMIT)
rlm@1 241 return 1;
rlm@1 242
rlm@1 243 return 0;
rlm@1 244 }
rlm@1 245
rlm@1 246 static int interp_32_diff(u32 p1, u32 p2)
rlm@1 247 {
rlm@1 248 int r, g, b;
rlm@1 249 int y, u, v;
rlm@1 250
rlm@1 251 if ((p1 & 0xF8F8F8) == (p2 & 0xF8F8F8))
rlm@1 252 return 0;
rlm@1 253
rlm@1 254 b = (int)((p1 & 0xFF) - (p2 & 0xFF));
rlm@1 255 g = (int)((p1 & 0xFF00) - (p2 & 0xFF00)) >> 8;
rlm@1 256 r = (int)((p1 & 0xFF0000) - (p2 & 0xFF0000)) >> 16;
rlm@1 257
rlm@1 258 y = r + g + b;
rlm@1 259 u = r - b;
rlm@1 260 v = -r + 2*g - b;
rlm@1 261
rlm@1 262 if (y < -INTERP_Y_LIMIT || y > INTERP_Y_LIMIT)
rlm@1 263 return 1;
rlm@1 264
rlm@1 265 if (u < -INTERP_U_LIMIT || u > INTERP_U_LIMIT)
rlm@1 266 return 1;
rlm@1 267
rlm@1 268 if (v < -INTERP_V_LIMIT || v > INTERP_V_LIMIT)
rlm@1 269 return 1;
rlm@1 270
rlm@1 271 return 0;
rlm@1 272 }
rlm@1 273
rlm@1 274
rlm@1 275 #define INTERP_LIMIT2 (96000)
rlm@1 276 #define ABS(x) ((x) < 0 ? -(x) : (x))
rlm@1 277 #define MAX(x,y) ((x) > (y) ? (x) : (y))
rlm@1 278 #define MIN(x,y) ((x) < (y) ? (x) : (y))
rlm@1 279
rlm@1 280 static int interp_16_diff2(u16 p1, u16 p2)
rlm@1 281 {
rlm@1 282 int r, g, b;
rlm@1 283 int y, u, v;
rlm@1 284
rlm@1 285 if ((p1 & 0xF79E) == (p2 & 0xF79E))
rlm@1 286 return 0;
rlm@1 287
rlm@1 288 if (interp_bits_per_pixel == 16) {
rlm@1 289 b = (int)((p1 & 0x1F) - (p2 & 0x1F)) << 3;
rlm@1 290 g = (int)((p1 & 0x7E0) - (p2 & 0x7E0)) >> 3;
rlm@1 291 r = (int)((p1 & 0xF800) - (p2 & 0xF800)) >> 8;
rlm@1 292 } else {
rlm@1 293 b = (int)((p1 & 0x1F) - (p2 & 0x1F)) << 3;
rlm@1 294 g = (int)((p1 & 0x3E0) - (p2 & 0x3E0)) >> 2;
rlm@1 295 r = (int)((p1 & 0x7C00) - (p2 & 0x7C00)) >> 7;
rlm@1 296 }
rlm@1 297
rlm@1 298 // yb = 30*r + 58*g + 12*b;
rlm@1 299 y = 33*r + 36*g + 31*b;
rlm@1 300 u = -14*r - 29*g + 44*b;
rlm@1 301 v = 62*r - 51*g - 10*b;
rlm@1 302
rlm@1 303 if (11*ABS(y) + 8*ABS(u) + 6*ABS(v) > INTERP_LIMIT2)
rlm@1 304 return 1;
rlm@1 305 return 0;
rlm@1 306 }
rlm@1 307
rlm@1 308 static int interp_32_diff2(u32 p1, u32 p2)
rlm@1 309 {
rlm@1 310 int r, g, b;
rlm@1 311 int y, u, v;
rlm@1 312
rlm@1 313 if ((p1 & 0xF0F0F0) == (p2 & 0xF0F0F0))
rlm@1 314 return 0;
rlm@1 315
rlm@1 316 b = (int)((p1 & 0xF8) - (p2 & 0xF8));
rlm@1 317 g = (int)((p1 & 0xF800) - (p2 & 0xF800)) >> 8;
rlm@1 318 r = (int)((p1 & 0xF80000) - (p2 & 0xF80000)) >> 16;
rlm@1 319
rlm@1 320 // y = 30*r + 58*g + 12*b;
rlm@1 321 y = 33*r + 36*g + 31*b;
rlm@1 322 u = -14*r - 29*g + 44*b;
rlm@1 323 v = 62*r - 51*g - 10*b;
rlm@1 324
rlm@1 325 if (11*ABS(y) + 8*ABS(u) + 6*ABS(v) > INTERP_LIMIT2)
rlm@1 326 return 1;
rlm@1 327
rlm@1 328 return 0;
rlm@1 329 }
rlm@1 330
rlm@1 331 static void interp_set(unsigned bits_per_pixel)
rlm@1 332 {
rlm@1 333 interp_bits_per_pixel = bits_per_pixel;
rlm@1 334
rlm@1 335 switch (bits_per_pixel) {
rlm@1 336 case 15 :
rlm@1 337 interp_mask[0] = 0x7C1F;
rlm@1 338 interp_mask[1] = 0x03E0;
rlm@1 339 break;
rlm@1 340 case 16 :
rlm@1 341 interp_mask[0] = 0xF81F;
rlm@1 342 interp_mask[1] = 0x07E0;
rlm@1 343 break;
rlm@1 344 case 32 :
rlm@1 345 interp_mask[0] = 0xFF00FF;
rlm@1 346 interp_mask[1] = 0x00FF00;
rlm@1 347 break;
rlm@1 348 }
rlm@1 349 }
rlm@1 350
rlm@1 351 #endif