Category Archives: Chords

counterpoint-composer-ui-mini-with-border

Introducing Counterpoint Composer

Note: This article is a remix for CulturedEar.com blog of my original post on JavaFXpert.com

It is hard to write a beautiful song. It is harder to write several individually beautiful songs that, when sung simultaneously, sound as a more beautiful polyphonic whole. The internal structures that create each of the voices separately must contribute to the emergent structure of the polyphony, which in turn must reinforce and comment on the structures of the individual voices. The way that is accomplished in detail is…’counterpoint’.
– John Rahn

As a part of my day job on the Pivotal evangelism team, one of my primary activities is to create demo applications and use them as a basis for technical presentations at conferences. I’d like to share with you the first such demo app, named Counterpoint Composer, located at CounterpointComposer.com

Counterpoint Composer, developed in the Java programming language, leverages rules expressed by composers such as Giovanni Pierluigi da Palestrina and Johann Joseph Fux in the 16th – 18th centuries to create counterpoint music. It also builds on the work of Bill Schottstaedt who coded those rules using the SAIL and C programming languages, and the chord analysis capabilities of JFugue by David Koelle. As an example of using Counterpoint Composer, here’s a two-minute video of creating a counterpoint tune from the melody known as Twinkle Twinkle Little Star:

If you’re new to counterpoint, a gentle introduction to it is the Species Counterpoint article by Nicholas H. Tollervey

Counterpoint Composer application diagram

If you’ll permit me to dive a bit into the software aspects of Counterpoint Composer, here’s a high-level diagram of the application:

counterpoint-composer-architecture

The user interface of this application is a one-page web app that uses a dynamically embedded music notation component from Noteflight.com. As shown in the diagram above, this application also includes the following two microservices available via HTTP protocols:

  • CounterpointService:  Given a JSON representation of the main melody, initial chord, counterpoint species, and music mode, this service returns a MusicXML representation of the resultant counterpoint composition.
  • ChordAnalyzerService:  This service analyzes a set of musical notes to see if they represent a musical chord, returning the name of an identified chord.

Here is an illustration of these services, including how the CounterpointService uses the ChordAnalyzer service:

rest-services

Getting up to speed with Counterpoint Composer

The best way to get up to speed with Counterpoint Composer is to follow the guidance of the Getting Started tutorial which is available in the app’s Help -> Getting Started menu item:

help-menu

The resources in the Getting Started tutorial demonstrate how to generate each of the five species of counterpoint, and how to select various scale modes.  The tutorial also demonstrates how to disable one or more of the 70+ counterpoint rules in the following dialog to see/hear the effects on the composition:

counterpoint-rules-dialog-toggled

In addition, the Help -> Technical Presentation menu item contains slides that give a technical perspective of the application.

Independently demonstrating the ChordAnalyzerService with the Web MIDI API

The penultimate slide in the deck mentioned previously contains the following diagram of how the ChordAnalyzerService may be demonstrated with a MIDI keyboard connected to a computer that has a Chrome browser. Opening the Chord Analyzer Client web app in the browser and playing simultaneous notes on the MIDI keyboard should result in the chords being identified and displayed as shown below:

chord-analyzer-architecture

Please note that it is best to use the Chrome browser, as that is currently (Nov 2015) the only one that supports the Web MIDI API. I’m sure that you recognize the innovative instrument in the diagram above is a LinnStrument (the current focus of this blog) but any conventional MIDI keyboard controller should work as well.

Downloading the source code

The microservices described are running in Cloud Foundry at Pivotal Web Services, so the application links above should always be available. The source code is licensed under Apache License 2.0 and may be download from the following GitHub repositories:

It is my hope that this Counterpoint Composer application will serve as a resource for music students, as well as software developers, of all ages!

Regards,

James Weaver
http://CulturedEar.com

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