13

Listen to your web pages · GitHub

 4 years ago
source link: https://gist.github.com/tomhicks/6cb5e827723c4eaef638bf9f7686d2d8
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Listen to your web pages · GitHub

Instantly share code, notes, and snippets.

Listen to your web pages
/*
Copy this into the console of any web page that is interactive and doesn't
do hard reloads. You will hear your DOM changes as different pitches of
audio.
I have found this interesting for debugging, but also fun to hear web pages
render like UIs do in movies.
*/
const audioCtx = new (window.AudioContext || window.webkitAudioContext)()
const observer = new MutationObserver(function(mutationsList) {
const oscillator = audioCtx.createOscillator()
oscillator.connect(audioCtx.destination)
oscillator.type = "sine"
oscillator.frequency.setValueAtTime(
Math.log(mutationsList.length + 5) * 880,
audioCtx.currentTime,
)
oscillator.start()
oscillator.stop(audioCtx.currentTime + 0.01)
})
observer.observe(document, {
attributes: true,
childList: true,
subtree: true,
characterData: true,
})

R4meau commented on Feb 15

Haha, I wonder what kind of debugging you're into. XD

Great idea +11st_place_medal

vprasanth commented on Feb 15

This hilarious! thanks!

tkesgar commented on Feb 15

This is cool stuff, thank you for sharing! +1+1+1

LXSMNSYC commented on Feb 15

I can never hear my websites the same way again. I need to release these souls from their agony.

asdfx86 commented on Feb 15

Sounds beautiful, love it heartsheartpulse

lenaggar commented on Feb 15

wow! I like it grin

Make a browser extensions before somebody else does. Take the credit! cool stuff!

I can never hear my websites the same way again. I need to release these souls from their agony.

True that!

Brilliant!

m00dy commented on Feb 16

very smart !!!

SeriousM commented on Feb 16

I can never hear my websites the same way again. I need to release these souls from their agony.

True that!

And add a sound output for network activity!

R4meau commented on Feb 16

And add a sound output for network activity!

Now this!

nessup commented on Feb 16

Awesome!

dsharhon commented on Feb 16

edited
javascript:(function plink_plonk_bookmarklet () {
  /*
  Author: Tom Hicks
  Copy this into a bookmark URL and click on it from any web page that is 
  interactive and doesn't do hard reloads. You will hear your DOM changes as
  different pitches of audio.
  
  I have found this interesting for debugging, but also fun to hear web pages
  render like UIs do in movies.
  */
  const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
  const observer = new MutationObserver(function(mutationsList) {
    const oscillator = audioCtx.createOscillator();

    oscillator.connect(audioCtx.destination);
    oscillator.type = "sine";
    oscillator.frequency.setValueAtTime(
      Math.log(mutationsList.length + 5) * 880,
      audioCtx.currentTime
    );

    oscillator.start();
    oscillator.stop(audioCtx.currentTime + 0.01);
  });

  observer.observe(document, {
    attributes: true,
    childList: true,
    subtree: true,
    characterData: true
  });
})();

Change that stop delay on line 22 to 0.03 on Facebook and SUDDENLY I'M IN THE FUTURE.

68747470733a2f2f6d656469612e67697068792e636f6d2f6d656469612f4a31346478686f4a4c576c49342f67697068792e676966

jcraigk commented on Feb 16

This is absolutely brilliant. And useful.

sbrichardson commented on Feb 16

edited

Here's a funny variation that speaks out the counts in different pitches/rates

const speechSynthesis = window.speechSynthesis
const min = 0
const max = 100
const bad = 15 // just a random max to enable 'bad developer' mode

const observer = new MutationObserver(function(mutationsList) {
  const msg = new SpeechSynthesisUtterance()
  const len = mutationsList.length
  
  if (len > bad) {
    msg.text = 'Bad Developer'
  } else {
    const n = len > max ? max : len
    const pitch = ((n - min) / (100 - min)) * 2
    msg.text = len
    msg.rate = 4 - pitch * 4
    msg.pitch = 2 - (pitch * 1.6 * 1.2)
  }

  speechSynthesis.speak(msg)
})

observer.observe(document, {
  attributes: true,
  childList: true,
  subtree: true,
  characterData: true,
})  

Can anyone upload what they hear on some sites?

Hahaha, great work!

LXSMNSYC commented on Feb 16

