In this post I describe the concept language of the music AI. It is based on fuzzy first-order logic.

It has two data types: phrases, and floating point numbers.

Phrases are of two types: notes, and complex phrases. Complex phrases are phrases consisting of a set of sub-phrases.

Notes have three properties: pitch (0 to 87, for the 88 piano keys), velocity (0 to 127 — the MIDI velocity values), and duration (in ticks — some unit of time).

Complex phrases are sequences (the order is arbitrary) of phrases. Each phrase is coupled with an offset value, saying how many ticks away from the start the phrase is.

A truth value is a number between 0.0 (false) and 1.0 (true).

The following primitive constants are defined:

* Zero.

* The empty complex phrase (nil).

The following primitive functions are defined (and possibly others that prove useful):

* Successor, addition, subtraction, multiplication, division, round down.

* Note pitch, note velocity, note duration.

* Number of sub-phrases in a complex phrase.

* Duration in ticks of a complex phrase.

* Make note with a given pitch, velocity, and duration.

* Non-destructively add sub-phrase to complex phrase. (cons)

The following operations (from the definition of primitive recursive functions) can be used to make new functions:

* The projection functions.

* Composition.

* Primitive recursion.

The following primitive predicates are defined (and possibly others that prove useful):

* Is a number? Is an integer? Is a phrase? Is a note? Is a complex phrase?

* Less than, greater than, equals, less than or equal, greater than or equal.

* Number is in range of possible note pitches.

* Number is in range of possible note velocities.

The following operations can be used to make new predicates:

* Not P, P and Q, P or Q, P xor Q, P only if Q, P iff Q.

* Truth value of P is {equal to, less than, greater than, less or equal, greater or equal} N.

* Given a number 0.0 <= N <= 1.0, yield truth-value N.

* Universal and existential quantifiers over the members of a specified complex phrase. (The quantifier creates variables for both the sub-phrase and its offset.)

* Universal and existential quantifiers over a specified range of integers.

Predicates can take data parameters, and substitute them in the body of the predicate. Predicates can invoke other predicates. There cannot be circular dependencies in the invocation graph; direct or indirect recursion is not allowed.

This language is primitive recursive, rather than recursive. This means that it is impossible to write functions or predicates that take infinite time to compute.