Monthly Archives: July 2015

Public Domain image via Wikimedia Commons

Getting Real on LinnStrument – Saxophone Edition

Guest article by Jeremy Cubert honoring Adolphe Sax

In Part I of this series, I introduced the topic of Getting “Real” on LinnStrument. In Part II, let’s explore playing a modeled saxophone on LinnStrument. As most keyboard / synthesizer / sampler players know, saxophone presets on keyboard instruments leave much to be desired. Often, the basic sound is fairly accurate, but any attempt to move the pitch or tonality around like a saxophone player gives away the fact the listener is hearing a poor imitation of a saxophone.  Antoine-Joseph “Adolphe” Sax (inventor of several instruments including the saxophone) probably would have desired higher audio fidelity of his brainchild by electronic instruments 170 years later.  Fortunately, the synergistic effect of some recent innovations have enabled dramatic improvements.

Sound Generators

Roger Linn’s LinnStrument website has a handy page summarizing Recommended Sound Generators. Sample Modeling instruments are listed under Single-Channel MIDI Sound Generators With Special Advantages for LinnStrument. With respect to Sample Modeling instruments like “The Saxes,” this is a bit of an understatement. While missing certain features (like Y-axis control), these instruments have leapt ahead in realism, especially when combined with LinnStrument.

Sample Modeling “The Saxes” use their own SWAM (Synchronous Wavelength Acoustic Modeling) engine. While the SWAM engine has preferred features for use with LinnStrument (e.g., Y-axis control), it can only be used as a DAW (digital audio workstation) plug-in and is not a standalone instrument.

For those not experienced in the minutia of MIDI (myself included!), Roger provides recommended settings for using LinnStrument with “The Saxes.” There are two pages for settings on each saxophone instrument (Soprano, Alto, and Baritone) – main page and options page as shown below:

Screen Shot 2015-07-27 at 8.34.05 PM

Sax configuration main page

Screen Shot 2015-07-27 at 8.34.30 PM

Sax configuration options page

For convenience, I saved presets for each saxophone in Logic Pro to avoid the process of entering the various parameters each time I use an instrument. Your DAW may also have the ability to save instrument presets.

Although designed to be played on a standard piano keyboard or with a wind controller, the Sample Modeling instruments are ideally suited for LinnStrument because you can access multiple articulations without lifting your finger off the playing surface. For realistic playing, this feature is key.

Thinking Like a Sax Player

Unlike playing a note on a piano, playing a saxophone note is a complex combination of mouth and breath control and pressing the appropriate key combinations on the instrument. Not only does the sax player need to play a particular note at a particular time, she also needs to move from one note to another musically using articulations such as slide, slur, and staccato. Realism in imitating a saxophone is more about what happens between the notes using these articulations.

Thinking like a saxophone player requires not only thinking about the notes you want to play and their duration, but how to get from one note to another. Do you want to play staccato or legato? Slur the notes? Ascend chromatically? On top of these decisions, you need to be aware of the dynamics which can be carefully controlled through breath control.

Many advanced sample libraries provide these articulations through key switches (e.g., press a key to switch to a desired articulation). However, using key switching can be cumbersome and requires timing the key switching with one hand while playing with the other. What if you also want to bend the pitch? That requires another hand to move the wheel and yet another hand to change the modulation. The LinnStrument provides one surface to achieve all of these articulations.

Breath Control

As a wind instrument, dynamic control of a saxophone comes from breath control. On LinnStrument, pressure is the proxy for breath control. I found adjusting the velocity and pressure sensitivity settings on LinnStrument was helpful to varying degrees, depending on the saxophone instrument I was playing (Soprano, Alto, and Baritone).  Velocity and Pressure Sensitivity can be adjusted under Global Settings as shown below:

Configuring LinnStrument Velocity and Pressure Sensitivity

Configuring LinnStrument Velocity and Pressure Sensitivity

Reducing the pressure sensitivity was helpful for higher register playing. Breath control was the most difficult articulation to control for me because of how sensitive the virtual instrument is to changes in pressure.

Sliding and Pitch Bend

After selecting the appropriate pitch bend setting (+/- 12) (under Per-Split Settings -> Bend Range -> 3rd button down from the top row), I found sliding between notes to be very easy and natural as long as I maintain control over the pressure. Slight variations in pressure can cause unwanted squealing from the instrument.

