iGetIt! Music

Online music education courseware for non-musicians who want to learn how to write their own rock songs.

My Photo
Name: Jim Plamondon
Location: Austin, Texas, United States

This blog documents the development of JIMS iGetIt! Music System (JIMS). JIMS' goal is to help you Understand Music in 24 Hours™, if you are (a) a non-musician (b) who wants to learn how to write your own rock songs. Requiring no instrument other than your own computer, and without using traditional notation, JIMS is being designed to deliver a deep understanding of tonal structure...in just 24 hours.

Wednesday, April 15, 2009

iGetIt! QWERTY keyboard component, v.000001

Here's my first crack at implementing the iGetIt!/JIMS note-layout on a standard computer keyboard:



PLEASE NOTE: you must click on the component with your mouse before it will start recognizing keyboard presses. Other than that, the on-screen keyboard does not respond to mouse clicks; you play it by pressing the keys of your computer's physical keyboard.

This component is not done by any means. It suffers from myriad annoying little problems. However, the basic functionality is there. You can use your computer keyboard to control musical notes in the iGetIt!/JIMS note-layout.

The pitch slider changes the pitch of "Re0," which is the note controlled by the QWERTY keyboard's 'H' key. This allows you to "change key" to any arbitrary frequency in a one-octave range. It should be noted that the selected pitch does NOT need to match the pitches defined by the standard A4=440Hz concert pitch in 12-tone equal temperament tuning; the structure of (harmonic) musical sound is the same for every frequency and tuning.

I do not propose that such a pitch slider is a good user interface for changing keys during performace. It's just a tool for demonstrating that the pattern of (tonic solfa) notes used by the iGetIt! keyboard stays the same, no matter what frequency is chosen as its key.

Each button displays its QWERTY label, its note name (e.g., Re0 on the keyboard's H key), and the coordinates of that note in tonal space (e.g., [0, 0] for Re0). The note Re0 is the "origin," which sounds the pitch chosen using the Pitch Slider. The pitch of note [x, y] is (x*P8 + y*P5) cents away from the pitch of Re0, where P8 is the octave (1200 cents) and P5 is the tempered perfect fifth (currently defaulting to 700 cents, with no user interface for changing that default). (If you think that sounds complicated, check out the formula for determining the pitch of a note in 12-tone equal temperament.) The coordinates are displayed for debugging purposes; no novice music student needs to see them.

An octave's notes are numbered from Re, rather than from Do as is typical. This is not a feature of the iGetIt!/JIMS music system; it's a bug that I haven't addressed yet. Notes are traditionally numbered from D0 and I see no reason to change that.

Each button's information is drawn poorly, due to problems that I do not yet know how to fix, but it's legible.

If it doesn't work on your browser/computer configuration, please let me know.

"View source..." doesn't work, because I don't yet know how to make the source available. Once I figure that out, I'll come back and make it work.

Thanks! :-)

Labels: , ,

Tuesday, April 14, 2009

What I Hate About Computer Programming

By and large, I'm enjoying my return to computer programming after a 17-year hiatus. However, the experience is also reminding me of the things about computer programming that I hated before, and still hate today.

Here's an example.

My PitchSlider component is a subclass of the Flex class named VSlider.  No problems there. In PitchSlider's current implementation, one must specify, in one's application, a "thumbHandler()" function that deals with mouse presses on the slider's thumb (the thing you drag around to change the slider's value, and hence the pitch of the PitchSlider).  This implementation is kinda grungy, because the application using the PitchSlider needs to know a lot about how of the PitchSlider's internal details.  It's a "tightly-coupled" design. What I'd like to do is move the thumb-handling code into the PitchSlider class instead -- hiding it from the application -- and then dispatch a custom event when the thumb is released, advising all listeners that the pitch slider's pitch has changed. This latter approach would enable a looser coupling between the PitchSlider and its container/application, which is a Good Thing.

Unfortunately, writing PitchSlider this way appears to be *&^%$#@ing impossible.

All I need to do is override three methods of VSlider's superclass, named Slider: onThumbPress(), onThumMove(), and onThumbRelease(). My overrides would call the inherited method and then (respectively) start playing the current pitch; change the current pitch; and stop playing the current pitch (then dispatching a custom event indicating the final pitch).  That should be no problem, I figured; this kind of "extension by subclassing" is exactly what object-oriented programming is all about. 15 minutes, tops.

But noooooo.  Inside of the Slider class, these methods are hidden away in a special "mx_internal" namespace. A Google search on "mx_internal" indicated that any method flagged mx_internal is not to be overridden because Adobe (creators of the Flex framework, of which the Slider class is a part) might change its implementation in future, and therefore wants to be able to say "here there be dragons; use these implementation details at your own risk."

Excuse me?  I can't override any of the three methods that uniquely distinguish sliders from all other controls? WTF? When I was napping with Rip van Winkle, did subclassing become passe?

There had to be a way around this. 

Google led me to a discussion of how to get past the "mx_internal" barrier: just import and then use the mx_internal namespace.  Good enough --  I'd use this work-around in the short run to get the PitchSlider working, so that I could focus my attention on learning how to use try/catch blocks or some other more-pressing concern.

But noooooo.  The work-around works when *calling* hidden methods, but not when *over-riding* them. Instead, the compiler barfs an error message that is helpful only as the basis of another Google search.  Googling it, I found an official Adobe bug report saying that the work-around didn't work when using it to override methods.  This required *another* work-around, to wit, omitting the keyword "override" in the definition of the function.

Fine, OK, whatever. Omitting the "override" keyword did indeed allow the code to compile, thus successfully working around the compiler bug. I figured that I was home free.

But noooooo. Running the application threw up a run-time error, telling me that I had illegally overriden a Flex method.

*&^%$#@er - *&^%$#@ers!

Apparently I was simply not going to be allowed to do the obviously-right thing by overriding these *&^%$#@ing methods.

Deep breath. Om mani padme hum. I am but scum on Buddha's foot; all striving is vanity; and this *&^%$#@ing approach isn't helping me to attain any *&^%$#@ing enlightenment anyway, so forget it and move on (as the Dalai Lama might say).

Time to go to Plan B: have my PitchSlider add event listeners to itself, so that it can "notify itself" when its *&^%$#@ing super-class is done handling thumb press, movement, and release actions.

The right time to add these event listeners is when the PitchSlider's instance is done being created. The Slider class' superclass, UIComponent, has a nice little "creationCompleteHandler()" method that's called at just the right time, too.  I figured that I would just override that method to install my event listeners. It's not an "mx_internal" method, either, so that should work.

But noooooo.  creationCompleteHandler() is marked as a "private" method, which means that it can't be overriden, either.

*&^%$#@er - *&^%$#@ers!

I was never a great computer programmer.  I was good, but never great.  And I know that I've been out of the loop for an outrageously long time, so...perhaps there's some new way to accomplish this task that would be patently obvious to anyone lacking grey hair. I'd welcome the opportunity to become enlightened.

But *&^%$#@us *&^%$#@ing *&^%$#@st, I absolutely HATE this cascading series of problems, work-arounds, and work-arounds for work-arounds, with each level delaying the release of my product by hours or even days.  I just want things to *&^%$#@ing *work*.

(It's exactly this kind of short-tempered frustration that drove me to create the iGetIt! Music System in the first place, of course.  If I'd been more patient, I would have just learned music the way everyone else did...the hard way.)

Labels: , ,

Saturday, April 4, 2009

First Flash control: PitchSlider

To develop my forthcoming music education courseware using Adobe's Flash/Flex/AIR, I'm developing a suite of components that display and control musical information.  This is going well, considering. Although I have a Computer Science degree, I haven't written a line of code since 1992...17 years ago.  Climbing up the Flash/Flex/AIR/ActionScript/Eclipse/XML learning curve is fun but challenging.

My first Flash control is a slider that allows the user to choose a frequency (it works best if you drag the thumb slowly):


No big deal, but writing it helped me understand a lot of stuff, including Flash 10's new sound synthesis API SampleDataEvent. 

I've seen other posts in which the source code to such controls is easily available (by right-clicking on the control and choosing "View Source" from a pop-up menu), but I don't know how to support that feature. I can't find any documentation for it; apparently it's so "obvious" that it is never described. If a reader could please tell me how to add support for Flash's "View Source" feature -- in full newbie-tutorial detail -- I'd be happy to make the code available for this and subsequent iGetIt! controls.  (iGetIt!'s proprietary value is in the patent-pending iGetIt! Music System and the lessons based on it, not in its Flash controls.)

I expect to use the PitchSlider control (or something like it) to show the student that musical pitch (frequency) is continuous, varying in a smooth and unbroken manner. Some frequencies have names (such as 440Hz, which is named A4), and some do not, but all are musically equal. The structure of music is the same for all frequencies.  Obviously, this ignores a ton of psychoacoustic issues like the human ear's range of hearing and critical band, but... close enough, as a first approximation.

Labels: , , , ,