Showing posts with label javascript. Show all posts
Showing posts with label javascript. Show all posts

24 September 2018

Imaginary Museum of Musical Representations

I was rereading Lydia Goehr's The Imaginary Museum of Musical Works the other evening after a long day spent translating several of music21's score-representation code from Python to JavaScript (for music21j).  What struck me when I was reading the introduction, which lays out several pre-existing theories about the work-concept, and the relationship(s) among the musical idea, the building blocks of scores (pitches, etc.), the score-copy, and performances, was my own need to take a stand on the proper relationships of such conceptions when choosing a computational language in which to express musical languages. 

Those who haven't programmed may not know that no modern computer program (or very very few) is built from a single code file, or flowchart leading from input to output.  Instead each program is built from components (a file browser, a set of functions for manipulating canvases for drawing, a module for representing tempo) that can be called upon by other components in a systematized but reusable and testable manner.  These are get bundled or packed or linked together to make a complete or extensible application or library.  Different philosophies exist about which structures (or ontologies, to use a word with related but quite different meanings between the humanities and computer science) can be well-formed or desirable. 

These philosophies about file linking--importing and exporting--lie close to the marrow of the designs of various computer languages and in many cases evolved in response to the environments within which the languages were originally created.  Python, a language run on individual computers that came of age in the era of fast hard drives and, from the user's perspective, near instantaneous loading of small files, aims to put as few limitations on the possible relationships between modules as possible.  JavaScript, on the other hand, which appeared first on the web in the time of dialup internet and unreliable connections, has, even in its most recent incarnations, placed sharper restrictions on connecting resources in the name of efficiency.

Translating music analysis software from the first language to the other has raised complex problems for the representation of music in code.  Python allowed me to interweave different levels of musical thought, such that notes could will into existence a measure (say by asking for the creation of an object to encompass them) while a measure could in another context give birth to notes (for instance by asking for a suitable number to fill it, given some metrical, harmonic, and accentual constraints).  A score could of course be a container to many measures, but a measure could also be linked or contain many scores (for instance as a key or heading to a catalogue of quotations or standard topoi).  As I created the original music21 in Python, I reveled in the multiplicity of possible relationships, in the way some musical philosophers might argue that a score gives rise to a performance which, if transcribed or imagined, gives rise to a new score, which gives rise to a new performance, and so on to infinity.

Rewriting the "same code" posed, and continues to pose, a challenge to my ecumenical notion of musical relationships. (With "same code" in quotation marks since the work-concept-concept for computer works has not been the subject of nearly so much rumination.) In JavaScript, in order to make sure that everything has been loaded before the user closes her browser in frustration, in general if one module (A) uses another module (B) in its code, then the second module (B) cannot use, or import, the first (A) into its code. What some, perhaps those trained as humanists, might exult as a beautiful web of inter-compu-textuality, is called a cyclic or circular dependency and it is easy to find categorial pronouncements that such things are bad or the result of lazy or sloppy thinking.  They resist creating a hierarchy of elements, and prevent creating beautiful tree structures that are, or at least were during the time when computers were problem-solving devices and not enablers of exploration, the key to moving in an efficient manner for point A to point Z without getting into an endless loop somewhere around J to M.  (A programmer--who had apparently gotten too deep into the trenches of coding to remember that the terms which undergird so many computational structures are metaphors--once criticized a part of my code that had many pointers running up and down a hierarchy by saying, "This is absurd! A child cannot have more than one parent.")

In Python, I could say that a Note in the presence of another Note created an Interval. (Like in German, in most computer languages, nouns, or Objects, are capitalized.)  And, I could simultaneously say that an Interval, given a starting Note for reference, could define a second Note that fulfilled it.  Both of these generating relationships seemed not just plausible, but natural and essential to a full representation of the complexity of music.  The ambiguity of which came first, the interval or the note can never be resolved.  In JavaScript, however, the programming musicologist is left with a decision to be made: either Notes can create Intervals or Intervals can create Notes, but not both.  The work creates the score (or performance), or the performance or the score creates the work, but not both.  The one who is able to create both Notes and Intervals is an entity that stands outside the system--the calling program--which is perhaps better named "the observer" in the best literary criticism traditions, since the network of Notes and Intervals cannot operate with knowledge that it exists.

