]> git.0d.be Git - nanofun.git/blobdiff - nanofun.js
display keyboard shortcut
[nanofun.git] / nanofun.js
index 13813a124f7b979bedd07e4dac9d7eb19cd94f5b..5deb9c4eba92a4a24a1677b5314e6adeb8ba4ec4 100644 (file)
@@ -295,6 +295,8 @@ var nanofun = function() {
   var self = this;
 
   self.initAudio = function() {
+    self.focused_pad = undefined;
+    self.cycle_being_pressed = false;
     self.sample_buffers = Array(NANOPAD_TOUCHS.length);
     self.samples = Array(NANOPAD_TOUCHS.length);
     self.sample_start_times = Array(NANOPAD_TOUCHS.length);
@@ -340,6 +342,7 @@ var nanofun = function() {
     for (var i=0; i<NANOPAD_TOUCHS.length; i++) {
       var $new_touch = $nanotouch.clone();
       $new_touch.attr('data-touch', i);
+      $new_touch.find('.key').text(KEYBOARD_CODES[i]);
       $new_touch.appendTo($nanopad);
     }
     $nanotouch.remove(); /* remove template */
@@ -370,11 +373,17 @@ var nanofun = function() {
     });
 
     midi.onTouchOn = function(port, data, sample_idx) {
-      self.startSample(sample_idx);
+      self.toggleSample(sample_idx);
     }
 
     midi.onControlChange = function(port, data, control, value) {
       if (control > 7 && control < 16) return; /* range between sliders and pots */
+      if (control == 46) {
+        /* cycle -> alternate mode, make faders control effects when pressed
+         * (moving faders when cycle is pressed) */
+        self.cycle_being_pressed = (value != 0);
+        return;
+      }
       if (control >= 32 && control < 40) { /* "S" buttons -> loop */
           var nanotouch = $('.nanotouch')[control-32];
           if (value == 127) {
@@ -404,7 +413,45 @@ var nanofun = function() {
           }
 
       }
+      if ((control == 58 || control == 59) && value == 127) {
+        /* track < and > buttons: move focus between pads for special functions */
+        if (self.focused_pad === undefined) {
+          self.focused_pad = 0;
+        } else if (control == 58) {
+          self.focused_pad = self.focused_pad - 1;
+          if (self.focused_pad < 0) self.focused_pad = 15;
+        } else if (control == 59) {
+          self.focused_pad = self.focused_pad + 1;
+          if (self.focused_pad > 15) self.focused_pad = 0;
+        }
+        $('[data-touch]').removeClass('focus');
+        $('[data-touch=' + self.focused_pad + ']').addClass('focus');
+      }
+      if (control == 41 && value == 127 && self.focused_pad !== undefined) { /* play */
+        var nanotouch = $('.nanotouch')[self.focused_pad];
+        if ($(nanotouch).is('.playing')) {
+          self.samples[self.focused_pad].onended = function() {};  // disable callback
+          self.stopSample(self.focused_pad);
+        }
+        self.startSample(self.focused_pad);
+      }
+      if (control == 42 && value == 127 && self.focused_pad !== undefined) { /* stop */
+        self.stopSample(self.focused_pad);
+      }
       if (control > 23) return; /* after pots */
+      if (self.cycle_being_pressed) {
+        /* 4 -> delay, 5 -> feedback, 6 -> filter, 7 -> master */
+        if (control == 4) {
+          $('#delay').val(value / 127 * 5).trigger('change');
+        } else if (control == 5) {
+          $('#feedback').val(value / 127 * 1).trigger('change');
+        } else if (control == 6) {
+          $('#filter').val(value / 127 * 5000).trigger('change');
+        } else if (control == 7) {
+          $('#master-gain').val(value).trigger('change');
+        }
+        return;
+      }
       if (control < 8) {
         control += 8; /* sliders, control bottom pads (8-15) */
       } else {
@@ -423,7 +470,7 @@ var nanofun = function() {
     $(document).keypress(function(ev) {
       var sample_idx = KEYBOARD_CODES.indexOf(ev.key);
       if (sample_idx != -1) {
-        self.startSample(sample_idx);
+        self.toggleSample(sample_idx);
       }
     });
 
@@ -440,7 +487,7 @@ var nanofun = function() {
     $('#master-gain').on('change', function() {
       var fraction = parseInt(this.value) / parseInt(127);
       var now = self.audioCtx.currentTime;
-      self.masterGainNode.gain.exponentialRampToValueAtTime((fraction * fraction) || 0.01, now + 0.015);
+      self.masterGainNode.gain.exponentialRampToValueAtTime((fraction * fraction) || 0.0001, now + 0.015);
     });
 
     $('#delay').on('change', function() {
@@ -449,14 +496,14 @@ var nanofun = function() {
         self.delay.disconnect();
       } else {
         var now = self.audioCtx.currentTime;
-        self.delay.delayTime.exponentialRampToValueAtTime(value || 0.01, now + 0.015);
+        self.delay.delayTime.exponentialRampToValueAtTime(value || 0.0001, now + 0.015);
         self.delay.connect(self.audioCtx.destination);
       }
     });
 
     $('#feedback').on('change', function() {
       var now = self.audioCtx.currentTime;
-      self.feedback.gain.exponentialRampToValueAtTime(this.value || 0.01, now + 0.015);
+      self.feedback.gain.exponentialRampToValueAtTime(this.value || 0.0001, now + 0.015);
     });
 
     $('#filter').on('change', function() {
@@ -467,7 +514,11 @@ var nanofun = function() {
       var fraction = parseInt(this.value) / parseInt(127);
       var touchIdx = parseInt($(this).parent().data('touch'));
       var now = self.audioCtx.currentTime;
-      self.touchGainNodes[touchIdx].gain.exponentialRampToValueAtTime((fraction * fraction) || 0.01, now + 0.015);
+      if (fraction == 0) {
+        self.touchGainNodes[touchIdx].gain.value = 0;
+      } else {
+        self.touchGainNodes[touchIdx].gain.exponentialRampToValueAtTime((fraction * fraction) || 0.0001, now + 0.015);
+      }
     });
 
     self.time_interval_id = setInterval(function() {
@@ -485,29 +536,42 @@ var nanofun = function() {
     }, 250);
   }
 
+  self.toggleSample = function(sample_idx) {
+    var nanotouch = $('.nanotouch')[sample_idx];
+    if ($(nanotouch).is('.playing')) {
+      self.stopSample(sample_idx);
+    } else {
+      self.startSample(sample_idx);
+    }
+  }
+
   self.startSample = function(sample_idx) {
     var sample_buffer = self.sample_buffers[sample_idx];
     var nanotouch = $('.nanotouch')[sample_idx];
     if (typeof(sample_buffer) != 'undefined') {
-      if (typeof(samples[sample_idx]) != 'undefined' && samples[sample_idx].context.state == 'running') {
+      var sample = self.audioCtx.createBufferSource();
+      var gainNode = self.touchGainNodes[sample_idx];
+      self.samples[sample_idx] = sample;
+      sample.loop = ($(nanotouch).find('.loop input:checked').length == 1);
+      sample.connect(gainNode);
+      sample.buffer = sample_buffer;
+      sample.onended = function() {
+        $(nanotouch).removeClass('playing');
+        var duration = $(nanotouch).find('span.duration');
+        $(duration).text(parseInt($(duration).data('duration')) + 's');
+        self.samples[sample_idx] = undefined;
+      }
+      $(nanotouch).addClass('playing');
+      self.sample_start_times[sample_idx] = sample.context.currentTime;
+      sample.start(0);
+    }
+  }
+  self.stopSample = function(sample_idx) {
+    var sample_buffer = self.sample_buffers[sample_idx];
+    if (typeof(sample_buffer) != 'undefined') {
+      if (typeof(samples[sample_idx]) != 'undefined') {
         self.samples[sample_idx].stop(0);
         self.samples[sample_idx] = undefined;
-      } else {
-        var sample = self.audioCtx.createBufferSource();
-        var gainNode = self.touchGainNodes[sample_idx];
-        self.samples[sample_idx] = sample;
-        sample.loop = ($(nanotouch).find('.loop input:checked').length == 1);
-        sample.connect(gainNode);
-        sample.buffer = sample_buffer;
-        sample.onended = function() {
-          $(nanotouch).removeClass('playing');
-          var duration = $(nanotouch).find('span.duration');
-          $(duration).text(parseInt($(duration).data('duration')) + 's');
-          self.samples[sample_idx] = undefined;
-        }
-        $(nanotouch).addClass('playing');
-        self.sample_start_times[sample_idx] = sample.context.currentTime;
-        sample.start(0);
       }
     }
   }