The instrument also has a very sophisticated slurring feature – if you hold down a first note and press a second note while still holding the first note, the note values will slide up chromatically in a very realistic way. However, if you do not want the “chromatic slide” you have to be sure to lift your finger off of the first note before you play the second (Note: These are all monophonic instruments).

Examples

Here is a video of one of my first attempts at playing the Sample Modeled Alto Sax:

At this point, I was still having difficulty fully controlling the pressure sensitivity. This improved over time, and I began to appreciate the dynamic range that you can achieve by combining the pressure sensitivity of LinnStrument with the breath control sensitivity of the Sample Modeling’s Saxophone instruments. I suggest adjusting the pressure control on the LinnStrument to find a comfortable setting for your playing.

Below is a video example in a trio context (bass, drums, soprano saxophone). Here, I am using a lighter touch which helps with control of the dynamics and pitch slides.

Suggested Approach

First, you will need to take the time to install the instrument and make the technical adjustments in the plug-in itself and the LinnStrument. The links above should help you with this task. It is very important to adjust the pitch bend setting to +/- 12 on the LinnStrument to take advantage of the full range (12 semitones) of the instrument for sliding.

Second, take the time to get used to the breath control/pressure sensitivity and make adjustments on the LinnStrument. There are three settings for High, Medium, and Low along the bottom row in the settings panel.

Third, practice articulating between notes – staccato, sliding your finger into the next note, and the slurring feature (holding down the first note and holding down a second note for the chromatic slur).

Above all, have fun!

Jeremy Cubert

Jeremy Cubert

Jeremy Cubert

Jeremy Cubert is a solo artist and member of the jazz fusion band Apothecary (www.apothecaryband.com) and international progressive rock band Formativ (www.soundcloud.com/formativ). He has recorded with Jon Anderson and Billy Sherwood of Yes and the bands Quest, Zapotec, History of Ties, and the Archaic Revival.

While primarily a piano and keyboard player, Jeremy has studied and played instruments including the Chapman Stick, LinnStrument, Zendrum, Eigenharp, guitar, Godin MultiOud, and trumpet.

soundcloud.com/jeremycubert
The Jeremy Cubert Project

All screen shots used in this blog post are used with permission from Roger Linn Design. The saxophone image is a Public Domain image via Wikimedia Commons.

Logic Pro Scripter editor

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.

As part of my musical journey with LinnStrument, I’m exploring ways to exploit more fully both its expressive and polyphonic capabilities.  One tool that I’m using for this purpose is the Logic Pro Scripter MIDI plug-in.  Scripter enables a developer to write Logic Pro extensions in JavaScript that process MIDI events as well as generate them.  To help me grok the Logic Pro Scripter API I created the quick reference located in the following section.

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/
 MADSP.framework/Versions/A/Resources/EventTypes.js
Scripter  – Global attributes and functions
NeedsTimingInfo:boolean Defining NeedsTimingInfo as true at the global scope enables the GetTimingInfo() function
ResetParameterDefaults:boolean Sets UI controls to default values
HandleMIDI(Event) 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.
ProcessMIDI() 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.
ParameterChanged(integer, real) 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.
Reset() This function is called when the plugin is reset
Trace(value) Prints a message to the console that represents the supplied value of any type
GetTimingInfo():TimingInfo Retrieves a TimingInfo object, which contains timing information that describes the state of the host transport and the current musical tempo and meter.
GetParameter(string):real Returns a given parameter’s current value. GetParameter() is typically called inside the HandleMIDI() or ProcessMIDI() functions.

Event – Base class for all events
send() Send the event
sendAfterMilliseconds(ms:real) Send the event after the specified value has elapsed
sendAtBeat(beat:real) Send the event at a specific beat in the host’s timeline
sendAfterBeats(beats:real) Similar to sendAtBeat(), but uses the beat value as a delay in beats from the current position.
trace() Prints the event to the plug-in console
toString() Returns a string representation of the event
channel(integer) 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
Note() Constructor
toString() Returns a String representation of the Note event.

NoteOn – Represents a note on event
NoteOn(Event) Constructor
pitch(integer) Pitch from 1–127
velocity(integer) 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
NoteOff(Event) Constructor
pitch(integer) Pitch from 1–127
velocity(integer) Velocity from 0–127

