Home Forums Logelloop 6 (English spoken) Dynamic playback/stretch control of a current Korpus looper

Viewing 15 posts - 1 through 15 (of 18 total)
  • Author
    Posts
  • #6638
    Patrick KiznyPacocreative
    Participant

    Hey,

    I’d like to assign midi controllers to playback speed of FX tracks loopers sitting under Korpus.
    While Korpus midi controls allow for navigating across loopers and triggering rec/play/fade etc…, I can’t seem to have access to playback speed and mode.
    I understand I could control some some properties of each FX track’s looper directly (as shown on image below), but I’d prefer to have controls over the speed of a *currently selected* looper.

    1/ Do you plan on adding such controls in the future to the midi config UI? This would be handy
    2/ I guess it’s doable via macros, but I’m a newbie. Could you suggest a way?

    Specifically, I’d like to have a way of controlling via midi the following properties of a *currently selected* looper:
    ⇀ Reverse
    ⇀ Freeze
    ⇀ Speed multiplier (midi CC 00-127 mapped to 1-x range)
    ⇀ Speed up/slowdown (x2 /2)
    ⇀ Speed reset
    ⇀ * Mode cycle (tape/extreme stretch etc…

    https://www.dropbox.com/scl/fi/jdsg2yist94h4vad50w4p/LooperMidi.jpg?rlkey=gqsdx72gjv884iru1bseykb1f&dl=0

    Thanks!

    #6640
    Patrick KiznyPacocreative
    Participant

    What I’ve managed to do is the following:

    CC11 is coming from an expression pedal and is 0-127 range.

    1. Created a macro, for now it’s static FX target
    InsertSendMessage fx1 1 HTSSpeed $midiv_cc1$

    2. Made id available in the project
    3. Assigned a macro midi listener for CC11
    4. Added a macro triggered by midi CC11

    But it does not seem to work properly.
    When I send CC11 it does not seem to trigger the macro, but sets the variable.
    When I click “start” on macro, it sets the HTSSpeed to last changed variable.

    I’m not sure if that’s the right way of doing that.
    When a macro is assigned to a midi trigger, I’d be expecting that the midi CC value be passed to the midi as a param.
    I wasn’t able to find something like that in the docs, I only found the setting a listener path that I explored.

    Still need help with:
    ⇀ Accessing currently selected Korpus looper in the macro editor
    ⇀ Passing this looper address to send commands like HTSSpeed etc…
    ⇀ Properly capturing CC value in macro (assuming there’s a simpler way than a listener)
    ⇀ How to map $midiv_cc1$ (0-127) to speed range 1-50 for example (I’m having syntax issues)

    InsertSendMessage fx1 1 HTSSpeed $midiv_cc1$/127*10
    Line: 1, Error in command: lexical error At position 44, separator needed after ", but / found instead!

    Thanks

    https://www.dropbox.com/scl/fi/8sbjmf2v3ticlczsdopu1/LooperMacro2.jpg?rlkey=u4mts00ky59we0z9fkrfep63y&dl=0

    #6641
    Patrick KiznyPacocreative
    Participant

    Figured out the syntax thing, but still, I’m getting a very choppy and messy experience when using the expression pedal.
    InsertSendMessage fx1 1 { $midiv_cc1$ / 127 * 100 }

    It seems like the fact this macro exists, starts repeating messages and it comes into some midi feedback loop.
    That’s something I’ll need help with in terms of the right approach.

    #6642
    Philippe OllivierPhilippe
    Keymaster

    Hi,
    There are plenty of things in your messages.
    I can’t answer everything now.

    1/
    the cc command is to trig the macro.
    And yes you should go with a variable to get the cc value. As you’ve done.

    To scale the variable, you should use :
    InsertSendMessage fx1 1 { scale($midiv_cc1$,0,127,0,1) }
    for example

    You will find those expression in the “references guide” (button at the bottom of the macro editor.

    2/ You should load Korpus in the data plug-ins page in place of in a track as we made before.
    I know there are no tutorials yet about this…
    But Korpus is more a data plug-in, a new thing in Logelloop 6.

    3/ In the macro variable viewer page, you can filter “Korpus” and see the variable $Korpus_data1_rank1_Counter_state$ that reports the current Korpus group.
    You can use this variable in you macro.

    And in the macro you should put :
    InsertSendMessage fx[$Korpus_data1_rank1_Counter_state$] 1 SpeedFloat {scale(currentCaseOptionValueFloat(0), 0, 127, -20, 20)}

    assuming Korpus is in data 1 rank 1…

    4/ you may organize a loop in your macro, like this :

    DoRepeat
    InsertSendMessage fx[$Korpus_data1_rank1_Counter_state$] 1 SpeedFloat {scale(currentCaseOptionValueFloat(0), 0, 127, -20, 20)}
    Sleep 50
    While true

    Then, as soon as the macro is running, the speed will be updated every 50 ms.

    Please, note that I didn’t test those macro, so maybe there are some typos…

    This topic is interesting, I will answer more later, and perhaps I will make a tutos.
    Best,
    Philippe

    #6643
    Patrick KiznyPacocreative
    Participant

    Thanks for your help on this. Very helpful.
    I’m still not sure of a preferred approach:

    Approach 1
    Use Macro Variable Listener to continuously update CC variable
    Trigger macro once, but have it looping let’s say in 50ms as you suggested

    Approach 2
    Use Macro Variable Listener to continuously update CC variable
    Use a Macro midi trigger on the same CC as the variable
    Wrap the macro in

    DoOnce
    	InsertSendMessage fx1 1 HTSSpeed { round ($midiv_cc1$ / 127 * 100) }
    EndDoOnce

    I am not sure which one is a better way given the overall architecture.

    Still, I’m having a performance issue due to some internal midi flooding.
    When there’s no listener defined, my expression control works nice and clean:
    I push the pedal, it immediately prints sweeping values to the console. The messages are clean and ordered:

    Midi input: ctlIn 30 7 16 "(value ctl channel)"
    Midi input: ctlIn 31 7 16 "(value ctl channel)"
    Midi input: ctlIn 33 7 16 "(value ctl channel)"
    Midi input: ctlIn 34 7 16 "(value ctl channel)"
    Midi input: ctlIn 35 7 16 "(value ctl channel)"
    Midi input: ctlIn 36 7 16 "(value ctl channel)"
    Midi input: ctlIn 37 7 16 "(value ctl channel)"
    Midi input: ctlIn 38 7 16 "(value ctl channel)"

    When a listener is defined, it seems there’s a sort of feedback or flood triggered and the console is lagging for a few seconds processing queued messages.
    You can see that the values start jumping erratically,

    Midi input: ctlIn 1 11 16 "(value ctl channel)"
    Midi input: ctlIn 67 11 16 "(value ctl channel)"
    Midi input: ctlIn 66 11 16 "(value ctl channel)"
    Midi input: ctlIn 69 11 16 "(value ctl channel)"
    Midi input: ctlIn 74 11 16 "(value ctl channel)"
    Midi input: ctlIn 2 11 16 "(value ctl channel)"
    Midi input: ctlIn 73 11 16 "(value ctl channel)"
    Midi input: ctlIn 47 11 16 "(value ctl channel)"
    Midi input: ctlIn 56 11 16 "(value ctl channel)"

    Any ideas?

    #6645
    Philippe OllivierPhilippe
    Keymaster

    I think the best approach should be something else.
    I will think to it.

    For the midi issue, I wonder if this is the looper itsel taht is sending some midi value to the midi device and they come back to Logelloop… I don’t know.

    #6646
    Patrick KiznyPacocreative
    Participant

    Yeah, you’re right that none of these approaches is ideal.
    The reason being there’s just one continuously stored “global” speed (coming from CC) that’s redistributed to each slot as we cycle through them.
    If the macro is running in a loop, it’ll adjust the speed of each looper we jump to with the global value.
    We could try working around it by implementing additional change listener in macro, but that’s cumbersome and not an ideal design anyways.

    I guess a more ideal approach would be to expose direct parameter in midi automations, as we have for stop/overdub etc… but I understand that takes effort on your side.

    #6647
    Patrick KiznyPacocreative
    Participant

    Here’s my temporary solution:

    1/ Unplugged midi-in cable from FCB1010, this prevents flooding and midi feedback.
    But it seems that there’s something inside LL that does send midi signals out on the macro variable listeners.
    In other midi commands configurations there’s a “Note Out” checkbox that prevents this, which I keep unticked.
    Probably that’s something you may want to look into.

    2/ Following this fix:
    – Set macro CC variable listener on CC11
    – Set midi macro trigger on CC11
    – write macro as DoOnce

    DoOnce
    	Declare int $k_index$ = $Korpus_data1_rank1_Counter_state$
    	InsertSendMessage fx[$k_index$] 1 HTSSpeed {scale($midiv_cc1$, 0, 127, 100, 1)}
    EndDoOnce

    I could not get the following to work:
    InsertSendMessage fx[$k_index$] 1 HTSSpeed {scale(currentCaseOptionValueFloat(0), 0, 127, 100, 1)}

    Are you trying to say that “$currentCaseOptionValueFloat(0)” in a midi-triggered macro should return the original midi CC value?
    I haven’t found much documentation on using this. But it returns 0.0 float.

    #6648
    Philippe OllivierPhilippe
    Keymaster

    1/

    If you put :

    DoOnce
    Declare int $k_index$ = $Korpus_data1_rank1_Counter_state$
    InsertSendMessage fx[$k_index$] 1 HTSSpeed {scale($midiv_cc1$, 0, 127, 100, 1)}
    EndDoOnce

    it is the same as you put

    Declare int $k_index$ = $Korpus_data1_rank1_Counter_state$
    InsertSendMessage fx[$k_index$] 1 HTSSpeed {scale($midiv_cc1$, 0, 127, 100, 1)}

    DoOnce is not useful.

    2/
    You should not trig the macro with your expression pedal, because you will trig to many time the macro and that will create some issues in Logelloop.
    Please use a macro loop or something else instead.
    3/
    I made a mistake, when writing :

    DoRepeat
    InsertSendMessage fx[$Korpus_data1_rank1_Counter_state$] 1 SpeedFloat {scale($midiv_cc1$, 0, 127, -20, 20)}
    Sleep 50
    While true

    I wanted to write :

    DoRepeat
    InsertSendMessage fx[$Korpus_data1_rank1_Counter_state$] 1 SpeedFloat {scale(currentCaseOptionValueFloat(0), 0, 127, -20, 20)}
    Sleep 50
    While true

    Sorry

    #6649
    Patrick KiznyPacocreative
    Participant

    Mind explaining what “currentCaseOptionValueFloat(0)” refers to in this context?

    And is there a way of achieving something like this:
    $Looper_fx[$someindex$]_rank1_HTSFreeze_state$

    I’m currently using an ugly way:
    IfThen { $k_index$ == 1 } Do Set $c_freeze$ = $Looper_fx1_rank1_HTSFreeze_state$
    IfThen { $k_index$ == 2 } Do Set $c_freeze$ = $Looper_fx2_rank1_HTSFreeze_state$
    IfThen { $k_index$ == 3 } Do Set $c_freeze$ = $Looper_fx3_rank1_HTSFreeze_state$
    IfThen { $k_index$ == 4 } Do Set $c_freeze$ = $Looper_fx4_rank1_HTSFreeze_state$

    I know the array trick works at the end of the expression, but not to dynamically create a variable reference.
    What language are we using for these macros in general? I’d prefer to save you from questions I can find answers to.

    Thank you so much.

    #6650
    Philippe OllivierPhilippe
    Keymaster

    Mind explaining what “currentCaseOptionValueFloat(0)” refers to in this context?

    This is used in Matrix and Matrix arranger that are data plug-ins that use macro.

    And is there a way of achieving something like this:
    $Looper_fx[$someindex$]_rank1_HTSFreeze_state$

    Not currently, but yes, that would be great and it is on the to do list !

    I’m currently using an ugly way:
    IfThen { $k_index$ == 1 } Do Set $c_freeze$ = $Looper_fx1_rank1_HTSFreeze_state$
    IfThen { $k_index$ == 2 } Do Set $c_freeze$ = $Looper_fx2_rank1_HTSFreeze_state$
    IfThen { $k_index$ == 3 } Do Set $c_freeze$ = $Looper_fx3_rank1_HTSFreeze_state$
    IfThen { $k_index$ == 4 } Do Set $c_freeze$ = $Looper_fx4_rank1_HTSFreeze_state$

    Not so ugly as the index solution isn’t crurrently working ! 😊

    What language are we using for these macros in general? I’d prefer to save you from questions I can find answers to.

    This a native language, but many things are the same as they would be in Java…

    #6651
    Patrick KiznyPacocreative
    Participant

    Looks like I managed to implement most of the features I wanted for the modular looper via macros.
    The only issue remaining is figuring out a better approach to handling continuous/dense midi messages coming from the pedal.
    I did not use the looped macro, as it would mess up speed on counter change, unless I work on smart workarounds.
    For now, the triggered macro in a non-looped version does not seem to choke the system nor cause any bad behavior.

    I’m sharing my macros below, in case someone finds them useful.

    * All these macros assume Korpus running as a Data plugin on 1/1
    * All these macros assume modular loopers running on fx channels 1-4
    * All these macros add functionality for a *currently selected* looper in Korpus
    * I use all of these macros mapped to midi CC commands

    Macro#1 – ModLoop Play Mode
    Switch current looper between Tape Mode and Extreme Time Stretch

    Declare int $k_index$ = $Korpus_data1_rank1_Counter_state$
    Declare int $p_mode$ = 0
    
    //PlayerMode 0 ⇀ Tape
    //PlayerMode 2 ⇀ Stretch
    
    IfThen { $k_index$ == 1 } Do Set $p_mode$ = $Looper_fx1_rank1_PlayerMode_state$
    IfThen { $k_index$ == 2 } Do Set $p_mode$ = $Looper_fx2_rank1_PlayerMode_state$
    IfThen { $k_index$ == 3 } Do Set $p_mode$ = $Looper_fx3_rank1_PlayerMode_state$
    IfThen { $k_index$ == 4 } Do Set $p_mode$ = $Looper_fx4_rank1_PlayerMode_state$
    
    InsertSendMessage fx[$k_index$] 1 PlayerMode { $p_mode$ == 0 ? 2 : 0 }

    Macro#2 – ModLoop Reverse
    Reverse current mod looper direction

    // Find current looper index
    Declare int $k_index$ = $Korpus_data1_rank1_Counter_state$
    Declare int $p_mode$ = 0
    Declare float $c_speed$ = 1
    
    // Get current player mode
    // PlayerMode 0 ⇀ Tape
    // PlayerMode 2 ⇀ Stretch
    
    IfThen { $k_index$ == 1 } Do $p_mode$ = $Looper_fx1_rank1_PlayerMode_state$
    IfThen { $k_index$ == 2 } Do $p_mode$ = $Looper_fx2_rank1_PlayerMode_state$
    IfThen { $k_index$ == 3 } Do $p_mode$ = $Looper_fx3_rank1_PlayerMode_state$
    IfThen { $k_index$ == 4 } Do $p_mode$ = $Looper_fx4_rank1_PlayerMode_state$
    
    If {$p_mode$ != 2}
    
    	// Only change direction if we're NOT in Extreme Stretch mode
    
    	IfThen { $Korpus_data1_rank1_Counter_state$ == 1 } Do $c_speed$ = $Looper_fx1_rank1_SpeedFloat_state$
    	IfThen { $Korpus_data1_rank1_Counter_state$ == 2 } Do $c_speed$ = $Looper_fx2_rank1_SpeedFloat_state$
    	IfThen { $Korpus_data1_rank1_Counter_state$ == 3 } Do $c_speed$ = $Looper_fx3_rank1_SpeedFloat_state$
    	IfThen { $Korpus_data1_rank1_Counter_state$ == 4 } Do $c_speed$ = $Looper_fx4_rank1_SpeedFloat_state$
    
    	InsertSendMessage fx[$Korpus_data1_rank1_Counter_state$] 1 SpeedFloat {$c_speed$ * -1}
    EndIf

    Macro#3 – ModLoop Speed Reset
    Resets current looper speed to 1

    InsertSendMessage fx[$Korpus_data1_rank1_Counter_state$] 1 SpeedFloat 1

    Macro#4 – ModLoop Speed Set
    Set current mod looper speed to CC1 Variable.
    Freezes on max slowdown in Extreme Stretch

    # This macro assumes that speed is set via expression pedal (for example) and stored in CC variable #1
    # Requires setting both macro trigger and midi CC listener
    # It works in both modes – Extreme Stretch and standard Tape mode.
    # In extreme Stretch mode, when reaching minimum speed, it will switch to freeze
    # It’s NOT following Philippe’s recommendations, so use at your own risk

    // Find current looper index
    Declare int $k_index$ = $Korpus_data1_rank1_Counter_state$
    
    Declare float $spd_min1$ = 0.25   // Edit this to set min speed in Standard modes
    Declare float $spd_max1$ = 4     // Edit this to set max speed in Extreme Stretch Mode
    Declare float $spd_max2$ = 25     // Edit this to set max speed in Extreme Stretch Mode
    
    Declare int $frz$ = 0       // Looper will freeze when reaching max speed
    Declare float $spd$ = 1
    
    // Get current player mode
    // PlayerMode 0 ⇀ Tape
    // PlayerMode 2 ⇀ Stretch
    
    Declare int $p_mode$ = 0
    
    IfThen { $k_index$ == 1 } Do $p_mode$ = $Looper_fx1_rank1_PlayerMode_state$
    IfThen { $k_index$ == 2 } Do $p_mode$ = $Looper_fx2_rank1_PlayerMode_state$
    IfThen { $k_index$ == 3 } Do $p_mode$ = $Looper_fx3_rank1_PlayerMode_state$
    IfThen { $k_index$ == 4 } Do $p_mode$ = $Looper_fx4_rank1_PlayerMode_state$
    
    // Depending on the mode set speeds
    
    If {$p_mode$ == 2}
    	// Extreme Time Strech
    
    	$spd$ = {scale($midiv_cc1$, 3, 126, $spd_max2$, 1)}
    
    	IfThen {$spd$ > $spd_max2$ * 0.95} Do $frz$ = 1
    
    	InsertSendMessage fx[$k_index$] 1 HTSFreeze $frz$
    	InsertSendMessage fx[$k_index$] 1 HTSSpeed $spd$
    
    Else
    	// Tape or similar
    
    	// Calculate target speed
    	$spd$ = {scale($midiv_cc1$, 3, 126, $spd_min1$, $spd_max1$)}
    
    	// Check current speed to see if it's reversed or not
    	IfThen { $Korpus_data1_rank1_Counter_state$ == 1 } Do $c_speed$ = $Looper_fx1_rank1_SpeedFloat_state$
    	IfThen { $Korpus_data1_rank1_Counter_state$ == 2 } Do $c_speed$ = $Looper_fx2_rank1_SpeedFloat_state$
    	IfThen { $Korpus_data1_rank1_Counter_state$ == 3 } Do $c_speed$ = $Looper_fx3_rank1_SpeedFloat_state$
    	IfThen { $Korpus_data1_rank1_Counter_state$ == 4 } Do $c_speed$ = $Looper_fx4_rank1_SpeedFloat_state$
    
    	// Reverse if current speed was negative
    	IfThen { $c_speed$ < 0 } Do $spd$ = { $spd$ * -1 }
    
    	// Set Speed
    	InsertSendMessage fx[$Korpus_data1_rank1_Counter_state$] 1 SpeedFloat $spd$
    
    EndIf
    #6656
    Philippe OllivierPhilippe
    Keymaster

    Hi Patrick,
    So, yesterday morning, you wrote :

    I guess it’s doable via macros, but I’m a newbie. Could you suggest a way?

    And yesterday evening you posted four perfect macros…
    Yes, I think these macros will be useful for many users.

    Thank you for the great work !
    Best,
    Philippe

    #6657
    Patrick KiznyPacocreative
    Participant

    Merci, c’est rien.
    Despite being a ‘homemade’ tool, it’s a robustly designed platform, and incredibly versatile. That’s why it’s easy to learn.

    Moving forward, I’m thinking about handling some more automations via macros, and I wonder if the following architecture would make sense for more complex cases?

    Have one central looped macro running at 25fps/20ms that would actually have access to all recently received midi signals, and it would process multiple behaviors dependent on many mini signals from one central program. I wonder if this makes sense in terms of optimizing performance, versus using multiple listeners and multiple loops? Or, rather LL is written in such way, that multiple looped macros are not a performance strain?

    Wonder if exposing received midi in a more centralized way would be doable on your side?
    I guess with 8 available listeners I’ll be soon out of slots 😉

    #6658
    Patrick KiznyPacocreative
    Participant

    Here’s a version 2 of the Speed Changer

    # requires 2 expression pedals or similar signals on CC1 and CC2 variable
    # CC2 adjusts speed in tape mode and in ETS mode
    # CC1 allows to scrub through the sample in ETS freeze mode
    # Triggered once, and working in a loop, so a proper implementation
    # If looper is in freeze mode, CC1 allows to dynamically scrub through the buffer
    $ if speed is lifted up from freeze, or is in any of the tape modes, it ignores CC1
    # It does not mess up on looper change, as I implemented change listeners, so unless you start messing with CC1V CC2V, it does not automatically alter current looper settings

    Hell yeah!

    
    // Find current looper index
    Declare int $k_index$ = $Korpus_data1_rank1_Counter_state$
    
    Declare float $spd_min1$ = 0.25  // Edit this to set min speed in Standard modes
    Declare float $spd_max1$ = 4     // Edit this to set max speed in Extreme Stretch Mode
    Declare float $spd_max2$ = 25    // Edit this to set max speed in Extreme Stretch Mode
    
    Declare int $p_mode$ = 0         // Play mode
    Declare float $p_pos$ = 0        // ETS Freeze mode position scrubbing
    Declare float $p_pos_last$ = 0
    
    Declare int $frz$  = 0           // Looper will freeze when reaching max speed
    Declare float $spd$ = 1
    Declare float $bufsize$ = 0      // Buffer length in samples
    
    Declare float $midiv_cc1_last$ = $midiv_cc1$
    Declare float $midiv_cc2_last$ = $midiv_cc2$
    
    DoRepeat
    
    	// Get current player mode
    	// PlayerMode 0 ⇀ Tape
    	// PlayerMode 2 ⇀ Stretch
    
    	$k_index$ = $Korpus_data1_rank1_Counter_state$
    
    	IfThen { $k_index$ == 1 } Do $p_mode$ = $Looper_fx1_rank1_PlayerMode_state$
    	IfThen { $k_index$ == 2 } Do $p_mode$ = $Looper_fx2_rank1_PlayerMode_state$
    	IfThen { $k_index$ == 3 } Do $p_mode$ = $Looper_fx3_rank1_PlayerMode_state$
    	IfThen { $k_index$ == 4 } Do $p_mode$ = $Looper_fx4_rank1_PlayerMode_state$
    
    	IfThen { $k_index$ == 1 } Do $bufsize$ = $Looper_fx1_rank1_current_length$
    	IfThen { $k_index$ == 2 } Do $bufsize$ = $Looper_fx2_rank1_current_length$
    	IfThen { $k_index$ == 3 } Do $bufsize$ = $Looper_fx3_rank1_current_length$
    	IfThen { $k_index$ == 4 } Do $bufsize$ = $Looper_fx4_rank1_current_length$
    
    	// If { $p_mode$ == 2 and $midiv_cc1$ == $midiv_cc1_last$ }
    	//	Message "speed no change"
    	// EndIf
    	
            // Freeze player
    	// Set speeds in ETS Mode
    	If { $p_mode$ == 2 and $midiv_cc1$ != $midiv_cc1_last$ }
    		$spd$ = {scale($midiv_cc1$, 3, 126, $spd_max2$, 1)}
    		$frz$ = {$spd$ > ($spd_max2$ * 0.95) ? 1 : 0 }
    
    		InsertSendMessage fx[$k_index$] 1 HTSSpeed $spd$
    		InsertSendMessage fx[$k_index$] 1 HTSFreeze $frz$
    		$midiv_cc1_last$ = $midiv_cc1$
    
    	EndIf
    
    	// Store last position if playing
    	If { $p_mode$ == 2 and $frz$ == 0 and $midiv_cc1$ != $midiv_cc1_last$}
    		IfThen { $k_index$ == 1 } Do $p_pos_last$ = $Looper_fx1_rank1_Playing_head_position_samples$
    		IfThen { $k_index$ == 2 } Do $p_pos_last$ = $Looper_fx2_rank1_Playing_head_position_samples$
    		IfThen { $k_index$ == 3 } Do $p_pos_last$ = $Looper_fx3_rank1_Playing_head_position_samples$
    		IfThen { $k_index$ == 4 } Do $p_pos_last$ = $Looper_fx4_rank1_Playing_head_position_samples$
    		$midiv_cc2_last$ = $midiv_cc2$
    	EndIf
    
    	// Position scrubbing via midiv CC2 only on pedal change
    	If { $p_mode$ == 2 and $frz$ == 1 and $midiv_cc2$ != $midiv_cc2_last$}
    		$p_pos$ = {scale($midiv_cc2$, 0, 127, 0, $bufsize$)}
    		InsertController fx[$k_index$] 1 4 = $p_pos$
    	EndIf
    
    	// Tape or similar
    	If {$p_mode$ != 2 and $midiv_cc1$ != $midiv_cc1_last$}
    
    		// Calculate target speed
    		$spd$ = {scale($midiv_cc1$, 3, 126, $spd_min1$, $spd_max1$)}
    
    		// Check current speed to see if it's reversed or not
    		IfThen { $Korpus_data1_rank1_Counter_state$ == 1 } Do $c_speed$ = $Looper_fx1_rank1_SpeedFloat_state$
    		IfThen { $Korpus_data1_rank1_Counter_state$ == 2 } Do $c_speed$ = $Looper_fx2_rank1_SpeedFloat_state$
    		IfThen { $Korpus_data1_rank1_Counter_state$ == 3 } Do $c_speed$ = $Looper_fx3_rank1_SpeedFloat_state$
    		IfThen { $Korpus_data1_rank1_Counter_state$ == 4 } Do $c_speed$ = $Looper_fx4_rank1_SpeedFloat_state$
    
    		// Reverse if current speed was negative
    		IfThen { $c_speed$ < 0 } Do $spd$ = { $spd$ * -1 }
    
    		// Set Speed
    		InsertSendMessage fx[$Korpus_data1_rank1_Counter_state$] 1 SpeedFloat $spd$
    
    		$midiv_cc1_last$ = $midiv_cc1$
    	EndIf
    
    	Sleep 50
    While true
Viewing 15 posts - 1 through 15 (of 18 total)
  • You must be logged in to reply to this topic.