Csound Csound-dev Csound-tekno Search About

OOP or not? (perl Csound module)

Date1998-11-09 20:38
FromPaul Winkler
SubjectOOP or not? (perl Csound module)
Greetings, Csound users and Perl hackers. This message is being posted
to the Csound mailing list, and to comp.lang.perl.misc.

(I already sent this to the Csound list, but I think it bounced-- I sent
it from a non-subscribed account.)

The purpose of this letter is to announce a project I'm working on,
which I'm calling Pscore (short for Perl-score). It aims to be a Perl
library (probably to be called Csound::Pscore) intended to allow Csound
composers to write their score files directly in Perl. It will be
released under the GNU Public License.

I'm inviting suggestions, input, commentary, offers of collaboration,
etc., from any interested parties... hence this announcement. The main
question I have right now is whether or not to take an object-oriented
approach. Below, I'll explain why I can't decide...

To those unfamiliar with either language:

------- begin boring intro blah-blah ------------

Perl (http://www.perl.org) is ... oh, c'mon, you know what Perl is. It's
a fairly easy-to-learn language that excels at (among other things)
processing text, and it's been ported to all the platforms Csound runs
on (I think).

Briefly, Csound is a language for generating digital sound by creating
an "orchestra" file (basically a collection of virtual synthesizers) and
a "score" file (a collection of events in time which are passed to the
orchestra for rendering into digital audio). It is notoriously flexible
and notoriously difficult. It's been ported to a wide variety of
platforms including many flavors of Unix, Mac, and Wintel.

Csound score files are made entirely of... guess what... text. Each line
is an event, split into "p-fields": p1 gives the instrument number from
the score to use; p2 gives the time the event starts; p3 gives the
duration of the event; and an arbitrary number of following pfields do
any damn thing you want them to.

Csound has a new home page in progress at:
http://www.ping.be/calliope/Csound/
And an outdated front page at:
http://www.leeds.ac.uk/music/Man/c_front.html

------ end boring intro blah-blah. -----------

Now, why would I want a perl Csound::Pscore library?

What started the idea was being frustrated with the Csound standard
numeric score. The S.N.S. does (recently) allow for repeated sections
and macros, but in limited ways. For instance, there's no way to write
two different repeating sections that overlap in time, except to put
them in separate .sco files, invoke csound to do all the soring etc.,
and then find and combine the relevant parts of the output score.srt
files by hand. YUCK.

I posted a question about this to the Csound mailing list months ago,
and Eric Lyon wrote me to suggest using a scripting language to do it,
in particular Perl. I'd been interested in Perl, but Eric's mail was the
straw that, er, broke the camel's back, so I got "Learning Perl" and
have gone through the whole book and many of the Perl man pages.
 
While thinking about the original problem, I thought of all sorts of
other fun things you could implement while you were solving it!

For instance:
--Create a named sequence of events (let's call it a "pattern").
--Play arbitrarily selected sections of named patterns.
--Extensively modify arbitrarily selected sections of patterns.
--More easily & flexibly specify the timing of patterns relative to
other events... I've put a lot of thought into how to handle keeping
track of & using timing...
--Score-level global variables could be useful for lots of things and
could be generated in all kinds of interesting ways.

These ideas have obvious implications for composers. It should be a lot
easier to write any kind of repetitious music, and it could be a very
useful environment for playing with algorithmic composition.

When I started working on the project a month or so ago, I was basically
inventing a new score language, a "meta-score" if you will, that would
be interpreted by a Perl script which would output a score useable by
Csound. This approach quickly seemed short-sighted: Why invent a new
language that's not useful for any other purpose? Why not re-implement
my functions as a Perl library, allowing one to basically compose music
directly in Perl? That way, anyone who knows Perl and Csound would
already know the syntax, and would just have to learn some new
functions. And if something was lacking from the capabilities I'd
already provided for, you could quickly roll your own in plain old Perl,
and add code to the module if it's something that would be useful in the
future.

Some knowledgeable Csounders might be saying, "Why don't you just learn
Common Music?" (CM has a page at
http://ccrma-www.stanford.edu/CCRMA/Software/cm/cm.html ... which begins
like this:

"Common Music (CM) is an object-oriented music composition environment.
It produces sound by transforming a high-level representation of musical
structure into a variety of contol protocols for sound synthesis and
display: MIDI, Csound, Common Lisp Music, Music Kit, C Mix, C Music,
M4C, RT, Mix, VRML and Common  Music Notation. Common Music defines an
extensive library of compositional tools and provides a public interface
through which the composer may easily modify and extend the system."
It's implemented in Lisp and has a Lisp-like syntax.

Well, the answer is: Eventually, I might. It looks like pretty much
everything I want to do with composition is do-able in CM.

But for now:
--I don't know Lisp at all.
--I like Perl.
--Lots of other people like Perl and don't know Lisp.
--Some of those people might be fellow Csounders.
--There is room for many ways to generate Csound scores... and this
might be a very useful addition to the existing tools (CM, Cscore, SCOT,
cecilia & cybil, SILENCE, HPKComposer, Midi2CS, ermmm... what else?)
--Just for the heck of it, it would probably be pretty easy to add a
graphical front-end in Perl/TK.

Commentary is welcome. Probably the best forum for discussion of these
ideas is the Csound mailing list, except for technical questions about
Perl which belong in comp.lang.perl.misc.

As I said, the big question is whether to take an OOP approach or not.

Reasons Why OOP:
--might make usage syntax easier? We're dealing with a pretty unwieldy
data structure (see below).
--might make extension of the module easier?

Reasons Why NOT OOP:
--I don't really understand OOP.
--I think I know how to do what I want in traditional programming.
--Don't have to worry about mucking around outside of established class
methods.

The main issue is whether or not an OOP approach would make the system
easier to use? Remember, the scripts we're writing with this Perl module
are compositions, not applications!  So it's important that they be
quick & easy to write, and easy to read.

Probably at this point it would be helpful if I gave an example of what
I want to be able to do.

OK... here's a sample composition (or "script" if you prefer), though
all these functions are purely hypothetical and might end up with
different names and arguments... sorry for any blatantly bad code:

#!/usr/bin/perl -w
use Csound::Pscore;

pattern_from_file(Verse1, "some-score-file.sco", [ 4 .. 10 ]);
# We keep stuff in a big data 
# structure: a hash of list refs. of list refs. The hash keys
# are pattern names; the first-level list is of line numbers; the
# second-level list contains each line's pfields.
# pattern_from_file() would take three args: a name to give this
# pattern, a file to read score events from, and a reference to an
# array tells which lines we want. In this case it's an anonymous
# array which says use lines 4 to 10. The array could as easily be
# generated by a function...   Anyway, moving on:

play(Verse1, 2); # Plays Verse1 twice.
rewind(); # Set time to whatever it was when the last function was
          # called.
play(Verse2);    # Plays Verse2 at same start time as the first
                 # Verse1. If rewind() hadn't been there, it would
                 # come after the Verse1's...
                 # and there's lots of ways to do things like that.

select_pat(Verse2); # load it but don't do anything yet.
shuffle_pfield (pfield(5, beats(4 to 9),  *= 2));
play();

# set Verse2 as the "current pattern", do some interesting things
# to it (but don't save the changes!), and play the modified version.
# Here's what the shuffle_pfield(... line does:
# Read the fifth "p-field", a.k.a. p5,
# from any events occurring between
# beats 4 and 9 in the current pattern, and then multiply those p5's
# by 2, and then shuffle them randomly back into the lines they came
# from. Fun stuff! We can do this because shuffle_pfield expects
# an int (the pfield) followed by an array ref. (which line numbers?)
# as its arguments, and that's exactly what
# pfield() returns...




So, there's a taste of the ideas I have... there's lots more but this
message is already too long.

Am I nuts for doing things this way? Would OOP make life easier or
harder? If I followed an OOP strategy, what might the above code look
like? Are there some existing Perl modules that might be useful? (I
haven't found any yet...)

Please comment!

Thanks,

Paul Winkler

Date1998-11-09 21:01
FromAaron Isaksen
SubjectRe: OOP or not? (perl Csound module)
> For instance:
> --Create a named sequence of events (let's call it a "pattern").
> --Play arbitrarily selected sections of named patterns.
> --Extensively modify arbitrarily selected sections of patterns.
> --More easily & flexibly specify the timing of patterns relative to
> other events... I've put a lot of thought into how to handle keeping
> track of & using timing...
> --Score-level global variables could be useful for lots of things and
> could be generated in all kinds of interesting ways.

This PERL module would be useful, but not just to CSound users.  If you
are mostly concerned with the score file part of CSound, then I wouldn't
make it only for CSound.  Why not output MIDI score, or some other kind?

So, if you think that you'd want your functions to sometimes output MIDI,
and sometimes output CSound .sco, then you probably want an object
oriented programming approach.


-Aaron