-- set up values used by the handler functions local nrpnScale = 1.0/16383.0 local ccScale = 1.0/127.0 local paramID_Pitch = getParameterID( "Pitch" ) local paramID_DelaySliderMin = getParameterID( "Delay Slider Min" ) local paramID_DelaySliderMax = getParameterID( "Delay Slider Max" ) local paramID_DelayTime = getParameterID( "Delay Time" ) local paramID_Beats = getParameterID( "Beats" ) local paramID_BeatDivisor = getParameterID( "Beat Divisor" ) local paramID_FilterCutoff = getParameterID( "Filter Cutoff" ) local paramID_FilterLFOSpeed = getParameterID( "Filter LFO Speed" ) local paramID_PitchLFOSpeed = getParameterID( "Pitch LFO Speed" ) local ccMap = { [5] = getParameterID( "Master feedback" ), [14] = getParameterID( "Monoize Input" ), [15] = getParameterID( "Initial Pan" ), [18] = getParameterID( "Pitch" ), [19] = getParameterID( "PitchInertia" ), [20] = getParameterID( "Dry Level" ), [21] = getParameterID( "Effect Level" ), [22] = getParameterID( "Input Level" ), [23] = getParameterID( "L->L time" ), [24] = getParameterID( "L->R time" ), [25] = getParameterID( "R->L time" ), [26] = getParameterID( "R->R time" ), [27] = getParameterID( "Filter LFO Speed" ), [28] = getParameterID( "Filter LFO Depth" ), [29] = getParameterID( "Pitch LFO Depth" ), [31] = getParameterID( "Host Sync" ), [32] = getParameterID( "Triplet" ), [33] = getParameterID( "Beats" ), [34] = getParameterID( "Beat Divisor" ), [70] = getParameterID( "R->L feedback" ), [71] = getParameterID( "Filter Q" ), [72] = getParameterID( "R->R feedback" ), [73] = getParameterID( "L->L feedback" ), [74] = getParameterID( "Filter Cutoff" ), [75] = getParameterID( "L->R feedback" ), [76] = getParameterID( "Pitch LFO Speed" ), [78] = getParameterID( "Trigger" ), [79] = getParameterID( "Saturation" ), [80] = getParameterID( "Saturation Shape" ), [81] = getParameterID( "Saturation On/Off" ), [85] = getParameterID( "Filter Type" ), [86] = getParameterID( "Freeze Loop" ), [87] = getParameterID( "Tap Tempo" ), [88] = getParameterID( "Pause Clock" ), [89] = getParameterID( "Reverse" ), [92] = getParameterID( "Tap Record" ), [96] = getParameterID( "Env Attack" ), [97] = getParameterID( "Env Release" ), [100] = getParameterID( "Clear Loop" ), [101] = getParameterID( "Punch In Quantize" ), [102] = getParameterID( "Punch Out Quantize" ), [103] = getParameterID( "Punch Out Type" ), [104] = getParameterID( "Punch In Set Input Level" ), [105] = getParameterID( "Punch Out Set Input Level" ), [106] = getParameterID( "Auto Clear After Fade" ), [107] = getParameterID( "Env Gate" ), [108] = getParameterID( "Env Override" ), [109] = getParameterID( "Delay Inertia Mode" ), [110] = getParameterID( "Delay Inertia Fade Time" ), [111] = getParameterID( "Digital Mode" ), [112] = getParameterID( "Stop" ), [114] = getParameterID( "Tape Read Mode" ), [115] = getParameterID( "Sync Group Mode" ), [116] = getParameterID( "Sync Group Number" ), [117] = getParameterID( "Freeze Mode" ), [118] = getParameterID( "Low Cut Freq" ), [119] = getParameterID( "Low Cut Amount" ), [120] = getParameterID( "High Cut Freq" ), [121] = getParameterID( "High Cut Amount" ), [122] = getParameterID( "Crunch" ), [123] = getParameterID( "Drive" ), [124] = getParameterID( "Post Gain" ), } local nrpnMap = { [128] = getParameterID( "Delay Slider Min" ), [129] = getParameterID( "Delay Slider Max" ), [130] = getParameterID( "Delay Time" ), } -- define the handler functions -- set the pitch via note on messages local function handleNoteOn( channel, noteNumber, velocity ) if not prefRxAllChannels then if channel ~= 2 then return end end -- the pitch is centred on middle C (note number 60) local pitch = noteNumber - 60 if pitch >= -12 and pitch <= 12 then setParameter( paramID_Pitch, pitch ) end end -- set most parameters via CC messages local function handleCC( channel, cc, value ) if not prefRxAllChannels then if channel ~= 1 then return end end -- look up the cc in the table local param = ccMap[ cc ] if param then local minv, maxv = getParameterMinMax( param ) -- scale the value if param == paramID_Pitch then if value <= 64 then value = value / 128.0 else value = 0.5 + ( value - 64 ) * ( 0.5/63.0 ) end elseif param == paramID_Beats or param == paramID_BeatDivisor then value = value else value = value * ccScale end -- offset the value if param == paramID_FilterCutoff or param == paramID_FilterLFOSpeed or param == paramID_PitchLFOSpeed then -- log2( x ) == log( x ) / log( 2 ) == log( x ) * 1.4426950409 value = minv * math.pow( 2.0, math.log( maxv/minv ) * 1.4426950409 * value ) elseif param == paramID_Beats then value = value + 1 elseif param == paramID_BeatDivisor then value = value else value = minv + value * ( maxv - minv ) end setParameter( param, value ) end end -- set parameters via NRPN messages local function handleNRPN( channel, nrpn, value ) if not prefRxAllChannels then if channel ~= 1 then return end end -- look up the nrpn in the table local param = nrpnMap[ nrpn ] if param then local minv, maxv = getParameterMinMax( param ) setParameter( param, minv + nrpnScale * value * ( maxv - minv ) ) end end -- set the delay slider -- value has been scaled to 0.0-1.0 range local function handleDelaySlider( channel, value ) if not prefRxAllChannels then if channel ~= 1 then return end end -- calculate the delay value from the slider settings local minv = getParameter( paramID_DelaySliderMin ) local maxv = getParameter( paramID_DelaySliderMax ) setParameter( paramID_DelayTime, minv + value * ( maxv - minv ) ) end -- set up the MIDI events we're interested in requestAllNoteOn( handleNoteOn ) requestAllCC( handleCC ) requestAllNRPN( handleNRPN ) requestCC( 12, function( channel, cc, value ) handleDelaySlider( channel, value * ccScale ) end ) requestNRPN( 131, function( channel, nrpn, value ) handleDelaySlider( channel, value * nrpnScale ) end )