Melanalyze

OSCAR's Ears consists of a set of subroutines to construct probability arrays based on harmonic and melodic analysis. The harmonic and melodic analysis processes run simultaneously and in parallel. The melodic analysis process starts with input modules called |melinputmodule|. Each musical voice (on it's own MIDI channel) will use it's own |melinputmodule|.

A |melinputmodule| receives MIDI Note On and Note Off messages in it's inlets. |stripnote| removes Note Off messages and passes Note On messages. The Note On messages are then sent into |shiftanddiff|, which calculates the melodic interval between each note and the note that came immediately before it. |shiftanddiff| outputs a string of melodic intervals.

Melinputmodule Shiftanddiff
|melinputmodule| |shiftanddiff|
Melsort  
|melsort|

The string of melodic intervals is input into the top of |melsort|. |melsort| first checks to make sure that all of the intervals are in the allowable -12 to 12 range, and corrects any that fall outside of this range. The stream of melodic intervals is then broken into packets. Each packet contains two intervals, the current interval and the previous interval. Importantly, each interval that is input into melsort is included in two packets: first as the current interval, and then again as the previous interval when a new current interval is received.

The bottom portion of |melsort| is a routing mechanism that connects to the |melanalmodule| objects in the central analyzer |melanalyze|. The previous interval determines the routing of the current interval; if the interval packet is rising major third, falling minor second [4, -1], then the falling major second [-2] will be sent out the rising major third [4] outlet, called |s p4m|. The "s" is a "send" object, a kind of remote patch cable that connects to an "r" object with the same name; the "p" stands for positive or "rising" interval (as opposed to "n" or "u," which stand for "negative" and "unison"); and the "m" stands for "melodic".

|melanalmod| is at the heart of the array-creation process. One |melanalmod| object is used for each melodic interval in the range -12 to 12; the particular interval being tracked by a |melanalmod| is given in it's initialization argument. |melanalmod n12|, for example, keeps track of the intervals that follow a decending octave.

Melanalmod
|melanalmod|

A portion of a |melanalmod| object is presented here. The patch is large and complex, but is extremely redundant; aside from a few auxillary objects, a |melanalmod| consists of the same few objects, repeated twenty-five times (once for each possible interval). As mentioned, the "$1" that appears in nearly every object is replaced by |melanalmod|'s initialization argument. In the case of our example, |melanalmod n12|, every "$1" will be replaced with "n12." The |r $1m| at the top left of the patch becomes |r n12m|. This "receive" object is the destination of one of the |s| objects in |melsort|. In this case, this |melanalmod| will receive all interval packets that have "n12" as their previous melodic interval.

When a new interval is recieved in the |r|, several things happen. First, a running count of the total number of intervals that have been received is updated. This total is sent through the |s $1mtotal| connection for use elsewhere. The total is also displayed in the number box at the top right of the patch.

The new interval is then sent to the |select| object. |select| sends out a BANG whenever it receives input that matches one of it's initialization arguments. This |select| has twenty-five initialization arguments, namely the integers -12 through 12, and it has twenty-five outlets which correspond to the initialization arguments. An extra outlet (which is not connected to anything in this case) outputs any input that doesn't match any of the arguments.

Probcalc  
|probcalc|

Each of the outputs of the |select| object is connected to a |probcalc| object--there is one |probcalc| for each possible interval. When |melanalmod| receives a new interval, the |select| object sends a BANG to the corresponding |probcalc|.

|probcalc| counts the number of BANG messages it has received; it then divides it's count by the total counted by |melanalmod| (which is received in the |r $1total| object), resulting in a percentage. Notice that the |r $1total| is connected to the left inlet of the |/ | (division) object; this makes the |probcalc| update it's calculations each time a new total is received. Therefore, every time the |melanalmod| receives any new input (causing it's "total" counter in increment and send out a new value) each of it's |probcalc| objects will update it's calculations.

|probcalc| has a few more inlets and outlets that should be mentioned. A BANG coming from the |r reset| object (initiated by the user clicking on the "Reset" button in |listen_panel|) will reset |probcalc|'s counter to zero. |probcalc|'s right inlet receives information from a "restore" that resets the calculations to a previously saved state. |probcalc| has two outlets; one outputs the number of BANG messages that have been received, and one outputs the calculated percentage.

|melanalmod| also has a some additional inlets and outlets that haven't been mentioned. |s $1emelstoren12| and it's siblings (|s $1emelstoren11|, etc.) send the calculated probabilities to data arrays. |r $1restoren12| and it's siblings receive data that allows |melanalmod| to be restored to a previously saved state.

The melodic analysis process can be summarized:
      A voice connected to a |melinputmodule| plays a new note.
      The melodic inteval between the new note and the note that was played immediately before the new note is calculated by |shiftanddiff|.
      The new melodic interval is sent to |melsort|, which packs the new interval into a package with the previous interval
      The package is sent to a |melanalmod|. The first half of the package (the previous interval) determines which |melanalmod| is to be used. The first half of the package is then discarded.
      The second half of the package (the new interval) is receieved in the correct |melanalmod|. The |melanalmod|'s "total" counter is incremented, and the new count is distributed.
      The interval is routed to the |select| object, which sends a BANG to the |probcalc| that corresponds to that interval.
      The counter inside the |probcalc| is incremented.
      All of the |probcalc| objects redo their calculations using the incremented counts, generating new probability percentages.
      The new percentages are sent to the analysis arrays.

At the end of an analysis session, the analysis arrays contain information about the music that has been analyzed. If asked the question, "Given a melodic interval, what should the next interval be?" an analysis array would tell you, "Ten percent of the time it should be a rising perfect fifth, eight percent of the time it should be a decending minor second. . ."


Email Greg OSCAR Main PageHarmonanal