Public
Edited
Aug 13, 2023
Insert cell
Insert cell
Insert cell
// viewof audioHTML = html`
// <audio/mp3
// controls
// crossorigin="anonymous"
// id="audio"
// src="${audioUrl}"
// autoplay
// >
// </audio>
// `
Insert cell
myCanvas = html`<canvas id="my-canvas" width="480" height="270"></canvas>`
Insert cell
myVideo = html`<video id="my-video" controls="true" width="480" height="270" crossorigin="anonymous">
<source src="http://jplayer.org/video/webm/Big_Buck_Bunny_Trailer.webm" type="video/webm">
<source src="http://jplayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v" type="video/mp4">
</video>`
Insert cell
// displayDistortedImage(scrub_input, reverseMap)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
processor = ({
timerCallback: function() {
if (this.video.paused || this.video.ended) {
return;
}
this.computeFrame();
var self = this;
setTimeout(function() {
self.timerCallback();
}, 16); // roughly 60 frames per second
},

doLoad: function() {
this.video = myVideo;
this.c1 = myCanvas;
this.ctx1 = this.c1.getContext("2d");
var self = this;

this.video.addEventListener(
"play",
function() {
self.width = self.video.width;
self.height = self.video.height;
self.timerCallback();
},
false
);
},

// computeFrame: function() {
// this.ctx1.drawImage(this.video, 0, 0, this.width, this.height);
// var input = this.ctx1.getImageData(0, 0, this.width, this.height);
// var output = this.cctx1.getImageData(0, 0, this.width, this.height);

// distortPixels(input, output, this.width, this.height, reverseMap);
// var frame = this.ctx1.getImageData(0, 0, this.width, this.height);
// var l = frame.data.length / 4;


// for (var i = 0; i < l; i++) {
// var grey =
// (frame.data[i * 4 + 0] +
// frame.data[i * 4 + 1] +
// frame.data[i * 4 + 2]) /
// 3;

// frame.data[i * 4 + 0] = grey;
// frame.data[i * 4 + 1] = grey;
// frame.data[i * 4 + 2] = grey;
// }
// this.ctx1.putImageData(frame, 0, 0);

// return;
// }

// computeFrame: function() {
// this.ctx1.drawImage(this.video, 0, 0, this.width, this.height);
// var frame = this.ctx1.getImageData(0, 0, this.width, this.height);
// var l = frame.data.length / 4;

// for (var i = 0; i < l; i++) {
// var grey =
// (frame.data[i * 4 + 0] +
// frame.data[i * 4 + 1] +
// frame.data[i * 4 + 2]) /
// 3;

// frame.data[i * 4 + 0] = grey;
// frame.data[i * 4 + 1] = grey;
// frame.data[i * 4 + 2] = grey;
// }
// this.ctx1.putImageData(frame, 0, 0);

// return;
// }

// computeFrame: function() {
// this.ctx1.drawImage(this.video, 0, 0, this.width, this.height);
// var frame = this.ctx1.getImageData(0, 0, this.width, this.height);
// var l = frame.data.length / 4;

// for (var i = 0; i < l; i++) {
// var grey =
// (frame.data[i * 4 + 0] +
// frame.data[i * 4 + 1] +
// frame.data[i * 4 + 2]) /
// 3;

// frame.data[i * 4 + 0] = grey;
// frame.data[i * 4 + 1] = grey;
// frame.data[i * 4 + 2] = grey;
// }
// this.ctx1.putImageData(frame, 0, 0);

// return;
// }




computeFrame: function() {
this.ctx1.drawImage(this.video, 0, 0, this.width, this.height);
var frame = this.ctx1.getImageData(0, 0, this.width, this.height);
// var l = frame.data.length / 4;
var l = frame.data.length;



if (color_fluct != 0 | color_base != 0) {
// let cur = episode_selection[img_choice]

// if (colorMap == "Color Pallette") {
// interpolator = d3.interpolateRgb(...cur_colors);
// } else {
// interpolator = d3[`interpolate${colorMap}`];
// }

let interpolator = d3[`interpolate${colorMap}`];
const LUT = Array.from({ length: 256 }, (_, i) => d3.color(interpolator(i / 255)));
let w = color_fluct*spectralSpread/50 + color_base*spectralCentroid/50
for(let i=0; i < l; i+=4) {
const color = LUT[frame.data[i]];
// frame.data[i] = (1-w) * frame.data[i] + w*color.r;
// frame.data[i+1] = (1-w) * frame.data[i+1] + w*color.g;
// frame.data[i+2] = (1-w) * frame.data[i+2] + w*color.b;
frame.data[i] = color.r;
frame.data[i+1] = color.g;
frame.data[i+2] = color.b;
}
// var grey =
// (frame.data[i] +
// frame.data[i+1] +
// frame.data[i+2]) /
// 3;
// frame.data[i] = grey;
// frame.data[i+1] = grey;
// frame.data[i+2] = grey;
// }
}

this.ctx1.putImageData(frame, 0, 0);

return;
}
})
Insert cell
processor.doLoad();
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function initialize() {
// if (!audioUrl) {
// return null;
// }
const audioContext = new AudioContext()
invalidation.then(() => audioContext.close());
let htmlAudioElement = document.querySelector('video');
const source = audioContext.createMediaElementSource(htmlAudioElement);
source.connect(audioContext.destination);

const analyzer = meyda.createMeydaAnalyzer({
"audioContext": audioContext,
"source": source,
"bufferSize": 512,
"windowingFunction": 'hanning',
"featureExtractors": ["energy", "spectralFlatness", "spectralCentroid", "spectralSpread"],
});

analyzer.start();
return analyzer;
}

