Commits

Eric Fredricksen committed 70d1a82

Add delay effect, simplify controls

Comments (0)

Files changed (1)

 <h3>
   Formula
 </h3>
-  <input id=formula size=100 type=text 
-   value="((t<<1)^((t<<1)+(t>>7)&t>>12))|t>>(4-(1^7&(t>>19)))|t>>7" 
+  <input id=formula size=80 type=text 
+   value="((t<<1)^((t<<1)+(t>>7)&t>>12))|t>>(4-(1^7&(t>>19)))|t>>7"
    onKeyUp="reformulate(this.value)">
 <br>
+  <button onclick='t = 0'> &lt;&lt; </button>
+  <button id=paws onclick='node.togglePlay()'> || </button>
+    &nbsp;    &nbsp;    &nbsp;    &nbsp;
   <button onclick='bits(-1)'> - </button>
   <span id=bits>10</span> bits
   <button onclick='bits(+1)'> + </button>
     &nbsp;    &nbsp;    &nbsp;    &nbsp;
-  <button onclick='node.pause()'> &#x25fb; </button>
-  <button onclick='node.play()'> &#x25b7; </button>
+  
 <p>
 <hr>
 <h3>About</h3>
 <li> The sample rate is fixed at 44100 Hz; compositions for 8 kHz
   audio will sound quite different here.
 
-<li> The playback is stereo with the right channel on a slight delay
-  to add some space.
+<li> To sweeten the sound, heavy delay, stereo separation, and low
+pass filter are added.
 
 <li> The default composition is "Crowd" by Kragen Javier Sitaker.
 </ul>
 
-<script src=live.js></script>
 <script>
 
 var context = new webkitAudioContext();
-var CHANNELS = 2;
 var node = context.createJavaScriptNode(4096, 0, CHANNELS);
 
-var generator = function (t) {
-  return ((t<<1)^((t<<1)+(t>>7)&t>>12))|t>>(4-(1^7&(t>>19)))|t>>7;
-}
+var CHANNELS = 2;
+var SEPARATION = Math.round(context.sampleRate * 0.015);
+var BITS = 10;
+var GAIN = 0.25; // amplitude of the generated waveform
+
+var generator = function (t) { return t; }
+
+function rightGen(t) { return generator(t + SEPARATION); };
 
 function reformulate(v) {
   try {
   }
 }
 
-var x = 0;
-node.sample_rate = context.sampleRate;
-node.gain = 0.25;
-var DELAY = Math.round(node.sample_rate * 0.015);
-var BITS = 10;
-node.rightfn = function (t) { return generator(t+DELAY); };
+var t = 0;
+
+
 node.onaudioprocess = function (e) {
   var mask = (1 << BITS) - 1;
   var div = 1 << (BITS - 1);
   if (CHANNELS > 1)
     var right = e.outputBuffer.getChannelData(1);
   for (var i = 0; i < left.length; ++i) {
-    t = x++;
-    left[i] = this.gain * ((mask & generator(t)) / div - 1);
+    left[i] = GAIN * ((mask & generator(t)) / div - 1);
     if (CHANNELS > 1)
-      right[i] = this.gain * ((mask & this.rightfn(t)) / div - 1); 
+      right[i] = GAIN * ((mask & rightGen(t)) / div - 1); 
+    ++t;
   }
+  console.log(BITS, mask, div);
 }
-  
+
 var filter = context.createBiquadFilter();
 if (filter) {
   filter.type = filter.LOWPASS;
   filter.Q.value = 0.75;
 }
 
-var reverb// = context.createConvolver();
-if (reverb) {
-  /*
-  reverb.buffer = context.createBuffer(CHANNELS, 2 * context.sampleRate, 
-                                       context.sampleRate);
-  for (var c = 0; c < reverb.buffer.numberOfChannels; ++c) {
-    var d = reverb.buffer.getChannelData(c);
-    for (var i = 0; i < reverb.buffer.length; ++i)
-      //d[i] = (Math.random() * 2 - 1) * Math.pow(1 - i / reverb.buffer.length, 2);
-      d[i] = (Math.sin(i / 10) * 2 - 1) * Math.pow(1 - i / reverb.buffer.length, 2);
-  }
-  */
-  loadWav('feedback-spring.wav', function (buffer) { reverb.buffer = buffer; });
-}
+var compressor = context.createDynamicsCompressor();
+if (!compressor) compressor = context.createGainNode();  // shunt
+
 
 var delay = context.createDelayNode();
 if (delay) {
   delay.delayTime.value = .4;
 }
 
-var compressor = context.createDynamicsCompressor();
-if (compressor) compressor = context.createGainNode();  // shunt
 
-node.playing = false;
+var wet = context.createGainNode();
+wet.gain.value = 0.6;
 
-var source = context.createGainNode();
-var endpoint = source;
+var feedback = context.createGainNode();
+feedback.gain.value = 0.5;
 
-if (filter) {
-  endpoint.connect(filter);
-  endpoint = filter;
-}
 
-if (reverb) {
-  source.connect(reverb);
-  
-  var g = context.createGainNode();
-  reverb.connect(g);
-  
-  g.connect(compressor||context.destination);
-  
-  /*
-    var s = context.createBufferSource();
-    s.buffer = reverb.buffer;
-    s.connect(context.destination);
-    s.noteOn(0);
-    */
-}
+node.connect(filter);
+filter.connect(compressor);  // dry
+filter.connect(delay);
+delay.connect(wet);
+wet.connect(compressor);
+wet.connect(feedback);
+feedback.connect(delay);
 
-if (delay) {
-  endpoint.connect(delay);
-  var g = context.createGainNode();
-  delay.connect(g);
-  g.gain.value = 0.6;
-  g.connect(compressor||context.destination);
-  g.connect(delay);
-}
 
-endpoint.connect(compressor);
-compressor.connect(context.destination);
-
-node.play = function () {
-  if (this.playing) return;
-  node.connect(source);
-  //compressor.connect(context.destination);
-  this.playing = true;
-}
+node.playing = false;
 
-node.pause = function () {
-  if (!this.playing) return;
-  node.disconnect();
-  //compressor.disconnect();
-  this.playing = false;
+node.togglePlay = function () {
+  this.playing = !this.playing;
+  document.getElementById('paws').innerText = this.playing ? '||' : '>';
+  if (this.playing) {
+    compressor.connect(context.destination);
+  } else {
+    compressor.disconnect();
+  }
 }
 
 function bits(inc) {
   document.getElementById('bits').innerText = BITS;
 }
 
-function loadWav(url, callback) {
-  var request = new XMLHttpRequest();
-  request.open("GET", url, true);
-  request.responseType = "arraybuffer";
-  request.onload = function() {
-    context.decodeAudioData(this.response, callback);
-  }
-  request.onerror = function() { console.log('XHR ERROR SOUND', this.sound); }
-  request.send();
-}
-
-
-bits(0);
-node.play();
+bits(+0);
+reformulate(document.getElementById('formula').value);
+node.togglePlay();
 
 </script>