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);
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 */
});
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 >= 32 && control < 40) { /* "S" buttons */
+ 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) {
var checked = $(nanotouch).find('.loop input').prop('checked');
$(nanotouch).find('.loop input').prop('checked', true);
device("nanoKONTROL2 MIDI 1").cc(control, 127);
}
+ $(nanotouch).find('.loop input').trigger('change');
}
}
+ if (control >= 48 && control < 55) { /* "M" buttons -> effects */
+ var nanotouch = $('.nanotouch')[control-48];
+ if (value == 127) {
+ var checked = $(nanotouch).find('.effects input').prop('checked');
+ if (checked) {
+ $(nanotouch).find('.effects input').prop('checked', false);
+ device("nanoKONTROL2 MIDI 1").cc(control, 0);
+ } else {
+ $(nanotouch).find('.effects input').prop('checked', true);
+ device("nanoKONTROL2 MIDI 1").cc(control, 127);
+ }
+ $(nanotouch).find('.effects input').trigger('change');
+ }
+
+ }
+ 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 {
$('[data-touch=' + control + '] .touch-gain').val(value).trigger('change');
}
+ $('.loop input').on('change', function() {
+ var sample_idx = parseInt($(this).parents('[data-touch]').data('touch'));
+ if (self.samples[sample_idx]) {
+ self.samples[sample_idx].loop = $(this).is(':checked');
+ }
+ });
+
$(document).keypress(function(ev) {
var sample_idx = KEYBOARD_CODES.indexOf(ev.key);
if (sample_idx != -1) {
- self.startSample(sample_idx);
+ self.toggleSample(sample_idx);
}
});
$('#master-gain').on('change', function() {
var fraction = parseInt(this.value) / parseInt(127);
- self.masterGainNode.gain.value = fraction * fraction;
+ var now = self.audioCtx.currentTime;
+ self.masterGainNode.gain.exponentialRampToValueAtTime((fraction * fraction) || 0.0001, now + 0.015);
});
$('#delay').on('change', function() {
if (value == 0) {
self.delay.disconnect();
} else {
- self.delay.delayTime.value = value;
+ var now = self.audioCtx.currentTime;
+ self.delay.delayTime.exponentialRampToValueAtTime(value || 0.0001, now + 0.015);
self.delay.connect(self.audioCtx.destination);
}
});
$('#feedback').on('change', function() {
- self.feedback.gain.value = this.value;
+ var now = self.audioCtx.currentTime;
+ self.feedback.gain.exponentialRampToValueAtTime(this.value || 0.0001, now + 0.015);
});
$('#filter').on('change', function() {
$('.touch-gain').on('change', function() {
var fraction = parseInt(this.value) / parseInt(127);
var touchIdx = parseInt($(this).parent().data('touch'));
- self.touchGainNodes[touchIdx].gain.value = fraction * fraction;
+ var now = self.audioCtx.currentTime;
+ 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() {
}, 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);
}
}
}