Tag Archives: grammar

Additive Rhythmic Grammar

As part of a larger scheme for building more coherent melodies, I'm looking into a better grammatical method for representing rhythms.  The additive rhythmic grammar technique may pave the way for better rhythmic coherence in future melodic plugins.

The general idea is to create very simple rhythmic words.  Then, define probabilities for each word - for example, the probability that the word will occur in the first, second, etc. measure.  These probabilities should, for maximum coherence, be either very large (~1) or very small (~0).  Finally, when retrieving the total rhythmic format for a given measure, simply "add" each rhythmic word that has an adequate chance of occuring in the measure.  The key here is that we can treat the words as simple mathematical entities that can be summed, subtracted, and have basic binary operations performed on them.  In this way, it is possible to create a complex rhythmic pattern by using only simple building blocks.

Yes, in reality, it's a very simple idea.  Nonetheless, I've never tried such "additive grammar" before.  Anything is worth trying.

Grammar + MSE = gMSE

Both the multi-state engine and the Markov engine have been finished in the past week.  Now, to tackle a new implementation of GGrewve with maximum ease-of-use, I've dreamed up yet another type of engine.  It's a rather simple hybrid type that will combine grammar with multi-state analysis.  Not surprisingly, I will call it gMSE (grammatical multi-state engine).

One can think of gMSE as being a valuation dictionary based on a plurality of states.  The gMSE answers queries of the form "What quantitative value would [word] receive based on past analysis and given that the current state is [state plurality]?"  Perhaps more importantly, gMSE can answer queries of the form "Which word would received the highest/lowest quantitative score based on past analysis and given that the current state is [state plurality]?"  In this way, the grammatical multi-state engine embeds grammatical data in the analysis of state pluralities.

This new engine will, ideally, make a newer and better version of GGrewve quite easy to create.  Since GGrewve is based on probabilistic grammar analysis, it is easy to see how gMSE could accommodate the GGrewve engine plus added levels of depth thanks to the multi-state analysis.  All of this can be accomplished with just a single object: a gMSE space.  The gMSE space itself contains a grammar dictionary, an MSE space, and an MSE statestream, all wrapped into a single, easily-manageable object.

Fractal Grammar

For some time now I have been thinking about using random cutting as a "base" method for a hybrid engine, using the cutting space to control the behavior of another process. These thoughts came to a head a few nights ago when, despite an enormous amount of brainstorming and coding, contour grammar failed to deliver the immediate results for which I was looking. I wasn't joking when I suggested a "fractal grammar" in the last post. Indeed, having now toyed around with implementations of the idea, I believe that this hybrid technique will capitalize on both the contextual coherence of random cutting as well as the internal consistency of grammatical systems. I will refer to the method as fractal grammar from now on.

Fractal grammar is, to put it simply, a grammar system driven by a random cutting engine (which, as discussed previously, falls under the category of fractal methods - specifically, Brownian motion). The engine first performs the same preliminary steps used in Fraccut, placing cutting blocks on the roots (or another specified interval) of each chord, then performing random cutting to subdivide the blocks. Instead of mapping the subdivided blocks directly to pitch space, however, the fractal grammar engine maps block offsets to indexes of words.

Here's an overview of the basic fractal grammar process:

  1. Create a space for random cutting
  2. Map chord progression to blocks in the cutting space
  3. Perform random cutting on the space
  4. Create a phrase (in the style of Contour Grammar)
  5. Map the cutting space to the phrase
    1. Iterate through blocks, for each:
      1. Map the vertical position (traditionally pitch offset) to the index of a word and add the corresponding word to the active phrase
      2. Map the width (traditionally duration) to the duration of the specific element of the active phrase
  6. Convert the phrase into a polystream
  7. Apply final mappings (offset->pitch, time scaling, etc.)
  8. Convert the polystream to a pattern

Note that the first three steps are precisely the steps taken by Fraccut, while the last three steps are precisely those taken by Contour Grammar.  The middle steps, then, are the most important - it is the mapping between the fractal engine and the grammar system that is most crucial to the final product.