(To be fair, there are some complex and fragile ways to work with circular dependencies in JavaScript, and in Python, true circular dependencies are also impossible: either the Note can only become aware of its ability to create Intervals at the moment of action [an import nested in a method] or vice-versa.)

I have found that programming musical logic has sharpened my awareness of the ambiguities, hierarchies, and underdefined elements of music. By underdefined elements, I suggest: is the interval from E# to Fb an ascending doubly-diminished second or a descending doubly-diminished second? If spelling matters more than sound, such that C-G is consonant but Dbb-G is dissonant, is the bass of a chord beginning on E##-Fbb-Bb the E## or the Fbb? (If it's the Fbb, then is a B###-Dbbb-F# chord in root position or first inversion? If the E##, does that mean that we cannot determine the bass of a chord by ear?)  These may be absurdities to practicing musicians but deciding a "right answer" to them makes all the difference in how standard musical relationships should be represented and encoded.

It is extremely difficult to tell a computer to hold off on making a decision or to leave a paradox in place to solve later.  The human ability (flaw?) in being able to reason around ambiguity, or to hold conflicting ideas without breaking down, is a capacity that those who design practical computing systems have either not been able to replicate or have deliberately chosen not to.  Within the limited choices, I have generally been drawn to computing frameworks that let me come as close as possible to representing multiple perspectives. (Ironically, I've found the closest match so far in Python, despite its community adopting a motto that says there should be only one way to do it.)  There is a danger that when good but still inadequate tools are used to model human behavior and creativity, eventually human behavior will bend to suit the tools, rather than the other way around.  It is a force that those who design and use these tools must be aware of and continually fight against.
(updated 2022.02.03 -- corrected "revealed" to "reveled")

26 June 2016

Create a realistic plan for the day from Things and Calendar (OS X/macOS)

For the past few years, I've been trying to use the Getting Things Done philosophy with Cultured Code's application Things to manage my tasks and todos.

My two biggest problems preventing success have been (1) Maintaining an Inbox Zero philosophy, where at least daily, I get my Inbox to zero, by deleting messages, doing a very quick reply, or immediately creating a task for a message that requires more than 2–5 minutes to take care of, and (2) being realistic about the number of tasks that I can possibly say yes to and have the time to actually do.

Sometimes, I can maintain Inbox Zero for six or eight months.  Other times, I get way behind on Inbox Zero and need to resort to an Inbox DMZ to reset the obligations that I have. Usually the thrill of an empty inbox at that point will let me get out of DMZ in a few weeks.  Maybe someday I'll write about how this happens to me and how I break the cycle (at least so I can read this post again later), but at this moment, I'm almost out of Inbox/Email Hell.  So my big problem lately is the second one.

When I was a graduate student, or just starting out as a professor, I was so thrilled that someone was asking little ol' me to be on a committee, help them with a problem in my field ("Can you transcribe this medieval song?"), or, big honor, fly out and give a talk at their school.  I am still honored to be asked, but fortunately or unfortunately, at this point in my career, I'm asked to do far too many things that I could possibly do.

One of the hardest parts about saying "no," is that I have always been far too much of an optimist about how long a particular task will take.  Sure, it'd just take twenty minutes to write that recommendation letter, IF I were in the right mental state, not distracted, had all my ducks in a row, etc.  Realistically, I've never gotten one done in under an hour, and three hours is more usual.  An article review? I need to learn that I write far too many notes to the author, duplicate too much of the research, order sources from ILL, etc., and so eight hours is a realistic timeline for me for a twenty-page review.

I've figured that I have about sixty hours of work in me per week (not just academic work but also counting certain stressful obligations, such as being a trustee, dealing with a plumber, etc. that I don't consider fun time). Of those sixty hours, I know that recurring obligations such as teaching and advising will take up about 30 hours a week most of the year.  This leaves about 30 hours per week (1500 hours per year) to do everything else I've either agreed to do, or need to do to continue to develop as a professor (researching and writing articles and books, developing music analysis software, etc.).  Twenty letters of recommendation and ten article reviews per year eats up 10% of that time.  Joining a board is probably 50 hours a year.  Etc. etc.  Adding it all up and it's easy to see why the years when I say "No" often, I can write, say, two chapters and three articles, and those that I don't, I'm lucky to get a single article out.

