Monday, August 6, 2007

well, we're moving right along. last week i did clefs, importing measures (exporting had been done a while back) and notes of varying duration. I made an executive decision on that last one not to support importing chords with notes of more than one duration - something that's not really supported in Gsharp. While nothing in MusicXML stops you from doing it, it's not usually the best notational style; if the notes have different durations, they should probably be notated as being in separate voices.

I capped it off over the weekend by doing rests. Had a brief moment of trying to leverage CL's method combinations to export rests, since both they and clusters are melody-elements with the same interface for rhythmic properties and whatnot. I decided not to do it, because the nature of the whole thing seemed to make it more trouble than it was worth.

Thursday, July 26, 2007

More formal midsummer overview

(Current code. Requires the puri and cxml packages in addition to Gsharp's other dependencies.)

As it is the midpoint of the summer, it seems an appropriate time to take a step back and examine my progress so far. Besides basic sequences of notes, the following features are now fully supported in both import and export, except where noted:

  • Accidentals
  • Key signatures
  • Chords/clusters
  • Multiple staves
  • Measures (export only)

The last feature tackled prior to this report was support for multiple staves. Several more basic features demand attention: clefs, and perhaps most prominently notes that vary by duration are good examples (right now my work assumes that everything is a whole note). But a certain group of features are more "basic" in a completely different way: they are at the root of the structure of the musical data as represented in Gsharp and MusicXML. These are best implemented sooner than later because doing so touches a great deal of other code already written; this is partly because in order to do anything, including the simple "hello world" example with which this project began, code had to be written to supply constant versions of these structures. Early versions of the code always created one staff in one layer with one measure. Working on these features has also uncovered weaknesses in my Lisp programming technique and overall design; I discovered, for example, that I was overzealous in my use of generic functions and this was hindering my progress.

I have had my previous programming experience hinder me here and there as well. For example, I recently had an occasion where I was passing a variable down as a function parameter through several layers of functions, refusing to make it a global variable simply because it had been drilled into my head that such behavior was acceptable only on very specific occasions, and this was clearly not one of them. Christophe kindly reminded me that I could use real honest-to-goodness dynamic scoping and that my choices weren't limited to 2 kinds of ugliness. Overall however, I am not under the impression that my previous experience has been too much of a burden.

My biggest obstacle continues to be a problem I have, over the years, realized occurs in all kinds of engineering projects (for me anyhow). I simply try to implement five things at once instead of focusing my attention at one specific task at a time. This happened right at the beginning of the project, when implementing the initial, "hello world" parser. Only after a few days did I realize that i was trying to parse multiple staves, multiple voices and multiple measures. I think this might present more of a problem in this context because being fairly new to Lisp means I am less able to picture the general structure of the program in my head before I write it.

The following features remain to be implemented:

  • Clefs (export completed as of this writing)
  • Notes of varying durations
  • Multiple voices/MusicXML motion declarations
  • Rests
  • Ties
  • Lyrics
  • Menu entries for export and import

"Notes of varying durations" will also entail beams/flags and dots. "MusicXML motion declarations" refers to the "forward" and "backup" elements, which are used in MusicXML "to coordinate multiple voices in one part" -- the current implementation for more than one stave does not correctly deal with concurrent clusters on those staves. This feature is dependent on notes of varying durations. Given my current rate of progress, I see no reason why these features should not be completed by the end of the summer.

Monday, July 9, 2007

an overdue update

when we last left our intrepid programmer, he had produced basic code that exported from Gsharp to MusicXML in record time, leaving him with a program that could convert but a single note from Gsharp to MusicXML and back. Since then, he has added support for a number of additional musical features:

  • More than one note
  • Measures
  • Accidentals
  • Key signatures
  • Chords

All of these things can be both imported and exported. We rejoin our hero as he is working on adding support for multiple staffs (staves? i like staffs myself). There are a number of more basic things which need to be added (say, notes of varying duration) but that fiendish villain Multiple Staffs is threatening to disturb a lot of code in his quest to control all of the innocent notes and rests that populate the fair city of Gsharp, so Brian has elected to vanquish him now, though perhaps not once and for all. Waiting around that next dark corner are more complicated features, like Multiple Voices and Ties, and our programmer is only beginning to suspect to what level they are in cahoots with Staffs in some kind of unholy criminal alliance.

As for the state of my lispiness, despite the considerate speed discussed in my last post, my progress seemed to slow down immensely immediately thereafter. However, I think my fluency continues to improve at a steady pace. Christophe (my mentor on this project) says that he thinks it takes 10 years to become truly fluent, so I'm feeling pretty good.

Thursday, June 7, 2007

i am, at least in the non-programming sense, fairly functional

hooray, for i did the first iteration of MusicXML export in less than a day. I had a little bit of fighting with lisp, particularly where I tried to be extra lispy and use mapcar. Eventually, I realized that mapcar just wasn't doing what I wanted and I switched it to loop. I felt like I cheated a little, since I know that some lispers consider loop to be insufficiently lispy, and one of my major goals for the summer is to be able to think in lisp, whatever that means. On the other hand, I think the real spirit of lisp is probably more along the lines of this programming language makes it easier for you to hack code. Given that as an ethos, using loop allowed me to meet my goal, and got me there significantly faster than figuring out the right functional way would have. hence it was the right choice.

Wednesday, June 6, 2007

in the beginning was the note

well it's a milestone day here, as I have reached the point where saying the magic words (gsharp::gsharp-common (parse-mxml (musicxml-document "tests/helloworld.xml")) nil "Gsharp" 900 600) to SLIME produce this window: Exciting stuff I know. I'm actually a bit behind where I'd like to be at this point, and would like to have had this and the complimentary code that translates it back into XML done by now. Part of my delay was that, in spite of my illustrious proposal, I found it difficult to avoid feature creep as I wrote the initial, very simple version of my parsing function. Without really realizing what I was doing, at one point I was trying to work in support for multiple staffs and multiple parts in this initial version—big mistake. Once I came to my senses this came together pretty quickly.

I have hit a few snags along my way, including a bug in Gsharp itself, but my mentor has been helpful and the snags have so far been minor, especially compared to my Lisp inexperience which is still the major stumbling block. I don't expect that to change anytime soon, but I'm okay with it because part of the reason I wanted to do this project was that I knew I'd never learn lisp well enough to be useful unless I had a project that I needed to execute with it.

Wednesday, May 30, 2007

version control

well, yesterday was the first official day of coding for SoC. Besides spending time looking through code and playing around with some ideas, I also decided to set up some revision control for myself.

Gsharp is held in CVS on common-lisp.net, which i do not have write access to (nor do I want to at this time). My initial thought was to check it out of CVS, and then use some tool to make a private, local branch that I could work on (since CVS itself can't do branches which the central repository doesn't know about, hence requiring a commit bit on the tree). Some quick reading revealed that the newfangled git did exactly this fairly well, so i set about the task.

first step: checking out the source from common-lisp.net. No problem here, just followed instructions.

step 2: running git-cvsimport. You are supposed to be able to simply enter the checked-out cvs directory, specify where you want the git repository, et voila. It didn't really work like that. I tried specifying the cvsroot manually, running it from different directories and on and on, to no avail. I got a number of different error messages depending on exactly what directory I ran the command in and other things, but the one that kept popping up again and again was:

AuthReply: cvs [pserver aborted]: descramble: unknown scrambling method
After wrestling this for a while I gave up and skipped step 3.

step 3: run git-clone on the new git repository and get coding.

after spending some time dealing with the problem in step 2, i thought about what i was doing. in the end, 99.9% of my changes are going to be in one, new file. There are a couple of existing files that will get touched, but only in very small, easily reproduced ways (things like the asd file, which has a list of all of the other files). Thinking about it, I decided that this whole git operation was overkill anyhow. I'm just gonna use RCS.

UPDATE: since writing this, I couldn't help but think about the error message I got, and eventually I figured out what the problem was: when checking out the source from CVS, I used a newer form of the checkout command for anonymous pserver access. older clients (and apparently git or possibly cvsps which is used by git) require the old style cvs login in order to work with pserver. I was able to get the whole thing working fairly easily after that, but decided that my previous conclusion (learning a new VC just to maintain one file is silly) was still valid. I do have a tip however: when using git-cvsimport, be sure to use the -v flag. It can take a few minutes to run, so without output it's hard to tell if it's actually working.

Friday, April 13, 2007

project proposal

There has been some interest on the Summer of Code discussion list in seeing accepted proposals, so here's mine. Please note that the format is based on one provided to me by the mentoring organization, LispNYC.

Name

Brian Gruber

Project Title

Music interchange format support for Gsharp

Synopsis

Functionality will be added to the Gsharp score editor allowing the importing and exporting of scores in the MusicXML format.

Benefits to the Lisp/Scheme Community

With support for this interchange format, users of Gsharp will be able to integrate it into a work environment that includes a bevy of other music software. Furthermore, composers not currently using Gsharp could be enticed to try it, assured that it will play well with the other tools they have become accustomed to.

Project Details

The project will focus on adding import/export functionality to the Gsharp score editor. Gsharp could be a powerful application for creating and editing sheet music, but currently work created in Gsharp is effectively stuck in Gsharp. This severely limits the application's utility.

MusicXML, an XML interchange format for sheet music, was specifically designed to provide an open format, usable by as many applications as possible. A long list of software reads and writes music data in this format, including other open source applications like Rosegarden, LilyPond and FOMUS (also written in Lisp).

The project will therefore focus on converting between Gsharp's internal data structure and MusicXML. It will be written entirely in Common Lisp with the object of being integrated into the application proper. It will utilize one of several existing Lisp libraries for working with XML. Development will begin with simple Lisp routines translating trivial, one-note scores between the two encodings. Score features supported in Gsharp will then be added one by one to both the importer and exporter.

Please note that the project description as posted on the LispNYC Summer of Code website suggests first creating a MIDI import module (MIDI export already exists, and will hopefully inform this project's work with MusicXML). This has been omitted from this proposal with the belief that time would be better spent focusing on MusicXML. There are already tools available for creating MusicXML from MIDI files, effectively reducing the problem of importing MIDI into Gsharp to the problem of importing MusicXML.

Deliverables

The first stage of the project will be Lisp routines that translate a very basic example between Gsharp's internal format and MusicXML (something like the MusicXML "hello world" example available at http://www.recordare.com/xml/helloworld.html). This should provide an opportunity to grow comfortable with both encodings. Also, this project will make use of an external XML library. Several are available and one will have to be selected. This simple first stage should provide a sanity check to make sure that selection was made prudently.

Development can then continue by adding support for progressively more complicated score features: accidentals; key signatures; note clusters; notes of different duration; multiple staffs; voices; beaming, etc. Each feature will be added to both the import and export code before moving on to the next, though major obstacles on one side or the other for any particular feature should not be allowed to hold up overall progress.

The final deliverable will take the form of a patch for Gsharp integrating the fully functional "Import MusicXML" and "Export MusicXML" routines with the application proper, ideally with menu entries to boot. The code should be able to export, and re-import, all of the examples currently shipping in the Scores directory with Gsharp.

Biography

Brian Gruber is currently completing his Master's degree in Music Technology at New York University. His thesis focuses on the application of algorithmic composition techniques in auditory displays; it attempts to attach emotional content to the results of trend analyses on data streams. Other projects at NYU have included: work with sonically-enhanced widgets involving Csound and MPEG-4 Structured Audio; modifying a pre-existing C++ sound processing library to be cross-platform by the use of PortAudio, libsndfile and GNU Autotools; a study of SIMD instructions on IA-32 processors for use in DSP applications; and a program for Max/MSP written with Java which processes mathematical statements written in MathML to provide a melodic "glance" at the statement intended for the blind and visually handicapped. In the course of his studies, he has created several algorithmic compositions using tools including Csound, RTCMix, Perl and Max/MSP.

Another project Brian executed while at NYU involved the use of XML to create unit generator code that could be used in a variety of signal processing applications. Frustrated that while many audio processing systems possessed great similarities, each one required slightly different code to achieve the same results, he implemented a system which captures the common functionality of unit generator functions in an XML format. Using XSL transformations and Make, this system is able to generate objects for either Max/MSP or PD on several platforms with one simple command.

While at NYU, Brian worked in the Enterprise Application Infrastructure group at Morgan Stanley. There, his projects included: modifying a 3rd-party bug-tracking system (Jira) to interface with a 3rd-party source-control system (Perforce); creating a prototype Enterprise Change Management system which would track C++ library dependencies firm-wide; and a web application allowing firm developers to add pre-existing projects to a centralized automated build infrastructure. This last project involved the use of JDOM and XSLT to read, write and modify the XML configuration files used by the build daemon.

The bulk of Brian's coding experience has been in C, C++, Java and Perl. Recent projects have also included code written Python and IA-32 assembly language. He first became interested in functional languages when taking courses in Programming Languages and Translators and Mathematical Logic in the same semester as an undergraduate. His interest was once again piqued in graduate school when, while doing research on algorithmic composition, he discovered the existence of the LispNYC Music Special Interest Group. In 2006 he bit the bullet and, for fun, learned Common Lisp. He hopes this experience will help him to both firm up that knowledge and make him an active member of the musical Lisp community.

Brian graduated cum laude from Columbia University in 2003 with a degree in Computer Engineering. It was at Columbia that he began his formal studies in music theory. He has also studied music in the form of piano and voice lessons, and has been performing on-stage since he was ten years old.