Thankfully, fractal grammar has already produced some nice results.  Though not quite up to par with Fraccut yet, I have no doubt that the fractal grammar method, when it reaches maturity, will far surpass the abilities of random cutting and contour grammar.

Sample 15, the first in three months, will come online shortly!

Contour Grammar vs. Fractal Cutting

Finally, having completed a basic implementation of Contour Grammar, I am getting to see what the idea sounds like in musical form. Indeed, some very interesting effects have been achieved thanks to the functional phrase language as well as the use of coherent random sources (which I will discuss at some point in another post). However, even this idea is lacking the coherence of Fraccut, and it bothers me enormously that such an elaborate idea as Contour Grammar can't even beat a relatively simple implementation of random fractal cutting, a rudimentary mathematical process.

Of course, it's very obvious why Fraccut still holds the record for best melodies. Since the cutting engine essentially starts with the chord progression as a seed, coherence is almost guaranteed. It's a powerful effect. Yet, the reality is that Fraccut is hardly aware of what it is doing. In a sense, the coherence generated by Fraccut is nothing more than a cheap trick stemming from the clever picking of the seed. Nonetheless, it undeniably works better than anything else. In the end, I am concerned only with the audible quality of the results, not with the route taken to achieve said results.

That being said, the big question now is: how can Contour Grammar pay closer attention to context in order to achieve greater contextual coherence? It would be nice to somehow combine the internal consistency of Contour Grammar with the external, contextual coherence of Fraccut.

Grammatical fractal cutting, anyone?

Contour Grammar Process Flowchart

The Contour Grammar engine, though still young, is already evolving into a complex system of data handling that will, if expectations are met, provide a great deal of both creativity and coherence in future melodic plugins.

The data structure, in brief, works as follows:

  • Words comprise an array of offsets
  • dWords comprise a word dedicated to pitch offsets and a word dedicated to rhythmic blocks
  • Dictionaries comprise many words or dWords
  • Phrases comprise a pointer to the base dictionary of the language in which the phrase is "spoken," a word that provides the rhythmic structure of the phrase (think: rhythmic shells technique), a dWord array that contains the words within the phrase and an array of lengths for the words; this last piece of data is only necessary if the structure word is omitted
  • Polystreams comprise separate arrays for the different elements of a musical note

It is far easier to understand the process through visualization:

Note that, if the engine is instructed to use the accent list (i.e. use the array of lengths for phrase rhythmic structure rather than a word), then this technique requires random or chaotic sources in two places. If the plugin uses words for rhythmic structure, then the technique requires a total of three such sources. This requirement provides ample opportunity for creativity, as we could try different combinations of random sources and observe the results.

Though work on Contour Grammar is progressing at a rather sluggish pace due to an unusually busy week, I anticipate a very productive weekend.

Functional Phrase Language for Contour Grammar

Unfortunately, most of my work over the past week has been devoted entirely to the internals of Contour Grammar.  The format of the data structures will completely govern the quality of the plugin's future, so I wish to spend a great deal of time and thought on the layout of the grammar engine.

A minor breakthrough (which, oddly enough occurred in an airport) did provide a boost of inspiration. One of the current problems with Contour Grammar lies in the ambiguity in defining phrases. How should phrases be picked to maximize coherence? My newest solution to the problem entails a sub-grammar that I call functional phrase language, since it uses functions to indicate derivations of new words from parent words. In this way, rather than filling phrases with a random array of words, the program will fill the phrase with a random array of functional instructions that should ensure greater coherence.

Here's an example of what a line of such instructions might look like:

1,2,1.up.up,2.invert,1.maxdown

