waterfall.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. var Waterfall = (function(options){
  2. var id = options.id || 'waterfall';
  3. var width = options.width || 1024;
  4. var height = options.height || 400;
  5. var background = "rgba(0, 0, 0, 1)";
  6. var audioStream = options.stream;
  7. var audioContext = options.context;
  8. var gainNode = audioContext.createGain ? audioContext.createGain() : audioContext.createGainNode();
  9. gainNode.gain.value = 0.1;
  10. var osci = audioContext.createOscillator();
  11. osci.type = "sine";
  12. gainNode.connect(audioContext.destination);
  13. osci.start ? osci.start(0) : osci.noteOn(0);
  14. var timeout = null;
  15. var target = document.getElementById(id);
  16. var canvas = document.createElement('canvas');
  17. var info = document.createElement('div');
  18. target.appendChild(info);
  19. canvas.width = width;
  20. canvas.height = height;
  21. target.appendChild(canvas);
  22. var canvasContext = canvas.getContext('2d');
  23. canvasContext.fillStyle = background;
  24. canvasContext.fillRect(0, 0, width, height);
  25. var analyser = audioContext.createAnalyser();
  26. audioStream.connect(analyser);
  27. var moveBy = 1;
  28. var heatmap = ["05000b", "05000b", "0a000a", "0a000a", "0e000f", "0e000f", "130014", "130014", "190018", "190018", "1e001e", "1e001e", "230022", "230022", "290029", "290029", "2e002e", "2e002e", "320033", "320033", "370037", "370037", "3d003d", "3d003d", "450046", "450046", "4e014e", "4e014e", "560157", "560157", "5f005e", "5f005e", "670167", "670167", "6f0070", "6f0070", "780179", "780179", "81017b", "81017b", "870278", "870278", "8d0272", "8d0272", "94036c", "94036c", "9a0467", "9a0467", "a00560", "a00560", "a8065a", "a8065a", "ad0753", "ad0753", "b4084d", "b4084d", "bb0a47", "bb0a47", "c10a40", "c10a40", "c60b38", "c60b38", "cc0c33", "cc0c33", "d30e2c", "d30e2c", "d90d26", "d90d26", "df0f1f", "df0f1f", "e61019", "e61019", "ec1213", "ec1213", "f3120d", "f3120d", "f91306", "f91306", "fc1601", "fc1601", "fe2000", "fe2000", "ff2a01", "ff2a01", "ff3501", "ff3501", "ff3f00", "ff3f00", "ff4b01", "ff4b01", "ff5500", "ff5500", "ff5f01", "ff5f01", "ff6901", "ff6901", "ff7300", "ff7300", "ff7f00", "ff7f00", "ff8901", "ff8901", "ff9400", "ff9400", "ff9f01", "ff9f01", "ffa900", "ffa900", "ffb401", "ffb401", "ffbd02", "ffbd02", "ffc303", "ffc303", "ffc704", "ffc704", "ffcb06", "ffcb06", "ffd009", "ffd009", "ffd30a", "ffd30a", "ffd70d", "ffd70d", "ffdb0d", "ffdb0d", "ffdf10", "ffdf10", "fee310", "fee310", "ffe713", "ffe713", "ffec15", "ffec15", "ffef17", "ffef17", "fff319", "fff319", "fff61b", "fff61b", "fffb1d", "fffb1d", "feff20", "feff20", "f9fb1f", "f9fb1f", "f3f71f", "f3f71f", "eff41f", "eff41f", "eaf01f", "eaf01f", "e5ed20", "e5ed20", "dee920", "dee920", "dae720", "dae720", "d5e320", "d5e320", "cfdf20", "cfdf20", "cbdc21", "cbdc21", "c5d720", "c5d720", "c1d521", "c1d521", "bad020", "bad020", "b5cd21", "b5cd21", "afc920", "afc920", "abc621", "abc621", "a6c220", "a6c220", "a1c021", "a1c021", "9bbc20", "9bbc20", "96b823", "96b823", "93b82a", "93b82a", "91b932", "91b932", "8ebb3c", "8ebb3c", "8bbb43", "8bbb43", "8abc4c", "8abc4c", "88bd54", "88bd54", "85bd5c", "85bd5c", "83be64", "83be64", "80bf6e", "80bf6e", "7dbf75", "7dbf75", "7bc07e", "7bc07e", "7ac187", "7ac187", "78c290", "78c290", "75c298", "75c298", "72c4a1", "72c4a1", "70c5aa", "70c5aa", "6ec4b2", "6ec4b2", "6cc5ba", "6cc5ba", "6ac7c3", "6ac7c3", "6ac6c6", "6ac6c6", "72cbcd", "72cbcd", "7aced1", "7aced1", "83d1d5", "83d1d5", "8ed5d7", "8ed5d7", "97d8da", "97d8da", "a0dcdd", "a0dcdd", "a9dfe1", "a9dfe1", "b3e3e5", "b3e3e5", "bee7e9", "bee7e9", "c6e9eb", "c6e9eb", "d0eef0", "d0eef0", "d9f1f3", "d9f1f3", "e3f5f7", "e3f5f7", "edf9fa", "edf9fa", "f6fcfd", "f6fcfd", "fdffff", "fdffff"];
  29. var pxToFreq = function(px){
  30. return (px / width) * 22000;
  31. };
  32. var addEventListeners = function(elem, events, f){
  33. if(typeof events == 'string'){events = events.split(' ');}
  34. for(var i=0; i<events.length; i++){elem.addEventListener(events[i], f)};
  35. };
  36. addEventListeners(canvas, "mousemove touchmove", function(e){
  37. e.preventDefault();
  38. info.innerText = pxToFreq(e.touches ? e.touches[0].pageX : e.offsetX);
  39. }, false);
  40. addEventListeners(canvas, "mousedown touchstart", function(e){
  41. e.preventDefault();
  42. var x = pxToFreq(e.touches ? e.touches[0].pageX : e.offsetX);
  43. info.innerText = x;
  44. play(x);
  45. }, false);
  46. addEventListeners(canvas, "mouseup touchend", function(e){
  47. e.preventDefault();
  48. stop();
  49. }, false);
  50. var draw = function() {
  51. window.requestAnimationFrame(draw);
  52. frequencies = new Uint8Array(analyser.frequencyBinCount);
  53. analyser.getByteFrequencyData(frequencies);
  54. canvasContext.drawImage(canvasContext.canvas, 0, 0, width, height - moveBy, 0, moveBy, width, height - moveBy);
  55. var centroidIndex = 0;
  56. var valueSum = 0;
  57. for(var i = 0; i < frequencies.length; i++) {
  58. var mag = frequencies[i];
  59. //mag = Math.floor(Math.pow(mag/255, 0.5)*255);
  60. centroidIndex += mag * i;
  61. valueSum += mag;
  62. canvasContext.fillStyle = '#'+heatmap[mag]; //"rgba(0,"+mag+",0,1)";
  63. canvasContext.fillRect(i, 0, 1, moveBy);
  64. }
  65. centroidIndex /= valueSum;
  66. canvasContext.fillStyle = 'white';
  67. canvasContext.fillRect(centroidIndex, 0, 2, 2*moveBy);
  68. };
  69. var sequence = function(seq){
  70. if(seq.length==0){
  71. stop();
  72. }else{
  73. var fd = seq.shift();
  74. if(fd[0]==0) stop();
  75. else play(fd[0]);
  76. timout = setTimeout(function(){sequence(seq)}, fd[1]);
  77. }
  78. };
  79. var play = function(freq){
  80. //osci.disconnect();
  81. osci.frequency.value = freq;
  82. osci.connect(gainNode);
  83. };
  84. var stop = function(){
  85. if(timeout) clearTimeout(timeout);
  86. osci.disconnect();
  87. };
  88. draw();
  89. return {
  90. play: play,
  91. stop: stop,
  92. sequence: sequence,
  93. pxToFreq: pxToFreq,
  94. };
  95. });