Can anyone upload what they hear on some sites?

You'll just hear a Chewbacca Jr. talking

Hahaha great idea! +1 (could be a nice prank too)
Didn't work on Firefox, but Chrome is heavy_check_mark

R4meau commented on Feb 16

I honestly didn't like it at first, then I realized how useful it can actually be :) . So I turned it into a basic Chrome extension: https://github.com/R4meau/plink-plonk

I'll be working on it every Sunday (very slow for now) and I'm open for any contributions at any time. Thanks for the head start @tomhicks.

iAnatoly commented on Feb 17

edited

I have moved out the constants into variables, to be able to play with the settings more easily.
I also added a random component. to make it sound less monotonous:

// origin: https://gist.github.com/tomhicks/6cb5e827723c4eaef638bf9f7686d2d8 ,  tomhicks/plink-plonk.js

const audioCtx = new (window.AudioContext || window.webkitAudioContext)()
var delay = 0.03
var freqbase = 600
var freqrnd = 400
const observer = new MutationObserver(function(mutationsList) {
  const oscillator = audioCtx.createOscillator()

  oscillator.connect(audioCtx.destination)
  oscillator.type = "sine"
  oscillator.frequency.setValueAtTime(
    Math.log(mutationsList.length + 5) * (Math.random()*freqrnd + freqbase),
    audioCtx.currentTime,
  )

  oscillator.start()
  oscillator.stop(audioCtx.currentTime + delay)
})

observer.observe(document, {
  attributes: true,
  childList: true,
  subtree: true,
  characterData: true,
})  

Then you can play with delay and freq on the fly.

aflemi2 commented on Feb 17

Love this!

iAnatoly commented on Feb 17

This one randomly decreases/increases tone until it reaches a threshold. Makes it a bit more harmonious:

// origin: https://gist.github.com/tomhicks/6cb5e827723c4eaef638bf9f7686d2d8 ,  tomhicks/plink-plonk.js

const audioCtx = new (window.AudioContext || window.webkitAudioContext)()
var delay = 0.03
// parameters of the random increment/decrement
var freqstart = 600
var freqlow = 400
var freqhigh = 900
var freqspeed = 50
// initial values
var freqinc = 25
var freq = 600

const observer = new MutationObserver(function(mutationsList) {
  const oscillator = audioCtx.createOscillator()

  oscillator.connect(audioCtx.destination)
  oscillator.type = "sine"
  oscillator.frequency.setValueAtTime(
    Math.log(mutationsList.length + 5) * freq,
    audioCtx.currentTime,
  )
  freq += freqinc
  if (freq > freqhigh || freq<freqlow) {
    // reset if we have reached the high or low bound
    freq = freqstart
    freqinc = (Math.random()-0.5)*freqspeed
  }

  oscillator.start()
  oscillator.stop(audioCtx.currentTime + delay)
})

observer.observe(document, {
  attributes: true,
  childList: true,
  subtree: true,
  characterData: true,
})  

Genius!

epranka commented on Feb 17

Nice work! Check this out https://soundcode.now.sh too slightly_smiling_face

ttcremers commented on Feb 17

Absolutely wonderful! smile

fbedussi commented on Feb 17

awesome! My computer now sounds like one from a '70s TV serial

Could replace the pulses with Rice Krispies sounds. Now, web == tasty breakfast!

try this on a typing test website. very enjoyable lol

MarkArts commented on Feb 18

Added quantization and randomness + delay for a cuter effect innocent

https://gist.github.com/MarkArts/3d4217f957df8a30802a8cbf962fa204

// origin: https://gist.github.com/tomhicks/6cb5e827723c4eaef638bf9f7686d2d8 ,  tomhicks/plink-plonk.js

/*
Copy this into the console of any web page that is interactive and doesn't
do hard reloads. You will hear your DOM changes as different pitches of
audio.
I have found this interesting for debugging, but also fun to hear web pages
render like UIs do in movies.
*/

// dorian (-)   C     E      F     G-     A     B-   
let scale = [
  264, 330, 352, 391.1, 440, 488.9 
]
scale = scale.concat(scale.map(x=>x*2))

console.log(scale)

function quantize(scale, freq) {
  return scale.reduce(function(prev, curr){
    return (Math.abs(curr - freq) < Math.abs(prev - freq) ? curr : prev);
  });
}

