home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / Kasumi / source / resample_kernels.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  6.9 KB  |  256 lines

  1. #include <math.h>
  2. #include <vd2/Kasumi/resample_kernels.h>
  3.  
  4. ///////////////////////////////////////////////////////////////////////////
  5. //
  6. // utility functions
  7. //
  8. ///////////////////////////////////////////////////////////////////////////
  9.  
  10. namespace {
  11.     inline sint32 scale32x32_fp16(sint32 x, sint32 y) {
  12.         return (sint32)(((sint64)x * y + 0x8000) >> 16);
  13.     }
  14.  
  15.     inline double sinc(double x) {
  16.         return fabs(x) < 1e-9 ? 1.0 : sin(x) / x;
  17.     }
  18. }
  19.  
  20. ///////////////////////////////////////////////////////////////////////////
  21. //
  22. // VDResamplerAxis
  23. //
  24. ///////////////////////////////////////////////////////////////////////////
  25.  
  26. void VDResamplerAxis::Init(sint32 dudx) {
  27.     this->dudx = dudx;
  28. }
  29.  
  30. void VDResamplerAxis::Compute(sint32 count, sint32 u0, sint32 w, sint32 kernel_width) {
  31.     u = u0;
  32.     dx = count;
  33.  
  34.     sint32 du_kern    = (kernel_width-1) << 16;
  35.     sint32 u2        = u + dudx*(dx-1);
  36.     sint32 u_limit    = w << 16;
  37.  
  38.     dx_precopy    = 0;
  39.     dx_preclip    = 0;
  40.     dx_active    = 0;
  41.     dx_postclip    = 0;
  42.     dx_postcopy = 0;
  43.     dx_dualclip    = 0;
  44.  
  45.     sint32 dx_temp = dx;
  46.     sint32 u_start = u;
  47.  
  48.     // (desired - u0 + (dudx-1)) / dudx : first pixel >= desired
  49.  
  50.     sint32 dudx_m1_mu0    = dudx - 1 - u;
  51.     sint32 first_preclip    = (dudx_m1_mu0 + 0x10000 - du_kern) / dudx;
  52.     sint32 first_active        = (dudx_m1_mu0                    ) / dudx;
  53.     sint32 first_postclip    = (dudx_m1_mu0 + u_limit - du_kern) / dudx;
  54.     sint32 first_postcopy    = (dudx_m1_mu0 + u_limit - 0x10000) / dudx;
  55.  
  56.     // clamp
  57.     if (first_preclip < 0)
  58.         first_preclip = 0;
  59.     if (first_active < first_preclip)
  60.         first_active = first_preclip;
  61.     if (first_postclip < first_active)
  62.         first_postclip = first_active;
  63.     if (first_postcopy < first_postclip)
  64.         first_postcopy = first_postclip;
  65.     if (first_preclip > dx)
  66.         first_preclip = dx;
  67.     if (first_active > dx)
  68.         first_active = dx;
  69.     if (first_postclip > dx)
  70.         first_postclip = dx;
  71.     if (first_postcopy > dx)
  72.         first_postcopy = dx;
  73.  
  74.     // determine widths
  75.  
  76.     dx_precopy    = first_preclip;
  77.     dx_preclip    = first_active - first_preclip;
  78.     dx_active    = first_postclip - first_active;
  79.     dx_postclip    = first_postcopy - first_postclip;
  80.     dx_postcopy    = dx - first_postcopy;
  81.  
  82.     // sanity checks
  83.     sint32 pos0 = dx_precopy;
  84.     sint32 pos1 = pos0 + dx_preclip;
  85.     sint32 pos2 = pos1 + dx_active;
  86.     sint32 pos3 = pos2 + dx_postclip;
  87.  
  88.     VDASSERT(!((dx_precopy|dx_preclip|dx_active|dx_postcopy|dx_postclip) & 0x80000000));
  89.     VDASSERT(dx_precopy + dx_preclip + dx_active + dx_postcopy + dx_postclip == dx);
  90.  
  91.     VDASSERT(!pos0            || u_start + dudx*(pos0 - 1) <  0x10000 - du_kern);    // precopy -> preclip
  92.     VDASSERT( pos0 >= pos1    || u_start + dudx*(pos0    ) >= 0x10000 - du_kern);
  93.     VDASSERT( pos1 <= pos0    || u_start + dudx*(pos1 - 1) <  0);                    // preclip -> active
  94.     VDASSERT( pos1 >= pos2    || u_start + dudx*(pos1    ) >= 0 || !dx_active);
  95.     VDASSERT( pos2 <= pos1    || u_start + dudx*(pos2 - 1) <  u_limit - du_kern || !dx_active);    // active -> postclip
  96.     VDASSERT( pos2 >= pos3    || u_start + dudx*(pos2    ) >= u_limit - du_kern);
  97.     VDASSERT( pos3 <= pos2    || u_start + dudx*(pos3 - 1) <  u_limit - 0x10000);    // postclip -> postcopy
  98.     VDASSERT( pos3 >= dx    || u_start + dudx*(pos3    ) >= u_limit - 0x10000);
  99.  
  100.     u += dx_precopy * dudx;
  101.  
  102.     // test for overlapping clipping regions
  103.     if (!dx_active && kernel_width > w) {
  104.         dx_dualclip = dx_preclip + dx_postclip;
  105.         dx_preclip = dx_postclip = 0;
  106.     }
  107. }
  108.  
  109. ///////////////////////////////////////////////////////////////////////////
  110. //
  111. // VDResamplerLinearFilter
  112. //
  113. ///////////////////////////////////////////////////////////////////////////
  114.  
  115. VDResamplerLinearFilter::VDResamplerLinearFilter(double twofc)
  116.     : mScale(twofc)
  117.     , mTaps((int)ceil(1.0 / twofc) * 2)
  118. {
  119. }
  120.  
  121. int VDResamplerLinearFilter::GetFilterWidth() const {
  122.     return mTaps;
  123. }
  124.  
  125. double VDResamplerLinearFilter::EvaluateFilter(double t) const {
  126.     t = 1.0f - fabs(t)*mScale;
  127.  
  128.     return t + fabs(t);
  129. }
  130.  
  131. void VDResamplerLinearFilter::GenerateFilter(float *dst, double offset) const {
  132.     double pos = -((double)((mTaps>>1)-1) + offset) * mScale;
  133.  
  134.     for(unsigned i=0; i<mTaps; ++i) {
  135.         double t = 1.0 - fabs(pos);
  136.  
  137.         *dst++ = (float)(t+fabs(t));
  138.         pos += mScale;
  139.     }
  140. }
  141.  
  142. void VDResamplerLinearFilter::GenerateFilterBank(float *dst) const {
  143.     for(int offset=0; offset<256; ++offset) {
  144.         GenerateFilter(dst, offset * (1.0f / 256.0f));
  145.         dst += mTaps;
  146.     }
  147. }
  148.  
  149. ///////////////////////////////////////////////////////////////////////////
  150. //
  151. // VDResamplerCubicFilter
  152. //
  153. ///////////////////////////////////////////////////////////////////////////
  154.  
  155. VDResamplerCubicFilter::VDResamplerCubicFilter(double twofc, double A)
  156.     : mScale(twofc)
  157.     , mA0( 1.0  )
  158.     , mA2(-3.0-A)
  159.     , mA3( 2.0+A)
  160.     , mB0(-4.0*A)
  161.     , mB1( 8.0*A)
  162.     , mB2(-5.0*A)
  163.     , mB3(     A)
  164.     , mTaps((int)ceil(2.0 / twofc)*2)
  165. {
  166. }
  167.  
  168. int VDResamplerCubicFilter::GetFilterWidth() const { return mTaps; }
  169.  
  170. double VDResamplerCubicFilter::EvaluateFilter(double t) const {
  171.     t = fabs(t)*mScale;
  172.  
  173.     if (t < 1.0)
  174.         return mA0 + (t*t)*(mA2 + t*mA3);
  175.     else if (t < 2.0)
  176.         return mB0 + t*(mB1 + t*(mB2 + t*mB3));
  177.     else
  178.         return 0;
  179. }
  180.  
  181. void VDResamplerCubicFilter::GenerateFilter(float *dst, double offset) const {
  182.     double pos = -((double)((mTaps>>1)-1) + offset) * mScale;
  183.  
  184.     for(unsigned i=0; i<mTaps; ++i) {
  185.         double t = fabs(pos);
  186.         double v = 0;
  187.  
  188.         if (t < 1.0)
  189.             v = mA0 + (t*t)*(mA2 + t*mA3);
  190.         else if (t < 2.0)
  191.             v = mB0 + t*(mB1 + t*(mB2 + t*mB3));
  192.  
  193.         *dst++ = (float)v;
  194.         pos += mScale;
  195.     }
  196. }
  197.  
  198. void VDResamplerCubicFilter::GenerateFilterBank(float *dst) const {
  199.     for(int offset=0; offset<256; ++offset) {
  200.         GenerateFilter(dst, offset * (1.0f / 256.0f));
  201.         dst += mTaps;
  202.     }
  203. }
  204.  
  205. ///////////////////////////////////////////////////////////////////////////
  206. //
  207. // VDResamplerLanczos3Filter
  208. //
  209. ///////////////////////////////////////////////////////////////////////////
  210.  
  211. VDResamplerLanczos3Filter::VDResamplerLanczos3Filter(double twofc)
  212.     : mScale(twofc)
  213.     , mTaps((int)ceil(3.0 / twofc)*2)
  214. {
  215. }
  216.  
  217. int VDResamplerLanczos3Filter::GetFilterWidth() const {
  218.     return mTaps;
  219. }
  220.  
  221. double VDResamplerLanczos3Filter::EvaluateFilter(double t) const {
  222.     static const double pi  = 3.1415926535897932384626433832795;    // pi
  223.     static const double pi3 = 1.0471975511965977461542144610932;    // pi/3
  224.  
  225.     t *= mScale;
  226.  
  227.     if (fabs(t) < 3.0)
  228.         return sinc(pi*t) * sinc(pi3*t);
  229.     else
  230.         return 0.0;
  231. }
  232.  
  233. void VDResamplerLanczos3Filter::GenerateFilter(float *dst, double offset) const {
  234.     static const double pi  = 3.1415926535897932384626433832795;    // pi
  235.     static const double pi3 = 1.0471975511965977461542144610932;    // pi/3
  236.  
  237.     double t = -(((double)((mTaps>>1)-1) + offset) * mScale);
  238.  
  239.     for(unsigned i=0; i<mTaps; ++i) {
  240.         double v = 0;
  241.  
  242.         if (fabs(t) < 3.0)
  243.             v = sinc(pi*t) * sinc(pi3*t);
  244.  
  245.         *dst++ = (float)v;
  246.         t += mScale;
  247.     }
  248. }
  249.  
  250. void VDResamplerLanczos3Filter::GenerateFilterBank(float *dst) const {
  251.     for(int offset=0; offset<256; ++offset) {
  252.         GenerateFilter(dst, offset * (1.0f / 256.0f));
  253.         dst += mTaps;
  254.     }
  255. }
  256.