Using Python with the External SoundObject versus the Python SoundObject

This has been the most often asked question since the addition of the external SoundObject blue, and when I initially put in the external SoundObject, I thought that the Python SoundObject would become somewhat unnecessary.

But a week or so after the addition the of externalObject, I started using Python alot more in conjunction with blue and found that the Python SoundObject has a few key benefits which make me use it now everyday.

The Case for Using the External SoundObject

First of all, performance of the PythonObject is not as fast as using the standard Python interpreter with the external SoundObject. For simple scripts, the difference in speed isn't that noticeable, but when using something like pmask which has alot of calculations when generating score output, the speed difference does become an issue. If speed is an issue, then you might choose to use the external SoundObject, if the benefits listed below aren't an issue.

Also, if you have an existing Python interpreter installed on your computer and have libraries installed and are just simply used to your setup, then it might be just plain easier to use your existing Python setup rather than dealing with where things are in blue and managing having libraries installed for both the resident Python interpreter and blue's PythonLib.

And to add to all of that, you may be using features which are part of the most recent Python interpeter version, and those features may not be available as part of Jython (more information as to what Jython supports is available at the Jython homepage, Also, if you're using libraries which call native code, they will not work with Jython.

So, if the Python SoundObject is slower, if you have to manage another set of libraries, and you might not have all of the features of standard Python available, why use the Python SoundObject at all?

The Case for Using the Python SoundObject

Now, just to let you know, I use exclusively the Python SoundObject when I'm doing Python scripts in blue. I haven't come across any of the standard libraries I've needed that were't included with Jython, and if it's a sign of anything, Maurizio Umberto Puxeddu's pmask library works fine with the PythonObject.

One of the things I used to do is keep an installation of blue on a zip disk, including my work. The nice thing about this was that I was able to take this disk and work off it while at work on a windows machine, as well as take it home everyday to my linux machine and start up blue without having to do anything different. Because I used the PythonObject at that time, I didn't have to worry at all about anything installed within either system, as all of it was contained within blue. It's also a reassuring thought that if I took my work to a friend's computer, be it a macintosh, windows, or linux pc, I wouldn't have to worry about if Python was installed on their computer.

Besides these very practical issues, the way you can go about using the PythonObject differs very much from the usage of Python with the externalObject.

With the externalObject, each script run is its own entity, run with a different interpreter. This means that memory is not shared between instances of the externalObject: variables and results of execution in one externalObject are not accessible to another externalObject. However, with the PythonObject, the interpreter is not reinitialized between runs, meaning you can share results between one PythonObject and the next. This can of course lead to very convoluted methods of developing scripts within blue, which is of course not recommended, but it does have some very pragmatic possibilities which are very useful.

In my latest work with blue, I've been using almost exclusively the PythonObject for all of my SoundObjects in blue. I did use some sound SoundObjects initially to draft some sounds out, converting them to instruments in the orchestra manager later. I also used genericScore objects for writing some test notes for my instruments which I keep around also for experimenting, but for the piece's final output, they are not being used.

For setting up my piece, I developed some classes to use in Python, instantiated multiple instances of the classes set with different parameters, and then use those instances in different PythonObjects in blue for creating the score of my piece. Because the interpreter is not being reinitialized between uses by the PythonObject, I'm able to use one PythonObject to hold only definitions of functions and classes, another PythonObject which only has my initialization scripts that makes instances of the classes defined in the first PythonObject, and from all other PythonObjects, I use the instances from the second PythonObject as my generators.

to better clarify, my first PythonObject has scripts like:

class Yo(): 
    def do(self, a,b):
        print "doing something with " + str(a) + " : " + str(b)

    def yoyo(self, a,b):
        print "do something with a and b which are instances of Yo()"

while my second PythonObject has script like:

generator1 = Yo()
generator2 = Yo()
generator3 = Yo()

while all other PythonObjects in my piece have a minimal amount of script, something like:

generator1.generateNotes(input1, input2, input3)

I find that it's a nice way to separate the concerns of each object. as I'm currently in the middle of working on the piece, I'm finding that first PythonObject getting a bit big, so I'm thinking i'll split that into different PythonObjects, which I can visually see labeled on the timeline by changing their names to something like "generator classes", "generator utility functions", "constants", etc. and probably in the future, as I get to finishing this piece, I'll probably take all of these class definitions and make a library of Python code out of it and just have it installed into my PythonLib directory. But having the way it is now I've found to be very convenient in development as it's easy to find all of my code.

Note: the execution order of blue is top-down per soundLayer, meaning it will process all SoundObjects in the first soundLayer, and if it finds a polyObject, it will go down into that and process the first soundLayer, etc. before going on to the next SoundObject. because of the execution order, I can put all of my PythonObjects that have nothing to do with note generation (my class definitions, utility functions, and intitialization scripts) in the first few soundLayers of my piece and know that they'll always get interpreted by the jython interpreter and left in the memory space first before trying to process the other SoundObjects.

Note: as a warning, also because of the execution order, if you reopen your piece and try the [test] button on a PythonObject that uses code from the initial PythonObjects and find that it's not generating notes, it's because that code has yet to be entered into the memory space of the interpreter. either individually running all of the PythonObjects that deal with class definitions and initialization or just pressing the [play/stop] button to generate your score will get those objects interpreted and entered into the jython interpreter's memory.

Because of this alone, I find I use the Python SoundObject more than I do using the external SoundObject. if I was to use the external SoundObject and wanted work an even remotely similar manner, I'd have to come up with some strange hack to maybe write script in one external object have the execution of that object write that script into a file which would have to be reimported into other scripts. not a horrible hack, but enough for me to want to avoid, especially when it's not necessary. (though, if you're programming in a scripting language besides Python, you would hack to work in a manner like this...)