Tag Archives: c++

Cranking out Engines

It's almost mid-March already.  I don't like that fact the the samples haven't improved appreciably in a while.  As I noted earlier, it's mostly due to the fact that I've been upgrading internals rather than working on sound.  Still, it's time to step on it.

Over the past few weeks, I've been working like mad to re-code all the old engines in c++, taking advantage of the massive optimizations possible therein.  So far, the following engines are now at least partially-functional as part of the new c++ library:

  • Artificial Neural Network Engine (was actually never implemented in AHK and has yet to be used in a plugin)
  • Contour Grammar
  • Evolutionary Engine
  • Fraccut
  • Markov Engine
  • Multi-State Engine

ALL of the new implementations are better than their predecessors, both in terms of efficiency and ease-of-use.  Certain complex engines such as the Markov engine may see speed increases of over a thousand fold thanks to redesigning.

By the end of the month, these myriad engines should be coming together to form some really powerful new plugins.  All it takes is code.

Contour Grammar: Initial Results

It's been a long, bumpy road to the first functional mGen plugin written in c++. Nonetheless, tonight has seen preliminary results of the work-in-progress contour grammar system embodied in c++.

Contour grammar is, essentially, a marriage of two previously-brainstormed ideas: rhythmic shells and curve splicing. The name refers to the fact that, at heart, the engine is grammatical, using the method of rhythmic shells to handle words and phrases in context, but that words are defined using basic contours like those described in the curve-splicing method.

Unlike the grammar engine of GGrewve or GrammGen, contour grammar is functional in form, meaning that a word is not necessarily limited to a certain length. Rather than using an array of pitch or rhythmic offsets to characterize a word, contour grammar uses an array of coefficients that determine the properties of an infinite contour. Rhythmic shells then give precise instructions for transforming sets of these infinite contours into concrete, finite note streams.

Some expected advantages of contour grammar:

  • Arbitrary note size makes words extremely flexible (any given word can fill up any given amount of space, so no length-checking is necessary)
  • Rhythmic shells preserve rhythmic integrity of phrases
    • Shells still allow for variation by providing direct access to the words upon which the shell is built
    • Tweaking a single word's coefficients will change a specific part of the shell while preserving everything else, allowing for great coherence
  • Object-oriented data structures provide means of easily manipulating high-level variables that result in subtle, low-level changes
  • Very little conversion necessary between rhythmic shell and raw pattern
    • Rhythmic shell -> Polystream
    • Polystream -> Contextual Polystream (snap to key, duration *= quanta, etc.)
    • Contextual Polystream -> Pattern

So, in summary, contour grammar provides a flexible, coherent, and easily-variable data structure while still remaining concrete enough to require only a few minor steps to convert to pattern format.  In general, abstractions such as those made by grammar engines suffer from either a lack of coherence or a difficulty in de-abstraction (returning them to the base format).  Contour grammar, it seems, circumvents these drawbacks with a well-designed data structure.

Preliminary results with contour grammar already display some degree of coherence, a great deal of variability, and, most importantly, the potential for continued development and improvement.  February will surely bring some new, interesting samples!

MainBlock Importing Now Functional!

The c++ mGen Library is taking shape very rapidly. I am writing hundreds of lines of code each night in a furious attempt to get back on track with developing new and better plugins, since the month of January saw no sample clip activity. The MainBlock structure, set up to mimic the identically-named central data structure handled by the mGen framework and used to pass data to external plugins, now has full loading capabilities. In other words, output from the main framework can be read into this extensive c++ structure.

One might ask why on Earth managing to read one's own data structures should be applauded. The answer lies the differences between the AHK and c++ languages. In AHK, which the main framework uses to manipulate and write the data, the information is stored, essentially, as one huge string. I created special functions that encoded the strings in certain ways to allow them to function more like objects, but these did not actually extend the functionality of AHK, they only faciliated the organization of data within strings. Bringing the information contained within MainBlock into a c++ structure requires decoding a large, messy data string and parsing it, using the parsed data to create real data objects within structures that can be directly manipulated without string hackery.

The main point here is that MainBlock importing represents the first step in allowing external modules written in alternate programming languages to communicate with the central mGen framework, written in AHK. The next task will, naturally, be the ability to save a c++ MainBlock structure to the encoded string format that the framework expects to receive back from modules.

A visual of the exciting moment in which a full .gds MainBlock was imported into a c++ program:

GDS Interface Working

Just a quick update to indicate the rate at which progress on the c++ interface is coming - the GDS method of data handling has already been rewritten in c++.  Even though it's rather old and obsolete, this functionality will allow newer code to continue to communicate with older portions of the framework that use the GDS handling standard.

