├── .gitignore ├── LICENSE ├── README.md ├── free-for-all ├── dd-glitch-assist-scriptsv10 │ ├── Readme.md │ ├── instant_damage │ │ ├── RP_average.js │ │ ├── RP_mv_sink_and_rise.js │ │ ├── dd_AverageBastard.js │ │ ├── dd_AverageBastard2.js │ │ ├── dd_AverageBastard3.js │ │ ├── dd_antiGravity.js │ │ ├── dd_circle.js │ │ ├── dd_circular.js │ │ ├── dd_delay.js │ │ ├── dd_doubleRight.js │ │ ├── dd_doubleSpeed.js │ │ ├── dd_gravity.js │ │ ├── dd_horizontalZoom.js │ │ ├── dd_largestRandom.js │ │ ├── dd_maxZero.js │ │ ├── dd_minZero.js │ │ ├── dd_mirrorX.js │ │ ├── dd_mirrorY.js │ │ ├── dd_onlyFall.js │ │ ├── dd_onlyRise.js │ │ ├── dd_randomiser.js │ │ ├── dd_reverse.js │ │ ├── dd_ringBuffer.js │ │ ├── dd_rotate180.js │ │ ├── dd_rotate180Negative.js │ │ ├── dd_slamZoom.js │ │ ├── dd_splitPhase.js │ │ ├── dd_swap.js │ │ ├── dd_verticalZoom.js │ │ ├── dd_zoomIn.js │ │ ├── dd_zoomInOut.js │ │ ├── dd_zoomOut.js │ │ └── dd_zoomWhoops.js │ ├── random_damage │ │ ├── dd_RandomDamage(180).js │ │ ├── dd_RandomDamage(antiGrav).js │ │ ├── dd_RandomDamage(circular).js │ │ ├── dd_RandomDamage(displaceX).js │ │ ├── dd_RandomDamage(displaceY).js │ │ ├── dd_RandomDamage(double).js │ │ ├── dd_RandomDamage(grav).js │ │ ├── dd_RandomDamage(invert).js │ │ ├── dd_RandomDamage(invertN).js │ │ ├── dd_RandomDamage(invertRandomN).js │ │ ├── dd_RandomDamage(progDisplaceX).js │ │ ├── dd_RandomDamage(progDisplaceY).js │ │ ├── dd_RandomDamage(progSlamZoom).js │ │ ├── dd_RandomDamage(progZoom).js │ │ ├── dd_RandomDamage(random).js │ │ ├── dd_RandomDamage(randomMultiple).js │ │ ├── dd_RandomDamage(randomX).js │ │ ├── dd_RandomDamage(randomY).js │ │ ├── dd_RandomDamage(randomZoom).js │ │ ├── dd_RandomDamage(shear).js │ │ ├── dd_RandomDamage(slamZoom).js │ │ ├── dd_RandomDamage(sliceHB).js │ │ ├── dd_RandomDamage(sliceHT).js │ │ ├── dd_RandomDamage(sliceVL).js │ │ ├── dd_RandomDamage(sliceVR).js │ │ ├── dd_RandomDamage(stop).js │ │ ├── dd_RandomDamage(stopX).js │ │ ├── dd_RandomDamage(stopXY).js │ │ ├── dd_RandomDamage(stopXYSmash).js │ │ ├── dd_RandomDamage(stopY).js │ │ ├── dd_RandomDamage(swap).js │ │ ├── dd_RandomDamage(swapN).js │ │ ├── dd_RandomDamage(swapRandomN).js │ │ ├── dd_RandomDamage(twitch).js │ │ ├── dd_RandomDamage(wave).js │ │ ├── dd_RandomDamage(wave2).js │ │ └── dd_RandomDamage(zoom).js │ └── selective_damage │ │ ├── dd_BlurFastest.js │ │ ├── dd_BlurSlowest.js │ │ ├── dd_MultiplyFastest.js │ │ └── dd_MultiplySlowest.js ├── helpers.mjs ├── mb_type-midi.js ├── midi.js ├── midi_v2.js ├── mv_average.js ├── mv_average_0.10.js ├── mv_avgpan.js ├── mv_sink.js ├── offset.js ├── pict_types-midi.js ├── pict_types.js ├── sdl.js ├── snes.js └── vf_script │ ├── pixelsort_gbrp-midi.js │ ├── pixelsort_gbrp.js │ └── pixelsort_yuv444p.js ├── fubar2k23 ├── helpers.mjs ├── mb_type-midi.js ├── midi.js ├── mv_average.js ├── mv_average.sh ├── mv_pan.js ├── mv_pan.sh ├── pixelsort.js └── pixelsort.sh ├── mv_server ├── mv_producer.js ├── mv_receiver.js └── mv_server.py └── tutorial ├── CEP00109_mpeg4.avi ├── lena.jpg ├── lena.png ├── readme.md ├── readme_linux.md ├── readme_macos.md ├── readme_windows.md ├── scripts ├── helpers │ └── midi.js ├── jpeg │ ├── dqt.js │ └── q_dc_delta.js ├── mpeg4 │ ├── mb_type_midi.js │ ├── mv_average.js │ ├── mv_pan.js │ ├── mv_pan_midi.js │ ├── mv_sink_and_rise.js │ └── mv_sink_and_rise_fast.js └── png │ └── idat.js └── sh ├── fflive_pipe.sh └── file_to_mpeg4.sh /.gitignore: -------------------------------------------------------------------------------- 1 | bin -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ffglitch-scripts 2 | 3 | This repository aims to create a grand unified script for FFglitch. 4 | 5 | For that purpose, there will be a `free-for-all` directory where 6 | anything can be submitted in no particular order or structure, and 7 | people are encouraged to make pull requests with whatever they're 8 | working on. 9 | 10 | # License 11 | 12 | This project uses the [Unlicense](https://en.wikipedia.org/wiki/Unlicense). 13 | Consider any contributions as being in the public domain. 14 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/Readme.md: -------------------------------------------------------------------------------- 1 | # DD-GlitchAssist Scripts for FFGlitch v10 2 | 3 | This is a porting of scripts made by Daz Disley for his tool [dd_GlitchAssist](http://dazdisley.co.uk/#!/page:./dd_GlitchAssist/). 4 | 5 | The original version of the scripts in this folder come from the download link [here](http://dazdisley.co.uk/dd_GlitchAssist/dd_GlitchAssist.zip). 6 | 7 | All scripts are made to be compatible with ffglitch v10.x 8 | 9 | Scripts in these folders are presented as is. -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/RP_average.js: -------------------------------------------------------------------------------- 1 | // average.js glitch script 2 | // stolen directly from Ramiro Polla's tutorial page ... 3 | // global variable holding forward motion vectors from previous frames 4 | var prev_fwd_mvs = [ ]; 5 | 6 | // change this value to use a smaller or greater number of frames to 7 | // perform the average of motion vectors 8 | var tail_length = 10; 9 | 10 | // calculate average of previous motion vectors 11 | function average_mv(mv, i, j, n, k) 12 | { 13 | let sum = 0; 14 | for ( let t = 0; t < n; t++ ) 15 | sum += prev_fwd_mvs[t][i][j][k]; 16 | let val = Math.round(sum / n); 17 | val = Math.max(val, -64); 18 | val = Math.min(val, 63); 19 | return val; 20 | } 21 | 22 | export function setup(args) 23 | { 24 | args.features = [ "mv" ]; 25 | } 26 | 27 | export function glitch_frame(frame) 28 | { 29 | // bail out if we have no forward motion vectors 30 | const fwd_mvs = frame.mv?.forward; 31 | if ( !fwd_mvs ) 32 | return; 33 | 34 | // set motion vector overflow behaviour in ffedit to "truncate" 35 | frame.mv.overflow = "truncate"; 36 | 37 | // update variable holding forward motion vectors from previous 38 | // frames. note that we perform a deep copy of the clean motion 39 | // vector values before modifying them. 40 | let json_str = JSON.stringify(fwd_mvs); 41 | let deep_copy = JSON.parse(json_str); 42 | // push to the end of array 43 | prev_fwd_mvs.push(deep_copy); 44 | // drop values from earliest frames to always keep the same tail 45 | // length 46 | if ( prev_fwd_mvs.length > tail_length ) 47 | prev_fwd_mvs = prev_fwd_mvs.slice(1); 48 | 49 | // bail out if we still don't have enough frames 50 | if ( prev_fwd_mvs.length != tail_length ) 51 | return; 52 | 53 | // replace all motion vectors of current frame with an average 54 | // of the motion vectors from the previous 10 frames 55 | for ( let i = 0; i < fwd_mvs.length; i++ ) 56 | { 57 | // loop through all rows 58 | let row = fwd_mvs[i]; 59 | for ( let j = 0; j < row.length; j++ ) 60 | { 61 | // loop through all macroblocks 62 | let mv = row[j]; 63 | 64 | // THIS IS WHERE THE MAGIC HAPPENS 65 | 66 | mv[0] = average_mv(mv, i, j, tail_length, 0); 67 | mv[1] = average_mv(mv, i, j, tail_length, 1); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/RP_mv_sink_and_rise.js: -------------------------------------------------------------------------------- 1 | // mv_sink_and_rise.js glitch script 2 | // stolen directly from Ramiro Polla's tutorial page ... 3 | export function setup(args) 4 | { 5 | args.features = [ "mv" ]; 6 | } 7 | 8 | export function glitch_frame(frame) 9 | { 10 | // bail out if we have no forward motion vectors 11 | const fwd_mvs = frame.mv?.forward; 12 | if ( !fwd_mvs ) 13 | return; 14 | 15 | // set motion vector overflow behaviour in ffedit to "truncate" 16 | frame.mv.overflow = "truncate"; 17 | 18 | // clear horizontal element of all motion vectors 19 | for ( let i = 0; i < fwd_mvs.length; i++ ) 20 | { 21 | // loop through all rows 22 | let row = fwd_mvs[i]; 23 | for ( let j = 0; j < row.length; j++ ) 24 | { 25 | // loop through all macroblocks 26 | let mv = row[j]; 27 | 28 | // THIS IS WHERE THE MAGIC HAPPENS 29 | 30 | mv[0] = 0; // this sets the horizontal motion vector to zero 31 | // mv[1] = 0; // you could also change the vertical motion vector 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_AverageBastard.js: -------------------------------------------------------------------------------- 1 | // dd_AverageBastard 2 | 3 | // global variable holding forward motion vectors from previous frames 4 | let prev_average_mvs; 5 | let average_mv_sum = new MV(0, 0); 6 | 7 | // change this value to use a smaller or greater number of frames to 8 | // perform the average of motion vectors 9 | // you can also change it using the `-sp ` command line option 10 | let tail_length = 20; 11 | 12 | export function setup(args) 13 | { 14 | args.features = [ "mv" ]; 15 | 16 | // Pass "-sp " in the command line, where is an 17 | // integer from 0 to 100. 18 | if ( "params" in args ) 19 | tail_length = args.params; 20 | } 21 | 22 | export function glitch_frame(frame) 23 | { 24 | // bail out if we have no forward motion vectors 25 | const fwd_mvs = frame.mv?.forward; 26 | if ( !fwd_mvs ) 27 | return; 28 | 29 | // set motion vector overflow behaviour in ffedit to "truncate" 30 | frame.mv.overflow = "truncate"; 31 | 32 | let average_mv = new MV(0, 0); 33 | fwd_mvs.forEach((mv) => { 34 | average_mv[0] += mv[0]; 35 | average_mv[1] += mv[1]; 36 | }); 37 | const length = fwd_mvs.height * fwd_mvs.width; 38 | average_mv[0] = Math.floor(average_mv[0] / length); 39 | average_mv[1] = Math.floor(average_mv[1] / length); 40 | 41 | if ( !prev_average_mvs ) 42 | prev_average_mvs = Array(tail_length - 1).fill(MV(0, 0)); 43 | 44 | // push to the end of array 45 | prev_average_mvs.push(average_mv); 46 | 47 | // update average_mv_sum by removing the motion vector values from 48 | // the oldest frame and adding the values from the current frame. 49 | if ( prev_average_mvs.length > tail_length ) 50 | { 51 | average_mv_sum.sub(prev_average_mvs[0]); 52 | prev_average_mvs = prev_average_mvs.slice(1); 53 | } 54 | average_mv_sum.add(average_mv); 55 | 56 | // set new values for current frame to (average_mv_sum / tail_length) 57 | if ( prev_average_mvs.length == tail_length ) 58 | { 59 | const deep_copy = fwd_mvs.dup(); 60 | fwd_mvs.assign(average_mv_sum); 61 | fwd_mvs.div(MV(tail_length, tail_length)); 62 | fwd_mvs.add(deep_copy); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_AverageBastard2.js: -------------------------------------------------------------------------------- 1 | // dd_AverageBastard2 2 | 3 | // global variable holding forward motion vectors from previous frames 4 | let prev_average_mvs; 5 | let average_mv_sum = new MV(0, 0); 6 | 7 | // change this value to use a smaller or greater number of frames to 8 | // perform the average of motion vectors 9 | // you can also change it using the `-sp ` command line option 10 | let tail_length = 20; 11 | 12 | export function setup(args) 13 | { 14 | args.features = [ "mv" ]; 15 | 16 | // Pass "-sp " in the command line, where is an 17 | // integer from 0 to 100. 18 | if ( "params" in args ) 19 | tail_length = args.params; 20 | } 21 | 22 | export function glitch_frame(frame) 23 | { 24 | // bail out if we have no forward motion vectors 25 | const fwd_mvs = frame.mv?.forward; 26 | if ( !fwd_mvs ) 27 | return; 28 | 29 | // set motion vector overflow behaviour in ffedit to "truncate" 30 | frame.mv.overflow = "truncate"; 31 | 32 | let average_mv = new MV(0, 0); 33 | fwd_mvs.forEach((mv) => { 34 | average_mv[0] += mv[0]; 35 | average_mv[1] += mv[1]; 36 | }); 37 | const length = fwd_mvs.height * fwd_mvs.width; 38 | average_mv[0] = Math.floor(average_mv[0] / length); 39 | average_mv[1] = Math.floor(average_mv[1] / length); 40 | 41 | if ( !prev_average_mvs ) 42 | prev_average_mvs = Array(tail_length - 1).fill(MV(0, 0)); 43 | 44 | // push to the end of array 45 | prev_average_mvs.push(average_mv); 46 | 47 | // update average_mv_sum by removing the motion vector values from 48 | // the oldest frame and adding the values from the current frame. 49 | if ( prev_average_mvs.length > tail_length ) 50 | { 51 | average_mv_sum.sub(prev_average_mvs[0]); 52 | prev_average_mvs = prev_average_mvs.slice(1); 53 | } 54 | average_mv_sum.add(average_mv); 55 | 56 | // set new values for current frame to (average_mv_sum / tail_length) 57 | if ( prev_average_mvs.length == tail_length ) 58 | { 59 | fwd_mvs.assign(average_mv_sum); 60 | fwd_mvs.div(MV(tail_length, tail_length)); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_AverageBastard3.js: -------------------------------------------------------------------------------- 1 | // dd_AverageBastard3 2 | 3 | export function setup(args) 4 | { 5 | args.features = [ "mv" ]; 6 | } 7 | 8 | export function glitch_frame(frame) 9 | { 10 | // bail out if we have no forward motion vectors 11 | const fwd_mvs = frame.mv?.forward; 12 | if ( !fwd_mvs ) 13 | return; 14 | 15 | // set motion vector overflow behaviour in ffedit to "truncate" 16 | frame.mv.overflow = "truncate"; 17 | 18 | let sumX = 0; 19 | let sumY = 0; 20 | fwd_mvs.forEach((mv) => { 21 | sumX += mv[0]; 22 | sumY += mv[1]; 23 | }); 24 | const length = fwd_mvs.height * fwd_mvs.width; 25 | sumX = Math.floor(sumX / length); 26 | sumY = Math.floor(sumY / length); 27 | 28 | // attack the mvs 29 | fwd_mvs.forEach((mv) => { 30 | mv[0] += sumX; 31 | mv[1] += sumY; 32 | }); 33 | } 34 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_antiGravity.js: -------------------------------------------------------------------------------- 1 | // dd_antiGravity.js 2 | 3 | // global variable holding forward motion vectors from previous frames 4 | let old_mvs; 5 | // a variable for gravity 6 | let gravity = -10; 7 | 8 | export function setup(args) 9 | { 10 | args.features = [ "mv" ]; 11 | 12 | // Pass "-sp " in the command line, where is an 13 | // integer. 14 | if ( "params" in args ) 15 | gravity = args.params; 16 | } 17 | 18 | export function glitch_frame(frame) 19 | { 20 | // bail out if we have no forward motion vectors 21 | const fwd_mvs = frame.mv?.forward; 22 | if ( !fwd_mvs ) 23 | return; 24 | 25 | // set motion vector overflow behaviour in ffedit to "truncate" 26 | frame.mv.overflow = "truncate"; 27 | 28 | // buffer first set of vectors. . . 29 | if ( !old_mvs ) 30 | old_mvs = fwd_mvs.dup(); 31 | 32 | const deep_copy = fwd_mvs.dup(); 33 | const mask = fwd_mvs.compare_lt_v(0); 34 | fwd_mvs.assign_v(old_mvs, mask); 35 | old_mvs.add_v(deep_copy, mask); 36 | old_mvs.sub_v(gravity, mask); 37 | } 38 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_circle.js: -------------------------------------------------------------------------------- 1 | // dd_circle.js 2 | 3 | export function setup(args) 4 | { 5 | args.features = [ "mv" ]; 6 | } 7 | 8 | export function glitch_frame(frame) 9 | { 10 | // bail out if we have no forward motion vectors 11 | const fwd_mvs = frame.mv?.forward; 12 | if ( !fwd_mvs ) 13 | return; 14 | 15 | // set motion vector overflow behaviour in ffedit to "truncate" 16 | frame.mv.overflow = "truncate"; 17 | 18 | const H = fwd_mvs.height; 19 | const W = fwd_mvs.width; 20 | fwd_mvs.forEach((mv, i, j) => { 21 | mv[0] *= Math.sin(i / H * Math.PI * 2); 22 | mv[1] *= Math.cos(j / W * Math.PI * 2); 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_circular.js: -------------------------------------------------------------------------------- 1 | // dd_circular.js 2 | 3 | export function setup(args) 4 | { 5 | args.features = [ "mv" ]; 6 | } 7 | 8 | export function glitch_frame(frame) 9 | { 10 | // bail out if we have no forward motion vectors 11 | const fwd_mvs = frame.mv?.forward; 12 | if ( !fwd_mvs ) 13 | return; 14 | 15 | // set motion vector overflow behaviour in ffedit to "truncate" 16 | frame.mv.overflow = "truncate"; 17 | 18 | fwd_mvs.forEach((mv, i, j) => { 19 | mv[0] *= Math.sin(i); 20 | mv[1] *= Math.cos(j); 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_delay.js: -------------------------------------------------------------------------------- 1 | // dd_delay.js 2 | // works kinda like an audio delay 3 | // stacks the previous n frames into a buffer 4 | 5 | // try making the delay long enough to overlap an edit in the content ... 6 | let delay = 20; 7 | 8 | // global variable holding forward motion vectors from previous frames 9 | let prev_fwd_mvs = [ ]; 10 | 11 | export function setup(args) 12 | { 13 | args.features = [ "mv" ]; 14 | 15 | // Pass "-sp " in the command line, where is an 16 | // integer. 17 | if ( "params" in args ) 18 | delay = args.params; 19 | } 20 | 21 | export function glitch_frame(frame) 22 | { 23 | // bail out if we have no forward motion vectors 24 | const fwd_mvs = frame.mv?.forward; 25 | if ( !fwd_mvs ) 26 | return; 27 | 28 | // set motion vector overflow behaviour in ffedit to "truncate" 29 | frame.mv.overflow = "truncate"; 30 | 31 | // update variable holding forward motion vectors from previous 32 | // frames. note that we perform a deep copy of the clean motion 33 | // vector values before modifying them. 34 | let deep_copy = fwd_mvs.dup(); 35 | // push to the end of array 36 | prev_fwd_mvs.push(deep_copy); 37 | // drop values from earliest frames to always keep the same tail 38 | // length 39 | if ( prev_fwd_mvs.length > delay ) 40 | prev_fwd_mvs = prev_fwd_mvs.slice(1); 41 | 42 | // bail out if we still don't have enough frames 43 | if ( prev_fwd_mvs.length != delay ) 44 | return; 45 | 46 | fwd_mvs.assign(prev_fwd_mvs[0]); 47 | } 48 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_doubleRight.js: -------------------------------------------------------------------------------- 1 | // dd_doubleRight.js 2 | // every mv on the right of the frame is multiplied by 2 3 | 4 | export function setup(args) 5 | { 6 | args.features = [ "mv" ]; 7 | } 8 | 9 | export function glitch_frame(frame) 10 | { 11 | // bail out if we have no forward motion vectors 12 | const fwd_mvs = frame.mv?.forward; 13 | if ( !fwd_mvs ) 14 | return; 15 | 16 | // set motion vector overflow behaviour in ffedit to "truncate" 17 | frame.mv.overflow = "truncate"; 18 | 19 | const MID_POINT = fwd_mvs.width / 2; 20 | const subarray = fwd_mvs.subarray([MID_POINT, 0]); 21 | subarray.mul(2, 2); 22 | } 23 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_doubleSpeed.js: -------------------------------------------------------------------------------- 1 | // dd_doubleSpeed.js 2 | // every mv is multiplied by 2 3 | 4 | export function setup(args) 5 | { 6 | args.features = [ "mv" ]; 7 | } 8 | 9 | export function glitch_frame(frame) 10 | { 11 | // bail out if we have no forward motion vectors 12 | const fwd_mvs = frame.mv?.forward; 13 | if ( !fwd_mvs ) 14 | return; 15 | 16 | // set motion vector overflow behaviour in ffedit to "truncate" 17 | frame.mv.overflow = "truncate"; 18 | 19 | fwd_mvs.mul(2, 2); 20 | } 21 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_gravity.js: -------------------------------------------------------------------------------- 1 | // dd_gravity.js 2 | 3 | // global variable holding forward motion vectors from previous frames 4 | let old_mvs; 5 | // a variable for gravity 6 | let gravity = 10; 7 | 8 | export function setup(args) 9 | { 10 | args.features = [ "mv" ]; 11 | 12 | // Pass "-sp " in the command line, where is an 13 | // integer. 14 | if ( "params" in args ) 15 | gravity = args.params; 16 | } 17 | 18 | export function glitch_frame(frame) 19 | { 20 | // bail out if we have no forward motion vectors 21 | const fwd_mvs = frame.mv?.forward; 22 | if ( !fwd_mvs ) 23 | return; 24 | 25 | // set motion vector overflow behaviour in ffedit to "truncate" 26 | frame.mv.overflow = "truncate"; 27 | 28 | // buffer first set of vectors. . . 29 | if ( !old_mvs ) 30 | old_mvs = fwd_mvs.dup(); 31 | 32 | const deep_copy = fwd_mvs.dup(); 33 | const mask = fwd_mvs.compare_gt_v(0); 34 | fwd_mvs.assign_v(old_mvs, mask); 35 | old_mvs.add_v(deep_copy, mask); 36 | old_mvs.sub_v(gravity, mask); 37 | } 38 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_horizontalZoom.js: -------------------------------------------------------------------------------- 1 | // dd_horizontalZoom.js 2 | 3 | let zspeed = -15; 4 | 5 | export function setup(args) 6 | { 7 | args.features = [ "mv" ]; 8 | 9 | // Pass "-sp " in the command line, where is an 10 | // integer. 11 | if ( "params" in args ) 12 | zspeed = args.params; 13 | } 14 | 15 | export function glitch_frame(frame) 16 | { 17 | // bail out if we have no forward motion vectors 18 | const fwd_mvs = frame.mv?.forward; 19 | if ( !fwd_mvs ) 20 | return; 21 | 22 | // set motion vector overflow behaviour in ffedit to "truncate" 23 | frame.mv.overflow = "truncate"; 24 | 25 | const MID_POINT = fwd_mvs.width / 2; 26 | fwd_mvs.forEach((mv, i, j) => { 27 | if ( j > MID_POINT ) 28 | mv[0] += zspeed; 29 | else 30 | mv[0] -= zspeed; 31 | mv[1] = 0; 32 | }); 33 | } 34 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_largestRandom.js: -------------------------------------------------------------------------------- 1 | // dd_largestRandom.js 2 | // only fuck things up if mv > movement_threshold 3 | var LARGEST = 0; 4 | var SOME_PERCENTAGE = 0.85; // only the fastest 15% of mv's in each frame get glitched 5 | 6 | export function setup(args) 7 | { 8 | args.features = [ "mv" ]; 9 | 10 | // Pass "-sp " in the command line, where is an 11 | // integer from 0 to 100. 12 | if ( "params" in args ) 13 | SOME_PERCENTAGE = (100 - args.params) / 100; 14 | } 15 | 16 | export function glitch_frame(frame) 17 | { 18 | LARGEST = 0; 19 | // bail out if we have no forward motion vectors 20 | const fwd_mvs = frame.mv?.forward; 21 | if ( !fwd_mvs ) 22 | return; 23 | 24 | // set motion vector overflow behaviour in ffedit to "truncate" 25 | frame.mv.overflow = "truncate"; 26 | 27 | const largest = fwd_mvs.largest_sq(); 28 | const threshold = Math.floor(SOME_PERCENTAGE * largest[2]); 29 | const mask = fwd_mvs.compare_gt(threshold); 30 | 31 | fwd_mvs.maskedForEach(mask, (mv) => { 32 | mv[0] += (Math.random() * 100) - 50; 33 | mv[1] += (Math.random() * 100) - 50; 34 | }); 35 | } 36 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_maxZero.js: -------------------------------------------------------------------------------- 1 | // dd_maxZero.js 2 | 3 | // only fuck things up if mv > movement_threshold 4 | let movement_threshold = 10; 5 | 6 | export function setup(args) 7 | { 8 | args.features = [ "mv" ]; 9 | 10 | // Pass "-sp " in the command line, where is an 11 | // integer. 12 | if ( "params" in args ) 13 | movement_threshold = args.params; 14 | } 15 | 16 | export function glitch_frame(frame) 17 | { 18 | // bail out if we have no forward motion vectors 19 | const fwd_mvs = frame.mv?.forward; 20 | if ( !fwd_mvs ) 21 | return; 22 | 23 | // set motion vector overflow behaviour in ffedit to "truncate" 24 | frame.mv.overflow = "truncate"; 25 | 26 | const mask = fwd_mvs.compare_gt(movement_threshold * movement_threshold); 27 | fwd_mvs.assign(0, 0, mask); 28 | } 29 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_minZero.js: -------------------------------------------------------------------------------- 1 | // dd_minZero.js 2 | 3 | // only fuck things up if mv < movement_threshold 4 | let movement_threshold = 10; 5 | 6 | export function setup(args) 7 | { 8 | args.features = [ "mv" ]; 9 | 10 | // Pass "-sp " in the command line, where is an 11 | // integer. 12 | if ( "params" in args ) 13 | movement_threshold = args.params; 14 | } 15 | 16 | export function glitch_frame(frame) 17 | { 18 | // bail out if we have no forward motion vectors 19 | const fwd_mvs = frame.mv?.forward; 20 | if ( !fwd_mvs ) 21 | return; 22 | 23 | // set motion vector overflow behaviour in ffedit to "truncate" 24 | frame.mv.overflow = "truncate"; 25 | 26 | const mask = fwd_mvs.compare_lt(movement_threshold * movement_threshold); 27 | fwd_mvs.assign(0, 0, mask); 28 | } 29 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_mirrorX.js: -------------------------------------------------------------------------------- 1 | // dd_mirrorX.js 2 | 3 | export function setup(args) 4 | { 5 | args.features = [ "mv" ]; 6 | } 7 | 8 | export function glitch_frame(frame) 9 | { 10 | // bail out if we have no forward motion vectors 11 | const fwd_mvs = frame.mv?.forward; 12 | if ( !fwd_mvs ) 13 | return; 14 | 15 | // set motion vector overflow behaviour in ffedit to "truncate" 16 | frame.mv.overflow = "truncate"; 17 | 18 | fwd_mvs.reverse_h(); 19 | fwd_mvs.mul(-1, 1); 20 | } 21 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_mirrorY.js: -------------------------------------------------------------------------------- 1 | // dd_mirrorY.js 2 | 3 | export function setup(args) 4 | { 5 | args.features = [ "mv" ]; 6 | } 7 | 8 | export function glitch_frame(frame) 9 | { 10 | // bail out if we have no forward motion vectors 11 | const fwd_mvs = frame.mv?.forward; 12 | if ( !fwd_mvs ) 13 | return; 14 | 15 | // set motion vector overflow behaviour in ffedit to "truncate" 16 | frame.mv.overflow = "truncate"; 17 | 18 | fwd_mvs.reverse_v(); 19 | fwd_mvs.mul(1, -1); 20 | } 21 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_onlyFall.js: -------------------------------------------------------------------------------- 1 | // dd_onlyFall.js 2 | // only let's y-dimension mv's through if they're falling 3 | 4 | export function setup(args) 5 | { 6 | args.features = [ "mv" ]; 7 | } 8 | 9 | export function glitch_frame(frame) 10 | { 11 | // bail out if we have no forward motion vectors 12 | const fwd_mvs = frame.mv?.forward; 13 | if ( !fwd_mvs ) 14 | return; 15 | 16 | // set motion vector overflow behaviour in ffedit to "truncate" 17 | frame.mv.overflow = "truncate"; 18 | 19 | const mask = fwd_mvs.compare_gt_v(0); 20 | fwd_mvs.assign_v(0, mask); 21 | } 22 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_onlyRise.js: -------------------------------------------------------------------------------- 1 | // dd_onlyRise.js 2 | // only let's y-dimension mv's through if they're rising 3 | 4 | export function setup(args) 5 | { 6 | args.features = [ "mv" ]; 7 | } 8 | 9 | export function glitch_frame(frame) 10 | { 11 | // bail out if we have no forward motion vectors 12 | const fwd_mvs = frame.mv?.forward; 13 | if ( !fwd_mvs ) 14 | return; 15 | 16 | // set motion vector overflow behaviour in ffedit to "truncate" 17 | frame.mv.overflow = "truncate"; 18 | 19 | const mask = fwd_mvs.compare_lt_v(0); 20 | fwd_mvs.assign_v(0, mask); 21 | } 22 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_randomiser.js: -------------------------------------------------------------------------------- 1 | // dd_randomiser.js 2 | 3 | let randomness = 10; 4 | let bias = (randomness / 2); 5 | 6 | export function setup(args) 7 | { 8 | args.features = [ "mv" ]; 9 | 10 | // Pass "-sp " in the command line, where is an 11 | // integer. 12 | if ( "params" in args ) 13 | { 14 | randomness = args.params; 15 | bias = (randomness / 2); 16 | } 17 | } 18 | 19 | export function glitch_frame(frame) 20 | { 21 | // bail out if we have no forward motion vectors 22 | const fwd_mvs = frame.mv?.forward; 23 | if ( !fwd_mvs ) 24 | return; 25 | 26 | // set motion vector overflow behaviour in ffedit to "truncate" 27 | frame.mv.overflow = "truncate"; 28 | 29 | fwd_mvs.forEach((mv, i, j) => { 30 | mv[0] += Math.floor((Math.random() * randomness) - bias); 31 | mv[1] += Math.floor((Math.random() * randomness) - bias); 32 | }); 33 | } 34 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_reverse.js: -------------------------------------------------------------------------------- 1 | export function setup(args) 2 | { 3 | args.features = [ "mv" ]; 4 | } 5 | 6 | export function glitch_frame(frame) 7 | { 8 | // bail out if we have no forward motion vectors 9 | const fwd_mvs = frame.mv?.forward; 10 | if ( !fwd_mvs ) 11 | return; 12 | 13 | // set motion vector overflow behaviour in ffedit to "truncate" 14 | frame.mv.overflow = "truncate"; 15 | 16 | fwd_mvs.mul(-1, -1); 17 | } 18 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_ringBuffer.js: -------------------------------------------------------------------------------- 1 | // dd_ring_buffer.js 2 | // works kinda like an audio delay 3 | // stacks the previous n frames into a buffer 4 | 5 | // try making the delay long enough to overlap an edit in the content ... 6 | let delay = 10; 7 | 8 | // divisor controls "feedback" ... or "feedforward" which ever is a better description ... 9 | let feedback = 0.5; // a number between 0.000001 and .... yeah - controls how much of the buffered mv gets into the next pass 10 | let divisor = 1.0 / feedback; 11 | 12 | // global variable holding forward motion vectors from previous frames 13 | let prev_fwd_mvs = [ ]; 14 | 15 | export function setup(args) 16 | { 17 | args.features = [ "mv" ]; 18 | 19 | // Pass "-sp " in the command line, where is an 20 | // integer. 21 | if ( "params" in args ) 22 | delay = args.params; 23 | } 24 | 25 | export function glitch_frame(frame) 26 | { 27 | // bail out if we have no forward motion vectors 28 | const fwd_mvs = frame.mv?.forward; 29 | if ( !fwd_mvs ) 30 | return; 31 | 32 | // set motion vector overflow behaviour in ffedit to "truncate" 33 | frame.mv.overflow = "truncate"; 34 | 35 | // update variable holding forward motion vectors from previous 36 | // frames. note that we perform a deep copy of the clean motion 37 | // vector values before modifying them. 38 | let deep_copy = fwd_mvs.dup(); 39 | // push to the end of array 40 | prev_fwd_mvs.push(deep_copy); 41 | // drop values from earliest frames to always keep the same tail 42 | // length 43 | if ( prev_fwd_mvs.length > delay ) 44 | prev_fwd_mvs = prev_fwd_mvs.slice(1); 45 | 46 | // bail out if we still don't have enough frames 47 | if ( prev_fwd_mvs.length != delay ) 48 | return; 49 | 50 | const delay_fwd_mvs = prev_fwd_mvs[0].dup(); 51 | fwd_mvs.assign(delay_fwd_mvs); 52 | delay_fwd_mvs.div(divisor, divisor); 53 | delay_fwd_mvs.add(deep_copy); 54 | // feedback = (old / divisor) + new 55 | prev_fwd_mvs[delay - 1].assign(delay_fwd_mvs); 56 | } 57 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_rotate180.js: -------------------------------------------------------------------------------- 1 | // dd_rotate180.js 2 | 3 | export function setup(args) 4 | { 5 | args.features = [ "mv" ]; 6 | } 7 | 8 | export function glitch_frame(frame) 9 | { 10 | // bail out if we have no forward motion vectors 11 | const fwd_mvs = frame.mv?.forward; 12 | if ( !fwd_mvs ) 13 | return; 14 | 15 | // set motion vector overflow behaviour in ffedit to "truncate" 16 | frame.mv.overflow = "truncate"; 17 | 18 | fwd_mvs.reverse(); 19 | } 20 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_rotate180Negative.js: -------------------------------------------------------------------------------- 1 | // dd_rotate180Negative.js 2 | 3 | export function setup(args) 4 | { 5 | args.features = [ "mv" ]; 6 | } 7 | 8 | export function glitch_frame(frame) 9 | { 10 | // bail out if we have no forward motion vectors 11 | const fwd_mvs = frame.mv?.forward; 12 | if ( !fwd_mvs ) 13 | return; 14 | 15 | // set motion vector overflow behaviour in ffedit to "truncate" 16 | frame.mv.overflow = "truncate"; 17 | 18 | fwd_mvs.reverse(); 19 | fwd_mvs.mul(-1, -1); 20 | } 21 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_slamZoom.js: -------------------------------------------------------------------------------- 1 | // dd_slamZoom.js 2 | 3 | let ZOOM = -20; 4 | 5 | export function setup(args) 6 | { 7 | args.features = [ "mv" ]; 8 | 9 | // Pass "-sp " in the command line, where is an 10 | // integer. 11 | if ( "params" in args ) 12 | ZOOM = args.params; 13 | } 14 | 15 | export function glitch_frame(frame) 16 | { 17 | // bail out if we have no forward motion vectors 18 | const fwd_mvs = frame.mv?.forward; 19 | if ( !fwd_mvs ) 20 | return; 21 | 22 | // set motion vector overflow behaviour in ffedit to "truncate" 23 | frame.mv.overflow = "truncate"; 24 | 25 | const M_H = fwd_mvs.height / 2; 26 | const M_W = fwd_mvs.width / 2; 27 | 28 | fwd_mvs.forEach((mv, i, j) => { 29 | mv[0] = ((M_W - j) / 100) * ZOOM; 30 | mv[1] = ((M_H - i) / 100) * ZOOM; 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_splitPhase.js: -------------------------------------------------------------------------------- 1 | // dd_splitPhase.js 2 | // alternates between blocking horizontal or veritcal elements of mv 3 | // switch happens every (phase) frames 4 | 5 | let frames_per_phase = 5; 6 | 7 | let phase = true; 8 | let count = 0; 9 | 10 | export function setup(args) 11 | { 12 | args.features = [ "mv" ]; 13 | 14 | // Pass "-sp " in the command line, where is an 15 | // integer. 16 | if ( "params" in args ) 17 | frames_per_phase = args.params; 18 | } 19 | 20 | export function glitch_frame(frame) 21 | { 22 | // bail out if we have no forward motion vectors 23 | const fwd_mvs = frame.mv?.forward; 24 | if ( !fwd_mvs ) 25 | return; 26 | 27 | // set motion vector overflow behaviour in ffedit to "truncate" 28 | frame.mv.overflow = "truncate"; 29 | 30 | if ( phase ) 31 | fwd_mvs.assign_h(0); 32 | else 33 | fwd_mvs.assign_v(0); 34 | 35 | if ( count++ >= frames_per_phase ) 36 | { 37 | phase = !phase; 38 | count = 0; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_swap.js: -------------------------------------------------------------------------------- 1 | // dd_swap.js 2 | // swaps x and y components of mv 3 | 4 | export function setup(args) 5 | { 6 | args.features = [ "mv" ]; 7 | } 8 | 9 | export function glitch_frame(frame) 10 | { 11 | // bail out if we have no forward motion vectors 12 | const fwd_mvs = frame.mv?.forward; 13 | if ( !fwd_mvs ) 14 | return; 15 | 16 | // set motion vector overflow behaviour in ffedit to "truncate" 17 | frame.mv.overflow = "truncate"; 18 | 19 | fwd_mvs.swap_hv(); 20 | } 21 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_verticalZoom.js: -------------------------------------------------------------------------------- 1 | // dd_verticalZoom.js 2 | 3 | let zspeed = -15; 4 | 5 | export function setup(args) 6 | { 7 | args.features = [ "mv" ]; 8 | 9 | // Pass "-sp " in the command line, where is an 10 | // integer. 11 | if ( "params" in args ) 12 | zspeed = args.params; 13 | } 14 | 15 | export function glitch_frame(frame) 16 | { 17 | // bail out if we have no forward motion vectors 18 | const fwd_mvs = frame.mv?.forward; 19 | if ( !fwd_mvs ) 20 | return; 21 | 22 | // set motion vector overflow behaviour in ffedit to "truncate" 23 | frame.mv.overflow = "truncate"; 24 | 25 | const MID_POINT = fwd_mvs.height / 2; 26 | fwd_mvs.forEach((mv, i, j) => { 27 | mv[0] = 0; 28 | if ( i > MID_POINT ) 29 | mv[1] += zspeed; 30 | else 31 | mv[1] -= zspeed; 32 | }); 33 | } 34 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_zoomIn.js: -------------------------------------------------------------------------------- 1 | // dd_zoomIn.js 2 | 3 | let ZOOM = 20; 4 | 5 | export function setup(args) 6 | { 7 | args.features = [ "mv" ]; 8 | 9 | // Pass "-sp " in the command line, where is an 10 | // integer. 11 | if ( "params" in args ) 12 | ZOOM = args.params; 13 | } 14 | 15 | export function glitch_frame(frame) 16 | { 17 | // bail out if we have no forward motion vectors 18 | const fwd_mvs = frame.mv?.forward; 19 | if ( !fwd_mvs ) 20 | return; 21 | 22 | // set motion vector overflow behaviour in ffedit to "truncate" 23 | frame.mv.overflow = "truncate"; 24 | 25 | const M_H = fwd_mvs.height / 2; 26 | const M_W = fwd_mvs.width / 2; 27 | 28 | fwd_mvs.forEach((mv, i, j) => { 29 | mv[0] += ((M_W - j) / 100) * ZOOM; 30 | mv[1] += ((M_H - i) / 100) * ZOOM; 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_zoomInOut.js: -------------------------------------------------------------------------------- 1 | // dd_zoomInOut.js 2 | 3 | let ZOOM = 20; 4 | 5 | export function setup(args) 6 | { 7 | args.features = [ "mv" ]; 8 | 9 | // Pass "-sp " in the command line, where is an 10 | // integer. 11 | if ( "params" in args ) 12 | ZOOM = args.params; 13 | } 14 | 15 | export function glitch_frame(frame) 16 | { 17 | // bail out if we have no forward motion vectors 18 | const fwd_mvs = frame.mv?.forward; 19 | if ( !fwd_mvs ) 20 | return; 21 | 22 | // set motion vector overflow behaviour in ffedit to "truncate" 23 | frame.mv.overflow = "truncate"; 24 | 25 | const M_H = fwd_mvs.height / 2; 26 | const M_W = fwd_mvs.width / 2; 27 | 28 | fwd_mvs.forEach((mv, i, j) => { 29 | if ( i > M_H ) 30 | { 31 | mv[0] += ((M_W - j) / 100) * ZOOM; 32 | mv[1] += ((M_H - i) / 100) * ZOOM; 33 | } 34 | else 35 | { 36 | mv[0] -= ((M_W - j) / 100) * ZOOM; 37 | mv[1] -= ((M_H - i) / 100) * ZOOM; 38 | } 39 | }); 40 | } 41 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_zoomOut.js: -------------------------------------------------------------------------------- 1 | // dd_zoomOut.js 2 | 3 | let ZOOM = -20; 4 | 5 | export function setup(args) 6 | { 7 | args.features = [ "mv" ]; 8 | 9 | // Pass "-sp " in the command line, where is an 10 | // integer. 11 | if ( "params" in args ) 12 | ZOOM = args.params; 13 | } 14 | 15 | export function glitch_frame(frame) 16 | { 17 | // bail out if we have no forward motion vectors 18 | const fwd_mvs = frame.mv?.forward; 19 | if ( !fwd_mvs ) 20 | return; 21 | 22 | // set motion vector overflow behaviour in ffedit to "truncate" 23 | frame.mv.overflow = "truncate"; 24 | 25 | const M_H = fwd_mvs.height / 2; 26 | const M_W = fwd_mvs.width / 2; 27 | 28 | fwd_mvs.forEach((mv, i, j) => { 29 | mv[0] += ((M_W - j) / 100) * ZOOM; 30 | mv[1] += ((M_H - i) / 100) * ZOOM; 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/instant_damage/dd_zoomWhoops.js: -------------------------------------------------------------------------------- 1 | // dd_zoomWhoops.js 2 | 3 | let ZOOM = -20; 4 | 5 | export function setup(args) 6 | { 7 | args.features = [ "mv" ]; 8 | 9 | // Pass "-sp " in the command line, where is an 10 | // integer. 11 | if ( "params" in args ) 12 | ZOOM = args.params; 13 | } 14 | 15 | export function glitch_frame(frame) 16 | { 17 | // bail out if we have no forward motion vectors 18 | const fwd_mvs = frame.mv?.forward; 19 | if ( !fwd_mvs ) 20 | return; 21 | 22 | // set motion vector overflow behaviour in ffedit to "truncate" 23 | frame.mv.overflow = "truncate"; 24 | 25 | const M_H = fwd_mvs.height / 2; 26 | const M_W = fwd_mvs.width / 2; 27 | 28 | fwd_mvs.forEach((mv, i, j) => { 29 | mv[0] += ((i - M_W) / 100) * ZOOM; 30 | mv[1] += ((j - M_H) / 100) * ZOOM; 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(180).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(180).js 2 | // randomly rotate by 180 x and y components of mv if threshold met for frame 3 | 4 | let threshold = 95; 5 | var ZOOM = 100; 6 | 7 | export function setup(args) 8 | { 9 | args.features = [ "mv" ]; 10 | } 11 | 12 | export function glitch_frame(frame) 13 | { 14 | var do_or_not = Math.random() * 100; 15 | // only do the glitch if our random number crosses the threshold 16 | if(do_or_not > threshold){ 17 | ZOOM = Math.random() * 100; 18 | var do_dir = Math.random() * 100; 19 | if(do_dir > 50){ 20 | ZOOM = 0 - ZOOM; 21 | } 22 | // bail out if we have no forward motion vectors 23 | const fwd_mvs = frame.mv?.forward; 24 | if ( !fwd_mvs ) 25 | return; 26 | 27 | // set motion vector overflow behaviour in ffedit to "truncate" 28 | frame.mv.overflow = "truncate"; 29 | 30 | // note that we perform a deep copy of the clean motion 31 | // vector values before modifying them. 32 | let deep_copy = fwd_mvs.dup(); 33 | 34 | 35 | // clear horizontal element of all motion vectors 36 | for ( let i = 0; i < fwd_mvs.length; i++ ) 37 | { 38 | // loop through all rows 39 | let row = fwd_mvs[i]; 40 | var row2 = deep_copy[(fwd_mvs.length-1)-i]; 41 | for ( let j = 0; j < row.length; j++ ) 42 | { 43 | // loop through all macroblocks 44 | let mv = row[j]; 45 | var mv2 = row2[(row.length - 1) - j]; 46 | mv[0] = -mv2[0]; 47 | mv[1] = -mv2[1]; 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(antiGrav).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(antiGrav).js 2 | // anitgravityify if threshold met for frame 3 | 4 | let threshold = 98; 5 | // global variable holding forward motion vectors from previous frames 6 | var old_mvs = [ ]; 7 | // a variable for gravity 8 | var rt = 0; 9 | var gravity = 0 10 | var orig_gravity = 5; 11 | var TRIGGERED = 0; 12 | var frameCount = 10; 13 | var count = 0; 14 | 15 | export function setup(args) 16 | { 17 | args.features = [ "mv" ]; 18 | } 19 | 20 | export function glitch_frame(frame) 21 | { 22 | var do_or_not = Math.random() * 100; 23 | // only do the glitch if our random number crosses the threshold 24 | if(do_or_not > threshold | TRIGGERED == 1){ 25 | if(TRIGGERED == 0){ 26 | gravity = orig_gravity; 27 | TRIGGERED = 1; 28 | rt = 0; 29 | } 30 | // bail out if we have no forward motion vectors 31 | const fwd_mvs = frame.mv?.forward; 32 | if ( !fwd_mvs ) 33 | return; 34 | 35 | // set motion vector overflow behaviour in ffedit to "truncate" 36 | frame.mv.overflow = "truncate"; 37 | 38 | // buffer first set of vectors. . . 39 | if(rt == 0){ 40 | let deep_copy = fwd_mvs.dup(); 41 | // push to the end of array 42 | old_mvs[0] = (deep_copy); 43 | rt = 1; 44 | } 45 | 46 | // clear horizontal element of all motion vectors 47 | for ( let i = 0; i < fwd_mvs.length; i++ ) 48 | { 49 | // loop through all rows 50 | let row = fwd_mvs[i]; 51 | let old_row = old_mvs[0][i]; 52 | for ( let j = 0; j < row.length; j++ ) 53 | { 54 | // loop through all macroblocks 55 | let mv = row[j]; 56 | let omv = old_row[j]; 57 | mv[0] = mv[0]; 58 | var nmv = mv[1]; 59 | mv[1] = omv[1]; 60 | omv[1] = nmv + omv[1] + gravity; 61 | } 62 | } 63 | count++; 64 | if(count >= frameCount){ 65 | TRIGGERED = 0; 66 | count = 0; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(circular).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(circular).js 2 | // sin/cos x and y components of mv if threshold met for frame 3 | 4 | let threshold = 95; 5 | 6 | export function setup(args) 7 | { 8 | args.features = [ "mv" ]; 9 | } 10 | 11 | export function glitch_frame(frame) 12 | { 13 | var do_or_not = Math.random() * 100; 14 | // only do the glitch if our random number crosses the threshold 15 | if(do_or_not > threshold){ 16 | // bail out if we have no forward motion vectors 17 | const fwd_mvs = frame.mv?.forward; 18 | if ( !fwd_mvs ) 19 | return; 20 | 21 | // set motion vector overflow behaviour in ffedit to "truncate" 22 | frame.mv.overflow = "truncate"; 23 | 24 | fwd_mvs.forEach((mv, i, j) => { 25 | mv[0] *= Math.sin(i); 26 | mv[1] *= Math.cos(j); 27 | }); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(displaceX).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(displaceX).js 2 | // displace x component of mv if threshold met for frame 3 | 4 | let threshold = 95; 5 | 6 | var DISPLACE = 0; 7 | var MAGNITUDE = 100; 8 | 9 | export function setup(args) 10 | { 11 | args.features = [ "mv" ]; 12 | } 13 | 14 | export function glitch_frame(frame) 15 | { 16 | var do_or_not = Math.random() * 100; 17 | // only do the glitch if our random number crosses the threshold 18 | if(do_or_not > threshold){ 19 | DISPLACE = Math.random() * MAGNITUDE; 20 | // bail out if we have no forward motion vectors 21 | const fwd_mvs = frame.mv?.forward; 22 | if ( !fwd_mvs ) 23 | return; 24 | 25 | // set motion vector overflow behaviour in ffedit to "truncate" 26 | frame.mv.overflow = "truncate"; 27 | 28 | fwd_mvs.add_h(DISPLACE); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(displaceY).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(displaceY).js 2 | // displace y component of mv if threshold met for frame 3 | 4 | let threshold = 95; 5 | 6 | var DISPLACE = 0; 7 | var MAGNITUDE = 100; 8 | 9 | export function setup(args) 10 | { 11 | args.features = [ "mv" ]; 12 | } 13 | 14 | export function glitch_frame(frame) 15 | { 16 | var do_or_not = Math.random() * 100; 17 | // only do the glitch if our random number crosses the threshold 18 | if(do_or_not > threshold){ 19 | DISPLACE = Math.random() * MAGNITUDE; 20 | // bail out if we have no forward motion vectors 21 | const fwd_mvs = frame.mv?.forward; 22 | if ( !fwd_mvs ) 23 | return; 24 | 25 | // set motion vector overflow behaviour in ffedit to "truncate" 26 | frame.mv.overflow = "truncate"; 27 | 28 | fwd_mvs.add_v(DISPLACE); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(double).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(double).js 2 | // doubles x and y components of mv if threshold met for frame 3 | 4 | let threshold = 95; 5 | 6 | export function setup(args) 7 | { 8 | args.features = [ "mv" ]; 9 | } 10 | 11 | export function glitch_frame(frame) 12 | { 13 | var do_or_not = Math.random() * 100; 14 | // only do the glitch if our random number crosses the threshold 15 | if(do_or_not > threshold){ 16 | // bail out if we have no forward motion vectors 17 | const fwd_mvs = frame.mv?.forward; 18 | if ( !fwd_mvs ) 19 | return; 20 | 21 | // set motion vector overflow behaviour in ffedit to "truncate" 22 | frame.mv.overflow = "truncate"; 23 | 24 | fwd_mvs.mul(2, 2); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(grav).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(Grav).js 2 | // gravityify if threshold met for frame 3 | 4 | let threshold = 98; 5 | // global variable holding forward motion vectors from previous frames 6 | var old_mvs = [ ]; 7 | // a variable for gravity 8 | var rt = 0; 9 | var gravity = 0 10 | var orig_gravity = 5; 11 | var TRIGGERED = 0; 12 | var frameCount = 10; 13 | var count = 0; 14 | 15 | export function setup(args) 16 | { 17 | args.features = [ "mv" ]; 18 | } 19 | 20 | export function glitch_frame(frame) 21 | { 22 | var do_or_not = Math.random() * 100; 23 | // only do the glitch if our random number crosses the threshold 24 | if(do_or_not > threshold | TRIGGERED == 1){ 25 | if(TRIGGERED == 0){ 26 | gravity = orig_gravity; 27 | TRIGGERED = 1; 28 | rt = 0; 29 | } 30 | // bail out if we have no forward motion vectors 31 | const fwd_mvs = frame.mv?.forward; 32 | if ( !fwd_mvs ) 33 | return; 34 | 35 | // set motion vector overflow behaviour in ffedit to "truncate" 36 | frame.mv.overflow = "truncate"; 37 | 38 | // buffer first set of vectors. . . 39 | if(rt == 0){ 40 | let deep_copy = fwd_mvs.dup(); 41 | // push to the end of array 42 | old_mvs[0] = (deep_copy); 43 | rt = 1; 44 | } 45 | 46 | // clear horizontal element of all motion vectors 47 | for ( let i = 0; i < fwd_mvs.length; i++ ) 48 | { 49 | // loop through all rows 50 | let row = fwd_mvs[i]; 51 | let old_row = old_mvs[0][i]; 52 | for ( let j = 0; j < row.length; j++ ) 53 | { 54 | // loop through all macroblocks 55 | let mv = row[j]; 56 | let omv = old_row[j]; 57 | mv[0] = mv[0]; 58 | var nmv = mv[1]; 59 | mv[1] = omv[1]; 60 | omv[1] = nmv + omv[1] - gravity; 61 | } 62 | } 63 | count++; 64 | if(count >= frameCount){ 65 | TRIGGERED = 0; 66 | count = 0; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(invert).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(invert).js 2 | // inverts x and y components of mv if threshold met for frame 3 | 4 | let threshold = 95; 5 | 6 | export function setup(args) 7 | { 8 | args.features = [ "mv" ]; 9 | } 10 | 11 | export function glitch_frame(frame) 12 | { 13 | var do_or_not = Math.random() * 100; 14 | // only do the glitch if our random number crosses the threshold 15 | if(do_or_not > threshold){ 16 | // bail out if we have no forward motion vectors 17 | const fwd_mvs = frame.mv?.forward; 18 | if ( !fwd_mvs ) 19 | return; 20 | 21 | // set motion vector overflow behaviour in ffedit to "truncate" 22 | frame.mv.overflow = "truncate"; 23 | 24 | fwd_mvs.mul(-1, -1); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(invertN).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(invertN).js 2 | // invert x and y component of mv for n framesif threshold met for frame 3 | 4 | let threshold = 95; 5 | var TRIGGERED = 0; 6 | var nFrames = 10; 7 | var frameCount = 0; 8 | 9 | export function setup(args) 10 | { 11 | args.features = [ "mv" ]; 12 | } 13 | 14 | export function glitch_frame(frame) 15 | { 16 | var do_or_not = Math.random() * 100; 17 | if(do_or_not > threshold){ 18 | if(TRIGGERED > 0){ 19 | 20 | }else{ 21 | TRIGGERED = 1; 22 | frameCount = 0; 23 | } 24 | } 25 | // only do the glitch if our random number crosses the threshold 26 | if(TRIGGERED > 0 & frameCount <= nFrames){ 27 | frameCount++; 28 | 29 | // bail out if we have no forward motion vectors 30 | const fwd_mvs = frame.mv?.forward; 31 | if ( !fwd_mvs ) 32 | return; 33 | 34 | // set motion vector overflow behaviour in ffedit to "truncate" 35 | frame.mv.overflow = "truncate"; 36 | 37 | fwd_mvs.mul(-1, -1); 38 | }else{ 39 | TRIGGERED = 0; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(invertRandomN).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(invertRandomN).js 2 | // invert x and y component of mv for random number of frames if threshold met for frame 3 | 4 | let threshold = 95; 5 | var TRIGGERED = 0; 6 | var nFrames = 10; 7 | var frameCount = 0; 8 | var MAGNITUDE = 20; 9 | 10 | export function setup(args) 11 | { 12 | args.features = [ "mv" ]; 13 | } 14 | 15 | export function glitch_frame(frame) 16 | { 17 | var do_or_not = Math.random() * 100; 18 | if(do_or_not > threshold){ 19 | if(TRIGGERED > 0){ 20 | 21 | }else{ 22 | TRIGGERED = 1; 23 | frameCount = 0; 24 | nFrames = Math.random() * MAGNITUDE; 25 | } 26 | } 27 | // only do the glitch if our random number crosses the threshold 28 | if(TRIGGERED > 0 & frameCount <= nFrames){ 29 | frameCount++; 30 | 31 | // bail out if we have no forward motion vectors 32 | const fwd_mvs = frame.mv?.forward; 33 | if ( !fwd_mvs ) 34 | return; 35 | 36 | // set motion vector overflow behaviour in ffedit to "truncate" 37 | frame.mv.overflow = "truncate"; 38 | 39 | fwd_mvs.mul(-1, -1); 40 | }else{ 41 | TRIGGERED = 0; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(progDisplaceX).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(progDisplaceX).js 2 | // progressive displace x components of mv if threshold met for frame 3 | 4 | let threshold = 95; 5 | 6 | 7 | 8 | var TRIGGERED = 0; 9 | var nFrames = 5; 10 | var frameCount = 0; 11 | var DISPLACE = 0; 12 | var doDISPLACE = 0; 13 | var MAGNITUDE = 100; 14 | 15 | export function setup(args) 16 | { 17 | args.features = [ "mv" ]; 18 | } 19 | 20 | export function glitch_frame(frame) 21 | { 22 | var do_or_not = Math.random() * 100; 23 | if(do_or_not > threshold){ 24 | if(TRIGGERED > 0){ 25 | 26 | }else{ 27 | TRIGGERED = 1; 28 | frameCount = 0; 29 | DISPLACE = Math.random() * MAGNITUDE; 30 | var do_dir = Math.random() * 100; 31 | if(do_dir > 50){ 32 | DISPLACE = 0 - DISPLACE; 33 | }else{ 34 | } 35 | doDISPLACE = 0; 36 | } 37 | } 38 | // only do the glitch if our random number crosses the threshold 39 | if(TRIGGERED > 0 & frameCount <= nFrames){ 40 | frameCount++; 41 | doDISPLACE += DISPLACE; 42 | 43 | // bail out if we have no forward motion vectors 44 | const fwd_mvs = frame.mv?.forward; 45 | if ( !fwd_mvs ) 46 | return; 47 | 48 | // set motion vector overflow behaviour in ffedit to "truncate" 49 | frame.mv.overflow = "truncate"; 50 | 51 | fwd_mvs.add_h(doDISPLACE); 52 | }else{ 53 | TRIGGERED = 0; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(progDisplaceY).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(progDisplaceY).js 2 | // progressive displace y components of mv if threshold met for frame 3 | 4 | let threshold = 95; 5 | 6 | 7 | 8 | var TRIGGERED = 0; 9 | var nFrames = 5; 10 | var frameCount = 0; 11 | var DISPLACE = 0; 12 | var doDISPLACE = 0; 13 | var MAGNITUDE = 100; 14 | 15 | export function setup(args) 16 | { 17 | args.features = [ "mv" ]; 18 | } 19 | 20 | export function glitch_frame(frame) 21 | { 22 | var do_or_not = Math.random() * 100; 23 | if(do_or_not > threshold){ 24 | if(TRIGGERED > 0){ 25 | 26 | }else{ 27 | TRIGGERED = 1; 28 | frameCount = 0; 29 | DISPLACE = Math.random() * MAGNITUDE; 30 | var do_dir = Math.random() * 100; 31 | if(do_dir > 50){ 32 | DISPLACE = 0 - DISPLACE; 33 | }else{ 34 | } 35 | doDISPLACE = 0; 36 | } 37 | } 38 | // only do the glitch if our random number crosses the threshold 39 | if(TRIGGERED > 0 & frameCount <= nFrames){ 40 | frameCount++; 41 | doDISPLACE += DISPLACE; 42 | 43 | // bail out if we have no forward motion vectors 44 | const fwd_mvs = frame.mv?.forward; 45 | if ( !fwd_mvs ) 46 | return; 47 | 48 | // set motion vector overflow behaviour in ffedit to "truncate" 49 | frame.mv.overflow = "truncate"; 50 | 51 | fwd_mvs.add_v(doDISPLACE); 52 | }else{ 53 | TRIGGERED = 0; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(progSlamZoom).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(progSlamZoom).js 2 | // progressive SlamZoom x and y components of mv if threshold met for frame 3 | 4 | let threshold = 95; 5 | 6 | var ZOOM = 0; 7 | var doZOOM = 0; 8 | var TRIGGERED = 0; 9 | var nFrames = 5; 10 | var frameCount = 0; 11 | 12 | export function setup(args) 13 | { 14 | args.features = [ "mv" ]; 15 | } 16 | 17 | export function glitch_frame(frame) 18 | { 19 | var do_or_not = Math.random() * 100; 20 | if(do_or_not > threshold){ 21 | if(TRIGGERED > 0){ 22 | 23 | }else{ 24 | TRIGGERED = 1; 25 | frameCount = 0; 26 | ZOOM = 0; 27 | } 28 | } 29 | // only do the glitch if our random number crosses the threshold 30 | if(TRIGGERED > 0 & frameCount <= nFrames){ 31 | frameCount++; 32 | ZOOM+= 10 33 | 34 | var do_dir = Math.random() * 100; 35 | if(do_dir > 50){ 36 | doZOOM = 0 - ZOOM; 37 | }else{ 38 | doZOOM = ZOOM 39 | } 40 | // bail out if we have no forward motion vectors 41 | const fwd_mvs = frame.mv?.forward; 42 | if ( !fwd_mvs ) 43 | return; 44 | 45 | // set motion vector overflow behaviour in ffedit to "truncate" 46 | frame.mv.overflow = "truncate"; 47 | 48 | const M_H = fwd_mvs.height / 2; 49 | const M_W = fwd_mvs.width / 2; 50 | 51 | fwd_mvs.forEach((mv, i, j) => { 52 | mv[0] = ((M_W - j) / 10) * doZOOM; 53 | mv[1] = ((M_H - i) / 10) * doZOOM; 54 | }); 55 | }else{ 56 | TRIGGERED = 0; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(progZoom).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(progZoom).js 2 | // progressive Zoom x and y components of mv if threshold met for frame 3 | 4 | let threshold = 95; 5 | 6 | var ZOOM = 0; 7 | var doZOOM = 0; 8 | var TRIGGERED = 0; 9 | var nFrames = 5; 10 | var frameCount = 0; 11 | 12 | export function setup(args) 13 | { 14 | args.features = [ "mv" ]; 15 | } 16 | 17 | export function glitch_frame(frame) 18 | { 19 | var do_or_not = Math.random() * 100; 20 | if(do_or_not > threshold){ 21 | if(TRIGGERED > 0){ 22 | 23 | }else{ 24 | TRIGGERED = 1; 25 | frameCount = 0; 26 | ZOOM = 0; 27 | } 28 | } 29 | // only do the glitch if our random number crosses the threshold 30 | if(TRIGGERED > 0 & frameCount <= nFrames){ 31 | frameCount++; 32 | ZOOM+= 10 33 | 34 | var do_dir = Math.random() * 100; 35 | if(do_dir > 50){ 36 | doZOOM = 0 - ZOOM; 37 | }else{ 38 | doZOOM = ZOOM 39 | } 40 | // bail out if we have no forward motion vectors 41 | const fwd_mvs = frame.mv?.forward; 42 | if ( !fwd_mvs ) 43 | return; 44 | 45 | // set motion vector overflow behaviour in ffedit to "truncate" 46 | frame.mv.overflow = "truncate"; 47 | 48 | const M_H = fwd_mvs.height / 2; 49 | const M_W = fwd_mvs.width / 2; 50 | 51 | fwd_mvs.forEach((mv, i, j) => { 52 | mv[0] += ((M_W - j) / 10) * doZOOM; 53 | mv[1] += ((M_H - i) / 10) * doZOOM; 54 | }); 55 | }else{ 56 | TRIGGERED = 0; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(random).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(random).js 2 | // randomise x and y component of mv if threshold met for frame 3 | 4 | let threshold = 95; 5 | 6 | var DISPLACE = 0; 7 | var DISPLACE2 = 0; 8 | var MAGNITUDE = 200; 9 | 10 | export function setup(args) 11 | { 12 | args.features = [ "mv" ]; 13 | } 14 | 15 | export function glitch_frame(frame) 16 | { 17 | var do_or_not = Math.random() * 100; 18 | // only do the glitch if our random number crosses the threshold 19 | if(do_or_not > threshold){ 20 | DISPLACE = Math.random() * MAGNITUDE; 21 | DISPLACE2 = Math.random() * MAGNITUDE; 22 | var n_DIR = Math.random() * 100; 23 | if(n_DIR > 50){ 24 | DISPLACE = 0-DISPLACE; 25 | } 26 | n_DIR = Math.random() * 100; 27 | if(n_DIR > 50){ 28 | DISPLACE2 = 0-DISPLACE2; 29 | } 30 | // bail out if we have no forward motion vectors 31 | const fwd_mvs = frame.mv?.forward; 32 | if ( !fwd_mvs ) 33 | return; 34 | 35 | // set motion vector overflow behaviour in ffedit to "truncate" 36 | frame.mv.overflow = "truncate"; 37 | 38 | fwd_mvs.forEach((mv) => { 39 | mv[0] += Math.random() * DISPLACE; 40 | mv[1] += Math.random() * DISPLACE2; 41 | }); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(randomMultiple).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(randomMultiple).js 2 | // radom multiplies x and y components of mv if threshold met for frame 3 | 4 | let threshold = 95; 5 | let multiplier = 10; 6 | 7 | export function setup(args) 8 | { 9 | args.features = [ "mv" ]; 10 | } 11 | 12 | export function glitch_frame(frame) 13 | { 14 | var do_or_not = Math.random() * 100; 15 | // only do the glitch if our random number crosses the threshold 16 | if(do_or_not > threshold){ 17 | // bail out if we have no forward motion vectors 18 | const fwd_mvs = frame.mv?.forward; 19 | if ( !fwd_mvs ) 20 | return; 21 | 22 | // set motion vector overflow behaviour in ffedit to "truncate" 23 | frame.mv.overflow = "truncate"; 24 | 25 | fwd_mvs.forEach((mv) => { 26 | mv[0] += Math.random() * multiplier; 27 | mv[1] += Math.random() * multiplier; 28 | }); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(randomX).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(randomX).js 2 | // randomise x component of mv if threshold met for frame 3 | 4 | let threshold = 95; 5 | 6 | var DISPLACE = 0; 7 | var DISPLACE2 = 0; 8 | var MAGNITUDE = 200; 9 | 10 | export function setup(args) 11 | { 12 | args.features = [ "mv" ]; 13 | } 14 | 15 | export function glitch_frame(frame) 16 | { 17 | var do_or_not = Math.random() * 100; 18 | // only do the glitch if our random number crosses the threshold 19 | if(do_or_not > threshold){ 20 | DISPLACE = Math.random() * MAGNITUDE; 21 | DISPLACE2 = Math.random() * MAGNITUDE; 22 | var n_DIR = Math.random() * 100; 23 | if(n_DIR > 50){ 24 | DISPLACE = 0-DISPLACE; 25 | } 26 | n_DIR = Math.random() * 100; 27 | if(n_DIR > 50){ 28 | DISPLACE2 = 0-DISPLACE2; 29 | } 30 | // bail out if we have no forward motion vectors 31 | const fwd_mvs = frame.mv?.forward; 32 | if ( !fwd_mvs ) 33 | return; 34 | 35 | // set motion vector overflow behaviour in ffedit to "truncate" 36 | frame.mv.overflow = "truncate"; 37 | 38 | fwd_mvs.forEach((mv) => { 39 | mv[0] += Math.random() * DISPLACE; 40 | }); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(randomY).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(randomX).js 2 | // randomise x component of mv if threshold met for frame 3 | 4 | let threshold = 95; 5 | 6 | var DISPLACE = 0; 7 | var DISPLACE2 = 0; 8 | var MAGNITUDE = 200; 9 | 10 | export function setup(args) 11 | { 12 | args.features = [ "mv" ]; 13 | } 14 | 15 | export function glitch_frame(frame) 16 | { 17 | var do_or_not = Math.random() * 100; 18 | // only do the glitch if our random number crosses the threshold 19 | if(do_or_not > threshold){ 20 | DISPLACE = Math.random() * MAGNITUDE; 21 | DISPLACE2 = Math.random() * MAGNITUDE; 22 | var n_DIR = Math.random() * 100; 23 | if(n_DIR > 50){ 24 | DISPLACE = 0-DISPLACE; 25 | } 26 | n_DIR = Math.random() * 100; 27 | if (n_DIR > 50) 28 | DISPLACE2 *= -1; 29 | // bail out if we have no forward motion vectors 30 | const fwd_mvs = frame.mv?.forward; 31 | if ( !fwd_mvs ) 32 | return; 33 | 34 | // set motion vector overflow behaviour in ffedit to "truncate" 35 | frame.mv.overflow = "truncate"; 36 | 37 | fwd_mvs.forEach((mv) => { 38 | mv[1] += Math.random() * DISPLACE2; 39 | }); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(randomZoom).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(randomZoom).js 2 | // randomlyZoom x and y components of mv if threshold met for frame 3 | 4 | let threshold = 95; 5 | 6 | var ZOOM = 100; 7 | 8 | export function setup(args) 9 | { 10 | args.features = [ "mv" ]; 11 | } 12 | 13 | export function glitch_frame(frame) 14 | { 15 | var do_or_not = Math.random() * 100; 16 | // only do the glitch if our random number crosses the threshold 17 | if(do_or_not > threshold){ 18 | ZOOM = Math.random() * 100; 19 | var do_dir = Math.random() * 100; 20 | if(do_dir > 50){ 21 | ZOOM = 0 - ZOOM; 22 | } 23 | // bail out if we have no forward motion vectors 24 | const fwd_mvs = frame.mv?.forward; 25 | if ( !fwd_mvs ) 26 | return; 27 | 28 | // set motion vector overflow behaviour in ffedit to "truncate" 29 | frame.mv.overflow = "truncate"; 30 | 31 | const M_H = fwd_mvs.height / 2; 32 | const M_W = fwd_mvs.width / 2; 33 | 34 | fwd_mvs.forEach((mv, i, j) => { 35 | mv[0] += ((M_W - j) / 10) * ZOOM; 36 | mv[1] += ((M_H - i) / 10) * ZOOM; 37 | }); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(shear).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(shear).js 2 | // shear x and y components of mv if threshold met for frame 3 | 4 | let threshold = 95; 5 | 6 | var ZOOM = 50; 7 | 8 | export function setup(args) 9 | { 10 | args.features = [ "mv" ]; 11 | } 12 | 13 | export function glitch_frame(frame) 14 | { 15 | var do_or_not = Math.random() * 100; 16 | // only do the glitch if our random number crosses the threshold 17 | if(do_or_not > threshold){ 18 | var do_dir = Math.random() * 100; 19 | if(do_dir > 50){ 20 | ZOOM = 0 - ZOOM; 21 | } 22 | // bail out if we have no forward motion vectors 23 | const fwd_mvs = frame.mv?.forward; 24 | if ( !fwd_mvs ) 25 | return; 26 | 27 | // set motion vector overflow behaviour in ffedit to "truncate" 28 | frame.mv.overflow = "truncate"; 29 | 30 | const M_H = fwd_mvs.height / 2; 31 | const M_W = fwd_mvs.width / 2; 32 | 33 | fwd_mvs.forEach((mv, i, j) => { 34 | mv[0] += ((i - M_W) / 100) * ZOOM; 35 | mv[1] += ((j - M_H) / 100) * ZOOM; 36 | }); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(slamZoom).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(slamZoom).js 2 | // slamZoom x and y components of mv if threshold met for frame 3 | 4 | let threshold = 95; 5 | 6 | var ZOOM = 0; 7 | var MAGNITUDE = 100; 8 | 9 | export function setup(args) 10 | { 11 | args.features = [ "mv" ]; 12 | } 13 | 14 | export function glitch_frame(frame) 15 | { 16 | var do_or_not = Math.random() * 100; 17 | // only do the glitch if our random number crosses the threshold 18 | if(do_or_not > threshold){ 19 | var do_dir = Math.random() * 100; 20 | ZOOM = Math.random() * MAGNITUDE; 21 | if(do_dir > 50){ 22 | ZOOM = 0 - ZOOM; 23 | } 24 | // bail out if we have no forward motion vectors 25 | const fwd_mvs = frame.mv?.forward; 26 | if ( !fwd_mvs ) 27 | return; 28 | 29 | // set motion vector overflow behaviour in ffedit to "truncate" 30 | frame.mv.overflow = "truncate"; 31 | 32 | const M_H = fwd_mvs.height / 2; 33 | const M_W = fwd_mvs.width / 2; 34 | 35 | fwd_mvs.forEach((mv, i, j) => { 36 | mv[0] = ((M_W - j) / 10) * ZOOM; 37 | mv[1] = ((M_H - i) / 10) * ZOOM; 38 | }); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(sliceHB).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(sliceHB).js 2 | // disrupt bottom of frame if threshold met 3 | 4 | let threshold = 95; 5 | 6 | var DISPLACE = 0; 7 | var MAGNITUDE = 500; 8 | 9 | export function setup(args) 10 | { 11 | args.features = [ "mv" ]; 12 | } 13 | 14 | export function glitch_frame(frame) 15 | { 16 | var do_or_not = Math.random() * 100; 17 | // only do the glitch if our random number crosses the threshold 18 | if(do_or_not > threshold){ 19 | DISPLACE = (Math.random() * MAGNITUDE) - (MAGNITUDE*0.5); 20 | // bail out if we have no forward motion vectors 21 | const fwd_mvs = frame.mv?.forward; 22 | if ( !fwd_mvs ) 23 | return; 24 | 25 | // set motion vector overflow behaviour in ffedit to "truncate" 26 | frame.mv.overflow = "truncate"; 27 | 28 | const M_H = fwd_mvs.height / 2; 29 | const M_W = fwd_mvs.width / 2; 30 | 31 | fwd_mvs.forEach((mv, i, j) => { 32 | if (i >= M_H) 33 | mv[0] += DISPLACE; 34 | }); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(sliceHT).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(sliceHT).js 2 | // disrupt top of frame if threshold met 3 | 4 | let threshold = 95; 5 | 6 | var DISPLACE = 0; 7 | var MAGNITUDE = 500; 8 | 9 | export function setup(args) 10 | { 11 | args.features = [ "mv" ]; 12 | } 13 | 14 | export function glitch_frame(frame) 15 | { 16 | var do_or_not = Math.random() * 100; 17 | // only do the glitch if our random number crosses the threshold 18 | if(do_or_not > threshold){ 19 | DISPLACE = (Math.random() * MAGNITUDE) - (MAGNITUDE*0.5); 20 | // bail out if we have no forward motion vectors 21 | const fwd_mvs = frame.mv?.forward; 22 | if ( !fwd_mvs ) 23 | return; 24 | 25 | // set motion vector overflow behaviour in ffedit to "truncate" 26 | frame.mv.overflow = "truncate"; 27 | 28 | const M_H = fwd_mvs.height / 2; 29 | const M_W = fwd_mvs.width / 2; 30 | 31 | fwd_mvs.forEach((mv, i, j) => { 32 | if (i <= M_H) 33 | mv[0] += DISPLACE; 34 | }); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(sliceVL).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(sliceVL).js 2 | // disrupt left of frame if threshold met 3 | 4 | let threshold = 95; 5 | 6 | var DISPLACE = 0; 7 | var MAGNITUDE = 500; 8 | 9 | export function setup(args) 10 | { 11 | args.features = [ "mv" ]; 12 | } 13 | 14 | export function glitch_frame(frame) 15 | { 16 | var do_or_not = Math.random() * 100; 17 | // only do the glitch if our random number crosses the threshold 18 | if(do_or_not > threshold){ 19 | DISPLACE = (Math.random() * MAGNITUDE) - (MAGNITUDE*0.5); 20 | // bail out if we have no forward motion vectors 21 | const fwd_mvs = frame.mv?.forward; 22 | if ( !fwd_mvs ) 23 | return; 24 | 25 | // set motion vector overflow behaviour in ffedit to "truncate" 26 | frame.mv.overflow = "truncate"; 27 | 28 | const M_H = fwd_mvs.height / 2; 29 | const M_W = fwd_mvs.width / 2; 30 | 31 | fwd_mvs.forEach((mv, i, j) => { 32 | if (j < M_W) 33 | mv[1] += DISPLACE; 34 | }); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(sliceVR).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(sliceVR).js 2 | // disrupt right of frame if threshold met 3 | 4 | let threshold = 95; 5 | 6 | var DISPLACE = 0; 7 | var MAGNITUDE = 500; 8 | 9 | export function setup(args) 10 | { 11 | args.features = [ "mv" ]; 12 | } 13 | 14 | export function glitch_frame(frame) 15 | { 16 | var do_or_not = Math.random() * 100; 17 | // only do the glitch if our random number crosses the threshold 18 | if(do_or_not > threshold){ 19 | DISPLACE = (Math.random() * MAGNITUDE) - (MAGNITUDE*0.5); 20 | // bail out if we have no forward motion vectors 21 | const fwd_mvs = frame.mv?.forward; 22 | if ( !fwd_mvs ) 23 | return; 24 | 25 | // set motion vector overflow behaviour in ffedit to "truncate" 26 | frame.mv.overflow = "truncate"; 27 | 28 | const M_H = fwd_mvs.height / 2; 29 | const M_W = fwd_mvs.width / 2; 30 | 31 | fwd_mvs.forEach((mv, i, j) => { 32 | if (j > M_W) 33 | mv[1] += DISPLACE; 34 | }); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(stop).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(stop).js 2 | // zeroes x and y components of mv if threshold met for frame 3 | 4 | let threshold = 95; 5 | 6 | export function setup(args) 7 | { 8 | args.features = [ "mv" ]; 9 | } 10 | 11 | export function glitch_frame(frame) 12 | { 13 | var do_or_not = Math.random() * 100; 14 | // only do the glitch if our random number crosses the threshold 15 | if(do_or_not > threshold){ 16 | // bail out if we have no forward motion vectors 17 | const fwd_mvs = frame.mv?.forward; 18 | if ( !fwd_mvs ) 19 | return; 20 | 21 | // set motion vector overflow behaviour in ffedit to "truncate" 22 | frame.mv.overflow = "truncate"; 23 | 24 | fwd_mvs.assign(0, 0); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(stopX).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(stopX).js 2 | // stop x component of mv for n framesif threshold met for frame 3 | 4 | let threshold = 95; 5 | var TRIGGERED = 0; 6 | var nFrames = 10; 7 | var frameCount = 0; 8 | 9 | export function setup(args) 10 | { 11 | args.features = [ "mv" ]; 12 | } 13 | 14 | export function glitch_frame(frame) 15 | { 16 | var do_or_not = Math.random() * 100; 17 | if(do_or_not > threshold){ 18 | if(TRIGGERED > 0){ 19 | 20 | }else{ 21 | TRIGGERED = 1; 22 | frameCount = 0; 23 | } 24 | } 25 | // only do the glitch if our random number crosses the threshold 26 | if(TRIGGERED > 0 & frameCount <= nFrames){ 27 | frameCount++; 28 | 29 | // bail out if we have no forward motion vectors 30 | const fwd_mvs = frame.mv?.forward; 31 | if ( !fwd_mvs ) 32 | return; 33 | 34 | // set motion vector overflow behaviour in ffedit to "truncate" 35 | frame.mv.overflow = "truncate"; 36 | 37 | fwd_mvs.assign_h(0); 38 | }else{ 39 | TRIGGERED = 0; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(stopXY).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(stopXY).js 2 | // stop x and y component of mv for n framesif threshold met for frame 3 | 4 | let threshold = 95; 5 | var TRIGGERED = 0; 6 | var nFrames = 10; 7 | var frameCount = 0; 8 | 9 | export function setup(args) 10 | { 11 | args.features = [ "mv" ]; 12 | } 13 | 14 | export function glitch_frame(frame) 15 | { 16 | var do_or_not = Math.random() * 100; 17 | if(do_or_not > threshold){ 18 | if(TRIGGERED > 0){ 19 | 20 | }else{ 21 | TRIGGERED = 1; 22 | frameCount = 0; 23 | } 24 | } 25 | // only do the glitch if our random number crosses the threshold 26 | if(TRIGGERED > 0 & frameCount <= nFrames){ 27 | frameCount++; 28 | 29 | // bail out if we have no forward motion vectors 30 | const fwd_mvs = frame.mv?.forward; 31 | if ( !fwd_mvs ) 32 | return; 33 | 34 | // set motion vector overflow behaviour in ffedit to "truncate" 35 | frame.mv.overflow = "truncate"; 36 | 37 | fwd_mvs.assign(0, 0); 38 | }else{ 39 | TRIGGERED = 0; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(stopXYSmash).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(stopXYSmash).js 2 | // stop x and y component of mv for n frames if threshold met for frame 3 | // then SMASH. 4 | 5 | let threshold = 98; 6 | var TRIGGERED = 0; 7 | var nFrames = 10; 8 | var MAXFRAMES = 10; 9 | var frameCount = 0; 10 | var MAGNITUDE = 100; 11 | export function setup(args) 12 | { 13 | args.features = [ "mv" ]; 14 | } 15 | 16 | export function glitch_frame(frame) 17 | { 18 | var do_or_not = Math.random() * 100; 19 | if(do_or_not > threshold){ 20 | if(TRIGGERED > 0){ 21 | 22 | }else{ 23 | TRIGGERED = 1; 24 | nFrames = Math.round((MAXFRAMES * 0.5) + (Math.random() * MAXFRAMES * 0.5)); 25 | frameCount = 0; 26 | } 27 | } 28 | // only do the glitch if our random number crosses the threshold 29 | if(TRIGGERED > 0 & frameCount <= nFrames){ 30 | 31 | // bail out if we have no forward motion vectors 32 | const fwd_mvs = frame.mv?.forward; 33 | if ( !fwd_mvs ) 34 | return; 35 | 36 | // set motion vector overflow behaviour in ffedit to "truncate" 37 | frame.mv.overflow = "truncate"; 38 | 39 | if (frameCount == nFrames) 40 | fwd_mvs.mul(MAGNITUDE, MAGNITUDE); 41 | else 42 | fwd_mvs.assign(0, 0); 43 | 44 | frameCount++; 45 | }else{ 46 | TRIGGERED = 0; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(stopY).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(stopY).js 2 | // stop y component of mv for n framesif threshold met for frame 3 | 4 | let threshold = 95; 5 | var TRIGGERED = 0; 6 | var nFrames = 10; 7 | var frameCount = 0; 8 | 9 | export function setup(args) 10 | { 11 | args.features = [ "mv" ]; 12 | } 13 | 14 | export function glitch_frame(frame) 15 | { 16 | var do_or_not = Math.random() * 100; 17 | if(do_or_not > threshold){ 18 | if(TRIGGERED > 0){ 19 | 20 | }else{ 21 | TRIGGERED = 1; 22 | frameCount = 0; 23 | } 24 | } 25 | // only do the glitch if our random number crosses the threshold 26 | if(TRIGGERED > 0 & frameCount <= nFrames){ 27 | frameCount++; 28 | 29 | // bail out if we have no forward motion vectors 30 | const fwd_mvs = frame.mv?.forward; 31 | if ( !fwd_mvs ) 32 | return; 33 | 34 | // set motion vector overflow behaviour in ffedit to "truncate" 35 | frame.mv.overflow = "truncate"; 36 | 37 | fwd_mvs.assign_v(0); 38 | }else{ 39 | TRIGGERED = 0; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(swap).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(swap).js 2 | // swaps x and y components of mv if threshold met for frame 3 | 4 | let threshold = 95; 5 | 6 | export function setup(args) 7 | { 8 | args.features = [ "mv" ]; 9 | } 10 | 11 | export function glitch_frame(frame) 12 | { 13 | var do_or_not = Math.random() * 100; 14 | // only do the glitch if our random number crosses the threshold 15 | if(do_or_not > threshold){ 16 | // bail out if we have no forward motion vectors 17 | const fwd_mvs = frame.mv?.forward; 18 | if ( !fwd_mvs ) 19 | return; 20 | 21 | // set motion vector overflow behaviour in ffedit to "truncate" 22 | frame.mv.overflow = "truncate"; 23 | 24 | fwd_mvs.swap_hv(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(swapN).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(swapN).js 2 | // swap x and y component of mv for n framesif threshold met for frame 3 | 4 | let threshold = 95; 5 | var TRIGGERED = 0; 6 | var nFrames = 5; 7 | var frameCount = 0; 8 | 9 | export function setup(args) 10 | { 11 | args.features = [ "mv" ]; 12 | } 13 | 14 | export function glitch_frame(frame) 15 | { 16 | var do_or_not = Math.random() * 100; 17 | if(do_or_not > threshold){ 18 | if(TRIGGERED > 0){ 19 | 20 | }else{ 21 | TRIGGERED = 1; 22 | frameCount = 0; 23 | } 24 | } 25 | // only do the glitch if our random number crosses the threshold 26 | if(TRIGGERED > 0 & frameCount <= nFrames){ 27 | frameCount++; 28 | 29 | // bail out if we have no forward motion vectors 30 | const fwd_mvs = frame.mv?.forward; 31 | if ( !fwd_mvs ) 32 | return; 33 | 34 | // set motion vector overflow behaviour in ffedit to "truncate" 35 | frame.mv.overflow = "truncate"; 36 | 37 | fwd_mvs.swap_hv(); 38 | }else{ 39 | TRIGGERED = 0; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(swapRandomN).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(invertRandomN).js 2 | // swap x and y component of mv for random number of frames if threshold met for frame 3 | 4 | let threshold = 95; 5 | var TRIGGERED = 0; 6 | var nFrames = 10; 7 | var frameCount = 0; 8 | var MAGNITUDE = 20; 9 | 10 | export function setup(args) 11 | { 12 | args.features = [ "mv" ]; 13 | } 14 | 15 | export function glitch_frame(frame) 16 | { 17 | var do_or_not = Math.random() * 100; 18 | if(do_or_not > threshold){ 19 | if(TRIGGERED > 0){ 20 | 21 | }else{ 22 | TRIGGERED = 1; 23 | frameCount = 0; 24 | nFrames = Math.random() * MAGNITUDE; 25 | } 26 | } 27 | // only do the glitch if our random number crosses the threshold 28 | if(TRIGGERED > 0 & frameCount <= nFrames){ 29 | frameCount++; 30 | 31 | // bail out if we have no forward motion vectors 32 | const fwd_mvs = frame.mv?.forward; 33 | if ( !fwd_mvs ) 34 | return; 35 | 36 | // set motion vector overflow behaviour in ffedit to "truncate" 37 | frame.mv.overflow = "truncate"; 38 | 39 | fwd_mvs.swap_hv(); 40 | }else{ 41 | TRIGGERED = 0; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(twitch).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(twitch).js 2 | // stop x then stop y component of mv for n frames if threshold met for frame 3 | 4 | 5 | let threshold = 95; 6 | var TRIGGERED = 0; 7 | var nFrames = 10; 8 | var MAXFRAMES = 10; 9 | var frameCount = 0; 10 | var MAGNITUDE = 5; 11 | export function setup(args) 12 | { 13 | args.features = [ "mv" ]; 14 | } 15 | 16 | export function glitch_frame(frame) 17 | { 18 | var do_or_not = Math.random() * 100; 19 | if(do_or_not > threshold){ 20 | if(TRIGGERED > 0){ 21 | 22 | }else{ 23 | TRIGGERED = 1; 24 | //nFrames = Math.random() * MAXFRAMES; 25 | frameCount = 0; 26 | } 27 | } 28 | // only do the glitch if our random number crosses the threshold 29 | if(TRIGGERED > 0 & frameCount <= nFrames){ 30 | 31 | // bail out if we have no forward motion vectors 32 | const fwd_mvs = frame.mv?.forward; 33 | if ( !fwd_mvs ) 34 | return; 35 | 36 | // set motion vector overflow behaviour in ffedit to "truncate" 37 | frame.mv.overflow = "truncate"; 38 | 39 | const M_H = fwd_mvs.height / 2; 40 | const M_W = fwd_mvs.width / 2; 41 | 42 | fwd_mvs.forEach((mv, i, j) => { 43 | if ( frameCount == 0 ) 44 | { 45 | mv[0] *= MAGNITUDE; 46 | mv[1] = 0; 47 | } 48 | if ( frameCount == 1 ) 49 | { 50 | mv[1] *= MAGNITUDE; 51 | mv[0] = 0; 52 | } 53 | }); 54 | 55 | frameCount++; 56 | }else{ 57 | TRIGGERED = 0; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(wave).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(wave).js 2 | // sin/cos x and y components of mv if threshold met for frame 3 | 4 | let threshold = 95; 5 | var nFrames = 5; 6 | var TRIGGERED = 0; 7 | var count = 0; 8 | 9 | export function setup(args) 10 | { 11 | args.features = [ "mv" ]; 12 | } 13 | 14 | export function glitch_frame(frame) 15 | { 16 | var do_or_not = Math.random() * 100; 17 | // only do the glitch if our random number crosses the threshold 18 | if(do_or_not > threshold | TRIGGERED == 1){ 19 | if(TRIGGERED == 0){ 20 | TRIGGERED = 1; 21 | count = 0; 22 | } 23 | // bail out if we have no forward motion vectors 24 | const fwd_mvs = frame.mv?.forward; 25 | if ( !fwd_mvs ) 26 | return; 27 | 28 | // set motion vector overflow behaviour in ffedit to "truncate" 29 | frame.mv.overflow = "truncate"; 30 | 31 | const M_H = fwd_mvs.height / 2; 32 | const M_W = fwd_mvs.width / 2; 33 | 34 | fwd_mvs.forEach((mv, i, j) => { 35 | mv[0] *= Math.sin(i/M_W*Math.PI*2); 36 | mv[1] *= Math.cos(j/M_H*Math.PI*2); 37 | }); 38 | 39 | count++; 40 | if(count >= nFrames){ 41 | TRIGGERED = 0; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(wave2).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(wave).js 2 | // sin/cos x and y components of mv if threshold met for frame 3 | 4 | let threshold = 95; 5 | var nFrames = 5; 6 | var TRIGGERED = 0; 7 | var count = 0; 8 | 9 | export function setup(args) 10 | { 11 | args.features = [ "mv" ]; 12 | } 13 | 14 | export function glitch_frame(frame) 15 | { 16 | var do_or_not = Math.random() * 100; 17 | // only do the glitch if our random number crosses the threshold 18 | if(do_or_not > threshold | TRIGGERED == 1){ 19 | if(TRIGGERED == 0){ 20 | TRIGGERED = 1; 21 | count = 0; 22 | } 23 | // bail out if we have no forward motion vectors 24 | const fwd_mvs = frame.mv?.forward; 25 | if ( !fwd_mvs ) 26 | return; 27 | 28 | // set motion vector overflow behaviour in ffedit to "truncate" 29 | frame.mv.overflow = "truncate"; 30 | 31 | const M_H = fwd_mvs.height / 2; 32 | const M_W = fwd_mvs.width / 2; 33 | 34 | fwd_mvs.forEach((mv, i, j) => { 35 | mv[0] = mv[0] + Math.sin(i/M_W*Math.PI*2)*mv[0]; 36 | mv[1] = mv[1] + Math.cos(j/M_H*Math.PI*2)*mv[1]; 37 | }); 38 | 39 | count++; 40 | if(count >= nFrames){ 41 | TRIGGERED = 0; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/random_damage/dd_RandomDamage(zoom).js: -------------------------------------------------------------------------------- 1 | // dd_RandomDamage(zoom).js 2 | // shear x and y components of mv if threshold met for frame 3 | 4 | let threshold = 95; 5 | 6 | var ZOOM = 100; 7 | 8 | export function setup(args) 9 | { 10 | args.features = [ "mv" ]; 11 | } 12 | 13 | export function glitch_frame(frame) 14 | { 15 | var do_or_not = Math.random() * 100; 16 | // only do the glitch if our random number crosses the threshold 17 | if(do_or_not > threshold){ 18 | var do_dir = Math.random() * 100; 19 | if(do_dir > 50){ 20 | ZOOM = 0 - ZOOM; 21 | } 22 | // bail out if we have no forward motion vectors 23 | const fwd_mvs = frame.mv?.forward; 24 | if ( !fwd_mvs ) 25 | return; 26 | 27 | // set motion vector overflow behaviour in ffedit to "truncate" 28 | frame.mv.overflow = "truncate"; 29 | 30 | const M_H = fwd_mvs.height / 2; 31 | const M_W = fwd_mvs.width / 2; 32 | 33 | fwd_mvs.forEach((mv, i, j) => { 34 | mv[0] += ((M_W - j) / 10) * ZOOM; 35 | mv[1] += ((M_H - i) / 10) * ZOOM; 36 | }); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/selective_damage/dd_BlurFastest.js: -------------------------------------------------------------------------------- 1 | // dd_blurFastest.js 2 | // apply 20-frame average to the fastest moving mv's 3 | var SOME_PERCENTAGE = 0.10; 4 | 5 | // global variable holding forward motion vectors from previous frames 6 | let prev_fwd_mvs = [ ]; 7 | let total_sum; 8 | 9 | // change this value to use a smaller or greater number of frmes to average 10 | var tail_length = 20; 11 | 12 | export function setup(args) 13 | { 14 | args.features = [ "mv" ]; 15 | 16 | // Pass "-sp " in the command line, where is an 17 | // integer from 0 to 100. 18 | if ( "params" in args ) 19 | SOME_PERCENTAGE = (100 - args.params) / 100; 20 | } 21 | 22 | export function glitch_frame(frame) 23 | { 24 | // bail out if we have no forward motion vectors 25 | const fwd_mvs = frame.mv?.forward; 26 | if ( !fwd_mvs ) 27 | return; 28 | 29 | // set motion vector overflow behaviour in ffedit to "truncate" 30 | frame.mv.overflow = "truncate"; 31 | 32 | const largest = fwd_mvs.largest_sq(); 33 | const threshold = Math.floor(SOME_PERCENTAGE * largest[2]); 34 | const mask = fwd_mvs.compare_gt(threshold); 35 | 36 | // update variable holding forward motion vectors from previous 37 | // frames. note that we perform a deep copy of the clean motion 38 | // vector values before modifying them. 39 | const deep_copy = fwd_mvs.dup(); 40 | // push to the end of array 41 | prev_fwd_mvs.push(deep_copy); 42 | 43 | // initialize total_sum to a [0,0] MV2DArray. 44 | if ( !total_sum ) 45 | total_sum = new MV2DArray(fwd_mvs.width, fwd_mvs.height); 46 | 47 | // update total_sum by removing the motion vector values from the 48 | // oldest frame and adding the values from the current frame. 49 | if ( prev_fwd_mvs.length > tail_length ) 50 | { 51 | total_sum.sub(prev_fwd_mvs[0]); 52 | prev_fwd_mvs = prev_fwd_mvs.slice(1); 53 | } 54 | total_sum.add(deep_copy); 55 | 56 | // set new values for current frame to (total_sum / tail_length) 57 | if ( prev_fwd_mvs.length == tail_length ) 58 | { 59 | fwd_mvs.assign(total_sum, mask); 60 | fwd_mvs.div(MV(tail_length, tail_length), mask); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/selective_damage/dd_BlurSlowest.js: -------------------------------------------------------------------------------- 1 | // dd_blurSlowest.js 2 | // apply 20-frame average to the slowest moving mv's 3 | var SOME_PERCENTAGE = 0.10; // only the slowest % of mv's in each frame get glitched 4 | 5 | // global variable holding forward motion vectors from previous frames 6 | let prev_fwd_mvs = [ ]; 7 | let total_sum; 8 | 9 | // change this value to use a smaller or greater number of frmes to average 10 | var tail_length = 20; 11 | 12 | export function setup(args) 13 | { 14 | args.features = [ "mv" ]; 15 | 16 | // Pass "-sp " in the command line, where is an 17 | // integer from 0 to 100. 18 | if ( "params" in args ) 19 | SOME_PERCENTAGE = (100 - args.params) / 100; 20 | } 21 | 22 | export function glitch_frame(frame) 23 | { 24 | // bail out if we have no forward motion vectors 25 | const fwd_mvs = frame.mv?.forward; 26 | if ( !fwd_mvs ) 27 | return; 28 | 29 | // set motion vector overflow behaviour in ffedit to "truncate" 30 | frame.mv.overflow = "truncate"; 31 | 32 | const largest = fwd_mvs.largest_sq(); 33 | const threshold = Math.floor(SOME_PERCENTAGE * largest[2]); 34 | const mask = fwd_mvs.compare_lt(threshold); 35 | 36 | // update variable holding forward motion vectors from previous 37 | // frames. note that we perform a deep copy of the clean motion 38 | // vector values before modifying them. 39 | const deep_copy = fwd_mvs.dup(); 40 | // push to the end of array 41 | prev_fwd_mvs.push(deep_copy); 42 | 43 | // initialize total_sum to a [0,0] MV2DArray. 44 | if ( !total_sum ) 45 | total_sum = new MV2DArray(fwd_mvs.width, fwd_mvs.height); 46 | 47 | // update total_sum by removing the motion vector values from the 48 | // oldest frame and adding the values from the current frame. 49 | if ( prev_fwd_mvs.length > tail_length ) 50 | { 51 | total_sum.sub(prev_fwd_mvs[0]); 52 | prev_fwd_mvs = prev_fwd_mvs.slice(1); 53 | } 54 | total_sum.add(deep_copy); 55 | 56 | // set new values for current frame to (total_sum / tail_length) 57 | if ( prev_fwd_mvs.length == tail_length ) 58 | { 59 | fwd_mvs.assign(total_sum, mask); 60 | fwd_mvs.div(MV(tail_length, tail_length), mask); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/selective_damage/dd_MultiplyFastest.js: -------------------------------------------------------------------------------- 1 | // dd_MultiplyFastest.js 2 | // Multiply fastest moving mv's 3 | var LARGEST = 0; 4 | var SOME_PERCENTAGE = 0.10; 5 | var MULTIPLE = 10; 6 | 7 | // change this value to use a smaller or greater number of frmes to average 8 | var tail_length = 20; 9 | 10 | export function setup(args) 11 | { 12 | args.features = [ "mv" ]; 13 | 14 | // Pass "-sp " in the command line, where is an 15 | // integer from 0 to 100. 16 | if ( "params" in args ) 17 | SOME_PERCENTAGE = (100 - args.params) / 100; 18 | } 19 | 20 | export function glitch_frame(frame) 21 | { 22 | // bail out if we have no forward motion vectors 23 | const fwd_mvs = frame.mv?.forward; 24 | if ( !fwd_mvs ) 25 | return; 26 | 27 | // set motion vector overflow behaviour in ffedit to "truncate" 28 | frame.mv.overflow = "truncate"; 29 | 30 | const largest = fwd_mvs.largest_sq(); 31 | const threshold = Math.floor(SOME_PERCENTAGE * largest[2]); 32 | const mask = fwd_mvs.compare_gt(threshold); 33 | 34 | fwd_mvs.mul(MV(MULTIPLE, MULTIPLE), mask); 35 | } 36 | -------------------------------------------------------------------------------- /free-for-all/dd-glitch-assist-scriptsv10/selective_damage/dd_MultiplySlowest.js: -------------------------------------------------------------------------------- 1 | // dd_MultiplySlowest.js 2 | // Multiply slowest moving mv's 3 | var LARGEST = 0; 4 | var SOME_PERCENTAGE = 0.10; 5 | var MULTIPLE = 10; 6 | 7 | // change this value to use a smaller or greater number of frmes to average 8 | var tail_length = 20; 9 | 10 | export function setup(args) 11 | { 12 | args.features = [ "mv" ]; 13 | 14 | // Pass "-sp " in the command line, where is an 15 | // integer from 0 to 100. 16 | if ( "params" in args ) 17 | SOME_PERCENTAGE = (100 - args.params) / 100; 18 | } 19 | 20 | export function glitch_frame(frame) 21 | { 22 | // bail out if we have no forward motion vectors 23 | const fwd_mvs = frame.mv?.forward; 24 | if ( !fwd_mvs ) 25 | return; 26 | 27 | // set motion vector overflow behaviour in ffedit to "truncate" 28 | frame.mv.overflow = "truncate"; 29 | 30 | const largest = fwd_mvs.largest_sq(); 31 | const threshold = Math.floor(SOME_PERCENTAGE * largest[2]); 32 | const mask = fwd_mvs.compare_lt(threshold); 33 | 34 | fwd_mvs.mul(MV(MULTIPLE, MULTIPLE), mask); 35 | } 36 | -------------------------------------------------------------------------------- /free-for-all/helpers.mjs: -------------------------------------------------------------------------------- 1 | /*********************************************************************/ 2 | /* motion vectors */ 3 | function get_mvs_internal(frame, overflow, which) 4 | { 5 | // bail out if we have no motion vectors 6 | let mvs = frame["mv"]; 7 | if ( !mvs ) 8 | return; 9 | // bail out if we have no forward motion vectors 10 | let fwd_mvs = mvs[which]; 11 | if ( !fwd_mvs ) 12 | return; 13 | if ( overflow ) 14 | mvs.overflow = overflow; 15 | return fwd_mvs; 16 | } 17 | 18 | /* Get forward motion vectors and set overflow flag */ 19 | export function get_forward_mvs(frame, overflow) 20 | { 21 | return get_mvs_internal(frame, overflow, "forward"); 22 | } 23 | 24 | /* Get backward motion vectors and set overflow flag */ 25 | export function get_backward_mvs(frame, overflow) 26 | { 27 | return get_mvs_internal(frame, overflow, "backward"); 28 | } 29 | 30 | function get_mvs_range_internal(frame, stream, which) 31 | { 32 | // bail out if we have no motion vectors 33 | let mvs = frame["mv"]; 34 | if ( !mvs ) 35 | return; 36 | 37 | const fcode = mvs["fcode"][which]; 38 | const bit_size = fcode - 1; 39 | const shift = (stream.codec == "mpeg2video") ? 5 40 | : (stream.codec == "mpeg4") ? 6 41 | : 5; 42 | const min_val = -(1<<(shift+bit_size-1)); 43 | const max_val = (1<<(shift+bit_size-1))-1; 44 | 45 | return [ min_val, max_val ]; 46 | } 47 | 48 | /* Get range for forward motion vectors */ 49 | export function get_forward_mvs_range(frame, stream) 50 | { 51 | return get_mvs_range_internal(frame, stream, 0); 52 | } 53 | 54 | /* Get range for backward motion vectors */ 55 | export function get_backward_mvs_range(frame, stream) 56 | { 57 | return get_mvs_range_internal(frame, stream, 1); 58 | } 59 | 60 | /*********************************************************************/ 61 | /* scales value from 'from' range to 'to' range */ 62 | export function scaleValue(value, from_min, from_max, to_min, to_max) 63 | { 64 | return (value - from_min) * (to_max - to_min) / (from_max - from_min) + to_min; 65 | } 66 | -------------------------------------------------------------------------------- /free-for-all/mb_type-midi.js: -------------------------------------------------------------------------------- 1 | import { MIDIInput } from "./midi.js"; 2 | 3 | import { 4 | get_forward_mvs, 5 | scaleValue, 6 | } from "./helpers.mjs"; 7 | 8 | const midiin = new MIDIInput(); 9 | let midi_range_y = [ 0, 0 ]; 10 | let midi_range_x = [ 0, 0 ]; 11 | 12 | const CANDIDATE_MB_TYPE_INTRA = (1 << 0); 13 | const CANDIDATE_MB_TYPE_INTER = (1 << 1); 14 | const CANDIDATE_MB_TYPE_INTER4V = (1 << 2); 15 | const CANDIDATE_MB_TYPE_INTER_I = (1 << 8); 16 | 17 | export function setup() 18 | { 19 | midiin.setup(); 20 | // midiin.setlog(true); 21 | /* faders */ 22 | midiin.onevent ( 4, function(v) { midi_range_y[0] = v; }); 23 | midiin.onevent ( 5, function(v) { midi_range_y[1] = v; }); 24 | midiin.onevent ( 6, function(v) { midi_range_x[0] = v; }); 25 | midiin.onevent ( 7, function(v) { midi_range_x[1] = v; }); 26 | } 27 | 28 | export function mb_type_func(args) 29 | { 30 | midiin.parse_events(); 31 | 32 | const mb_types = args.mb_types; 33 | const mb_height = mb_types.length; 34 | const mb_width = mb_types[0].length; 35 | 36 | let y_begin = Math.lround(scaleValue(midi_range_y[0], 0, 127, 0, mb_height)); 37 | let y_end = Math.lround(scaleValue(midi_range_y[1], 0, 127, 0, mb_height)); 38 | let x_begin = Math.lround(scaleValue(midi_range_x[0], 0, 127, 0, mb_width)); 39 | let x_end = Math.lround(scaleValue(midi_range_x[1], 0, 127, 0, mb_width)); 40 | 41 | /* copy our global mb_types to args */ 42 | for ( let mb_y = y_begin; mb_y < y_end; mb_y++ ) 43 | for ( let mb_x = x_begin; mb_x < x_end; mb_x++ ) 44 | mb_types[mb_y][mb_x] = CANDIDATE_MB_TYPE_INTRA; 45 | } 46 | -------------------------------------------------------------------------------- /free-for-all/midi.js: -------------------------------------------------------------------------------- 1 | export class MIDIInput 2 | { 3 | constructor() 4 | { 5 | this.midiin = new RtMidiIn(); 6 | this.midiout = new RtMidiOut(); 7 | this.events = {}; 8 | this.buttons = {}; 9 | this.log = false; 10 | } 11 | 12 | setup(arg) 13 | { 14 | let port_name; 15 | let port_num; 16 | let midiin = this.midiin; 17 | const repeater_name = "RtMidi Repeater"; 18 | let is_repeater = false; 19 | 20 | // Check arguments 21 | if ( arg !== undefined ) 22 | { 23 | if ( typeof arg === 'string' ) 24 | port_name = arg; 25 | else 26 | port_num = arg; 27 | } 28 | 29 | // Check if any MIDI ports are available 30 | const count = midiin.getPortCount(); 31 | let portS = "s"; 32 | if ( count === 1 ) 33 | portS = ""; 34 | console.log("RtMidi: " + count + " port" + portS + " found"); 35 | if ( count === 0 ) 36 | throw "No MIDI ports"; 37 | 38 | // Print names and select port number 39 | for ( let i = 0; i < count; i++ ) 40 | { 41 | const name = midiin.getPortName(i); 42 | if ( name == port_name ) 43 | port_num = i; 44 | console.log(i + ". " + name); 45 | } 46 | 47 | // Sanity check for port name 48 | if ( port_name !== undefined && port_num === undefined ) 49 | { 50 | console.log("Selected port name (" + port_name + ") is not available."); 51 | throw "Bad MIDI port name"; 52 | } 53 | 54 | // Sanity check for port number 55 | if ( port_num >= count ) 56 | { 57 | printf("Selected port number (" + port_num + ") greater than real number of ports (" + count + ")."); 58 | throw "Bad MIDI port number"; 59 | } 60 | 61 | // No port selected yet, use heuristics 62 | if ( port_num === undefined ) 63 | { 64 | for ( let i = 0; i < count; i++ ) 65 | { 66 | const name = midiin.getPortName(i); 67 | if ( name.includes("Midi Through") ) 68 | continue; 69 | if ( name.includes(repeater_name) ) 70 | { 71 | is_repeater = true; 72 | port_num = i; 73 | break; 74 | } 75 | if ( port_num === undefined ) 76 | port_num = i; 77 | } 78 | } 79 | 80 | // Open input port 81 | console.log("Opening input port number " + port_num); 82 | midiin.openPort(port_num); 83 | 84 | // Open output port 85 | this.midiout.openPort(port_num); 86 | 87 | // Prepare last_vals and setup callback 88 | midiin.ignoreTypes(false, false, false); 89 | 90 | // restore fader/slider values from RtMidi virtual port 91 | if ( is_repeater ) 92 | { 93 | this.midiout.sendMessage([ 0xF0, 0x00, 0xF7 ]); 94 | this.midiout.closePort(); 95 | } 96 | } 97 | 98 | setlog(b) 99 | { 100 | this.log = b; 101 | } 102 | 103 | onevent(v, func) 104 | { 105 | this.events[v] = func; 106 | } 107 | 108 | onbutton(v, func) 109 | { 110 | this.buttons[v] = func; 111 | } 112 | 113 | parse_events() 114 | { 115 | let midiin = this.midiin; 116 | if ( !midiin.isPortOpen() ) 117 | return; 118 | while ( 42 ) 119 | { 120 | let msg = midiin.getMessage(); 121 | const msglen = msg.length; 122 | if ( msglen == 0 ) 123 | break; 124 | if ( this.log ) 125 | console.log(JSON.stringify(msg)); 126 | if ( msglen == 3 ) 127 | { 128 | if ( msg[0] == 176 ) 129 | { 130 | let event_v = this.events[msg[1]]; 131 | if ( event_v !== undefined ) 132 | event_v(msg[2]); 133 | let button_v = this.buttons[msg[1]]; 134 | if ( button_v !== undefined ) 135 | button_v(msg[2] == 127); 136 | } 137 | } 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /free-for-all/midi_v2.js: -------------------------------------------------------------------------------- 1 | export class MIDIInput 2 | { 3 | constructor() 4 | { 5 | this.midiin = new RtMidiIn(RtMidi.WINDOWS_MM, "RtMidi Input Client", 1024); 6 | this.midiout = new RtMidiOut(); 7 | this.events = {}; 8 | this.buttons = {}; 9 | this.log = false; 10 | } 11 | 12 | setup(arg) 13 | { 14 | let port_name; 15 | let port_num; 16 | let midiin = this.midiin; 17 | const repeater_name = "RtMidi Repeater"; 18 | let is_repeater = false; 19 | 20 | // Check arguments 21 | if ( arg !== undefined ) 22 | { 23 | if ( typeof arg === 'string' ) 24 | port_name = arg; 25 | else 26 | port_num = arg; 27 | } 28 | 29 | // Check if any MIDI ports are available 30 | const count = midiin.getPortCount(); 31 | let portS = "s"; 32 | if ( count === 1 ) 33 | portS = ""; 34 | console.log("RtMidi: " + count + " port" + portS + " found"); 35 | if ( count === 0 ) 36 | throw "No MIDI ports"; 37 | 38 | // Print names and select port number 39 | for ( let i = 0; i < count; i++ ) 40 | { 41 | const name = midiin.getPortName(i); 42 | if ( name == port_name ) 43 | port_num = i; 44 | console.log(i + ". " + name); 45 | } 46 | 47 | // Sanity check for port name 48 | if ( port_name !== undefined && port_num === undefined ) 49 | { 50 | console.log("Selected port name (" + port_name + ") is not available."); 51 | throw "Bad MIDI port name"; 52 | } 53 | 54 | // Sanity check for port number 55 | if ( port_num >= count ) 56 | { 57 | printf("Selected port number (" + port_num + ") greater than real number of ports (" + count + ")."); 58 | throw "Bad MIDI port number"; 59 | } 60 | 61 | // No port selected yet, use heuristics 62 | if ( port_num === undefined ) 63 | { 64 | for ( let i = 0; i < count; i++ ) 65 | { 66 | const name = midiin.getPortName(i); 67 | if ( name.includes("Midi Through") ) 68 | continue; 69 | if ( name.includes(repeater_name) ) 70 | { 71 | is_repeater = true; 72 | port_num = i; 73 | break; 74 | } 75 | if ( port_num === undefined ) 76 | port_num = i; 77 | } 78 | } 79 | 80 | // Open input port 81 | console.log("Opening input port number " + port_num); 82 | midiin.openPort(port_num); 83 | 84 | // Open output port 85 | this.midiout.openPort(port_num); 86 | 87 | // Prepare last_vals and setup callback 88 | midiin.ignoreTypes(false, false, false); 89 | 90 | // restore fader/slider values from RtMidi virtual port 91 | if ( is_repeater ) 92 | { 93 | this.midiout.sendMessage([ 0xF0, 0x00, 0xF7 ]); 94 | this.midiout.closePort(); 95 | } 96 | } 97 | 98 | setlog(b) 99 | { 100 | this.log = b; 101 | } 102 | 103 | onevent(v, func) 104 | { 105 | this.events[v] = func; 106 | } 107 | 108 | onbutton(v, func) 109 | { 110 | this.buttons[v] = func; 111 | } 112 | 113 | parse_events() { 114 | let midiin = this.midiin; 115 | if (!midiin.isPortOpen()) 116 | return; 117 | while (true) { 118 | let msg = midiin.getMessage(); 119 | const msglen = msg.length; 120 | if (msglen === 0) 121 | break; 122 | if (this.log) 123 | console.log(JSON.stringify(msg)); 124 | if (msglen === 3) { 125 | let status = msg[0]; 126 | let channel = status & 0x0F; 127 | let type = status & 0xF0; 128 | let note = msg[1]; 129 | let velocity = msg[2]; 130 | 131 | // Call the event handler if one is registered for this note 132 | let eventHandler = this.events[note]; 133 | if (eventHandler) { 134 | eventHandler({ 135 | status: status, 136 | channel: channel, 137 | note: note, 138 | velocity: velocity, 139 | type: type 140 | }); 141 | } 142 | 143 | // Call the button handler if one is registered for this note 144 | let buttonHandler = this.buttons[note]; 145 | if (buttonHandler) { 146 | let pressed = type === 0x90 && velocity > 0; // Note On with velocity > 0 147 | let released = type === 0x80 || (type === 0x90 && velocity === 0); // Note Off, or Note On with velocity 0 148 | if (pressed || released) { 149 | buttonHandler(pressed); // true if pressed, false if released 150 | } 151 | } 152 | } 153 | } 154 | }} -------------------------------------------------------------------------------- /free-for-all/mv_average.js: -------------------------------------------------------------------------------- 1 | /*********************************************************************/ 2 | /* parameters */ 3 | 4 | // change this value to use a smaller or greater number of frames to 5 | // perform the average of motion vectors 6 | const tail_length = 3; 7 | 8 | /*********************************************************************/ 9 | class MVAverage 10 | { 11 | constructor() 12 | { 13 | this.prev_mvs = [ ]; 14 | } 15 | 16 | setup(tail_length) 17 | { 18 | this.tail_length_mv = MV(tail_length,tail_length); 19 | } 20 | 21 | run(mvs) 22 | { 23 | // update variable holding motion vectors from previous frames. 24 | // note that we perform a deep copy of the clean motion vector 25 | // values before modifying them. 26 | const deep_copy = mvs.dup(); 27 | // push to the end of array 28 | this.prev_mvs.push(deep_copy); 29 | 30 | if ( this.prev_mvs.length == 1 ) 31 | { 32 | // on first run, just initialize total_sum to the motion vector 33 | // values from the first frame. 34 | this.total_sum = deep_copy; 35 | } 36 | else 37 | { 38 | // update total_sum by removing the motion vector values from the 39 | // oldest frame and adding the values from the current frame. 40 | if ( this.prev_mvs.length > tail_length ) 41 | { 42 | this.total_sum.sub(this.prev_mvs[0]); 43 | this.prev_mvs = this.prev_mvs.slice(1); 44 | } 45 | this.total_sum.add(deep_copy); 46 | 47 | // set new values for current frame to (total_sum / tail_length) 48 | mvs.assign(this.total_sum); 49 | mvs.div(this.tail_length_mv); 50 | } 51 | } 52 | } 53 | 54 | /*********************************************************************/ 55 | import { 56 | get_forward_mvs, 57 | } from "./helpers.mjs"; 58 | 59 | let mv_average; 60 | 61 | export function setup(args) 62 | { 63 | args.features = [ "mv" ]; 64 | 65 | mv_average = new MVAverage(); 66 | mv_average.setup(tail_length); 67 | } 68 | 69 | export function glitch_frame(frame, stream) 70 | { 71 | const fwd_mvs = get_forward_mvs(frame, "truncate"); 72 | // bail out if we have no motion vectors 73 | if ( !fwd_mvs ) 74 | return; 75 | 76 | mv_average.run(fwd_mvs); 77 | } 78 | -------------------------------------------------------------------------------- /free-for-all/mv_average_0.10.js: -------------------------------------------------------------------------------- 1 | // global variable holding forward motion vectors from previous frames 2 | let prev_fwd_mvs = [ ]; 3 | let total_sum; 4 | 5 | // change this value to use a smaller or greater number of frames to 6 | // perform the average of motion vectors 7 | // you can also change it using the `-sp ` command line option 8 | let tail_length = 10; 9 | 10 | export function setup(args) 11 | { 12 | // select motion vector feature 13 | args.features = [ "mv" ]; 14 | 15 | // create a new output filename based on the current time 16 | // and the input filename 17 | const date_str = new Date().toISOString().replaceAll(':', '_'); 18 | const output_fname = `glitched_${date_str}`; 19 | args.output = output_fname; 20 | console.log(`Output filename is "${output_fname}"`); 21 | 22 | // parse tail_length param from command line if available 23 | if ( "params" in args ) 24 | tail_length = args.params; 25 | } 26 | 27 | export function glitch_frame(frame) 28 | { 29 | // bail out if we have no forward motion vectors 30 | const fwd_mvs = frame.mv?.forward; 31 | if ( !fwd_mvs ) 32 | return; 33 | 34 | // set motion vector overflow behaviour in ffedit to "truncate" 35 | frame.mv.overflow = "truncate"; 36 | 37 | // update variable holding forward motion vectors from previous 38 | // frames. note that we perform a deep copy of the clean motion 39 | // vector values before modifying them. 40 | const deep_copy = fwd_mvs.dup(); 41 | // push to the end of array 42 | prev_fwd_mvs.push(deep_copy); 43 | 44 | // initialize total_sum to a [0,0] MV2DArray. 45 | if ( !total_sum ) 46 | total_sum = new MV2DArray(fwd_mvs.width, fwd_mvs.height); 47 | 48 | // update total_sum by removing the motion vector values from the 49 | // oldest frame and adding the values from the current frame. 50 | if ( prev_fwd_mvs.length > tail_length ) 51 | { 52 | total_sum.sub(prev_fwd_mvs[0]); 53 | prev_fwd_mvs = prev_fwd_mvs.slice(1); 54 | } 55 | total_sum.add(deep_copy); 56 | 57 | // set new values for current frame to (total_sum / tail_length) 58 | if ( prev_fwd_mvs.length == tail_length ) 59 | { 60 | fwd_mvs.assign(total_sum); 61 | fwd_mvs.div(MV(tail_length, tail_length)); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /free-for-all/mv_avgpan.js: -------------------------------------------------------------------------------- 1 | // Combination of mv_average and mv_pan 2 | // with a toggle to switch between different glitch_frame() functions 3 | import { MIDIInput } from "./midi_v2.js"; 4 | 5 | import { 6 | get_forward_mvs, 7 | scaleValue, 8 | } from "./helpers.mjs"; 9 | 10 | 11 | /*********************************************************************/ 12 | const midiin = new MIDIInput(); 13 | let midi_range_y = [ 0, 0 ]; 14 | let midi_range_x = [ 0, 0 ]; 15 | 16 | const glitchFunctions = ['mv_avgpan', 'mv_average', 'mv_pan']; 17 | let currentFunctionIndex = 0; 18 | let activeGlitchFunction = glitchFunctions[0] 19 | 20 | /*********************************************************************/ 21 | let tail_length = 20; 22 | let total_sum; 23 | let prev_mvs = [ ]; 24 | let freeze_offset = false; 25 | 26 | /*********************************************************************/ 27 | 28 | 29 | export function setup(args) 30 | { 31 | args.features = [ "mv" ]; 32 | 33 | midiin.setup(); 34 | midiin.setlog(true); 35 | /* faders */ 36 | // Set up the event handlers for faders 37 | midiin.onevent ( 5, function(v) { tail_length = v.velocity; }); 38 | midiin.onevent ( 0, function(v) { midi_range_y[0] = v.velocity; }); 39 | midiin.onevent ( 1, function(v) { midi_range_y[1] = v.velocity; }); 40 | midiin.onevent ( 2, function(v) { midi_range_x[0] = v.velocity; }); 41 | midiin.onevent ( 3, function(v) { midi_range_x[1] = v.velocity; }); 42 | midiin.onbutton( 65, function(pressed) { freeze_offset = (pressed); }); 43 | 44 | 45 | /*********************************************************************/ 46 | // Hotkeys to trigger switching between glitch_frame() functions 47 | /*********************************************************************/ 48 | 49 | // Switch glitch_frame when pressed down, change back when released 50 | midiin.onbutton(62, function(pressed) { 51 | // pressed is a boolean indicating whether the note is pressed or released 52 | activeGlitchFunction = (activeGlitchFunction == glitchFunctions[0]) ? glitchFunctions[1] : glitchFunctions[0]; 53 | console.log('Changed glitch_frame function to: ' + activeGlitchFunction); 54 | }); 55 | } 56 | 57 | // Switch between all glitch_frame() functions in the glitchFunctions array 58 | midiin.onbutton(64, function(pressed) { 59 | if (pressed) { 60 | // Only toggle when the button is pressed down, not when it is released 61 | currentFunctionIndex = (currentFunctionIndex + 1) % glitchFunctions.length; 62 | 63 | // Call the current glitch function 64 | activeGlitchFunction = glitchFunctions[currentFunctionIndex]; 65 | 66 | // Output the name of the current function to the console 67 | console.log('Switched glitch_frame function to: ' + activeGlitchFunction); 68 | } 69 | }); 70 | 71 | 72 | /*********************************************************************/ 73 | 74 | 75 | // Define the original glitch_frame function from mv_pan.js, renamed to mv_pan 76 | export function mv_pan(frame, stream) 77 | { 78 | const fwd_mvs = get_forward_mvs(frame, "truncate"); 79 | // bail out if we have no motion vectors 80 | if ( !fwd_mvs ) 81 | return; 82 | 83 | const height = 64; 84 | const width = 64; 85 | let y_begin = Math.lround(scaleValue(midi_range_y[0], 0, 127, 0, height)); 86 | let y_end = Math.lround(scaleValue(midi_range_y[1], 0, 127, 0, height)); 87 | let x_begin = Math.lround(scaleValue(midi_range_x[0], 0, 127, 0, width)); 88 | let x_end = Math.lround(scaleValue(midi_range_x[1], 0, 127, 0, width)); 89 | 90 | // Use MIDI values for offset if val is true 91 | if (freeze_offset === false) { 92 | let mv_off = MV(y_end - y_begin, x_end - x_begin); 93 | fwd_mvs.add(mv_off); 94 | } 95 | 96 | // Freeze current offset if val is true 97 | else if (freeze_offset === true) { 98 | let mv_off = new MV(0,0) 99 | fwd_mvs.add(mv_off); 100 | } 101 | } 102 | 103 | 104 | // Define the original glitch_frame function from mv_average.js, renamed to mv_average 105 | export function mv_average(frame, stream) 106 | { 107 | const fwd_mvs = get_forward_mvs(frame, "truncate"); 108 | // bail out if we have no motion vectors 109 | if ( !fwd_mvs ) 110 | return; 111 | 112 | // update variable holding motion vectors from previous frames. 113 | // note that we perform a deep copy of the clean motion vector 114 | // values before modifying them. 115 | const deep_copy = fwd_mvs.dup(); 116 | // push to the end of array 117 | prev_mvs.push(deep_copy); 118 | 119 | if ( prev_mvs.length == 1 ) 120 | { 121 | // on first run, just initialize total_sum to the motion vector 122 | // values from the first frame. 123 | total_sum = deep_copy; 124 | } 125 | else 126 | { 127 | // update total_sum by removing the motion vector values from the 128 | // oldest frame and adding the values from the current frame. 129 | while ( prev_mvs.length > tail_length ) 130 | { 131 | total_sum.sub(prev_mvs[0]); 132 | prev_mvs = prev_mvs.slice(1); 133 | } 134 | total_sum.add(deep_copy); 135 | 136 | // set new values for current frame to (total_sum / tail_length) 137 | const actual_length = prev_mvs.length; 138 | if ( actual_length !== 0 ) 139 | { 140 | fwd_mvs.assign(total_sum); 141 | fwd_mvs.div(MV(actual_length,actual_length)); 142 | } 143 | } 144 | } 145 | 146 | 147 | // Class MVAverage from mv_average.js 148 | class MVAverage 149 | { 150 | constructor() 151 | { 152 | this.prev_mvs = []; 153 | this.tail_length_mv = MV(tail_length, tail_length); 154 | this.total_sum = null; 155 | } 156 | 157 | run(mvs) 158 | { 159 | // update variable holding motion vectors from previous frames. 160 | const deep_copy = mvs.dup(); 161 | this.prev_mvs.push(deep_copy); 162 | 163 | if (this.prev_mvs.length == 1) 164 | { 165 | this.total_sum = deep_copy; 166 | } 167 | else 168 | { 169 | if (this.prev_mvs.length > tail_length) 170 | { 171 | this.total_sum.sub(this.prev_mvs[0]); 172 | this.prev_mvs = this.prev_mvs.slice(1); 173 | } 174 | this.total_sum.add(deep_copy); 175 | mvs.assign(this.total_sum); 176 | mvs.div(this.tail_length_mv); 177 | } 178 | } 179 | } 180 | let mv_average_class = new MVAverage(); 181 | 182 | export function mv_avgpan(frame, stream) 183 | { 184 | const fwd_mvs = get_forward_mvs(frame, "truncate"); 185 | if (!fwd_mvs) 186 | return; 187 | 188 | // Apply MVAverage from mv_average.js 189 | mv_average_class.run(fwd_mvs); 190 | 191 | // Apply MIDI control from mv_pan.js 192 | midiin.parse_events(); 193 | const height = 64; 194 | const width = 64; 195 | let y_begin = Math.round(scaleValue(midi_range_y[0], 0, 127, 0, height)); 196 | let y_end = Math.round(scaleValue(midi_range_y[1], 0, 127, 0, height)); 197 | let x_begin = Math.round(scaleValue(midi_range_x[0], 0, 127, 0, width)); 198 | let x_end = Math.round(scaleValue(midi_range_x[1], 0, 127, 0, width)); 199 | const mv_off = MV(y_end - y_begin, x_end - x_begin); 200 | fwd_mvs.add(mv_off); 201 | } 202 | 203 | /*********************************************************************/ 204 | 205 | 206 | // Define the wrapper glitch_frame function that calls the currently active function 207 | export function glitch_frame(frame, stream) { 208 | 209 | midiin.parse_events(); 210 | 211 | // Use eval to call the function by its name 212 | eval(activeGlitchFunction + '(frame, stream)'); 213 | } 214 | 215 | /*********************************************************************/ 216 | -------------------------------------------------------------------------------- /free-for-all/mv_sink.js: -------------------------------------------------------------------------------- 1 | /*********************************************************************/ 2 | /* parameters */ 3 | 4 | // value to subtract from the vertical element of all motion vectors in 5 | // the frame. 6 | const value = 5; 7 | 8 | /*********************************************************************/ 9 | class MVSink 10 | { 11 | constructor(tail_length) 12 | { 13 | } 14 | 15 | setup(value) 16 | { 17 | this.value = value; 18 | } 19 | 20 | run(mvs) 21 | { 22 | // subtract value from the vertical element of all motion vectors 23 | // in the frame. 24 | mvs.sub_v(this.value); 25 | } 26 | } 27 | 28 | /*********************************************************************/ 29 | import { 30 | get_forward_mvs, 31 | } from "./helpers.mjs"; 32 | 33 | let mv_sink; 34 | 35 | export function setup(args) 36 | { 37 | args.features = [ "mv" ]; 38 | 39 | mv_sink = new MVSink(); 40 | mv_sink.setup(value); 41 | } 42 | 43 | export function glitch_frame(frame, stream) 44 | { 45 | const fwd_mvs = get_forward_mvs(frame, "truncate"); 46 | // bail out if we have no motion vectors 47 | if ( !fwd_mvs ) 48 | return; 49 | 50 | mv_sink.run(fwd_mvs); 51 | } 52 | -------------------------------------------------------------------------------- /free-for-all/offset.js: -------------------------------------------------------------------------------- 1 | import { MIDIInput } from "./midi.js"; 2 | 3 | import { 4 | get_forward_mvs, 5 | scaleValue, 6 | } from "./helpers.mjs"; 7 | 8 | const midiin = new MIDIInput(); 9 | let midi_range_y = [ 0, 0 ]; 10 | let midi_range_x = [ 0, 0 ]; 11 | 12 | export function setup(args) 13 | { 14 | args.features = [ "mv" ]; 15 | 16 | midiin.setup(); 17 | // midiin.setlog(true); 18 | /* faders */ 19 | midiin.onevent ( 0, function(v) { midi_range_y[0] = v; }); 20 | midiin.onevent ( 1, function(v) { midi_range_y[1] = v; }); 21 | midiin.onevent ( 2, function(v) { midi_range_x[0] = v; }); 22 | midiin.onevent ( 3, function(v) { midi_range_x[1] = v; }); 23 | } 24 | 25 | export function glitch_frame(frame, stream) 26 | { 27 | const fwd_mvs = get_forward_mvs(frame, "truncate"); 28 | // bail out if we have no motion vectors 29 | if ( !fwd_mvs ) 30 | return; 31 | 32 | midiin.parse_events(); 33 | 34 | const height = 64; 35 | const width = 64; 36 | let y_begin = Math.lround(scaleValue(midi_range_y[0], 0, 127, 0, height)); 37 | let y_end = Math.lround(scaleValue(midi_range_y[1], 0, 127, 0, height)); 38 | let x_begin = Math.lround(scaleValue(midi_range_x[0], 0, 127, 0, width)); 39 | let x_end = Math.lround(scaleValue(midi_range_x[1], 0, 127, 0, width)); 40 | 41 | const mv_off = MV(y_end - y_begin, x_end - x_begin); 42 | fwd_mvs.add(mv_off); 43 | } 44 | -------------------------------------------------------------------------------- /free-for-all/pict_types-midi.js: -------------------------------------------------------------------------------- 1 | import { MIDIInput } from "./midi.js"; 2 | 3 | const midiin = new MIDIInput(); 4 | let midi_val = false; 5 | 6 | export function setup() 7 | { 8 | midiin.setup(); 9 | midiin.onbutton(32, function(v) { midi_val = (v !== 0); }); 10 | } 11 | 12 | export function pict_type_func(args) 13 | { 14 | midiin.parse_events(); 15 | return midi_val ? "I" : "P"; 16 | } 17 | -------------------------------------------------------------------------------- /free-for-all/pict_types.js: -------------------------------------------------------------------------------- 1 | let frame_num = 0; 2 | export function pict_type_func(args) 3 | { 4 | if ( (frame_num++ & 3) ) 5 | return "P"; 6 | return "I"; 7 | } 8 | -------------------------------------------------------------------------------- /free-for-all/sdl.js: -------------------------------------------------------------------------------- 1 | export class SDLInput 2 | { 3 | constructor() 4 | { 5 | this.sdl = new SDL(); 6 | this.events_axis = {}; 7 | this.events_hat = {}; 8 | this.events_button = {}; 9 | this.lasthat = 0; 10 | this.log = false; 11 | } 12 | 13 | setup(arg) 14 | { 15 | // are we being called by fflive? 16 | if ( !this.sdl ) 17 | { 18 | console.log("we are not being called by fflive."); 19 | return false; 20 | } 21 | 22 | const njoysticks = this.sdl.numJoysticks(); 23 | console.log("number of joysticks: " + njoysticks); 24 | if ( njoysticks > 0 ) 25 | this.sdl.joystickOpen(0); 26 | 27 | return true; 28 | } 29 | 30 | setlog(b) 31 | { 32 | this.log = b; 33 | } 34 | 35 | on_axis(v, func) 36 | { 37 | this.events_axis[v] = func; 38 | } 39 | 40 | on_hat(v, func) 41 | { 42 | this.events_hat[v] = func; 43 | } 44 | 45 | on_button(v, func) 46 | { 47 | this.events_button[v] = func; 48 | } 49 | 50 | SDL_Event(event) 51 | { 52 | if ( this.log ) 53 | console.log(JSON.stringify(event)); 54 | 55 | // event.type 56 | // event.timestamp 57 | 58 | if ( event.type === SDL.SDL_JOYAXISMOTION ) 59 | { 60 | // event.which 61 | // event.axis 62 | // event.value 63 | const event_v = this.events_axis[event.axis]; 64 | if ( event_v !== undefined ) 65 | event_v(event.value); 66 | } 67 | else if ( event.type === SDL.SDL_JOYHATMOTION ) 68 | { 69 | // event.which 70 | // event.hat 71 | // event.value 72 | const event_v = this.events_hat[event.hat]; 73 | if ( event_v !== undefined ) 74 | event_v(event.value); 75 | } 76 | else if ( event.type === SDL.SDL_JOYBUTTONDOWN 77 | || event.type === SDL.SDL_JOYBUTTONUP ) 78 | { 79 | // event.which 80 | // event.button 81 | // event.state 82 | const event_v = this.events_button[event.button]; 83 | if ( event_v !== undefined ) 84 | event_v(event.state); 85 | } 86 | } 87 | 88 | parse_events() 89 | { 90 | while ( this.sdl ) 91 | { 92 | const event = this.sdl.getEvent(); 93 | if ( !event ) 94 | break; 95 | this.SDL_Event(event); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /free-for-all/snes.js: -------------------------------------------------------------------------------- 1 | import { 2 | get_forward_mvs, 3 | } from "./helpers.mjs"; 4 | 5 | import {SDLInput} from "./sdl.js"; 6 | 7 | let sdl = new SDLInput(); 8 | let do_v = false; 9 | let cur_off = new MV(0,0); 10 | const step = 4; 11 | let started = false; 12 | 13 | export function setup(args) 14 | { 15 | args.features = [ "mv" ]; 16 | sdl.setup(); 17 | // sdl.setlog(true); 18 | // X A B Y L R select start 19 | // 0 1 2 3 4 5 8 9 20 | sdl.on_button( 9, function(v) { if ( v ) started = true; }); 21 | sdl.on_button( 1, function(v) { cur_off = new MV(0,0); }); 22 | sdl.on_axis ( 0, function(v) { // horizontal 23 | if ( v === 32767 ) 24 | cur_off[0] -= step; 25 | else if ( v === -32768 ) 26 | cur_off[0] += step; 27 | }); 28 | sdl.on_axis ( 1, function(v) { // vertical 29 | if ( v === 32767 ) 30 | cur_off[1] -= step; 31 | else if ( v === -32768 ) 32 | cur_off[1] += step; 33 | }); 34 | } 35 | 36 | export function glitch_frame(frame, stream) 37 | { 38 | let fwd_mvs = get_forward_mvs(frame, "truncate"); 39 | // bail out if we have no motion vectors 40 | if ( !fwd_mvs ) 41 | return; 42 | 43 | // parse SDL events 44 | sdl.parse_events(); 45 | 46 | if ( started ) 47 | fwd_mvs.add(cur_off); 48 | } 49 | -------------------------------------------------------------------------------- /free-for-all/vf_script/pixelsort_gbrp-midi.js: -------------------------------------------------------------------------------- 1 | import { MIDIInput } from "../midi.js"; 2 | 3 | import { 4 | scaleValue 5 | } from "../helpers.mjs"; 6 | 7 | const midiin = new MIDIInput(); 8 | let midi_range_y = [ 0, 0 ]; 9 | let midi_range_x = [ 0, 0 ]; 10 | let midi_threshold_low = 0.25; 11 | let midi_threshold_high = 0.80; 12 | let midi_clength = 0; 13 | let midi_order = 0; 14 | let midi_trigger_by = 0; 15 | let midi_sort_by = 0; 16 | let midi_mode = 0; 17 | 18 | export function setup(args) 19 | { 20 | args.pix_fmt = "gbrp"; 21 | 22 | midiin.setup(); 23 | // midiin.setlog(true); 24 | /* faders */ 25 | midiin.onevent ( 0, function(v) { midi_range_y[0] = v; }); 26 | midiin.onevent ( 1, function(v) { midi_range_y[1] = v; }); 27 | midiin.onevent ( 2, function(v) { midi_range_x[0] = v; }); 28 | midiin.onevent ( 3, function(v) { midi_range_x[1] = v; }); 29 | midiin.onevent ( 4, function(v) { midi_mode = 0; midi_threshold_low = v; }); 30 | midiin.onevent ( 5, function(v) { midi_mode = 0; midi_threshold_high = v; }); 31 | midiin.onevent ( 6, function(v) { midi_mode = 1; midi_clength = v; }); 32 | /* buttons */ 33 | // set vertical 34 | midiin.onbutton(32, function(v) { if ( v ) midi_order = 0; }); 35 | midiin.onbutton(48, function(v) { if ( v ) midi_order = 0; }); 36 | midiin.onbutton(64, function(v) { if ( v ) midi_order = 0; }); 37 | midiin.onbutton(33, function(v) { if ( v ) midi_order = 0; }); 38 | midiin.onbutton(49, function(v) { if ( v ) midi_order = 0; }); 39 | midiin.onbutton(65, function(v) { if ( v ) midi_order = 0; }); 40 | // set horizontal 41 | midiin.onbutton(34, function(v) { if ( v ) midi_order = 1; }); 42 | midiin.onbutton(50, function(v) { if ( v ) midi_order = 1; }); 43 | midiin.onbutton(66, function(v) { if ( v ) midi_order = 1; }); 44 | midiin.onbutton(35, function(v) { if ( v ) midi_order = 1; }); 45 | midiin.onbutton(51, function(v) { if ( v ) midi_order = 1; }); 46 | midiin.onbutton(67, function(v) { if ( v ) midi_order = 1; }); 47 | // trigger_by 48 | midiin.onbutton(36, function(v) { if ( v ) midi_trigger_by = 0; }); 49 | midiin.onbutton(52, function(v) { if ( v ) midi_trigger_by = 1; }); 50 | midiin.onbutton(68, function(v) { if ( v ) midi_trigger_by = 2; }); 51 | // sort_by 52 | midiin.onbutton(37, function(v) { if ( v ) midi_sort_by = 0; }); 53 | midiin.onbutton(53, function(v) { if ( v ) midi_sort_by = 1; }); 54 | midiin.onbutton(69, function(v) { if ( v ) midi_sort_by = 2; }); 55 | } 56 | 57 | let first_frame = true; 58 | export function filter(args) 59 | { 60 | let data = args["data"]; 61 | const height = data[0].height; 62 | const width = data[0].width; 63 | 64 | midiin.parse_events(); 65 | 66 | if ( first_frame == true ) 67 | { 68 | // set default options 69 | midi_mode = 0; 70 | midi_order = 1; 71 | midi_trigger_by = 2; 72 | midi_sort_by = 2; 73 | first_frame = false; 74 | } 75 | 76 | let options = { 77 | pix_fmt: "hsl", // rgb, hsv, hsl 78 | trigger_by: "l", 79 | sort_by: "l", 80 | order: "horizontal", 81 | mode: "threshold", 82 | reverse_sort: false, 83 | threshold: [ 0.25, 0.80 ], // can be high low or low high 84 | clength: 100, 85 | }; 86 | 87 | if ( midi_mode === 0 ) 88 | options.mode = "threshold"; 89 | else 90 | options.mode = "random"; 91 | 92 | let y_begin = Math.lround(scaleValue(midi_range_y[0], 0, 127, 0, height)); 93 | let y_end = Math.lround(scaleValue(midi_range_y[1], 0, 127, 0, height)); 94 | let x_begin = Math.lround(scaleValue(midi_range_x[0], 0, 127, 0, width)); 95 | let x_end = Math.lround(scaleValue(midi_range_x[1], 0, 127, 0, width)); 96 | let threshold_low = scaleValue(midi_threshold_low, 0, 127, 0, 1); 97 | let threshold_high = scaleValue(midi_threshold_high, 0, 127, 0, 1); 98 | 99 | const swapped_y = (y_begin > y_end); 100 | const swapped_x = (x_begin > x_end); 101 | 102 | let reverse_sort = false; 103 | if ( (swapped_y && !midi_order) 104 | || (swapped_x && midi_order) ) 105 | { 106 | reverse_sort = true; 107 | } 108 | if ( swapped_y ) 109 | { 110 | const tmp = y_begin; 111 | y_begin = y_end; 112 | y_end = tmp; 113 | } 114 | if ( swapped_x ) 115 | { 116 | const tmp = x_begin; 117 | x_begin = x_end; 118 | x_end = tmp; 119 | } 120 | 121 | if ( midi_order === 0 ) 122 | { 123 | options.order = "vertical"; 124 | options.clength = Math.lround(scaleValue(midi_clength, 0, 127, 0, (x_end - x_begin))); 125 | } 126 | else 127 | { 128 | options.order = "horizontal"; 129 | options.clength = Math.lround(scaleValue(midi_clength, 0, 127, 0, (y_end - y_begin))); 130 | } 131 | 132 | if ( y_begin != y_end && y_end !== 0 && y_begin !== height 133 | && x_begin != x_end && x_end !== 0 && x_begin !== width ) 134 | { 135 | // update options 136 | options.reverse_sort = reverse_sort; 137 | options.threshold = [ threshold_low, threshold_high ]; 138 | options.trigger_by = options.pix_fmt[midi_trigger_by]; 139 | options.sort_by = options.pix_fmt[midi_sort_by]; 140 | 141 | const range_y = [ y_begin, y_end ]; 142 | const range_x = [ x_begin, x_end ]; 143 | 144 | // pixelsort(data, [ range y ], [ range x ], options) 145 | ffgac.pixelsort(data, range_y, range_x, options); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /free-for-all/vf_script/pixelsort_gbrp.js: -------------------------------------------------------------------------------- 1 | 2 | let options = { 3 | pix_fmt: "hsl", 4 | trigger_by: "l", 5 | sort_by: "l", 6 | order: "horizontal", 7 | mode: "threshold", 8 | reverse_sort: false, 9 | threshold: [ 0.25, 0.80 ], 10 | }; 11 | 12 | export function setup(args) 13 | { 14 | args.pix_fmt = "gbrp"; 15 | } 16 | 17 | export function filter(args) 18 | { 19 | let data = args["data"]; 20 | const height = data[0].height; 21 | const width = data[0].width; 22 | 23 | ffgac.pixelsort(data, [ 0, height ], [ 0, width ], options); 24 | } 25 | -------------------------------------------------------------------------------- /free-for-all/vf_script/pixelsort_yuv444p.js: -------------------------------------------------------------------------------- 1 | 2 | let options = { 3 | pix_fmt: "yuv", 4 | trigger_by: "y", 5 | sort_by: "y", 6 | order: "vertical", 7 | mode: "threshold", 8 | reverse_sort: false, 9 | threshold: [ 0.25, 0.80 ], 10 | }; 11 | 12 | export function setup(args) 13 | { 14 | args.pix_fmt = "yuv444p"; 15 | } 16 | 17 | export function filter(args) 18 | { 19 | let data = args["data"]; 20 | const height = data[0].height; 21 | const width = data[0].width; 22 | 23 | ffgac.pixelsort(data, [ 0, height ], [ 0, width ], options); 24 | } 25 | -------------------------------------------------------------------------------- /fubar2k23/helpers.mjs: -------------------------------------------------------------------------------- 1 | /*********************************************************************/ 2 | /* motion vectors */ 3 | function get_mvs_internal(frame, overflow, which) 4 | { 5 | // bail out if we have no motion vectors 6 | let mvs = frame["mv"]; 7 | if ( !mvs ) 8 | return; 9 | // bail out if we have no forward motion vectors 10 | let fwd_mvs = mvs[which]; 11 | if ( !fwd_mvs ) 12 | return; 13 | if ( overflow ) 14 | mvs.overflow = overflow; 15 | return fwd_mvs; 16 | } 17 | 18 | /* Get forward motion vectors and set overflow flag */ 19 | export function get_forward_mvs(frame, overflow) 20 | { 21 | return get_mvs_internal(frame, overflow, "forward"); 22 | } 23 | 24 | /* Get backward motion vectors and set overflow flag */ 25 | export function get_backward_mvs(frame, overflow) 26 | { 27 | return get_mvs_internal(frame, overflow, "backward"); 28 | } 29 | 30 | /*********************************************************************/ 31 | /* scales value from 'from' range to 'to' range */ 32 | export function scaleValue(value, from_min, from_max, to_min, to_max) 33 | { 34 | return (value - from_min) * (to_max - to_min) / (from_max - from_min) + to_min; 35 | } 36 | -------------------------------------------------------------------------------- /fubar2k23/mb_type-midi.js: -------------------------------------------------------------------------------- 1 | import { MIDIInput } from "./midi.js"; 2 | 3 | import { 4 | get_forward_mvs, 5 | scaleValue, 6 | } from "./helpers.mjs"; 7 | 8 | const midiin = new MIDIInput(); 9 | let midi_range_y = [ 0, 0 ]; 10 | let midi_range_x = [ 0, 0 ]; 11 | 12 | const CANDIDATE_MB_TYPE_INTRA = (1 << 0); 13 | const CANDIDATE_MB_TYPE_INTER = (1 << 1); 14 | const CANDIDATE_MB_TYPE_INTER4V = (1 << 2); 15 | const CANDIDATE_MB_TYPE_INTER_I = (1 << 8); 16 | 17 | export function setup() 18 | { 19 | midiin.setup(); 20 | // midiin.setlog(true); 21 | /* faders */ 22 | midiin.onevent ( 0, function(v) { midi_range_y[0] = v; }); 23 | midiin.onevent ( 1, function(v) { midi_range_y[1] = v; }); 24 | midiin.onevent ( 2, function(v) { midi_range_x[0] = v; }); 25 | midiin.onevent ( 3, function(v) { midi_range_x[1] = v; }); 26 | } 27 | 28 | export function mb_type_func(args) 29 | { 30 | midiin.parse_events(); 31 | 32 | const mb_types = args.mb_types; 33 | const mb_height = mb_types.length; 34 | const mb_width = mb_types[0].length; 35 | 36 | let y_begin = Math.lround(scaleValue(midi_range_y[0], 0, 127, 0, mb_height)); 37 | let y_end = Math.lround(scaleValue(midi_range_y[1], 0, 127, 0, mb_height)); 38 | let x_begin = Math.lround(scaleValue(midi_range_x[0], 0, 127, 0, mb_width)); 39 | let x_end = Math.lround(scaleValue(midi_range_x[1], 0, 127, 0, mb_width)); 40 | 41 | /* copy our global mb_types to args */ 42 | for ( let mb_y = y_begin; mb_y < y_end; mb_y++ ) 43 | for ( let mb_x = x_begin; mb_x < x_end; mb_x++ ) 44 | mb_types[mb_y][mb_x] = CANDIDATE_MB_TYPE_INTRA; 45 | } 46 | -------------------------------------------------------------------------------- /fubar2k23/midi.js: -------------------------------------------------------------------------------- 1 | export class MIDIInput 2 | { 3 | constructor() 4 | { 5 | this.midiin = new RtMidiIn(); 6 | this.midiout = new RtMidiOut(); 7 | this.events = {}; 8 | this.buttons = {}; 9 | this.log = false; 10 | } 11 | 12 | setup(arg) 13 | { 14 | let port_name; 15 | let port_num; 16 | let midiin = this.midiin; 17 | const repeater_name = "RtMidi Repeater"; 18 | let is_repeater = false; 19 | 20 | // Check arguments 21 | if ( arg !== undefined ) 22 | { 23 | if ( typeof arg === 'string' ) 24 | port_name = arg; 25 | else 26 | port_num = arg; 27 | } 28 | 29 | // Check if any MIDI ports are available 30 | const count = midiin.getPortCount(); 31 | let portS = "s"; 32 | if ( count === 1 ) 33 | portS = ""; 34 | console.log("RtMidi: " + count + " port" + portS + " found"); 35 | if ( count === 0 ) 36 | throw "No MIDI ports"; 37 | 38 | // Print names and select port number 39 | for ( let i = 0; i < count; i++ ) 40 | { 41 | const name = midiin.getPortName(i); 42 | if ( name == port_name ) 43 | port_num = i; 44 | console.log(i + ". " + name); 45 | } 46 | 47 | // Sanity check for port name 48 | if ( port_name !== undefined && port_num === undefined ) 49 | { 50 | console.log("Selected port name (" + port_name + ") is not available."); 51 | throw "Bad MIDI port name"; 52 | } 53 | 54 | // Sanity check for port number 55 | if ( port_num >= count ) 56 | { 57 | printf("Selected port number (" + port_num + ") greater than real number of ports (" + count + ")."); 58 | throw "Bad MIDI port number"; 59 | } 60 | 61 | // No port selected yet, use heuristics 62 | if ( port_num === undefined ) 63 | { 64 | for ( let i = 0; i < count; i++ ) 65 | { 66 | const name = midiin.getPortName(i); 67 | if ( name.includes("Midi Through") ) 68 | continue; 69 | if ( name.includes(repeater_name) ) 70 | { 71 | is_repeater = true; 72 | port_num = i; 73 | break; 74 | } 75 | if ( port_num === undefined ) 76 | port_num = i; 77 | } 78 | } 79 | 80 | // Open input port 81 | console.log("Opening input port number " + port_num); 82 | midiin.openPort(port_num); 83 | 84 | // Open output port 85 | this.midiout.openPort(port_num); 86 | 87 | // Prepare last_vals and setup callback 88 | midiin.ignoreTypes(false, false, false); 89 | 90 | // restore fader/slider values from RtMidi virtual port 91 | if ( is_repeater ) 92 | { 93 | this.midiout.sendMessage([ 0xF0, 0x00, 0xF7 ]); 94 | this.midiout.closePort(); 95 | } 96 | } 97 | 98 | setlog(b) 99 | { 100 | this.log = b; 101 | } 102 | 103 | onevent(v, func) 104 | { 105 | this.events[v] = func; 106 | } 107 | 108 | onbutton(v, func) 109 | { 110 | this.buttons[v] = func; 111 | } 112 | 113 | parse_events() 114 | { 115 | let midiin = this.midiin; 116 | if ( !midiin.isPortOpen() ) 117 | return; 118 | while ( 42 ) 119 | { 120 | let msg = midiin.getMessage(); 121 | const msglen = msg.length; 122 | if ( msglen == 0 ) 123 | break; 124 | if ( this.log ) 125 | console.log(JSON.stringify(msg)); 126 | if ( msglen == 3 ) 127 | { 128 | if ( msg[0] == 176 ) 129 | { 130 | let event_v = this.events[msg[1]]; 131 | if ( event_v !== undefined ) 132 | event_v(msg[2]); 133 | let button_v = this.buttons[msg[1]]; 134 | if ( button_v !== undefined ) 135 | button_v(msg[2] == 127); 136 | } 137 | } 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /fubar2k23/mv_average.js: -------------------------------------------------------------------------------- 1 | import { MIDIInput } from "./midi.js"; 2 | 3 | import { 4 | get_forward_mvs, 5 | scaleValue, 6 | } from "./helpers.mjs"; 7 | 8 | /*********************************************************************/ 9 | const midiin = new MIDIInput(); 10 | let tail_length = 20; 11 | 12 | /*********************************************************************/ 13 | let total_sum; 14 | let prev_mvs = [ ]; 15 | 16 | /*********************************************************************/ 17 | export function setup(args) 18 | { 19 | args.features = [ "mv" ]; 20 | midiin.setup(); 21 | // midiin.setlog(true); 22 | /* faders */ 23 | midiin.onevent ( 4, function(v) { tail_length = v; }); 24 | } 25 | 26 | export function glitch_frame(frame, stream) 27 | { 28 | const fwd_mvs = get_forward_mvs(frame, "truncate"); 29 | // bail out if we have no motion vectors 30 | if ( !fwd_mvs ) 31 | return; 32 | 33 | midiin.parse_events(); 34 | 35 | // update variable holding motion vectors from previous frames. 36 | // note that we perform a deep copy of the clean motion vector 37 | // values before modifying them. 38 | const deep_copy = fwd_mvs.dup(); 39 | // push to the end of array 40 | prev_mvs.push(deep_copy); 41 | 42 | if ( prev_mvs.length == 1 ) 43 | { 44 | // on first run, just initialize total_sum to the motion vector 45 | // values from the first frame. 46 | total_sum = deep_copy; 47 | } 48 | else 49 | { 50 | // update total_sum by removing the motion vector values from the 51 | // oldest frame and adding the values from the current frame. 52 | while ( prev_mvs.length > tail_length ) 53 | { 54 | total_sum.sub(prev_mvs[0]); 55 | prev_mvs = prev_mvs.slice(1); 56 | } 57 | total_sum.add(deep_copy); 58 | 59 | // set new values for current frame to (total_sum / tail_length) 60 | const actual_length = prev_mvs.length; 61 | if ( actual_length !== 0 ) 62 | { 63 | fwd_mvs.assign(total_sum); 64 | fwd_mvs.div(MV(actual_length,actual_length)); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /fubar2k23/mv_average.sh: -------------------------------------------------------------------------------- 1 | 2 | FFLIVE_PATH=/home/ramiro/code/ffglitch/build-fflive/ 3 | SESSION_TIME=60 4 | ${FFLIVE_PATH}ffgac -input_format mjpeg -video_size 1920x1080 -i /dev/video2 -mb_type_script mb_type-midi.js -vcodec mpeg4 -mpv_flags +nopimb+forcemv -qscale:v 1 -fcode 5 -g max -f rawvideo -flush_packets 1 -t ${SESSION_TIME} - | ${FFLIVE_PATH}fflive -probesize 32 -i - -autoexit -s mv_average.js 5 | -------------------------------------------------------------------------------- /fubar2k23/mv_pan.js: -------------------------------------------------------------------------------- 1 | import { MIDIInput } from "./midi.js"; 2 | 3 | import { 4 | get_forward_mvs, 5 | scaleValue, 6 | } from "./helpers.mjs"; 7 | 8 | /*********************************************************************/ 9 | const midiin = new MIDIInput(); 10 | let midi_range_y = [ 0, 0 ]; 11 | let midi_range_x = [ 0, 0 ]; 12 | 13 | /*********************************************************************/ 14 | export function setup(args) 15 | { 16 | args.features = [ "mv" ]; 17 | 18 | midiin.setup(); 19 | // midiin.setlog(true); 20 | /* faders */ 21 | midiin.onevent ( 4, function(v) { midi_range_y[0] = v; }); 22 | midiin.onevent ( 5, function(v) { midi_range_y[1] = v; }); 23 | midiin.onevent ( 6, function(v) { midi_range_x[0] = v; }); 24 | midiin.onevent ( 7, function(v) { midi_range_x[1] = v; }); 25 | } 26 | 27 | export function glitch_frame(frame, stream) 28 | { 29 | const fwd_mvs = get_forward_mvs(frame, "truncate"); 30 | // bail out if we have no motion vectors 31 | if ( !fwd_mvs ) 32 | return; 33 | 34 | midiin.parse_events(); 35 | 36 | const height = 64; 37 | const width = 64; 38 | let y_begin = Math.lround(scaleValue(midi_range_y[0], 0, 127, 0, height)); 39 | let y_end = Math.lround(scaleValue(midi_range_y[1], 0, 127, 0, height)); 40 | let x_begin = Math.lround(scaleValue(midi_range_x[0], 0, 127, 0, width)); 41 | let x_end = Math.lround(scaleValue(midi_range_x[1], 0, 127, 0, width)); 42 | 43 | const mv_off = MV(y_end - y_begin, x_end - x_begin); 44 | fwd_mvs.add(mv_off); 45 | } 46 | -------------------------------------------------------------------------------- /fubar2k23/mv_pan.sh: -------------------------------------------------------------------------------- 1 | 2 | FFLIVE_PATH=/home/ramiro/code/ffglitch/build-fflive/ 3 | SESSION_TIME=60 4 | ${FFLIVE_PATH}ffgac -input_format mjpeg -video_size 1920x1080 -i /dev/video2 -mb_type_script mb_type-midi.js -vcodec mpeg4 -mpv_flags +nopimb+forcemv -qscale:v 1 -fcode 5 -g max -f rawvideo -flush_packets 1 -t ${SESSION_TIME} - | ${FFLIVE_PATH}fflive -probesize 32 -i - -autoexit -s mv_pan.js 5 | -------------------------------------------------------------------------------- /fubar2k23/pixelsort.js: -------------------------------------------------------------------------------- 1 | import { MIDIInput } from "./midi.js"; 2 | 3 | import { 4 | scaleValue 5 | } from "./helpers.mjs"; 6 | 7 | const midiin = new MIDIInput(); 8 | let midi_range_y = [ 0, 0 ]; 9 | let midi_range_x = [ 0, 0 ]; 10 | let midi_threshold_low = 0.25; 11 | let midi_threshold_high = 0.80; 12 | let midi_clength = 0; 13 | let midi_order = 0; 14 | let midi_trigger_by = 0; 15 | let midi_sort_by = 0; 16 | let midi_mode = 0; 17 | 18 | export function setup(args) 19 | { 20 | args.pix_fmt = "gbrp"; 21 | 22 | midiin.setup(); 23 | // midiin.setlog(true); 24 | /* faders */ 25 | midiin.onevent ( 0, function(v) { midi_range_y[0] = v; }); 26 | midiin.onevent ( 1, function(v) { midi_range_y[1] = v; }); 27 | midiin.onevent ( 2, function(v) { midi_range_x[0] = v; }); 28 | midiin.onevent ( 3, function(v) { midi_range_x[1] = v; }); 29 | midiin.onevent ( 4, function(v) { midi_mode = 0; midi_threshold_low = v; }); 30 | midiin.onevent ( 5, function(v) { midi_mode = 0; midi_threshold_high = v; }); 31 | midiin.onevent ( 6, function(v) { midi_mode = 1; midi_clength = v; }); 32 | /* buttons */ 33 | // set vertical 34 | midiin.onbutton(32, function(v) { if ( v ) midi_order = 0; }); 35 | midiin.onbutton(48, function(v) { if ( v ) midi_order = 0; }); 36 | midiin.onbutton(64, function(v) { if ( v ) midi_order = 0; }); 37 | midiin.onbutton(33, function(v) { if ( v ) midi_order = 0; }); 38 | midiin.onbutton(49, function(v) { if ( v ) midi_order = 0; }); 39 | midiin.onbutton(65, function(v) { if ( v ) midi_order = 0; }); 40 | // set horizontal 41 | midiin.onbutton(34, function(v) { if ( v ) midi_order = 1; }); 42 | midiin.onbutton(50, function(v) { if ( v ) midi_order = 1; }); 43 | midiin.onbutton(66, function(v) { if ( v ) midi_order = 1; }); 44 | midiin.onbutton(35, function(v) { if ( v ) midi_order = 1; }); 45 | midiin.onbutton(51, function(v) { if ( v ) midi_order = 1; }); 46 | midiin.onbutton(67, function(v) { if ( v ) midi_order = 1; }); 47 | // trigger_by 48 | midiin.onbutton(36, function(v) { if ( v ) midi_trigger_by = 0; }); 49 | midiin.onbutton(52, function(v) { if ( v ) midi_trigger_by = 1; }); 50 | midiin.onbutton(68, function(v) { if ( v ) midi_trigger_by = 2; }); 51 | // sort_by 52 | midiin.onbutton(37, function(v) { if ( v ) midi_sort_by = 0; }); 53 | midiin.onbutton(53, function(v) { if ( v ) midi_sort_by = 1; }); 54 | midiin.onbutton(69, function(v) { if ( v ) midi_sort_by = 2; }); 55 | } 56 | 57 | let first_frame = true; 58 | export function filter(args) 59 | { 60 | let data = args["data"]; 61 | const height = data[0].height; 62 | const width = data[0].width; 63 | 64 | midiin.parse_events(); 65 | 66 | if ( first_frame == true ) 67 | { 68 | // set default options 69 | midi_mode = 0; 70 | midi_order = 0; 71 | midi_trigger_by = 2; 72 | midi_sort_by = 2; 73 | first_frame = false; 74 | } 75 | 76 | let options = { 77 | pix_fmt: "hsl", // rgb, hsv, hsl 78 | trigger_by: "l", 79 | sort_by: "l", 80 | order: "horizontal", 81 | mode: "threshold", 82 | reverse_sort: false, 83 | threshold: [ 0.25, 0.80 ], // can be high low or low high 84 | clength: 100, 85 | }; 86 | 87 | if ( midi_mode === 0 ) 88 | options.mode = "threshold"; 89 | else 90 | options.mode = "random"; 91 | 92 | let y_begin = Math.lround(scaleValue(midi_range_y[0], 0, 127, 0, height)); 93 | let y_end = Math.lround(scaleValue(midi_range_y[1], 0, 127, 0, height)); 94 | let x_begin = Math.lround(scaleValue(midi_range_x[0], 0, 127, 0, width)); 95 | let x_end = Math.lround(scaleValue(midi_range_x[1], 0, 127, 0, width)); 96 | let threshold_low = scaleValue(midi_threshold_low, 0, 127, 0, 1); 97 | let threshold_high = scaleValue(midi_threshold_high, 0, 127, 0, 1); 98 | 99 | const swapped_y = (y_begin > y_end); 100 | const swapped_x = (x_begin > x_end); 101 | 102 | let reverse_sort = false; 103 | if ( (swapped_y && !midi_order) 104 | || (swapped_x && midi_order) ) 105 | { 106 | reverse_sort = true; 107 | } 108 | if ( swapped_y ) 109 | { 110 | const tmp = y_begin; 111 | y_begin = y_end; 112 | y_end = tmp; 113 | } 114 | if ( swapped_x ) 115 | { 116 | const tmp = x_begin; 117 | x_begin = x_end; 118 | x_end = tmp; 119 | } 120 | 121 | if ( midi_order === 0 ) 122 | { 123 | options.order = "vertical"; 124 | options.clength = Math.lround(scaleValue(midi_clength, 0, 127, 0, (x_end - x_begin))); 125 | } 126 | else 127 | { 128 | options.order = "horizontal"; 129 | options.clength = Math.lround(scaleValue(midi_clength, 0, 127, 0, (y_end - y_begin))); 130 | } 131 | 132 | if ( y_begin != y_end && y_end !== 0 && y_begin !== height 133 | && x_begin != x_end && x_end !== 0 && x_begin !== width ) 134 | { 135 | // update options 136 | options.reverse_sort = reverse_sort; 137 | options.threshold = [ threshold_low, threshold_high ]; 138 | options.trigger_by = options.pix_fmt[midi_trigger_by]; 139 | options.sort_by = options.pix_fmt[midi_sort_by]; 140 | 141 | const range_y = [ y_begin, y_end ]; 142 | const range_x = [ x_begin, x_end ]; 143 | 144 | // pixelsort(data, [ range y ], [ range x ], options) 145 | ffgac.pixelsort(data, range_y, range_x, options); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /fubar2k23/pixelsort.sh: -------------------------------------------------------------------------------- 1 | 2 | FFLIVE_PATH=/home/ramiro/code/ffglitch/build-fflive/ 3 | SESSION_TIME=60 4 | ${FFLIVE_PATH}fflive -probesize 32 -input_format mjpeg -video_size 1920x1080 -i /dev/video2 -t ${SESSION_TIME} -vf script=pixelsort.js 5 | -------------------------------------------------------------------------------- /mv_server/mv_producer.js: -------------------------------------------------------------------------------- 1 | import { 2 | get_forward_mvs, 3 | } from "../free-for-all/helpers.mjs"; 4 | 5 | let zmq; 6 | let zpush; 7 | 8 | export function setup(args) 9 | { 10 | args.features = [ "mv" ]; 11 | 12 | zmq = new ZMQ(); 13 | zpush = zmq.socket(ZMQ.ZMQ_PUSH); 14 | zpush.connect("tcp://localhost:5555"); 15 | 16 | // (new ZMQ()).socket(ZMQ.ZMQ_PUSH); 17 | } 18 | 19 | export function glitch_frame(frame, stream) 20 | { 21 | const fwd_mvs = get_forward_mvs(frame, "truncate"); 22 | // bail out if we have no motion vectors 23 | if ( !fwd_mvs ) 24 | return; 25 | 26 | const data = fwd_mvs.serialize(); 27 | zpush.send(data, ZMQ.ZMQ_DONTWAIT); 28 | } 29 | -------------------------------------------------------------------------------- /mv_server/mv_receiver.js: -------------------------------------------------------------------------------- 1 | import { 2 | get_forward_mvs, 3 | } from "../free-for-all/helpers.mjs"; 4 | 5 | let zmq; 6 | let zreq; 7 | 8 | export function setup(args) 9 | { 10 | args.features = [ "mv" ]; 11 | 12 | zmq = new ZMQ(); 13 | zreq = zmq.socket(ZMQ.ZMQ_REQ); 14 | zreq.connect("tcp://localhost:5556"); 15 | } 16 | 17 | let request_sent = false; 18 | export function glitch_frame(frame, stream) 19 | { 20 | const fwd_mvs = get_forward_mvs(frame, "truncate"); 21 | // bail out if we have no motion vectors 22 | if ( !fwd_mvs ) 23 | return; 24 | 25 | if ( !request_sent ) 26 | { 27 | const data = new Uint8FFArray(1); // the content doesn't matter 28 | zreq.send(data, ZMQ.ZMQ_DONTWAIT); 29 | request_sent = true; 30 | } 31 | 32 | { 33 | const data = zreq.recv(zreq, ZMQ.ZMQ_DONTWAIT); 34 | if ( true ) { 35 | console.log(`received ${data.length} bytes`); 36 | fwd_mvs.assign(new MV2DArray(data)); 37 | request_sent = false; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /mv_server/mv_server.py: -------------------------------------------------------------------------------- 1 | import zmq 2 | 3 | context = zmq.Context() 4 | 5 | # PULL socket for gathering data from producers 6 | pull_socket = context.socket(zmq.PULL) 7 | pull_socket.bind("tcp://*:5555") 8 | 9 | # REP socket to serve the latest data to a client 10 | rep_socket = context.socket(zmq.REP) 11 | rep_socket.bind("tcp://*:5556") 12 | 13 | last_received_message = b"" # Initialize as bytes 14 | 15 | poller = zmq.Poller() 16 | poller.register(pull_socket, zmq.POLLIN) 17 | poller.register(rep_socket, zmq.POLLIN) 18 | 19 | while True: 20 | socks = dict(poller.poll()) 21 | 22 | # Check for new data from producers 23 | if pull_socket in socks: 24 | last_received_message = pull_socket.recv() # receive as bytes 25 | print(f"Received data of length: {len(last_received_message)} bytes") 26 | 27 | # Check for request for latest data from client 28 | if rep_socket in socks: 29 | _ = rep_socket.recv() # receive request (even this can be bytes) 30 | print("sending data"); 31 | rep_socket.send(last_received_message) # send latest data (bytes) 32 | -------------------------------------------------------------------------------- /tutorial/CEP00109_mpeg4.avi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiropolla/ffglitch-scripts/8a4c8a0f0c7e77994f710bd6f451552906cd20e5/tutorial/CEP00109_mpeg4.avi -------------------------------------------------------------------------------- /tutorial/lena.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiropolla/ffglitch-scripts/8a4c8a0f0c7e77994f710bd6f451552906cd20e5/tutorial/lena.jpg -------------------------------------------------------------------------------- /tutorial/lena.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramiropolla/ffglitch-scripts/8a4c8a0f0c7e77994f710bd6f451552906cd20e5/tutorial/lena.png -------------------------------------------------------------------------------- /tutorial/readme.md: -------------------------------------------------------------------------------- 1 | Set up 2 | ====== 3 | 4 | - [Set up FFglitch on Linux](readme_linux.md). 5 | - [Set up FFglitch on macOS](readme_macos.md). 6 | - [Set up FFglitch on Windows](readme_windows.md). 7 | 8 | JPEG glitches 9 | ============= 10 | 11 | Simple glitch that modifies the DC quantization coefficient: 12 | ``` 13 | ./bin/fflive -i lena.jpg -s scripts/jpeg/dqt.js 14 | ``` 15 | 16 | Simple glitch that modifies the quantized DC delta: 17 | ``` 18 | ./bin/fflive -i lena.jpg -s scripts/jpeg/q_dc_delta.js 19 | ``` 20 | 21 | PNG glitches 22 | ============ 23 | 24 | Modify the filter type of PNG images: 25 | ``` 26 | ./bin/fflive -i lena.png -s scripts/png/idat.js 27 | ``` 28 | 29 | MPEG4 glitches 30 | ============== 31 | 32 | Clear the horizontal element of all motion vectors: 33 | ``` 34 | ./bin/fflive -i CEP00109_mpeg4.avi -s scripts/mpeg4/mv_sink_and_rise.js 35 | ``` 36 | 37 | Clear the horizontal element of all motion vectors (faster): 38 | ``` 39 | ./bin/fflive -i CEP00109_mpeg4.avi -s scripts/mpeg4/mv_sink_and_rise_fast.js 40 | ``` 41 | 42 | Add value to all motion vectors: 43 | ``` 44 | ./bin/fflive -i CEP00109_mpeg4.avi -s scripts/mpeg4/mv_pan.js 45 | ``` 46 | 47 | Add value to all motion vectors (parameters on command line): 48 | ``` 49 | ./bin/fflive -i CEP00109_mpeg4.avi -s scripts/mpeg4/mv_pan.js -sp "[ 0, 10 ]" 50 | ``` 51 | 52 | Add value to all motion vectors (using MIDI controller): 53 | ``` 54 | ./bin/fflive -i CEP00109_mpeg4.avi -s scripts/mpeg4/mv_pan_midi.js 55 | ``` 56 | 57 | Run average of motion vectors over previous frames: 58 | ``` 59 | ./bin/fflive -i CEP00109_mpeg4.avi -s scripts/mpeg4/mv_average.js 60 | ``` 61 | 62 | Any input file -> MPEG4 glitches 63 | ================================ 64 | 65 | Convert any input file to MPEG4, run average of motion vectors over previous frames: 66 | ``` 67 | ./bin/ffgac -i MY_INPUT_FILE -vcodec mpeg4 -mpv_flags +nopimb+forcemv -qscale:v 1 -fcode 6 -g max -sc_threshold max -f rawvideo pipe: | ./bin/fflive -i pipe: -s scripts/mpeg4/mv_average.js -fs -asap 68 | ``` 69 | 70 | A shorter version of the commands above using helper scripts: 71 | ``` 72 | ./sh/file_to_mpeg4.sh MY_INPUT_FILE | ./sh/fflive_pipe -s scripts/mpeg4/mv_average.js -fs 73 | ``` 74 | 75 | Webcam MPEG4 glitches (Linux) 76 | ============================= 77 | 78 | Capture webcam, convert to MPEG4, run average of motion vectors over previous frames: 79 | ``` 80 | ./bin/ffgac -input_format mjpeg -video_size 1920x1080 -i /dev/video0 -vf hflip -vcodec mpeg4 -mpv_flags +nopimb+forcemv -qscale:v 1 -fcode 6 -g max -sc_threshold max -f rawvideo pipe: | ./bin/fflive -i pipe: -s scripts/mpeg4/mv_average.js -fs -asap 81 | ``` 82 | 83 | Capture webcam, convert to MPEG4, add value to all motion vectors (using MIDI controller): 84 | ``` 85 | ./bin/ffgac -input_format mjpeg -video_size 1280x720 -i /dev/video0 -vf hflip -c:v mpeg4 -q:v 1 -mpv_flags +nopimb+forcemv -g max -sc_threshold max -mb_type_script scripts/mpeg4/mb_type_midi.js -f avpipe - | ./bin/fflive -i - -s scripts/mpeg4/mv_pan_midi.js 86 | ``` 87 | NOTE: you can also clear the image with the MIDI controller (fader 0 selects time to clear, button 32 triggers it). 88 | 89 | Webcam MPEG4 glitches (Windows) 90 | =============================== 91 | 92 | Find webcam: 93 | ``` 94 | ./bin/ffgac -list_devices true -f dshow -i dummy 95 | ``` 96 | 97 | Capture webcam (replace `"HP Truevision HD Camera"` with appropriate output from the previous command), convert to MPEG4, run average of motion vectors over previous frames: 98 | ``` 99 | ./bin/ffgac -f dshow -i video="HP TrueVision HD Camera" -vf hflip -vcodec mpeg4 -mpv_flags +nopimb+forcemv -qscale:v 1 -fcode 6 -g max -sc_threshold max -f rawvideo pipe: | ./bin/fflive -i pipe: -s scripts/mpeg4/mv_sink_and_rise.js -fs -asap 100 | ``` 101 | 102 | YouTube Live MPEG4 glitches 103 | =========================== 104 | 105 | (make sure to have [yt-dlp](https://github.com/yt-dlp/yt-dlp) installed) 106 | 107 | Fetch live stream from YouTube, convert to MPEG4, run average of motion vectors over previous frames: 108 | ``` 109 | yt-dlp -o - 'https://youtu.be/XBzV4HzXymc' | ./bin/ffgac -i pipe: -vcodec mpeg4 -mpv_flags +nopimb+forcemv -qscale:v 1 -fcode 6 -g max -sc_threshold max -f rawvideo pipe: | ./bin/fflive -i pipe: -s scripts/mpeg4/mv_average.js -fs -asap 110 | ``` 111 | 112 | Same as above, another stream: 113 | ``` 114 | yt-dlp -o - 'https://youtu.be/czoEAKX9aaM' | ./bin/ffgac -i pipe: -vcodec mpeg4 -mpv_flags +nopimb+forcemv -qscale:v 1 -fcode 6 -g max -sc_threshold max -f rawvideo pipe: | ./bin/fflive -i pipe: -s scripts/mpeg4/mv_average.js -fs -asap 115 | ``` 116 | 117 | Screen capture MPEG4 glitches (Linux X11 only) 118 | ============================================== 119 | 120 | Screen capture region around mouse cursor, convert to MPEG4, run average of motion vectors over previous frames: 121 | ``` 122 | ./bin/ffgac -f x11grab -follow_mouse centered -framerate 15 -video_size 640x480 -i :0.0 -mpv_flags +nopimb+forcemv -qscale:v 1 -fcode 6 -sc_threshold max -g max -vcodec mpeg4 -f rawvideo pipe: | ./bin/fflive -i pipe: -s scripts/mpeg4/mv_average.js -fs -asap 123 | ``` 124 | 125 | Virtual Webcam MJPEG glitches (Linux only) 126 | ========================================== 127 | 128 | Install and start v4l2loopback: 129 | ``` 130 | sudo apt-get install v4l2loopback-utils 131 | sudo modprobe v4l2loopback video_nr=5 card_label="VirtualCam" exclusive_caps=1 132 | ``` 133 | 134 | Launch Virtual Webcam: 135 | ``` 136 | ./bin/ffgac -input_format mjpeg -video_size 1920x1080 -i /dev/video0 -vcodec copy -f rawvideo pipe: | ./bin/ffedit -i pipe: -s scripts/jpeg/dqt.js -o pipe: | ./bin/ffgac -i pipe: -vcodec copy -f v4l2 /dev/video5 137 | ``` 138 | 139 | You can now use the Virtual Webcam (`/dev/video5`) on Google Chrome, Telegram, or whatever... just like a normal webcam. 140 | -------------------------------------------------------------------------------- /tutorial/readme_linux.md: -------------------------------------------------------------------------------- 1 | Set up FFglitch on Linux 2 | ======================== 3 | 4 | - Either run this one magic command: 5 | ``` 6 | wget https://ffglitch.org/pub/bin/linux64/ffglitch-0.10.2-linux-x86_64.zip && \ 7 | unzip ffglitch-0.10.2-linux-x86_64.zip && \ 8 | mkdir -p bin && \ 9 | mv ffglitch-0.10.2-linux-x86_64/* bin/ && \ 10 | rmdir ffglitch-0.10.2-linux-x86_64 && \ 11 | rm ffglitch-0.10.2-linux-x86_64.zip 12 | ``` 13 | 14 | Or run the commands separately: 15 | - Download FFglitch: 16 | ``` 17 | wget https://ffglitch.org/pub/bin/linux64/ffglitch-0.10.2-linux-x86_64.zip 18 | ``` 19 | - Unpack it: 20 | ``` 21 | unzip ffglitch-0.10.2-linux-x86_64.zip 22 | ``` 23 | - Move its contents to a directory named `bin`: 24 | ``` 25 | mkdir -p bin 26 | mv ffglitch-0.10.2-linux-x86_64/* bin/ 27 | ``` 28 | - Cleanup 29 | ``` 30 | rmdir ffglitch-0.10.2-linux-x86_64 31 | rm ffglitch-0.10.2-linux-x86_64.zip 32 | ``` 33 | -------------------------------------------------------------------------------- /tutorial/readme_macos.md: -------------------------------------------------------------------------------- 1 | Set up FFglitch on macOS 2 | ======================== 3 | 4 | - Either run this one magic command: 5 | ``` 6 | curl -O https://ffglitch.org/pub/bin/mac64/ffglitch-0.10.2-macos-x86_64.zip && \ 7 | unzip ffglitch-0.10.2-macos-x86_64.zip && \ 8 | mkdir -p bin && \ 9 | mv ffglitch-0.10.2-macos-x86_64/* bin/ && \ 10 | rmdir ffglitch-0.10.2-macos-x86_64 && \ 11 | rm ffglitch-0.10.2-macos-x86_64.zip 12 | ``` 13 | 14 | Or run the commands separately: 15 | - Download FFglitch: 16 | ``` 17 | curl -O https://ffglitch.org/pub/bin/mac64/ffglitch-0.10.2-macos-x86_64.zip 18 | ``` 19 | - Unpack it: 20 | ``` 21 | unzip ffglitch-0.10.2-macos-x86_64.zip 22 | ``` 23 | - Move its contents to a directory named `bin`: 24 | ``` 25 | mkdir -p bin 26 | mv ffglitch-0.10.2-macos-x86_64/* bin/ 27 | ``` 28 | - Cleanup 29 | ``` 30 | rmdir ffglitch-0.10.2-macos-x86_64 31 | rm ffglitch-0.10.2-macos-x86_64.zip 32 | ``` 33 | -------------------------------------------------------------------------------- /tutorial/readme_windows.md: -------------------------------------------------------------------------------- 1 | Set up FFglitch on Windows 2 | ========================== 3 | 4 | The recommended way to use FFglitch on Windows is to install Linux and 5 | use FFglitch on Linux. 6 | 7 | If you **really** insist on using Windows, follow these steps: 8 | 9 | - Install Visual Studio Code and make sure you have bash working as a 10 | terminal, like here: 11 | 12 | https://stackoverflow.com/questions/42606837/how-do-i-use-bash-on-windows-from-the-visual-studio-code-integrated-terminal 13 | 14 | - Clone this repository 15 | - Open the terminal in Visual Studio Code 16 | - Change directory to ffglitch-scripts/tutorial 17 | 18 | - Either run this one magic command: 19 | ``` 20 | curl -O https://ffglitch.org/pub/bin/win64/ffglitch-0.10.2-windows-x86_64.zip && \ 21 | unzip ffglitch-0.10.2-windows-x86_64.zip && \ 22 | mkdir -p bin && \ 23 | mv ffglitch-0.10.2-windows-x86_64/* bin/ && \ 24 | rmdir ffglitch-0.10.2-windows-x86_64 && \ 25 | rm ffglitch-0.10.2-windows-x86_64.zip 26 | ``` 27 | 28 | Or run the commands separately: 29 | - Download FFglitch: 30 | ``` 31 | curl -O https://ffglitch.org/pub/bin/win64/ffglitch-0.10.2-windows-x86_64.zip 32 | ``` 33 | - Unpack it: 34 | ``` 35 | unzip ffglitch-0.10.2-windows-x86_64.zip 36 | ``` 37 | - Move its contents to a directory named `bin`: 38 | ``` 39 | mkdir -p bin 40 | mv ffglitch-0.10.2-windows-x86_64/* bin/ 41 | ``` 42 | - Cleanup 43 | ``` 44 | rmdir ffglitch-0.10.2-windows-x86_64 45 | rm ffglitch-0.10.2-windows-x86_64.zip 46 | ``` 47 | 48 | -------------------------------------------------------------------------------- /tutorial/scripts/helpers/midi.js: -------------------------------------------------------------------------------- 1 | import * as rtmidi from "rtmidi"; 2 | 3 | export class MIDIInput 4 | { 5 | constructor() 6 | { 7 | this.midiin = new rtmidi.In(); 8 | this.events = {}; 9 | this.buttons = {}; 10 | this.log = false; 11 | } 12 | 13 | setup(arg) 14 | { 15 | let port_name; 16 | let port_num; 17 | const midiin = this.midiin; 18 | 19 | // Check arguments 20 | if ( arg !== undefined ) 21 | { 22 | if ( typeof arg === 'string' ) 23 | port_name = arg; 24 | else 25 | port_num = arg; 26 | } 27 | 28 | // Check if any MIDI ports are available 29 | const count = midiin.getPortCount(); 30 | console.log(`RtMidi: ${count} port${count === 1 ? "" : "s"} found`); 31 | if ( count === 0 ) 32 | throw "No MIDI ports"; 33 | 34 | // Print names and select port number 35 | for ( let i = 0; i < count; i++ ) 36 | { 37 | const name = midiin.getPortName(i); 38 | if ( name == port_name ) 39 | port_num = i; 40 | console.log(i + ". " + name); 41 | } 42 | 43 | // Sanity check for port name 44 | if ( port_name !== undefined && port_num === undefined ) 45 | { 46 | console.log(`Selected port name (${port_name}) is not available.`); 47 | throw "Bad MIDI port name"; 48 | } 49 | 50 | // Sanity check for port number 51 | if ( port_num >= count ) 52 | { 53 | console.log(`Selected port number (${port_name}) greater than real number of ports (${count}).`); 54 | throw "Bad MIDI port number"; 55 | } 56 | 57 | // No port selected yet, use heuristics 58 | if ( port_num === undefined ) 59 | { 60 | for ( let i = 0; i < count; i++ ) 61 | { 62 | const name = midiin.getPortName(i); 63 | if ( name.includes("Midi Through") ) 64 | continue; 65 | if ( port_num === undefined ) 66 | port_num = i; 67 | } 68 | } 69 | 70 | // Open input port 71 | console.log(`Opening input port number ${port_num}`); 72 | midiin.openPort(port_num); 73 | 74 | // Prepare last_vals and setup callback 75 | midiin.ignoreTypes(false, false, false); 76 | } 77 | 78 | setlog(b) 79 | { 80 | this.log = b; 81 | } 82 | 83 | onevent(v, func) 84 | { 85 | this.events[v] = func; 86 | } 87 | 88 | onbutton(v, func) 89 | { 90 | this.buttons[v] = func; 91 | } 92 | 93 | parse_events() 94 | { 95 | let midiin = this.midiin; 96 | if ( !midiin.isPortOpen() ) 97 | return; 98 | while ( 42 ) 99 | { 100 | let msg = midiin.getMessage(); 101 | const msglen = msg.length; 102 | if ( msglen == 0 ) 103 | break; 104 | if ( this.log ) 105 | console.log(JSON.stringify(msg)); 106 | if ( msglen == 3 ) 107 | { 108 | if ( msg[0] == 176 ) 109 | { 110 | let event_v = this.events[msg[1]]; 111 | if ( event_v !== undefined ) 112 | event_v(msg[2]); 113 | let button_v = this.buttons[msg[1]]; 114 | if ( button_v !== undefined ) 115 | button_v(msg[2] == 127); 116 | } 117 | } 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /tutorial/scripts/jpeg/dqt.js: -------------------------------------------------------------------------------- 1 | // ./bin/fflive -i lena.jpg -s scripts/jpeg/dqt.js 2 | 3 | /*********************************************************************/ 4 | // new DC quantization coefficient 5 | const dc_quant = 63; // EXPERIMENT BY CHANGING THIS VALUE 6 | 7 | /*********************************************************************/ 8 | export function setup(args) 9 | { 10 | // select quantization table feature 11 | args.features = [ "dqt" ]; 12 | } 13 | 14 | export function glitch_frame(frame, stream) 15 | { 16 | const tables = frame.dqt.tables; 17 | const table0 = tables[0]; 18 | console.log(`The old DC quantization coefficient was ${table0[0]}`); 19 | // change the DC quantization coefficient for first table 20 | table0[0] = dc_quant; 21 | console.log(`The new DC quantization coefficient is ${table0[0]}`); 22 | } 23 | -------------------------------------------------------------------------------- /tutorial/scripts/jpeg/q_dc_delta.js: -------------------------------------------------------------------------------- 1 | // ./bin/fflive -i lena.jpg -s scripts/jpeg/q_dc_delta.js 2 | 3 | /*********************************************************************/ 4 | // new DC delta value 5 | const plane = 1; // EXPERIMENT BY CHANGING THIS VALUE FROM 0 to 2 6 | const mb_x = 16; // EXPERIMENT BY CHANGING THIS VALUE 7 | const mb_y = 16; // EXPERIMENT BY CHANGING THIS VALUE 8 | const dc_delta = 63; // EXPERIMENT BY CHANGING THIS VALUE 9 | 10 | /*********************************************************************/ 11 | export function setup(args) 12 | { 13 | // select quantized dc delta feature 14 | args.features = [ "q_dc_delta" ]; 15 | } 16 | 17 | export function glitch_frame(frame, stream) 18 | { 19 | const data = frame.q_dc_delta.data; 20 | // change the DC delta value of the specified plane and macroblock 21 | data[plane][mb_x][mb_y] = dc_delta; 22 | } 23 | -------------------------------------------------------------------------------- /tutorial/scripts/mpeg4/mb_type_midi.js: -------------------------------------------------------------------------------- 1 | import { MIDIInput } from "../helpers/midi.js"; 2 | 3 | /*********************************************************************/ 4 | const midiin = new MIDIInput(); 5 | 6 | /*********************************************************************/ 7 | const CANDIDATE_MB_TYPE_INTRA = (1 << 0); 8 | const CANDIDATE_MB_TYPE_INTER = (1 << 1); 9 | 10 | class Command 11 | { 12 | constructor() 13 | { 14 | this.mbs_per_frame = 0; 15 | } 16 | 17 | setup(nb_frames) 18 | { 19 | if ( !this.mb_height ) 20 | { 21 | console.log("mb_type cleaner still does not know dimensions"); 22 | return; 23 | } 24 | 25 | const mb_height = this.mb_height; 26 | const mb_width = this.mb_width; 27 | const total_mbs = mb_height * mb_width; 28 | const mbs_per_frame = Math.ceil(total_mbs / nb_frames); 29 | this.mbs_per_frame = mbs_per_frame; 30 | 31 | // Cleanup local mb_types array with P macroblocks 32 | const cur_mb_types = this.mb_types; 33 | for ( let mb_y = 0; mb_y < mb_height; mb_y++ ) 34 | { 35 | const row = cur_mb_types[mb_y]; 36 | for ( let mb_x = 0; mb_x < mb_width; mb_x++ ) 37 | row[mb_x] = CANDIDATE_MB_TYPE_INTER; 38 | } 39 | 40 | // Create array with all [ mb_y, mb_x ] indices 41 | const mb_array = new Array(total_mbs); 42 | for ( let mb_y = 0; mb_y < mb_height; mb_y++ ) 43 | for ( let mb_x = 0; mb_x < mb_width; mb_x++ ) 44 | mb_array[mb_y * mb_width + mb_x] = [ mb_y, mb_x ]; 45 | 46 | // Randomly shuffle array 47 | for ( let i = mb_array.length; i > 0; ) 48 | { 49 | const r = Math.floor(Math.random() * i); 50 | i--; 51 | [ mb_array[i], mb_array[r] ] = [ mb_array[r], mb_array[i] ]; 52 | } 53 | 54 | this.mb_array = mb_array; 55 | } 56 | 57 | run(mb_types, nb_frames) 58 | { 59 | if ( nb_frames !== null && nb_frames !== 0 ) 60 | this.setup(nb_frames); 61 | 62 | // On first run, create a local mb_types with the dimensions 63 | if ( !this.mb_height ) 64 | { 65 | const cur_mb_types = []; 66 | const mb_height = mb_types.length; 67 | const mb_width = mb_types[0].length; 68 | 69 | for ( let mb_y = 0; mb_y < mb_height; mb_y++ ) 70 | cur_mb_types[mb_y] = []; 71 | this.mb_types = cur_mb_types; 72 | this.mb_height = mb_height; 73 | this.mb_width = mb_width; 74 | } 75 | 76 | // Check if we need to run 77 | const mbs_per_frame = this.mbs_per_frame; 78 | if ( mbs_per_frame == 0 ) 79 | return; 80 | 81 | // Check if we have finished running 82 | if ( this.mb_array.length == 0 ) 83 | { 84 | this.mbs_per_frame = 0; 85 | return; 86 | } 87 | 88 | // Run 89 | { 90 | const cur_mb_types = this.mb_types; 91 | const mb_height = this.mb_height; 92 | const mb_width = this.mb_width; 93 | 94 | for ( let i = 0; this.mb_array.length != 0 && i < mbs_per_frame; i++ ) 95 | { 96 | const cur_mv = this.mb_array.pop(); 97 | cur_mb_types[cur_mv[0]][cur_mv[1]] = CANDIDATE_MB_TYPE_INTRA; 98 | } 99 | for ( let mb_y = 0; mb_y < mb_height; mb_y++ ) 100 | for ( let mb_x = 0; mb_x < mb_width; mb_x++ ) 101 | mb_types[mb_y][mb_x] = cur_mb_types[mb_y][mb_x]; 102 | } 103 | } 104 | } 105 | 106 | /*********************************************************************/ 107 | let command; 108 | let midi_val = 30; 109 | let nb_frames = null; 110 | 111 | export function setup() 112 | { 113 | command = new Command(); 114 | 115 | midiin.setup(); 116 | // NOTE: uncomment the following line to print the values from the MIDI events 117 | // midiin.setlog(true); 118 | /* faders */ 119 | midiin.onevent ( 0, function(v) { midi_val = v + 1; }); 120 | /* buttons */ 121 | midiin.onbutton(32, function(v) { if ( v ) nb_frames = midi_val; }); 122 | } 123 | 124 | export function mb_type_func(args) 125 | { 126 | midiin.parse_events(); 127 | command.run(args.mb_types, nb_frames); 128 | nb_frames = null; 129 | } 130 | -------------------------------------------------------------------------------- /tutorial/scripts/mpeg4/mv_average.js: -------------------------------------------------------------------------------- 1 | // ./bin/fflive -i CEP00109_mpeg4.avi -s scripts/mpeg4/mv_average.js 2 | 3 | /*********************************************************************/ 4 | // experiment with this value to use a smaller or greater number of 5 | // frames to perform the average of motion vectors 6 | const tail_length = 10; 7 | 8 | /*********************************************************************/ 9 | // global variable holding forward motion vectors from previous frames 10 | let prev_fwd_mvs = [ ]; 11 | let total_sum; 12 | 13 | export function setup(args) 14 | { 15 | // select motion vector feature 16 | args.features = [ "mv" ]; 17 | } 18 | 19 | export function glitch_frame(frame) 20 | { 21 | const fwd_mvs = frame.mv?.forward; 22 | // bail out if we have no forward motion vectors 23 | if ( !fwd_mvs ) 24 | return; 25 | 26 | // set motion vector overflow behaviour in ffedit to "truncate". 27 | // this means that, even if we write values well beyond the 28 | // acceptable range, ffedit will truncate them when writing 29 | // back to the bitstream. 30 | frame.mv.overflow = "truncate"; 31 | 32 | // update variable holding forward motion vectors from previous 33 | // frames. note that we perform a deep copy of the clean motion 34 | // vector values before modifying them. 35 | const deep_copy = fwd_mvs.dup(); 36 | // push to the end of array 37 | prev_fwd_mvs.push(deep_copy); 38 | 39 | // initialize total_sum to a [0,0] MV2DArray. 40 | if ( !total_sum ) 41 | total_sum = new MV2DArray(fwd_mvs.width, fwd_mvs.height); 42 | 43 | // update total_sum by removing the motion vector values from the 44 | // oldest frame and adding the values from the current frame. 45 | if ( prev_fwd_mvs.length > tail_length ) 46 | { 47 | total_sum.sub(prev_fwd_mvs[0]); 48 | prev_fwd_mvs = prev_fwd_mvs.slice(1); 49 | } 50 | total_sum.add(deep_copy); 51 | 52 | // set new values for current frame to (total_sum / tail_length) 53 | if ( prev_fwd_mvs.length == tail_length ) 54 | { 55 | fwd_mvs.assign(total_sum); 56 | fwd_mvs.div(MV(tail_length, tail_length)); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /tutorial/scripts/mpeg4/mv_pan.js: -------------------------------------------------------------------------------- 1 | // ./bin/fflive -i CEP00109_mpeg4.avi -s scripts/mpeg4/mv_pan.js 2 | // ./bin/fflive -i CEP00109_mpeg4.avi -s scripts/mpeg4/mv_pan.js -sp "[ 0, 10 ]" 3 | 4 | /*********************************************************************/ 5 | let pan_x = 1; // EXPERIMENT BY CHANGING THIS VALUE 6 | let pan_y = 0; // EXPERIMENT BY CHANGING THIS VALUE 7 | 8 | /*********************************************************************/ 9 | export function setup(args) 10 | { 11 | // select motion vector feature 12 | args.features = [ "mv" ]; 13 | 14 | // parse parameter from the command line if available 15 | // NOTE: the parameter from the command line should be an array with 16 | // two values, like this: 17 | // -sp "[ 1, 0 ]" 18 | // NOTE2: -sp means "script parameters" 19 | if ( "params" in args ) 20 | { 21 | const params = args.params; 22 | pan_x = params[0]; 23 | pan_y = params[1]; 24 | } 25 | } 26 | 27 | export function glitch_frame(frame, stream) 28 | { 29 | const fwd_mvs = frame.mv?.forward; 30 | // bail out if we have no forward motion vectors 31 | if ( !fwd_mvs ) 32 | return; 33 | 34 | // set motion vector overflow behaviour in ffedit to "truncate". 35 | // this means that, even if we write values well beyond the 36 | // acceptable range, ffedit will truncate them when writing 37 | // back to the bitstream. 38 | frame.mv.overflow = "truncate"; 39 | 40 | // add pan values to all macroblocks 41 | fwd_mvs.add(MV(pan_x, pan_y)); 42 | } 43 | -------------------------------------------------------------------------------- /tutorial/scripts/mpeg4/mv_pan_midi.js: -------------------------------------------------------------------------------- 1 | import { MIDIInput } from "../helpers/midi.js"; 2 | 3 | /*********************************************************************/ 4 | const midiin = new MIDIInput(); 5 | let midi_range_y = [ 0, 0 ]; 6 | let midi_range_x = [ 0, 0 ]; 7 | 8 | /*********************************************************************/ 9 | export function setup(args) 10 | { 11 | args.features = [ "mv" ]; 12 | 13 | midiin.setup(); 14 | // midiin.setlog(true); 15 | /* faders */ 16 | midiin.onevent ( 4, function(v) { midi_range_y[0] = v; }); 17 | midiin.onevent ( 5, function(v) { midi_range_y[1] = v; }); 18 | midiin.onevent ( 6, function(v) { midi_range_x[0] = v; }); 19 | midiin.onevent ( 7, function(v) { midi_range_x[1] = v; }); 20 | } 21 | 22 | export function glitch_frame(frame, stream) 23 | { 24 | const fwd_mvs = frame.mv?.forward; 25 | // bail out if we have no forward motion vectors 26 | if ( !fwd_mvs ) 27 | return; 28 | 29 | // set motion vector overflow behaviour in ffedit to "truncate". 30 | // this means that, even if we write values well beyond the 31 | // acceptable range, ffedit will truncate them when writing 32 | // back to the bitstream. 33 | frame.mv.overflow = "truncate"; 34 | 35 | midiin.parse_events(); 36 | 37 | const y_begin = midi_range_y[0]; 38 | const y_end = midi_range_y[1]; 39 | const x_begin = midi_range_x[0]; 40 | const x_end = midi_range_x[1]; 41 | 42 | // add pan values to all macroblocks 43 | const mv_off = MV(y_end - y_begin, x_end - x_begin); 44 | fwd_mvs.add(mv_off); 45 | } 46 | -------------------------------------------------------------------------------- /tutorial/scripts/mpeg4/mv_sink_and_rise.js: -------------------------------------------------------------------------------- 1 | // ./bin/fflive -i CEP00109_mpeg4.avi -s scripts/mpeg4/mv_sink_and_rise.js 2 | 3 | /*********************************************************************/ 4 | // Go down to WHERE THE MAGIC HAPPENS to experiment with this script. 5 | 6 | /*********************************************************************/ 7 | export function setup(args) 8 | { 9 | // select motion vector feature 10 | args.features = [ "mv" ]; 11 | } 12 | 13 | export function glitch_frame(frame) 14 | { 15 | const fwd_mvs = frame.mv?.forward; 16 | // bail out if we have no forward motion vectors 17 | if ( !fwd_mvs ) 18 | return; 19 | 20 | // clear horizontal element of all motion vectors 21 | for ( let i = 0; i < fwd_mvs.length; i++ ) 22 | { 23 | // loop through all rows 24 | const row = fwd_mvs[i]; 25 | for ( let j = 0; j < row.length; j++ ) 26 | { 27 | // loop through all macroblocks 28 | const mv = row[j]; 29 | 30 | // THIS IS WHERE THE MAGIC HAPPENS 31 | 32 | mv[0] = 0; // this sets the horizontal motion vector to zero 33 | // mv[1] = 0; // you could also change the vertical motion vector 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tutorial/scripts/mpeg4/mv_sink_and_rise_fast.js: -------------------------------------------------------------------------------- 1 | // ./bin/fflive -i CEP00109_mpeg4.avi -s scripts/mpeg4/mv_sink_and_rise_fast.js 2 | 3 | /*********************************************************************/ 4 | // This script has similar functionality to mv_sink_and_rise.js, but it 5 | // uses optimized functions that make it much much faster. 6 | // Go here for more documentation on the optimized functions: 7 | // - https://ffglitch.org/docs/0.10.2/quickjs/mv2darray#mv2darrayprototypemathop 8 | 9 | /*********************************************************************/ 10 | export function setup(args) 11 | { 12 | // select motion vector feature 13 | args.features = [ "mv" ]; 14 | } 15 | 16 | export function glitch_frame(frame) 17 | { 18 | const fwd_mvs = frame.mv?.forward; 19 | // bail out if we have no forward motion vectors 20 | if ( !fwd_mvs ) 21 | return; 22 | 23 | // assign 0 to the 'h'orizontal element of each motion vector, 24 | // effectively removing horizontal movement from the video. 25 | fwd_mvs.assign_h(0); 26 | } 27 | -------------------------------------------------------------------------------- /tutorial/scripts/png/idat.js: -------------------------------------------------------------------------------- 1 | // ./bin/fflive -i lena.png -s scripts/png/idat.js 2 | 3 | /*********************************************************************/ 4 | // these constants are part of the PNG specification 5 | // DO NOT CHANGE THESE VALUES HERE 6 | // instead, change the `filter_type` constant below to any of these 7 | // values here. 8 | const PNG_FILTER_VALUE_NONE = 0; 9 | const PNG_FILTER_VALUE_SUB = 1; 10 | const PNG_FILTER_VALUE_UP = 2; 11 | const PNG_FILTER_VALUE_AVG = 3; 12 | const PNG_FILTER_VALUE_PAETH = 4; 13 | 14 | /*********************************************************************/ 15 | // Uncomment **only one** of the lines below: 16 | // 17 | // const filter_type = PNG_FILTER_VALUE_NONE; 18 | // const filter_type = PNG_FILTER_VALUE_SUB; 19 | // const filter_type = PNG_FILTER_VALUE_UP; 20 | // const filter_type = PNG_FILTER_VALUE_AVG; 21 | const filter_type = PNG_FILTER_VALUE_PAETH; 22 | 23 | export function setup(args) 24 | { 25 | // select image data feature 26 | args.features = [ "idat" ]; 27 | } 28 | 29 | export function glitch_frame(frame, stream) 30 | { 31 | const rows = frame.idat?.rows; 32 | if ( !rows ) 33 | return; 34 | const length = rows.length; 35 | // change the filter type for each row 36 | for ( let i = 0; i < length; i++ ) 37 | { 38 | const row = rows[i]; 39 | row[0] = filter_type; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tutorial/sh/fflive_pipe.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ./bin/fflive -i pipe: -asap "$@" 4 | -------------------------------------------------------------------------------- /tutorial/sh/file_to_mpeg4.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check if a filename was passed as an argument 4 | if [ -z "$1" ]; then 5 | echo "Usage: $0 " 6 | exit 1 7 | fi 8 | 9 | # Check if stdout is being piped 10 | if [ -t 1 ]; then 11 | echo "Error: Output must be piped." 12 | exit 1 13 | fi 14 | 15 | # Run the command with the provided filename 16 | ./bin/ffgac -i "$1" -vcodec mpeg4 -mpv_flags +nopimb+forcemv -qscale:v 1 -fcode 6 -g max -sc_threshold max -f rawvideo pipe: 17 | --------------------------------------------------------------------------------