Insert cell
// function initialize() {
// if (!audioUrl) {
// return null;
// }
// const audioContext = new AudioContext()
// invalidation.then(() => audioContext.close());
// let htmlAudioElement = document.querySelector('audio');
// const source = audioContext.createMediaElementSource(htmlAudioElement);
// source.connect(audioContext.destination);

// const analyzer = meyda.createMeydaAnalyzer({
// "audioContext": audioContext,
// "source": source,
// "bufferSize": 512,
// "windowingFunction": 'hanning',
// "featureExtractors": ["energy", "spectralFlatness", "spectralCentroid", "spectralSpread"],
// });

// analyzer.start();
// return analyzer;
// }

Insert cell
audioElement = {
await analyzer
return document.getElementById('my-video');
// return document.getElementById('audio');
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
scrub_input = {
let img = vid_urls[img_choice]
let ctx = DOM.canvas(img.naturalWidth, img.naturalHeight).getContext("2d");
ctx.drawImage(img, 0, 0);

return {
data: ctx.getImageData(0, 0, img.naturalWidth, img.naturalHeight),
width: img.naturalWidth,
height: img.naturalHeight
};
}

Insert cell
Insert cell
function displayDistortedImage(input, reverseMap) {
const ctx = DOM.context2d(input.width, input.height, 1);
const outputPixels = ctx.getImageData(0, 0, input.width, input.height);
distortPixels(
input.data,
outputPixels,
input.width,
input.height,
reverseMap
);
if (color_fluct != 0 | color_base != 0) {
let cur = episode_selection[img_choice]
let interpolator
if (colorMap == "Color Pallette") {
interpolator = d3.interpolateRgb(...cur_colors);
} else {
interpolator = d3[`interpolate${colorMap}`];
}
const LUT = Array.from({ length: 256 }, (_, i) => d3.color(interpolator(i / 255)));

let w = color_fluct*spectralSpread/50 + color_base*spectralCentroid/50
for(let i=0; i<outputPixels.data.length; i+=4) {
const color=LUT[outputPixels.data[i]];
outputPixels.data[i] = (1-w)*outputPixels.data[i] + w*color.r;
outputPixels.data[i+1] = (1-w)*outputPixels.data[i+1] + w*color.g;
outputPixels.data[i+2] = (1-w)*outputPixels.data[i+2] + w*color.b;
}
}
ctx.putImageData(outputPixels, 0, 0);
ctx.canvas.style.maxWidth = "100%";
return html`${ctx.canvas}`;
}

Insert cell
// modification of https://observablehq.com/@kerryrodden/image-distortion-with-perlin-noise
function getShiftedPixelIndex(x, y, width, height) {
let scale = flatnessDistort*scaling/10
let amount = energy * amount_scale
let offset1a = offset1 * oscillation * multiplier + offset1
let offset2a = offset2 * oscillation * multiplier + offset2
// let shift1a = movement * oscillation * multiplier
const shift = {
x: amount * noise(scale * x, scale * y),
y: amount * noise(offset1a + scale * x, offset2a + scale * y)
};
const newX = clamp(Math.round(x + shift.x), 0, width - 1);
const newY = clamp(Math.round(y + shift.y), 0, height - 1);
return getPixelIndex(newX, newY, width);
}
Insert cell
function distortPixels(inputPixels, outputPixels, width, height, reverseMap) {
for (let x = 0; x < width; x++) {
for (let y = 0; y < height; y++) {
const inputIndex = reverseMap
? getShiftedPixelIndex(x, y, width, height)
: getPixelIndex(x, y, width);
const outputIndex = reverseMap
? getPixelIndex(x, y, width)
: getShiftedPixelIndex(x, y, width, height);
for (let i = 0; i < 4; i++) {
outputPixels.data[outputIndex + i] = inputPixels.data[inputIndex + i];
}
}
}
}
Insert cell
function getPixelIndex(x, y, width) {
return y * width * 4 + x * 4;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more