That's already one very large obstacle out of the way!

Thus Begins the Overhaul

Well, I can avoid it no longer.  Not having the ability to create plugins in an object-oriented programming language is simply killing me.  Hence, I will begin writing a c++ library for interfacing with the main framework.  The library will primarily be concerned with the ability to load data passed by the main framework into objects which will allow for more efficient processing, as well as the ability to save the data back to a format from which the main framework can integrate the new data into the composition.

Though the task is going to be rather daunting, thanks to the massive data structure specifications that I have created over time, it's also very exciting.  Building an object-oriented architecture just feels like it will offer immense benefits, and I have no doubt that it will speed up plugin-writing time, much like ScratchPad has done in recent months.

Little plugin coding progress has taken place this month thanks to my excursions in virtual worlds and artificial intelligence, and this trend will probably continue for the next few weeks.  Nevertheless, once the new library is complete, plugins will be back with a vengeance.  They'll be faster, easier, and more creative than ever before.

Revisiting aoAIm

To say that my recent efforts have been directed in nearly every direction imaginable would be an understatement.  Though part of me feels guilty for not having made any substantial progress in algorithmic composition in about two weeks, I have indeed accomplished a great amount of work.  Having written a full procedural particle-deposition terrain engine from scratch and finished part of the multithreading code to allow continuous terrain generation in real-time, I definitely feel good about the productivity of the month, even if mGen's code stagnated.

Now, with the rekindling of my interest in c++ as a viable platform for development (thanks to the discovery of some libraries that should drastically reduce development time), I am revisiting the component of my previous research that could have benefited most from an object-oriented language: aoAIm, the general artificial intelligence engine.

Previously, work on aoAIm, which was actually quite successful in many respects (see previous entries) halted due to the growing complexity of managing an object-oriented engine in a language with no objective capabilities and little real intensive processing capabilities.  It is for this reason that I am now rewriting the aoAIm engine in c++, taking advantage of the object-oriented nature if the language.  I've had a few good ideas concerning heuristic function evaluation as well, which should allow me to go further with the engine this time.

Once again, it is tempting to question how this relates to algorithmic composition.  I have previously provided rationales for pursuing a general artificial intelligence model based on the possibility of such a model introducing a sort of purpose or deliberacy into the music.  Now, considering the newly-widened scope of the project, it is clear that a general intelligence model would have great applicability in other algorithmic art fields as well.

A true model of intelligence is something from which I cannot forever hide.  At some point, mGen will be bottlenecked by a lack of intelligence, rather than a lack of algorithm choices.

Heading Towards c++

My investigations in neural networks have led me back to the conclusion that I can't hide from c++ forever. As well as AutoHotKey has served me over the past few years, I fear the power limits may finally be upon me. The fact of the matter is, c++ boasts a raw speed and power with which AHK can't compete. AHK wins for ease-of-use any day...but in algorithmic programming, the speed of c++ wins. As such, I'm bringing out the old c++ compilers again and learning my way around. I used to be pretty fluent in the language, but I've grown pretty rusty and have grown too content with the ease of AHK programming.

I'm reworking the neural network engine in c++, and looking to gain roughly a 100x performance increase (based on some numbers I've seen around the AHK forums). If there is justice in the world, that could mean 100x better function approximations, 100x larger neural nets, or even 100x better music. Who knows.

If c++ starts working for me again, I have a good compromise in mind. Design the GUIs in AHK, because they generally don't have to do much complicated work. They just have to look friendly. Then do the actually plugin processing in c++ to get the speed advantage. This part doesn't have to look good.

This should also solve another thing I've been worried about: code security from theft. If I really do release mGen, it'd be reverse engineer, cracked, and modified to the world's content by even the least adept hacker. The code of AHK is way too insecure because it's an interpreted language, which means the whole script is sitting right there in memory, waiting to be stolen. In c++, however, everything is compiled down to machine code, which would take way, way longer to reverse engineer. It could still be done. BUT, with c++, I could purchase obfuscation software, which would be the final step in preventing reverse engineering. It wouldn't keep out professionals that really want to crack my program. But obfuscated c++ would be about 1000x harder to reverse engineer than an AHK script (no obfuscation tools even exist for AHK). So that's something that's been sitting in the back of my mind.

Not to mention, it's nice to have an OOP language back. I've missed classes, and I my mind has matured to the point that I can now understand all the basic functions of c++, including classes, pointers & references, inheritance, etc. Hopefully my new neural net engine will prove it.