PolyPressure – Represents a Polyphonic aftertouch event
PolyPressure(Event) Constructor
pitch(integer) Pitch from 1–127
value(integer) Pressure value from 0–127
toString() Returns a String representation of the PolyPressure event.

ControlChange – Represents a ControlChange event
ControlChange(Event) Constructor
number(integer) Controller number from 0–127.
value(integer) Controller value from 0–127.
toString() Returns a String representation of the ControlChange event.

ProgramChange – Represents a ProgramChange event
ProgramChange(Event) Constructor
number(integer) Program change number from 0–127
toString() Returns a String representation of the ProgramChange event.

ChannelPressure – Represents a ChannelPressure event
ChannelPressure(Event) Constructor
value(integer) Aftertouch value from 0–127
toString() Returns a String representation of the ChannelPressure event.

PitchBend – Represents a PitchBend event
PitchBend(Event) Constructor
value(integer) 14-bit pitch bend value from -8192–8191. A value of 0 is center.
toString() Returns a String representation of the PitchBend event.

Fader – Represents a Fader event
Fader(Event) Constructor
value(integer) Fader value from 0–127
toString() 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
playing:boolean Value is true when the host transport is running
blockStartBeat:real Indicates the beat position at the start of the process block
blockEndBeat:real Indicates the beat position at the end of the process block
blockLength:real Indicates the length of the process block in beats.
tempo:real Indicates the host tempo.
meterNumerator:integer Indicates the host meter numerator
meterDemoninator:integer Indicates the host meter denominator.
cycling:boolean Value is true when the host transport is cycling
leftCycleBeat:real Indicates the beat position at the start of the cycle range
rightCycleBeat:real Indicates the beat position at the end of the cycle range

MIDI – Contains class-level variables and functions (you don’t instantiate MIDI).
_noteNames:string[] Contains names such as C and G# for all 128 MIDI notes
_ccNames:string[] Contains names such as Expression and Sustain for all 128 MIDI controller numbers
noteNumber(string) Returns the MIDI note number for a given note name. For example: C3 or B#2. Flats not permitted.
noteName(real) Returns the name for a given MIDI note number.
ccName(real) Returns the controller name for a given controller number
allNotesOff() Sends the all notes off message on all MIDI channels
normalizeStatus(real) Normalizes a value to the safe range of MIDI status bytes (128–239)
normalizeChannel(real) Normalizes a value to the safe range of MIDI channels (1–16)
normalizeData(real) Normalizes a value to the safe range of MIDI data bytes (0–127)
_sendEventOnAllChannels(Event) 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.

Anyway, that’s some of the functionality that currently exists.  To give you a feel for the JavaScript code used in this script, here are most of the contents of the HandleMIDI() function, which is called at runtime whenever a MIDI event is received:

function HandleMIDI (event) {
  if(event instanceof NoteOn) {
    LAST_NOTE_EVENT = event;
    if(event.pitch <= KEYBOARD_SPLIT_POINT && chordsEnabled) {
      triggerStrum(event);
    }
    else {
      event.send();
    }
  }
  else if (event instanceof NoteOff) {
    event.send();
    if (event.pitch <= KEYBOARD_SPLIT_POINT || 
        ACTIVE_NOTES.indexOf(event.pitch) !== -1) {
      cancelStrum(event);
    } 
    toggleTonality = false;
    play7th = false;
    assignChordsByKey();
  }
  else if (event instanceof ControlChange && 
           event.number === 64) {
    if (event.value <= 63 ) { 
      if (PEDAL_A_ENABLED) {  
        PEDAL_A_ENABLED = false; 
        cancelStrum(LAST_NOTE_EVENT); 
        assignChordsByKey(); 
      } 
    } 
    else { 
      if (!PEDAL_A_ENABLED) {
        PEDAL_A_ENABLED = true; 
        assignChordsByKey(); 
        if (ACTIVE_NOTES.length > 0) {
          cancelStrum(LAST_NOTE_EVENT);
          triggerStrum(LAST_NOTE_EVENT);
        }
      }
    }
  }
  else {
    event.send();
  }
}

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.

Regards,

James Weaver
Twitter: @JavaFXpert