Saturday, May 23, 2009

"No Other Name" Chorus

My last big effort was to get ready for the Creative House visual arts show. Now that the show is over I'm left with two things.

1) A house full of art. I'm in no hurry for everybody to pick up their work because my house looks great. If you haven't seen it, quick, come over before it's gone.

2) A crossroads. What am I going to concentrate on next? I asked Chris his opinion and he said it would probably be something music related. It was a prediction rather than a suggestion. Well, apparently he was right. I started working with Lilypond and I'm now in the midst of creating a class library in Perl for manipulating music and outputting Lilypond code.

The library as originally conceived is just about ready for initial use. It's not ready for publication because it doesn't have the error checking and documentation needed for that, but I can start using it and working out bugs and better interfaces. So, what do I want to do with it?

So far my experiments have been macros for music notation, a short hand. I think next I want to go a little further into "musical intelligence" (as David Cope calls it). However, not too far...more of a guide than algorithmic composition. I'm thinking of creating tools for making interesting melodies and then harmonizing them.

To that end, I'm rereading "Melody in Songwriting" by Jack Perricone (Berklee Press) and Tom Pankurst's SchenkerGUIDE.

Of course, I can't read anything good without creating something. So, I wrote this worship chorus:

no_other_name.ly
no_other_name.pdf
no_other_name.midi
no_other_name.ogg

The melody here was a result of the writing tip at the end of Chapter 2 in Perricone. He basically says to test the independence of a melody by droning the root of the key and listen to the melody on top of it. I like the song that resulted, but I'm not sure I really agree with the advice. A melody will demand a change in the bass even if it stands on its own. So, I've come up with my own tip for testing the independence of a melody: sing it out loud with no accompaniment. Duh!

I'm interested in your feedback. Also, I'm interested in lyrics submissions for the verses and bridge.

Saturday, May 16, 2009

Audio files of latest Perl compositions

I've been plugging away, making improvements to my Perl music scripts.

These were created with my scripts, lilypond and rendered to wav and ogg with timidity. The mp3 files were made with iTunes (see note below).

I previously posted the score to this recording but I only rendered half of it:
2009051101.pdf

Here's the recording:
2009051101.wav (big)
2009051101.ogg (smaller)
2009051101.mp3

Some you haven't seen/heard:

Very short piece in a Chinese scale:
2009051301.pdf
2009051301.wav (big)
2009051301.ogg (smaller)
2009051301.mp3

The first 13 bars of this are exactly the way I originally wrote this. However, be representing the piece abstractly I was able to create the rest of the variations easily:
test.pdf
test.wav was too big to upload to Blogger
test.ogg
test.mp3

NOTE:
I posted these as mp3 for those who don't have Ogg Vorbis players, but I really encourage you to look into Ogg. It doesn't have the licensing requirement that MP3 has. Thus it is much friendlier to open source programmers. If you want to play Ogg files with Windows Media Player, read http://windowsxp.mvps.org/ogg.htm

Thursday, May 14, 2009

Becoming a responsible Perl programmer

I turned my Lilypond routines (see previous blog entry) into a Perl module (but have not submitted it yet). I even read "perldoc perlnewmod" and followed the advice there.


Avoid Reinventing the Wheel (or the Music::Lilypond module)

The first advice was to search CPAN to make sure I'm not creating a redundant module. I'm glad I did that because I found some interesting stuff.

Music::Chord::Note
can create arrays like (0, 4, 7) from chord names. Doesn't support Lilypond chord syntax. Perhaps I can extend it.

Music::Scales
can create arrays like (0, 2, 4, 5, 7, 9, 11) from pretty big list of supported scales

This is the exact same array format I chose for chords and scales. Great minds think alike! That will save me some work. If I want to extend those, I will have to submit the changes to the author, but not before I can use my changed versions. I'm kinda eager to do a submission anyway. I want to learn this whole open source process.

Music::Note
OO code for representing a note. It doesn't support lilypond note format...perhaps I could extend it.

Music::Tempo
could be useful down the road to support italian tempo names

Music::Chord::Namer
Converts notes like C E G (string or array) to chord names C. Perhaps I can extend this in two ways. One, I'd like it to support Lilypond chord syntax (see App::Music::PlayTab::LyChord below). Two, I'd like it to work with arrays of semitones, such as (0, 4, 7) , and return the chord color name without the root note.

App::Music::PlayTab::LyChord
parses Lilypond chords for a Tab app. Might be a good reference. I might use it to extend Music::Chord::Namer and Music::Chord::Note


Use module-starter

This was another great piece of advice. Even if I never submit my module to CPAN, this gave me a structure for documenting my code, a way to add my documentation to perldoc and the man pages and a starter structure for module testing my code.

FYI, I used the Synaptic Package Manager to install module-starter on my Ubuntu machine. It is called libmodule-starter-perl there.


Use Carp

Another interesting thing that they advise is to use Carp to report errors in the way my routines are called and use warn and die for problems caused by my code. I didn't know about Carp. It makes a lot of sense.

Of course, I don't have no stinking error checking yet, but when I do, I'll use Carp.


It was easy and it actually worked!

I created one syntax error cutting and pasting from my old code, but other than that, I was able to convert my old script from using local routines to using my new module in the first try.

So, being a responsible Perl programmer actually isn't all that bad. I feel all grown up. Maybe I can move out of my parent's house? ...but I swear I'll scream if you try to take my blankey.

Tuesday, May 12, 2009

dipping my toe into the algorithmic composition pool

Listen to this midi file and read the score.
2009051101.midi
2009051101.pdf
These two files were output by LilyPond based on this input file:
2009051101.ly
That file was output by a Perl program I wrote. That program consists of generic routines and data for creating piano pieces from an abstract data type defining harmonic, melodic and rhythmic patterns. The portion of the script that defines the data specific to this piece is:
#patterns for the piece
my @harmonic_progression = (0, -4, -1, -5, -2, -6, -3);
my $rh_pattern = [[0,2], ['r'], [0], [1],
[0,2], [1], [0], [-3],
[3, 5], [0], [-3], [2,4],
[0], [-3], [1,3], [-3]]; #scale degrees
my @rh_rhythm = (16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16);
my $lh_pattern = [[0], [3], [7], [9]]; #scale degrees
my @lh_rhythm = ("4.", 8, "4.", 8);

#build the piece
my $scale = \@harmonic_minor_scale;
my $root = $middle_c - 3; #a
my @the_piece =
(
{
"scale" => $scale,
"harmonic_progression" => \@harmonic_progression,
"rh_pattern" => $rh_pattern,
"rh_root" => $root + 12,
"rh_rhythm" => \@rh_rhythm,
"lh_pattern" => $lh_pattern,
"lh_root" => $root - 12,
"lh_rhythm" => \@lh_rhythm,
"count" => 2
},
{
"scale" => $scale,
"harmonic_progression" => [0],
"rh_pattern" => [[0,2,4,7]],
"rh_root" => $root,
"rh_rhythm" => [1],
"lh_pattern" => $lh_pattern,
"lh_root" => $root - 12,
"lh_rhythm" => [1],
"count" => 1
},
);
If I change the line
my $scale = \@harmonic_minor_scale;
to
my $scale = \@major_scale;
the resulting piece has a completely different harmonic quality, but still works. If I've done things correctly, I could theoretically enter any piano piece in this format. Then I could tweak some of the parameters and end up with a different piece that also works.

At the core of the Perl program is the ability to modally transpose patterns based on other patterns. I've long thought modal transposition would be a great modification to LilyPond, but Perl is soooo much easier than Scheme and it's much easier to manipulate LilyPond code than to manipulate the internals of LilyPond. Someday I'll bite the bullet and either create some LilyPond/Scheme functions or actually extend LilyPond with C. Until then, I'm enjoying this.