const audioCtx = new (window.AudioContext || window.webkitAudioContext)()
const observer = new MutationObserver(observe)

function observe(mutationsList) {
  // with delay
  delayNote(gain => playNote(mutationsList, gain), 300, 0.2)  
  // without
  // playNote(mutationsList)
}


// Compressor as final stage to prevent clipping
const compressor = audioCtx.createDynamicsCompressor()
compressor.threshold.setValueAtTime(-40, audioCtx.currentTime);
compressor.knee.setValueAtTime(40, audioCtx.currentTime);
compressor.ratio.setValueAtTime(12, audioCtx.currentTime);
compressor.attack.setValueAtTime(0, audioCtx.currentTime);
compressor.release.setValueAtTime(0.25, audioCtx.currentTime);
compressor.connect(audioCtx.destination)

async function playNote(mutationsList, gain = 1) {  
  audioCtx.resume()
  
  const oscillator = audioCtx.createOscillator()
  oscillator.type = "triangle"
  const biquadFilter = audioCtx.createBiquadFilter();
  biquadFilter.type = "lowpass";
  const gainNode = audioCtx.createGain();
  const panNode = audioCtx.createStereoPanner();  
  
  // Setup audio chain 
  oscillator.connect(biquadFilter);
  biquadFilter.connect(gainNode);
  gainNode.connect(panNode);
  panNode.connect(compressor)
  
  let freq = quantize(scale, 440 * (Math.random() * 3))
  
  oscillator.frequency.setValueAtTime(
    quantize(scale, freq),
    audioCtx.currentTime,
  )
  
  // Low pass gate 
  biquadFilter.frequency.setValueAtTime(
    quantize(scale, freq * 4), 
    audioCtx.currentTime
  );
  
  biquadFilter.frequency.setTargetAtTime(
    freq, 
    audioCtx.currentTime,
    0.09,
  );  
  
  // accend the low pass gate with normal attenuatiob
  gainNode.gain.setValueAtTime(
    gain, 
    audioCtx.currentTime
  );    
  
  gainNode.gain.setTargetAtTime(
    0, 
    audioCtx.currentTime,
    0.1,
  );  

  // random stereo pan
  panNode.pan.setValueAtTime(
    Math.random() * 2 - 1, 
    audioCtx.currentTime
  );
  
  oscillator.start()
  oscillator.stop(audioCtx.currentTime + 1)
}

async function delayNote(f, time, decay, gain = 1){  
  if (gain <= 0) {
    return // stop repeats when they become inaudible
  }
  
  f(gain)
  
  setTimeout( _ => delayNote(f, time, decay, gain - decay), time);
}

observer.observe(document, {
  attributes: true,
  childList: true,
  subtree: true,
  characterData: true,
})  

Deploy this on production but use an Arnold Schwarzenegger sound bank which plays a random line at each DOM mutation.

Wow this is probably the best gist I've ever seen

dodds-cc commented on Feb 19

love this

Added quantization and randomness + delay for a cuter effect innocent

https://gist.github.com/MarkArts/3d4217f957df8a30802a8cbf962fa204

// origin: https://gist.github.com/tomhicks/6cb5e827723c4eaef638bf9f7686d2d8 ,  tomhicks/plink-plonk.js

/*
Copy this into the console of any web page that is interactive and doesn't
do hard reloads. You will hear your DOM changes as different pitches of
audio.
I have found this interesting for debugging, but also fun to hear web pages
render like UIs do in movies.
*/

// dorian (-)   C     E      F     G-     A     B-   
let scale = [
  264, 330, 352, 391.1, 440, 488.9 
]
scale = scale.concat(scale.map(x=>x*2))

console.log(scale)

function quantize(scale, freq) {
  return scale.reduce(function(prev, curr){
    return (Math.abs(curr - freq) < Math.abs(prev - freq) ? curr : prev);
  });
}

const audioCtx = new (window.AudioContext || window.webkitAudioContext)()
const observer = new MutationObserver(observe)

function observe(mutationsList) {
  // with delay
  delayNote(gain => playNote(mutationsList, gain), 300, 0.2)  
  // without
  // playNote(mutationsList)
}


