lowpass-notch-decode.fs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. #version 150
  2. #in filtertaps
  3. #in lumacutoff
  4. #in chromacutoff
  5. uniform sampler2D source[];
  6. uniform vec4 sourceSize[];
  7. uniform int phase;
  8. in Vertex {
  9. vec2 texCoord;
  10. };
  11. out vec4 fragColor;
  12. vec4 sample(vec2 coord) {
  13. const float min = 0.350*0.746;
  14. const float max = 1.962;
  15. const float black = 0.518;
  16. if (coord.x < 0.0 || coord.x > 1.0) return vec4(0.0);
  17. return (texture(source[0], coord) * vec4(max-min) + vec4(min-black)) / vec4(max-black);
  18. }
  19. vec4 sinc(vec4 x) {
  20. x = max(abs(x),vec4(0.0001));
  21. return sin(x)/x;
  22. }
  23. vec2 sinc(vec2 x) {
  24. x = max(abs(x),vec2(0.0001));
  25. return sin(x)/x;
  26. }
  27. void main() {
  28. const int width = filtertaps;
  29. const float bw_y = lumacutoff/12.0;
  30. const float bw_c = chromacutoff/12.0;
  31. int x = int(floor(texCoord.x*sourceSize[0].x));
  32. int y = int(floor(texCoord.y*sourceSize[0].y));
  33. int p = (x+y+phase) % 3;
  34. const vec4 one = vec4(1.0);
  35. const float PI = 3.14159265359;
  36. const vec4 PI_6 = vec4(PI/6.0);
  37. float norm_y = 0.0;
  38. float norm_c = 0.0;
  39. vec3 yiq = vec3(0.0);
  40. vec4 samp = sample(texCoord + vec2((-width/2 )*sourceSize[0].z,0));
  41. vec4 samp2 = sample(texCoord + vec2((-width/2+1)*sourceSize[0].z,0));
  42. // Hamming window
  43. const float alpha = 0.54;
  44. const float beta = 0.46;
  45. int i;
  46. for (i = -width/2; i <= width/2-2; i++) {
  47. vec4 window = vec4(alpha) - vec4(beta) * cos(vec4(2.0*PI/(4*width-7))*(vec4(4*(width/2+i))+vec4(0,1,2,3)));
  48. vec4 t = vec4(i*4)+vec4(-1.5,-0.5,+0.5,+1.5);
  49. #define lowpass(freq,x) vec4(2.0*(freq))*sinc(vec4(2.0*PI*(freq))*(x))
  50. vec4 lumafilt = lowpass(bw_y, t);
  51. vec4 chromafilt = lowpass(bw_c, t);
  52. #undef lowpass
  53. vec4 samp3 = sample(texCoord + vec2((i+2)*sourceSize[0].z,0));
  54. vec4 rsamp = vec4(samp2.zw, samp3.xy);
  55. vec4 filt = window*lumafilt;
  56. yiq.x += dot(samp, filt) + dot(rsamp,filt);
  57. norm_y += dot(one, filt);
  58. filt = window*chromafilt;
  59. yiq.y += dot(samp, filt*cos((vec4(0,1,2,3)+vec4(4*(i+p)))*PI_6));
  60. yiq.y += dot(rsamp,filt*cos((vec4(6,7,8,9)+vec4(4*(i+p)))*PI_6));
  61. yiq.z += dot(samp, filt*sin((vec4(0,1,2,3)+vec4(4*(i+p)))*PI_6));
  62. yiq.z += dot(rsamp,filt*sin((vec4(6,7,8,9)+vec4(4*(i+p)))*PI_6));
  63. norm_c += dot(one,filt);
  64. samp = samp2;
  65. samp2 = samp3;
  66. }
  67. vec2 window = vec2(alpha) - vec2(beta) * cos(vec2(2.0*PI/(4*width-7))*(vec2(4*(width/2+i))+vec2(0,1)));
  68. vec2 t = vec2(i*4)+vec2(-1.5,-0.5);
  69. #define lowpass(freq,x) vec2(2.0*(freq))*sinc(vec2(2.0*PI*(freq))*(x))
  70. vec2 lumafilt = lowpass(bw_y, t);
  71. vec2 chromafilt = lowpass(bw_c, t);
  72. #undef lowpass
  73. vec2 filt = window*lumafilt;
  74. yiq.x += dot(samp.xy, filt) + dot(samp2.zw, filt);
  75. norm_y += dot(one.xy, filt);
  76. filt = window*chromafilt;
  77. yiq.y += dot(samp.xy, filt*cos((vec2(0,1)+vec2(4*(i+p)))*vec2(PI/6.0)));
  78. yiq.y += dot(samp2.zw,filt*cos((vec2(6,7)+vec2(4*(i+p)))*vec2(PI/6.0)));
  79. yiq.z += dot(samp.xy, filt*sin((vec2(0,1)+vec2(4*(i+p)))*vec2(PI/6.0)));
  80. yiq.z += dot(samp2.zw,filt*sin((vec2(6,7)+vec2(4*(i+p)))*vec2(PI/6.0)));
  81. norm_c += dot(one.xy, filt);
  82. yiq *= vec3(0.5/norm_y, 1.0/norm_c, 1.0/norm_c);
  83. fragColor = vec4(dot(yiq, vec3(1.0, 0.946882, 0.623557)),
  84. dot(yiq, vec3(1.0,-0.274788,-0.635691)),
  85. dot(yiq, vec3(1.0,-1.108545, 1.709007)),
  86. 0.0);
  87. //fragColor = vec4(yiq+vec3(0,0.5,0.5),0.0);
  88. }