home *** CD-ROM | disk | FTP | other *** search
- function NumarkTotalControl() {}
-
- NumarkTotalControl.init = function(id) { // called when the MIDI device is opened & set up
- NumarkTotalControl.id = id; // Store the ID of this device for later use
-
- NumarkTotalControl.directoryMode = false;
-
- NumarkTotalControl.scratchMode = [false, false];
- NumarkTotalControl.scratchTimer = [-1, -1];
-
- NumarkTotalControl.simpleCue = false;
-
- NumarkTotalControl.extendedLooping = false;
- NumarkTotalControl.oldLoopStart = [-1, -1];
- NumarkTotalControl.extendedLoopingType = { "None": 0, "SetBegin": 1, "SetLength": 2 };
- NumarkTotalControl.extendedLoopingState = [NumarkTotalControl.extendedLoopingType.None, NumarkTotalControl.extendedLoopingType.None];
- NumarkTotalControl.extendedLoopingChanged = [false, false];
- NumarkTotalControl.extendedLoopingLEDState = [false, false];
- NumarkTotalControl.extendedLoopingLEDTimer = [-1, -1];
- NumarkTotalControl.extendedLoopingJogCarryOver = [0, 0];
-
- NumarkTotalControl.leds = [
- // Common
- { "directory": 0x56, "simpleCue": 0x33, "extendedLooping": 0x44 },
- // Deck 1
- { "rate": 0x34, "tap": 0x30, "scratchMode": 0x31, "loopIn": 0x3a, "loopOut": 0x3b, "loopHalve": 0x38, "loopDouble": 0x39 },
- // Deck 2
- { "rate": 0x43, "tap": 0x47, "scratchMode": 0x45, "loopIn": 0x4a, "loopOut": 0x4b, "loopHalve": 0x48, "loopDouble": 0x49 }
- ];
-
- NumarkTotalControl.setLED(NumarkTotalControl.leds[1]["rate"], true); // Turn on 0 rate lights
- NumarkTotalControl.setLED(NumarkTotalControl.leds[2]["rate"], true); // Turn on 0 rate lights
-
- engine.connectControl("[Channel1]", "loop_enabled", "NumarkTotalControl.loopLEDs");
- engine.connectControl("[Channel2]", "loop_enabled", "NumarkTotalControl.loopLEDs");
- }
-
- NumarkTotalControl.shutdown = function(id) { // called when the MIDI device is closed
- engine.connectControl("[Channel1]", "loop_enabled", "NumarkTotalControl.loopLEDs", true);
- engine.connectControl("[Channel2]", "loop_enabled", "NumarkTotalControl.loopLEDs", true);
-
- var lowestLED = 0x30;
- var highestLED = 0x56;
- for (var i=lowestLED; i<=highestLED; i++) {
- NumarkTotalControl.setLED(i, false); // Turn off all the lights
- }
- }
-
- NumarkTotalControl.groupToDeck = function(group) {
- var matches = group.match(/^\[Channel(\d+)\]$/);
- if (matches == null) {
- return -1;
- } else {
- return matches[1];
- }
- }
-
- NumarkTotalControl.samplesPerBeat = function(group) {
- // FIXME: Get correct samplerate and channels for current deck
- var sampleRate = 44100;
- var channels = 2;
- var bpm = engine.getValue(group, "file_bpm");
- return channels * sampleRate * 60 / bpm;
- }
-
- NumarkTotalControl.setLED = function(value, status) {
- if (status) {
- status = 0x64;
- } else {
- status = 0x00;
- }
- midi.sendShortMsg(0x90, value, status);
- }
-
- NumarkTotalControl.selectKnob = function(channel, control, value, status, group) {
- if (value > 63) {
- value = value - 128;
- }
- if (NumarkTotalControl.directoryMode) {
- if (value > 0) {
- for (var i = 0; i < value; i++) {
- engine.setValue(group, "SelectNextPlaylist", 1);
- }
- } else {
- for (var i = 0; i < -value; i++) {
- engine.setValue(group, "SelectPrevPlaylist", 1);
- }
- }
- } else {
- engine.setValue(group, "SelectTrackKnob", value);
- }
- }
-
- NumarkTotalControl.loopIn = function(channel, control, value, status, group) {
- if (value) {
- if (engine.getValue(group, "loop_enabled")) {
- engine.setValue(group, "reloop_exit", 1);
- }
- engine.setValue(group, "loop_in", 1);
- engine.setValue(group, "loop_end_position", -1);
- }
- }
-
- NumarkTotalControl.loopOut = function(channel, control, value, status, group) {
- if (value) {
- var start = engine.getValue(group, "loop_start_position");
- var end = engine.getValue(group, "loop_end_position");
- if (start != -1) {
- if (end != -1) {
- // Loop In and Out set -> call Reloop/Exit
- engine.setValue(group, "reloop_exit", 1);
- } else {
- // Loop In set -> call Loop Out
- if (NumarkTotalControl.extendedLooping) {
- var deck = NumarkTotalControl.groupToDeck(group);
- if (NumarkTotalControl.oldLoopStart[deck-1] == -1) {
- // Get current position by temporary setting loop start
- NumarkTotalControl.oldLoopStart[deck-1] = start;
- engine.setValue(group, "loop_in", 1);
- engine.beginTimer(20, "NumarkTotalControl.loopExtendedAdjustment('" + group + "')", true);
- }
- } else {
- engine.setValue(group, "loop_out", 1);
- }
- }
- }
- }
- }
-
- // Adjust loop length
- NumarkTotalControl.loopExtendedAdjustment = function(group) {
- var deck = NumarkTotalControl.groupToDeck(group);
- // Check if temporary loop start is already set
- var start = engine.getValue(group, "loop_start_position");
- if (start == NumarkTotalControl.oldLoopStart[deck-1]) {
- // Still old loop start -> retry later
- engine.beginTimer(20, "NumarkTotalControl.loopExtendedAdjustment('" + group + "')", true);
- return;
- }
-
- // Restore loop start position
- var currentPosition = start;
- start = NumarkTotalControl.oldLoopStart[deck-1];
- engine.setValue(group, "loop_start_position", start);
- NumarkTotalControl.oldLoopStart[deck-1] = -1;
- var len = currentPosition - start;
-
- // Calculate nearest beat
- var beatSamples = NumarkTotalControl.samplesPerBeat(group);
- var lenInBeats = len / beatSamples;
- if (lenInBeats > 1) {
- print("Full: " + Math.ceil(lenInBeats));
- print("Mult2: " + (Math.ceil(lenInBeats / 2) * 2));
- print("Pot2: " + Math.pow(2, Math.ceil(Math.log(lenInBeats) / Math.log(2))));
-
- // Round to full beats
- //lenInBeats = Math.ceil(lenInBeats);
-
- // Round to 2*x beats
- //lenInBeats = Math.ceil(lenInBeats / 2) * 2;
-
- // Round to 2^x beats
- lenInBeats = Math.pow(2, Math.ceil(Math.log(lenInBeats) / Math.log(2)));
- } else {
- print("Full: 1 / " + Math.floor(1 / lenInBeats));
- print("Mult2: 1 / " + (Math.floor(1 / lenInBeats / 2) * 2));
- print("Pot2: 1 / " + Math.pow(2, Math.floor(Math.log(1 / lenInBeats) / Math.log(2))));
-
- // Round to beat fragments
- //lenInBeats = 1 / Math.floor(1 / lenInBeats);
-
- // Round to fragments of 2*x beats
- //lenInBeats = 1 / (Math.floor(1 / lenInBeats / 2) * 2);
-
- // Round to fragments of 2^x beats
- lenInBeats = 1 / Math.pow(2, Math.floor(Math.log(1 / lenInBeats) / Math.log(2)));
- }
- len = lenInBeats * beatSamples;
-
- // Set calculated loop end
- engine.setValue(group, "loop_end_position", start + len);
-
- // Start looping
- engine.setValue(group, "reloop_exit", 1);
- }
-
- // Activates alternative function
- // Called by timer after button was 1sec pressed or by jog wheel movement
- NumarkTotalControl.loopExtendedChange = function(group, timerCall) {
- var deck = NumarkTotalControl.groupToDeck(group);
- if (!NumarkTotalControl.extendedLoopingChanged[deck-1]) {
- if (!timerCall) {
- // Stop extended loop change timer
- engine.stopTimer(NumarkTotalControl.extendedLoopingLEDTimer[deck-1]);
- }
- NumarkTotalControl.extendedLoopingChanged[deck-1] = true;
- // Get current LED status
- NumarkTotalControl.extendedLoopingLEDState[deck-1] = engine.getValue(group, "loop_enabled");
- // Start LED blink timer
- NumarkTotalControl.loopLEDBlink(deck);
- NumarkTotalControl.extendedLoopingLEDTimer[deck-1] = engine.beginTimer(333, "NumarkTotalControl.loopLEDBlink(" + deck + ")");
- }
- }
-
- // Set LEDs to current loop status
- NumarkTotalControl.loopLEDs = function(value, group, key) {
- var status = false;
- var deck = NumarkTotalControl.groupToDeck(group);
- if (value) {
- status = true;
- }
- NumarkTotalControl.setLED(NumarkTotalControl.leds[deck]["loopOut"], status);
-
- if (!NumarkTotalControl.extendedLooping) {
- status = false;
- }
- NumarkTotalControl.setLED(NumarkTotalControl.leds[deck]["loopHalve"], status);
- NumarkTotalControl.setLED(NumarkTotalControl.leds[deck]["loopDouble"], status);
- }
-
- // Let LED blink on alternative function
- NumarkTotalControl.loopLEDBlink = function(deck) {
- var led;
- switch (NumarkTotalControl.extendedLoopingState[deck-1]) {
- case NumarkTotalControl.extendedLoopingType.SetBegin:
- led = NumarkTotalControl.leds[deck]["loopHalve"];
- break;
- case NumarkTotalControl.extendedLoopingType.SetLength:
- led = NumarkTotalControl.leds[deck]["loopDouble"];
- break;
- default:
- return;
- }
- if (NumarkTotalControl.extendedLoopingLEDState[deck-1]) {
- NumarkTotalControl.extendedLoopingLEDState[deck-1] = false;
- } else {
- NumarkTotalControl.extendedLoopingLEDState[deck-1] = true;
- }
- NumarkTotalControl.setLED(led, NumarkTotalControl.extendedLoopingLEDState[deck-1]);
- }
-
- NumarkTotalControl.extendedFunctionButton = function(normalFunction, extendedLoopingFactor, extendedLoopingType, group, value) {
- var deck = NumarkTotalControl.groupToDeck(group);
- if (NumarkTotalControl.extendedLooping) {
- var start = engine.getValue(group, "loop_start_position");
- var end = engine.getValue(group, "loop_end_position");
- if (value) {
- if ((start != -1) && (end != -1) && (NumarkTotalControl.extendedLoopingState[deck-1] == NumarkTotalControl.extendedLoopingType.None)) {
- NumarkTotalControl.extendedLoopingState[deck-1] = extendedLoopingType;
- NumarkTotalControl.extendedLoopingChanged[deck-1] = false;
- NumarkTotalControl.extendedLoopingJogCarryOver[deck-1] = 0;
- // Start alternative function timer -> activated after button was 1sec pressed or jog wheel movement (see jogWheel function)
- NumarkTotalControl.extendedLoopingLEDTimer[deck-1] = engine.beginTimer(1000, "NumarkTotalControl.loopExtendedChange('" + group + "', true)", true);
- }
- } else {
- // Check if alternative function wasn't used
- if (!NumarkTotalControl.extendedLoopingChanged[deck-1] && (start != -1) && (end != -1)) {
- // Call default function
- engine.setValue(group, "loop_end_position", start + (end - start) * extendedLoopingFactor);
- }
- // Stop LED blink or extended loop change timer
- engine.stopTimer(NumarkTotalControl.extendedLoopingLEDTimer[deck-1]);
- NumarkTotalControl.extendedLoopingLEDTimer[deck-1] = -1;
- // Reset LEDs
- NumarkTotalControl.loopLEDs(engine.getValue(group, "loop_enabled"), group, "loop_enabled");
- // Reset alternative function variables
- NumarkTotalControl.extendedLoopingState[deck-1] = NumarkTotalControl.extendedLoopingType.None;
- NumarkTotalControl.extendedLoopingChanged[deck-1] = false;
- NumarkTotalControl.extendedLoopingJogCarryOver[deck-1] = 0;
- }
- } else {
- if (value) {
- engine.setValue(group, normalFunction, 1);
- } else {
- engine.setValue(group, normalFunction, 0);
- }
- }
- }
-
- NumarkTotalControl.leftFunction = function(channel, control, value, status, group) {
- NumarkTotalControl.extendedFunctionButton("rate_temp_down", 0.5, NumarkTotalControl.extendedLoopingType.SetBegin, group, value);
- }
-
- NumarkTotalControl.rightFunction = function(channel, control, value, status, group) {
- NumarkTotalControl.extendedFunctionButton("rate_temp_up", 2, NumarkTotalControl.extendedLoopingType.SetLength, group, value);
- }
-
- NumarkTotalControl.finePitch = function(channel, control, value, status, group) {
- if (value > 63) {
- value = value - 128;
- }
- engine.setValue(group, "rate", engine.getValue(group, "rate") + value / 512);
- }
-
- // Fixes cue_set glitches
- NumarkTotalControl.setCue = function(channel, control, value, status, group) {
- if (value) {
- engine.setValue(group, "cue_set", 1);
- }
- }
-
- // If playing, stutters from cuepoint; otherwise jumps to cuepoint and stops
- NumarkTotalControl.playFromCue = function(channel, control, value, status, group) {
- if (NumarkTotalControl.simpleCue) {
- if (value) {
- if (engine.getValue(group, "play")) {
- engine.setValue(group, "cue_goto", 1);
- } else {
- engine.setValue(group, "cue_gotoandstop", 1);
- }
- }
- } else {
- if (value) {
- if (engine.getValue(group, "play")) {
- engine.setValue(group, "play", 0);
- engine.setValue(group, "cue_gotoandstop", 1);
- } else {
- engine.setValue(group, "cue_preview", 1);
- }
- } else {
- engine.setValue(group, "cue_preview", 0);
- }
- }
- }
-
- // Jog values: (counter) fast slow still slow fast (clockwise)
- // Jog values: 064 127 - 001 063
- NumarkTotalControl.jogWheel = function(channel, control, value, status, group) {
- var deck = NumarkTotalControl.groupToDeck(group);
- var adjustedJog = parseFloat(value);
- var posNeg = 1;
- if (adjustedJog > 63) { // Counter-clockwise
- posNeg = -1;
- adjustedJog = value - 128;
- }
-
- if (NumarkTotalControl.extendedLoopingState[deck-1] == NumarkTotalControl.extendedLoopingType.SetBegin) {
- var start = engine.getValue(group, "loop_start_position");
- var end = engine.getValue(group, "loop_end_position");
- if ((start != -1) && (end != -1)) {
- // Activate alternative function SetBegin
- NumarkTotalControl.loopExtendedChange(group, false);
- // Adjust jog speed
- // FIXME: Get correct sample rate and channels from deck
- var channels = 2;
- var sampleRate = 44100;
- adjustedJog = adjustedJog * channels * sampleRate / 600;
- // Move loop
- engine.setValue(group, "loop_start_position", start + adjustedJog);
- engine.setValue(group, "loop_end_position", end + adjustedJog);
- }
- } else if (NumarkTotalControl.extendedLoopingState[deck-1] == NumarkTotalControl.extendedLoopingType.SetLength) {
- var start = engine.getValue(group, "loop_start_position");
- var end = engine.getValue(group, "loop_end_position");
- if ((start != -1) && (end != -1)) {
- // Activate alternative function SetLength
- NumarkTotalControl.loopExtendedChange(group, false);
- // Adjust jog speed and add remaining value from last jog change
- adjustedJog = adjustedJog / 40 + NumarkTotalControl.extendedLoopingJogCarryOver[deck-1];
- var beats;
- // Round to full beats
- if (adjustedJog > 0) {
- beats = Math.floor(adjustedJog);
- } else {
- beats = Math.ceil(adjustedJog);
- }
- // Save remaining value for next jog change
- NumarkTotalControl.extendedLoopingJogCarryOver[deck-1] = adjustedJog - beats;
- // Set new loop end
- engine.setValue(group, "loop_end_position", end + beats * NumarkTotalControl.samplesPerBeat(group));
- }
- } else if (NumarkTotalControl.scratchMode[deck-1]) {
- if (NumarkTotalControl.scratchTimer[deck-1] == -1) {
- engine.scratchEnable(deck, 128, 33+1/3, 1.0/8, (1.0/8)/32);
- } else {
- engine.stopTimer(NumarkTotalControl.scratchTimer[deck-1]);
- }
- engine.scratchTick(deck, adjustedJog);
- NumarkTotalControl.scratchTimer[deck-1] = engine.beginTimer(20, "NumarkTotalControl.jogWheelStopScratch(" + deck + ")", true);
- } else {
- var gammaInputRange = 64; // Max jog speed
- var maxOutFraction = 0.5; // Where on the curve it should peak; 0.5 is half-way
- var sensitivity = 0.5; // Adjustment gamma
- var gammaOutputRange = 3; // Max rate change
- if (engine.getValue(group,"play")) {
- adjustedJog = posNeg * gammaOutputRange * Math.pow(Math.abs(adjustedJog) / (gammaInputRange * maxOutFraction), sensitivity);
- } else {
- adjustedJog = gammaOutputRange * adjustedJog / (gammaInputRange * maxOutFraction);
- }
- engine.setValue(group, "jog", adjustedJog);
- }
- }
-
- NumarkTotalControl.jogWheelStopScratch = function(deck) {
- NumarkTotalControl.scratchTimer[deck-1] = -1;
- engine.scratchDisable(deck);
- }
-
- NumarkTotalControl.tap = function(channel, control, value, status, group) {
- var deck = NumarkTotalControl.groupToDeck(group);
- if (value) {
- NumarkTotalControl.setLED(NumarkTotalControl.leds[deck]["tap"], true);
- bpm.tapButton(deck);
- } else {
- NumarkTotalControl.setLED(NumarkTotalControl.leds[deck]["tap"], false);
- }
- }
-
- NumarkTotalControl.toggleDirectoryMode = function(channel, control, value, status, group) {
- // Toggle setting and light
- if (value) {
- if (NumarkTotalControl.directoryMode) {
- NumarkTotalControl.directoryMode = false;
- } else {
- NumarkTotalControl.directoryMode = true;
- }
- NumarkTotalControl.setLED(NumarkTotalControl.leds[0]["directory"], NumarkTotalControl.directoryMode);
- }
- }
-
- NumarkTotalControl.toggleScratchMode = function(channel, control, value, status, group) {
- var deck = NumarkTotalControl.groupToDeck(group);
- // Toggle setting and light
- if (value) {
- if (NumarkTotalControl.scratchMode[deck-1]) {
- NumarkTotalControl.scratchMode[deck-1] = false;
- } else {
- NumarkTotalControl.scratchMode[deck-1] = true;
- }
- NumarkTotalControl.setLED(NumarkTotalControl.leds[deck]["scratchMode"], NumarkTotalControl.scratchMode[deck-1]);
- }
- }
-
- NumarkTotalControl.toggleSimpleCue = function(channel, control, value, status, group) {
- // Toggle setting and light
- if (value) {
- if (NumarkTotalControl.simpleCue) {
- NumarkTotalControl.simpleCue = false;
- } else {
- NumarkTotalControl.simpleCue = true;
- }
- NumarkTotalControl.setLED(NumarkTotalControl.leds[0]["simpleCue"], NumarkTotalControl.simpleCue);
- }
- }
-
- NumarkTotalControl.toggleExtendedLooping = function(channel, control, value, status, group) {
- // Toggle setting and light
- if (value) {
- if (NumarkTotalControl.extendedLooping) {
- NumarkTotalControl.extendedLooping = false;
- } else {
- NumarkTotalControl.extendedLooping = true;
- }
- NumarkTotalControl.setLED(NumarkTotalControl.leds[0]["extendedLooping"], NumarkTotalControl.extendedLooping);
- NumarkTotalControl.loopLEDs(engine.getValue("[Channel1]", "loop_enabled"), "[Channel1]", "loop_enabled");
- NumarkTotalControl.loopLEDs(engine.getValue("[Channel2]", "loop_enabled"), "[Channel2]", "loop_enabled");
- }
- }
-