// Compressor as final stage to prevent clipping
const compressor = audioCtx.createDynamicsCompressor()
compressor.threshold.setValueAtTime(-40, audioCtx.currentTime);
compressor.knee.setValueAtTime(40, audioCtx.currentTime);
compressor.ratio.setValueAtTime(12, audioCtx.currentTime);
compressor.attack.setValueAtTime(0, audioCtx.currentTime);
compressor.release.setValueAtTime(0.25, audioCtx.currentTime);
compressor.connect(audioCtx.destination)

async function playNote(mutationsList, gain = 1) {  
  audioCtx.resume()
  
  const oscillator = audioCtx.createOscillator()
  oscillator.type = "triangle"
  const biquadFilter = audioCtx.createBiquadFilter();
  biquadFilter.type = "lowpass";
  const gainNode = audioCtx.createGain();
  const panNode = audioCtx.createStereoPanner();  
  
  // Setup audio chain 
  oscillator.connect(biquadFilter);
  biquadFilter.connect(gainNode);
  gainNode.connect(panNode);
  panNode.connect(compressor)
  
  let freq = quantize(scale, 440 * (Math.random() * 3))
  
  oscillator.frequency.setValueAtTime(
    quantize(scale, freq),
    audioCtx.currentTime,
  )
  
  // Low pass gate 
  biquadFilter.frequency.setValueAtTime(
    quantize(scale, freq * 4), 
    audioCtx.currentTime
  );
  
  biquadFilter.frequency.setTargetAtTime(
    freq, 
    audioCtx.currentTime,
    0.09,
  );  
  
  // accend the low pass gate with normal attenuatiob
  gainNode.gain.setValueAtTime(
    gain, 
    audioCtx.currentTime
  );    
  
  gainNode.gain.setTargetAtTime(
    0, 
    audioCtx.currentTime,
    0.1,
  );  

  // random stereo pan
  panNode.pan.setValueAtTime(
    Math.random() * 2 - 1, 
    audioCtx.currentTime
  );
  
  oscillator.start()
  oscillator.stop(audioCtx.currentTime + 1)
}

async function delayNote(f, time, decay, gain = 1){  
  if (gain <= 0) {
    return // stop repeats when they become inaudible
  }
  
  f(gain)
  
  setTimeout( _ => delayNote(f, time, decay, gain - decay), time);
}

observer.observe(document, {
  attributes: true,
  childList: true,
  subtree: true,
  characterData: true,
})  

This one's great~ innocent

everaldo commented on Feb 20

Awesome idea!

It would be nice to create some debugging library with sounds for Ajax Requests, Ajax failures, console errors etc.

R4meau commented on Feb 20

edited

@everaldo I'm working on it at the moment: https://github.com/r4meau/plink-plonk

Also, great idea about the console errors. Added this to the list of features in the README :). For the requests, it's already in the list.

everaldo commented on Feb 20

@R4meau, that's awesome!

Maybe someone makes some chrome extension?

And the bookmarklet version:

javascript:(function(){const%20audioCtx=new(window.AudioContext||window.webkitAudioContext);const%20oscillator=audioCtx.createOscillator();oscillator.connect(audioCtx.destination);oscillator.type="sine";let%20numItems=0;oscillator.frequency.setValueAtTime(1,audioCtx.currentTime);oscillator.start();const%20observer=new%20MutationObserver(function(mutationsList){numItems+=mutationsList.length;oscillator.frequency.setValueAtTime(Math.log(numItems+1)*440,audioCtx.currentTime);setTimeout(()=>{numItems-=mutationsList.length;if(numItems===0){oscillator.frequency.setValueAtTime(1,audioCtx.currentTime)}else{oscillator.frequency.setValueAtTime(Math.log(numItems+1)*440,audioCtx.currentTime)}},100)});observer.observe(document,{attributes:true,childList:true,subtree:true,characterData:true})})();

aibolik commented on Feb 21

Maybe someone makes some chrome extension?

Yeah, let's do it... (adding to backlog) sweat_smile

R4meau commented on Feb 21

edited

@aibolik Already in the making: https://github.com/r4meau/plink-plonk

Feel free to fork and contribute... or start your own. smile

I'm gonna go slow on it for now (Sunday only), but I'll accept useful PRs at anytime.

mahnouel commented on Feb 28

edited

Could anyone add reload support? This is so wonderful smiling_face_with_three_hearts Maybe via localStorage? Or as Firefox Extension?

iamnmanoj commented on Mar 4

Its so helpful to find out the DOM manipulations happening behind the eyes!!. Good job @R4meau

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK