Utilities to control Ableton Live
- Open Audio MIDI Setup
- Double-click IAC Driver (in red)
- Click
+
to add a Bus - Double-click the bus name and rename to
StreamDeck2Daw
- Click
+
to add a second Bus - Double-click the second bus name and rename to
Daw2StreamDeck
- Ensure that Device is online is checked
- Click Apply
- Open Ableton Live
- Open Settings > Link, Tempo & MIDI
- Under Input Ports, locate IAC Driver (StreamDeck2Daw) and select the Track and Remote checkboxes
- Under Input Ports, locate IAC Driver (Daw2StreamDeck) and select the Track and Remote checkboxes
- Configure Stream Deck > Midi (Stream Deck Midi plugin)
- Drag desired action to a slot, e.g. Note On/Off and configure as usual
- Set Midi Out port to IAC Driver StreamDeck2Daw
- Set Midi In port to IAC Driver Daw2StreamDeck
src/live/Audio Effects/Max Audio Effect/cl-presample-selected-track.js
src/live/Audio Effects/Max Audio Effect/Presample Selected Track.amxd
When jamming with soft synths or hardware synths, MIDI notes are driving that synth. Recording into the instrument channel would therefore record the MIDI input rather than the audio output. When recorded MIDI is played back at a later date, the sound is often different to what was originally played, due to some combination of synth settings not being saved with the MIDI input (this is especially the case with hardware synths). In this instance it's better to capture the audio output rather than the MIDI input. For synths that don't have MIDI input, audio capture is the only option.
On the Push2, creation of a track-based audio (or MIDI) resampling track necessitates multiple button presses and two hands. This interrupts the creative flow as it requires extensive hand-eye coordination:
- Press 'Mix'
- Press 'Mix'
- Press to select 'Input & Output'
- Scroll to select 'Input Type'
- Press Record + Track Select
- Rename new track in software
- Recolour new track
Key/MIDI mapping the Insert before
and Insert after
buttons automates this process, by:
- inserting a new track BEFORE (to the left of) or AFTER (to the right of) the selected track
- matching the type of the new track to the type of the selected track (Audio or MIDI)
- setting the input of the new track to the name of the selected track
- arming the new track
- naming the new track to indicate the source name and the time of creation
- recolouring the new track to match the selected track's colour
- returning the focus to the selected track
Recording can now be started via a single button press on the desired clip slot.
Note: This patch is functionally similar to ClyphX Pro's INSAUDIO
/INSMIDI
.
- add Presample Selected Track.amxd to the Master Audio track in Ableton Live
- map button on Push2 or other controller to
Insert before
and/orInsert after
button
- map button on Push2 or other controller to
- select an Audio, MIDI, or Instrument track
- push mapped button from (2) to insert a resampling track
- alternatively use Mira to view the Mira frame on an iPad, then tap one of the (Mira) buttons to insert a resampling track
src/live/Audio Effects/Max Audio Effect/cl-rename-selected-track.js
src/live/Audio Effects/Max Audio Effect/Rename Selected Track.amxd
When jamming it's easy to lose track of what each track represents. This function provides a quick way to name the track from a list of common options.
- add Rename Selected Track.amxd to the Master Audio track in Ableton Live
- map tabs object to encoder on non-Push controller
- select an Audio, MIDI, or Instrument track
- turn mapped encoder from (2) to change the track name and see it update instantly
- alternatively use Mira to view the Mira frame on an iPad, then tap a tab (option) on Mira to change the selected track name
- alternatively lock Push to the device on the Master track, and turn the
TRACKNAME
encoder
Patcher:
[live.tab] # UI object sending input to script
| | |
|
[js script-name.js] # js object containing script (see list of tested variations below)
JS:
function bang()
if (jsarguments.length > 1) {
post(jsarguments[0]); // script name
post(jsarguments[1]); // first argument
}
}
I couldn't figure out how to use a dynamic value with this approach, as when a value is sent into the js
object's inlet,
it is treated as a function name rather than a string argument. That generates an error as there is no matching function.
js: no function argName [script-name.js]
This error can be mitigated by adding an anything()
function:
function anything() {
console.log(jsarguments.length);
console.log(jsarguments[0], jsarguments[1]);
}
However I still couldn't figure out how to pass in a reference to the Symbol value generated by the middle outlet of live.tab
:
js script-name.js => anything() => script-name.js, <undefined>
sprintf js script-name.js %s => anything() => no output
prepend js script-name.js => anything() => no output
js rename-selected-track.js $1 => anything() => script-name.js, $1
js rename-selected-track.js $s => anything() => script-name.js, $s
Links:
- https://docs.cycling74.com/max8/refpages/js#jsarguments
- https://docs.cycling74.com/max8/vignettes/jsbasic#How_Input_to_the_js_Object_is_Handled
Patcher:
[live.tab] # UI object to listen to in script + named (via the Scripting Name field?)
[live.button] # live.button object to send bang
|
[js script-name.js] # js object containing script
JS:
function bang() {
// Run garbage collection
gc();
// Target object from patcher
const obj = this.patcher.getnamed('namedObject');
// Assign listener
const ml = new MaxobjListener(obj, objCallback);
// Get the current value
post(ml.getvalue());
}
// When the listener detects a change, fire a callback
function objCallback(data) {
// Get the latest value
post(data.value);
}
Issues:
When the object has multiple outlets, you can't choose the one with the data type you want.
For the live.tab
object, I wanted the middle outlet (string Symbol
) not the left outlet (Item Index
).
The latter would have only been useful if had access to the object's enum
so I could get the string that the index referred to.
Links:
- https://docs.cycling74.com/max8/vignettes/scripting_topic -
maxobjlistener-example.maxpat
- https://docs.cycling74.com/max8/vignettes/jsmaxobjlistener
As the above two techniques didn't work for me, I settled on using global functions.
This encouraged me to merge several separate scripts into one, and then to hide helper functions using privateFunctionName.local = 1
.
Patcher:
[live.tab] # UI object sending input to script
| | |
|
[functionName $1] # message object containing function to call + variable argument
|
[js script-name.js] # js object containing script containing function
JS:
function functionName(arg) {
post(arg);
}
Links:
For buttons (live.text
) MIDI mappable controls should activate on mouse down AND mouse up, to prevent 2 clicks being required to repeat the action.
For buttons (live.text
) Mira-only controls should only activate on transition from zero to one, otherwise every touch would trigger the action twice.
live.dial
(with label)live.grid
live.meter
live.number
live.slider
live.tab
live.text
(with label - button/toggle, also see prototypes)live.toggle
live.adsrui
live.arrows
live.comment
live.gain
live.line
live.menu
live.scope
live.step