And here's how the Contour Grammar engine would read and interpret the instructions:

  1. Draw a random word from the active dictionary, label it "1," and add it to the active phrase
  2. Draw a random word from the active dictionary, label it "2," and add it to the active phrase
  3. Take the first word, translate all pitches up 1 step, then translate all pitches up another step, and add the resulting derived word to the active phrase
  4. Take the second word, invert the pitches (horizontal reflection), and add the resulting derived word to the active phrase
  5. Take the first word, determine the maximum pitch, then translate each occurrence of the maximum pitch up 1 step, and add the resulting derived word to the active phrase

If everything goes according to plan, Contour Grammar should be off the ground and getting cold, hard results by the end of the week. As I mentioned before, I really hope to have some unique samples up for February before it comes to a close. Audible progress is real progress!

Rhythmic Shells

With the contour grammar engine in development, I am still searching for ways to simplify and optimize grammatical representations. At the moment, the most restrictive element of the engine is the separation between rhythm and pitch. In current engines, the two are completely separated into different streams driven by different grammar sets. Not only does this approach render it difficult to work with both streams at the same time, but it also negatively impacts the ability of the engine to produce coherence between pitch and rhythm.

A new idea I call "rhythmic shells," however, might promise an enormous simplification of the process, combining both streams into one while offering greatly improved coherence potential at the same time. The method focuses on stripping pitch words of all length dependency and transforming rhythm into a specification of pitch words. In essence, a rhythmic "shell" is selected, which contains a prescribed number of "slots," each with a distinct duration, and the slots are then filled with pitch words. The method requires that pitch words be functions rather than definitions - that is, they must be of arbitrary length and cannot be precomputed.

Here's a simple diagram of the method:

The shell stream can be specified with a simple data structure like this:

13:2,4,5
15:2,8,6
13:2,4,6

The number on the left side indicates the index of the pitch shell to be used, while the comma-delimited numbers indicate the indices of the pitch functions with which to fill each shell slot. Notice that the phrase produced by a shell can be variated by leaving one or more elements intact while changing the others, creating a different, but still somewhat similar phrase. This will certainly guarantee more coherence.

It is worth noting that, given the functional nature of the pitch words in this description, the method of rhythmic shells if very much like a generalized method of curve-splicing, which was discussed several weeks ago!

In the next few days I put a great deal of work into the contour grammar engine to try to implement the method of rhythmic shells. I also hope to continue finding new innovations for the simplification, unification, and overall improvement of grammar techniques.

Music, Grammar, and Information Theory

Spurred on by the idea of contour grammar, as explained in a recent post, I have been brainstorming grammar engines a good deal lately. I just finished drawing up a concept I call "unified grammar," which may present a promising method for abstracting units of pitch all the way up to phrases with contextual meaning. Of course, I wish to explore contour grammar a bit more before delving into a new grammar theory.

Thinking, however, has led me to an interesting proposition. I propose that much of the enjoyability of the music to which we listen stems from having a balanced amount of "information" contained within the music. This is not a novel theory, as others have explored it before - namely, Leonard Meyer. It struck me, as I analyzed one of my favorite orchestral pieces using my unified grammar method, that the melody of the piece could be represented, grammatically, by far fewer bytes of information than would be necessary to represent each pitch individually. That is, the melody had a sort of "compressibility" to it - one could compress the melody into several simple strings representing how values of different levels of a grammatical hierarchy change over time. It strikes me that the pieces of music I enjoy the most have some redundancy, but never too much.

Of course, it's obvious that music leans heavily on the concept of repetition, but information theory offers a new perspective in grammar applications. One could, for instance, limit the number of possible values for each level of the grammatical hierarchy, essentially placing an upper bound on the amount of information melodies could contain. This would prevent the piece from becoming too chaotic and uninterpretable. Likewise, one could place a lower bound on the number of values utilized for each level of the hierarchy, preventing the piece from becoming too monotonous. At the pitch level, this would mean that the melody must use between x and y unique pitches; at the word level, it would mean the melody must use between x and y different ways of grouping pitches; finally, at the phrase level, it would that the melody must use between x and y different ways of grouping words.