(And then there's the damage I do to others when I say "Yes, sure!" and then end up stretching or breaking deadlines or needing to cancel later; this is the worst of all possible options.)

I've been trying to find tools to help me manage this time better, but there's nothing I could find, so I finally took four of those 1500 hours and wrote a script to help me.  (Maybe I'll get half those hours back since I did learn a new skill of Javascript for Automation).  

Each day I try to create a realistic plan for the day during a morning review.  It always begins with Inbox zero as a task.  (Since 2012, I've tried to make every task begin with an action verb. "Inbox zero" has somehow remained as an exception, since I always know what to do about it).  Each task usually has two tags attached to it, a location tag ("@Any" is the most common.  "@Home", "@MIT" also appear), and a time tag ("5 min," "15 min", "1 hr", etc.).  When I've organized the ToDos in a good order for the day, and adjusted the times to what I think are realistic, I run the thingsToCal.scpt which puts all the todos on the calendar, making sure that they don't interfere with any events already in the calendar.   The results are below:



I can now see that, hmm... given that it's my turn to cook, I'm going to need to be willing to work until around 9:30 if I'm going to get all these things done; for a weekday, that's fine.  For Sunday night, I think I'd rather not.  Something (probably that "Get an Outline" for Tuesday's talk event) will need to go till to tomorrow.  (And that was before I added an hour-long "Blog about this system" todo).  After rearranging, etc., I rerun the script and the events for the day get removed and readded in the new order.

I'm hoping that this system works well.  If you are geeky and want to try it out, the code is at this link. It runs only with Things (if Time tags are set up properly) and OS X/macOS Calendar (with a calendar called Things) and you'll need to use it at your own risk (Sorry if something gets screwed up in your calendar), hence I'm not providing installation instructions beyond this link. But if I can get it to run faster (currently, figuring out my existing schedule on Calendar takes 20-30 seconds) and perhaps to work with next items beyond today (and maybe preserving non-working hours, etc.) then I'll make it a nicer script.

Wish me luck! Especially if you've been waiting on a reply or for me to do something for you.


26 May 2014

Country / Capital Challenge


Country / Capital Challenge is a Javascript game I made with Elina Hamilton based on our mutual love of learning geography.




Two players compete to create chains of capitals and countries as fast as they can. The first player chooses a country or capital (any). The second player must choose a country that either ends the same way as the previous country began or that begins the same way the previous countryended. For example, if the first player chose SpaiN, the second player could go with PariS or Nepal. Longer chains are possible, such as SpaIN to INdia.

You can also play in one-player mode.
  
By default, every 60 seconds of thinking, the opponent gets 1 point. Every time that a player repeats a country or capital, the opponent gets 1 point. If you can't come up with an answer, you can concede (giving the opponent a point) or challenge the other player. He or she then needs to answer quickly; if they can, they get two points. If they need to concede , you'll get a point. Countries that share an exact name with their capitals (such as Luxembourg, but not Mexico/Mexico City) appear only once, under countries. Play to a score that you'd like or a maximum time or total number of countries or capitals. There's no set "Game Over" point.

08 October 2013

Testing ability to render music in Blogger

The following score was written as: <div class="music21 tinyNotation">c4 d8 e8 f2</div>
c4 d8 e8 f2
and then rendered automatically via some plugins I have.
Here's another one. You can click either of them to hear them:
3/4 d8. f#16 e8 f g a c'#2. d'2.
Hope to be able to release this soon.
This might not work after a bit -- the loading is too slow and I might move the source code... Thanks to the folks at Vexflow and MIDI.js for the idea.