In which I weave music into my role as a Quantum Developer Advocate for IBM
Feels So Good on LinnStrument with Logic Pro Scripter
Exploring polyphonic expressiveness
In the Domo Arigato Tempo Rubato article we discussed that each note pad on the LinnStrument playing surface has three dimensions of musical expression: Moving your finger along the X-axis varies pitch, moving it on the Y-axis influences timbre, and varying its pressure on the Z-axis controls loudness. Given that each note pad has three dimensions of control, and each dimension has a resolution of 128 values, there is much expressiveness to be explored in each note being played. Because LinnStrument is a polyphonic instrument, you can play several notes simultaneously which further increases the potential for expressiveness. The trade-off is that the more fingers you’re simultaneously employing, the less focused you can be on the expressiveness of a given note.
Logic Pro Scripter API quick reference
The following tables in this quick reference includes information gleaned from the Apple Logic Pro Effects manual, example scripts such as Guitar Strummer included with Logic Pro, and the following file from the Logic Pro X installation on my Mac.
/Applications/Logic Pro X.app/Contents/Frameworks/
Scripter – Global attributes and functions
Defining NeedsTimingInfo as true at the global scope enables the GetTimingInfo() function
Sets UI controls to default values
This function is called each time a MIDI event is received by the plug-in, and is required to process incoming MIDI events. If you do not implement this function, events pass through the plug-in unaffected.
This function is called once per “process block,” which is determined by the host’s audio settings (sample rate and buffer size). This function is often used in combination with the TimingInfo object to make use of timing information from the host application. To enable the GetTimingInfo feature, add NeedsTimingInfo = true at the global script level.
This function is called each time one of the plug-in’s parameters is set to a new value. It is also called once for each parameter when you load a plug-in setting.
This function is called when the plugin is reset
Prints a message to the console that represents the supplied value of any type
Retrieves a TimingInfo object, which contains timing information that describes the state of the host transport and the current musical tempo and meter.
Returns a given parameter’s current value. GetParameter() is typically called inside the HandleMIDI() or ProcessMIDI() functions.
Event – Base class for all events
Send the event
Send the event after the specified value has elapsed
Send the event at a specific beat in the host’s timeline
Similar to sendAtBeat(), but uses the beat value as a delay in beats from the current position.
Prints the event to the plug-in console
Returns a string representation of the event
Sets MIDI channel 1 to 16. Note: Event.channel is an event property, rather than a method, so it may be used in expressions such as (evt.channel == 1) where evt is an instance of Event)
Note – Base class for note events
Returns a String representation of the Note event.
NoteOn – Represents a note on event
Pitch from 1–127
Velocity from 0–127. A velocity value of 0 is interpreted as a note off event, not a note on.
NoteOff – Represents a note off event
Pitch from 1–127
Velocity from 0–127
PolyPressure – Represents a Polyphonic aftertouch event
Pitch from 1–127
Pressure value from 0–127
Returns a String representation of the PolyPressure event.
ControlChange – Represents a ControlChange event
Controller number from 0–127.
Controller value from 0–127.
Returns a String representation of the ControlChange event.
ProgramChange – Represents a ProgramChange event
Program change number from 0–127
Returns a String representation of the ProgramChange event.
ChannelPressure – Represents a ChannelPressure event
Aftertouch value from 0–127
Returns a String representation of the ChannelPressure event.
PitchBend – Represents a PitchBend event
14-bit pitch bend value from -8192–8191. A value of 0 is center.
Returns a String representation of the PitchBend event.
Fader – Represents a Fader event
Fader value from 0–127
Returns a String representation of the Fader event.
TimingInfo – Contains timing information that describes the state of the host transport and the current musical tempo and meter
Value is true when the host transport is running
Indicates the beat position at the start of the process block
Indicates the beat position at the end of the process block
Indicates the length of the process block in beats.
Indicates the host tempo.
Indicates the host meter numerator
Indicates the host meter denominator.
Value is true when the host transport is cycling
Indicates the beat position at the start of the cycle range
Indicates the beat position at the end of the cycle range
Contains names such as C and G# for all 128 MIDI notes
Contains names such as Expression and Sustain for all 128 MIDI controller numbers
Returns the MIDI note number for a given note name. For example: C3 or B#2. Flats not permitted.
Returns the name for a given MIDI note number.
Returns the controller name for a given controller number
Sends the all notes off message on all MIDI channels
Normalizes a value to the safe range of MIDI status bytes (128–239)
Normalizes a value to the safe range of MIDI channels (1–16)
Normalizes a value to the safe range of MIDI data bytes (0–127)
Sends a given event to all MIDI channels
Leveraging Logic Pro Scripter for accompaniment
(click to see larger view)
Using the Guitar Strummer script that comes with Logic Pro as a starting point, I made modifications that achieve behavior including the following:
Allow selection of a music key signature and keyboard split point (see image of UI nearby)
Allow chord mode selection via a switch on LinnStrument (or pedal) that maps to a control change message. Primary modes currently consist of vanilla (major/minor/dim) vs. jazzy (maj7/min7/dom7/half dim7) chords.
When a single note below the split point is pressed, that note is output. In addition, a chord is output whose root is that note and appropriate to the chosen key signature. The chord is voiced (inversion, etc.) in a manner that assures minimal movement from the previous chord.
When two notes in the same octave below the split point are pressed, the higher note is the root of the chord output, and the lower note is output as well. This technique facilitates playing so-called slash chords.
When two notes an octave apart below the split point are pressed, the tonality toggles in most cases from major to minor and minor to major.
As a demonstration of the features outlined above, here’s a one-minute video of the first few measures of Feels So Good by Chuck Mangione. The LinnStrument is split, with a grand piano synth on the left and a trumpet synth on the right.
Très bien, Xavier!