One final remark: ensuring that such restrictions are placed upon grammatical engines in no way ensures coherence in melody. At best, these restrictions can prevent monotony and chaos. They do not, however, guarantee meaningful music. For this reason, it is critical that the engine perform careful analysis when choosing how to group pitches and words in order to bring the grammar back down to a concrete level. Working with hierarchical abstractions always introduces a danger of becoming too removed. Consequence analysis must be performed at the base level - that is, at the pitch level - before decisions are made.

Grammatical Representation of Contour

Though the mathematical melodies of Entropic Root provide excellent and oftentimes interesting background patterns, they still lack the coherence of a genuine, human-crafted melody. I do not wish to imply that no progress has been made towards that ultimate goal of realistic melodies, however, I must be realistic in admitting that a mathematical method like Entropic Root cannot achieve the same level of composition as a human because Entropic Root, at its core, does not have any concept of what it is creating: it is not intentional.

Contour seems to be a reasonable way to mold a melody before determining actual pitches. In the past, great success has been achieved with grammatical representations of music. GrammGen, the first I ever wrote, implemented a very simple grammatical system for generating melodies. Though not up to par with the performance of modern plugins, GrammGen often provided interesting melodies. Like Entropic Root, however, GrammGen had very little deliberateness in its actions. In order to resolve this, I hope to combine the premeditative abilities of contour shaping with the structural simplification of grammar engines to achieve a deliberate and coherent melody generation engine.

Essentially, I am introducing yet another grammatical engine. This engine, however, will be based on a “contour as a language” paradigm. In other words, it will treat the words of the grammar as having contextual significance because of a contour correspondence. Rather than assigning progressive, numerical values to randomly-generated words and jumbling them together to create a phrase, this “contour grammar” engine will recognized the contextual significance of each word by its parent type. There are eight parent types, which correspond directly to fundamental units of contour: two jump contours, two linear contours, and four “bounce” or “pivot” contours. Words will then be randomly generated under parent types, but the engine will know to which type of contour a given word belongs. A Markov engine or simple multi-state engine will determine the contextual significance of contour units.

Below is a quick sketch of the eight fundamental units of contour.

If we imagine that each line segment has an arbitrary magnitude (but that segments equal in size in the diagram have equal magnitudes), then it is not hard to see that these eight fundamental units actually characterize most possible monophonic melodies. This is especially true if one considers certain transformations such as stretching and splitting.

I am hopeful that the method of contour grammar will be a historic step towards intentionality in output for mGen, starting with melodies.

Spirit

Spirit is a new generative module designed to provide lead parts. Spirit operates on a hybrid algorithm with a paradigm similar to that of the partial idea stream idea that I brainstormed a few months back. It also exploits the ease-of-use of the new XIAS library.

Three separate "streams" power Spirit: control, config, and duration. The control stream tells Spirit how to behave - that is, whether to use arpeggiation, single notes, or chords. The configuration stream provides details that determine individual pitches (or words, in the case of the control stream requesting a grammar engine). Finally, the duration stream is exactly what one would expect - duration information. Separating the duration stream from the streams that control pitch allows the module to uphold a degree of rhythmic consistency. This is similar to the way that I separate the melodic and rhythmic seed strings in Fraccut to make rhythm and pitch somewhat independent.

Right now Spirit is making effective use of both the L-system and grammar engine features of XIAS.  Great - and unique - results have already been obtained even with a very rough version that made use of only three control types and three config types.  Sample 11 on the sample page showcases this early version of Spirit and promises much more to come!

Some long-term goals for Spirit:

  • Develop "character"  - distinct styles that vary with configuration
    • Restricted grammars
    • Beat emphasis
    • Markov data (as a supplemental "weight" in decision-making)
    • Global variables
    • Restrict algorithm types among configurations
    • Production rules (L-system)
  • Make effective use of all algorithms available in the XIAS engine (perhaps with the exception of the evolutionary engine, as it seems inapplicable)
  • Strictly obey the instructions of the coordination module
  • Achieve a level of creativity above that of any other generative modules
  • Achieve a level of coherence above that of any other generative modules