issue06

EMUSIC-L Digest                                      Volume 43, Issue 06

This issue's topics: Software questions and answers
	
	FM Plotting
	Indian Classical Music Auto-Composition (2 messages)
	PC scoring programs for Windows?
	Hyperupic - comp.music #4120 (2 messages)
	Performer DTLe problem (2 messages)
	Sound Designer format needed
	Technical article on implementing a sequencer

Your EMUSIC-L Digest moderator is Joe McMahon .
You may subscribe to EMUSIC-L by sending mail to listserv@american.edu with 
the line "SUB EMUSIC-L your name" as the text.
 
The EMUSIC-L archive is a service of SunSite (sunsite.unc.edu) at the 
University of North Carolina.
------------------------------------------------------------------------
Date:         Sun, 16 Aug 1992 11:42:00 EDT
From:         rg8 
Subject:      FM Plotting

I would greatly appreciate hearing from anyone who has or knows of a program
for the Mac which can produce a display of the sidebands resulting from
simple (or cascade) FM algorithms when the carrier and modulator
frequencies (and amplitudes) are input.  I am using Yamaha FM synths (DX7 and
SY77), and some tutorial examples which could be displayed graphically would
be very useful.  Any code which could be run under THINK C 5.0 to accomplish
the same end would also be welcome.

Thanks in advance for any replies.

Bob Gibson
rg8@umail.umd.edu

------------------------------
Date:         Wed, 5 Aug 1992 00:03:29 -0400
From:         music@PARCOM.ERNET.IN
Subject:      Indian Classical Music Auto-Composition


******************************************************************************
                    Knowledge Based Computing Systems Group
               Centre for Development of Advanced Computing (C-DAC)
   (A Scientific Society Under Department of Electronics, Government of India)

                       Announces a golden opportunity for:

                       o computer music composers
                       o those who are always in search of "MUSICAL IDEAS"
                       o who want to understand and experiment with Indian
                         Classical Music using computers
******************************************************************************


As part of our efforts to make available rich and intricate Raag Music of
India to  western music composers we are attempting to develop semi-automatic
composition based on Raag Music of India. We are planning to distribute
following software to music enthusiasts at nominal charges. Depending upon
the comments and responses of the volunteers in the initial survey the system
will be upgraded to satify the needs of composers in Western music world. (
Initial registered users will be considered for discounted rates of further
releases of the software).

We are looking forward to computer music enthusiasts, institutions for beta
testing of the software. You will be charged a nominal fee of $50  towards
registration as  beta user. >> You do not have to pay now. We would be
happy if you could communicate your inclination to participate in this
activity <<.

                      ****************************
                      * Features of the Software *
                      ****************************

o System Requirements

  PC/AT (286 with EGA color, with a good beeper)
  DOS 3.0 or above           ------------------


o No dedicated hardware required
o An editor which offers standard score editing
  facilities for a musical composition.

o A good library of traditional Indian songs from raag music plus
  a good number of computer generated compositions to shape your
  musical creativity and taste in Indian Classical music.

o Future version will provide a package with
  semi-automatic composition tools with the  standard musical interfaces
  such as Sound Blaster or Stereo F/X.

If you find this as an interesting opportunity please contact on following
address at earliest for the queries if any.

       Rajeev Upadhye
Email: music@parcom.ernet.in   .... OR... parcom!music@shakti.ernet.in

Post : Knowledge Based Computing Systems
       Centre for Development of Advanced Computing
       Pune University Campus
       Ganesh Khind
       Pune, Maharashtra, 411007
       INDIA.
Telex: 0145-7615 CDAC IN
FAX  : (0212) 337551

*******************************************************************************

------------------------------
Date:         Fri, 14 Aug 1992 16:27:55 EDT
From:         "Joseph D. McMahon" 
Subject:      Raags

music@parcom.ernet.in writes:
>  Dear Mr. Crispen,
>
>       Thanks for your message posted in EMUSIC-D. I will
> respond to views expressed by you soon. I hope this will
> to start discussion on Indian music with musicologists in the
> west.
> 	I will respond to your point regarding the criteria
> of "music lovers". We can classify music listeners in several
> ways.  casual listeners (those who claim to enjoy but do not understand),
> active listeners (those who "understand" upto a certain level), more
> dedicated listeners ( people who demand certain type of music for their
> enjoyment), amateur performers/composers & professional musicians.
> If you accept this hierarchy then my model of raag music which
> is used by computer can satisfy almost all execpt the last two.
> I consider it as significant achievement.
>
> Will respond you in detail.
> Regards,
> Rajeev Upadhye
> music@parcom.ernet.in
>
> PS: I can send you my publications if you could send me your
>     postal address.
> CC: EMUSIC-D
>

------------------------------
Date:         Sat, 1 Aug 1992 13:52:51 -0400
From:         E7M7GRI@TOWSONVX.BITNET
Subject:      Music Software

A few years ago, I purchased version 1.2 of SCORE (Passport Designs).  I used
this for several years with an IBM Music Feature Card on an AT clone.  It is
actually rather cumbersome to use,but after many hours I have become pretty
fast with it.

Now I
have acquired a 386 DX (33 mhz.) and want to move up to either a later version
of SCORE or, since I can now use WINDOWS, possibly a program like FINALE.  It
would be nice if I could continue using the IBM card.  Does anyone know
if both late versions of SCORE and FINALE use the IBM card?  Or are there
programs that would use this card.

My early version
of SCORE allowed me to playback only 4 independent parts on the IBM card.
Does anyone know what the capabilies of other programs are for playback
with the card?  Does the latest version of SCORE even use this card?

Also, I frequently need to "implode" 4-6 part scores of chansons etc. into a
harpsichord part.  Does anyone know if both of these programs are capable of
this?  Or do you know of other programs I might look into?  Since I use the
program a lot for preparing music for performance with an Early Music Ensemble
I don't need anything too "scholarly correct" as far as historical notation,
etc., but something that would handle lyrics easily would be helpful.

Would my experiences with the early version of SCORE be an asset to the later
version or are all the commands new?

Also, can anybody tell me how I might transfer files from my old SCORE program
into newer software?

Any help on these questions would be greatly appreciated.

H. Gene Griswold
Towson State University
(Director, Early Music Ensemble)

------------------------------
Date:         Wed, 12 Aug 1992 12:56:56 EDT
From:         "Joseph D. McMahon" 
Subject:      New! Hyperupic.app!  Image to Sound Transduction - comp.music #4120

Reply-To: EMUSIC-L@AUVM.AMERICAN.EDU
In article <1992Aug12.013532.29859@Princeton.EDU>, ramirez.Princeton.EDU!penrose
 (Christopher Penrose) writes:
>
> Hyperupic is a *new* image to sound transduction package developed on
> the NeXT workstation.
>
> Similar in concept to the Upic system conceived by Greek supercomposer
> Iannis Xenakis, Hyperupic takes visual data and converts it into digital
> sound data.  Though, Hyperupic is not a real-time system like Upic, Hyperupic
> has the consciousness of an additional dimension:  *color*.  Color is mapped
> onto the magnitude of a synthetic frequency distribution that you generate
 with
> Hyperupic.  Hyperupic provides many different data mapping schemes.  You can
> eavesdrop on the Last Supper!  Hear the face of Hasan Mutlu!
>
> Hyperupic has the potential of being a powerful synthesis tool;  then again,
 it
> could merely be a bucket 'o kludge.  "You'll have to decide!"  Author a
> J. Pollack masterpiece with Icon's multi-colored brushes - then transduce it
> with Hyperupic.  Marvelous!
>
> Version 1.1 has just been released; those of you who picked up Hyperupic
> early, may want to get this new version.
>
> Hyperupic is free and includes source code!  On-line documentation!  Political
> propaganda and other infotainment!  Hooray!
>
> Christopher Penrose
> penrose@silvertone.princeton.edu

--
 --- Joe M.

                            THE AUDIENCE IS NOW DEAF

------------------------------
Date:         Wed, 12 Aug 1992 12:58:59 EDT
From:         "Joseph D. McMahon" 
Subject:      Hyperupic - where to get it

Reply-To: xrjdm@calvin.gsfc.nasa.gov
In article <1992Aug12.013835.473@Princeton.EDU>, ramirez.Princeton.EDU!penrose
 (Christopher Penrose) writes:
>
> Here is where to get it via ftp:
>
>     princeton.edu:		/pub/music/Hyperupic.tar.Z
>
> and for the time being:
>
>     [nova,sonata].cc.purdue.edu:	/pub/next/submissions	/Hyperupic.tar.Z
>     cs.orst.edu:			/pub/next/submissions	/Hyperupic.tar.Z
>
>
> Christopher Penrose
> penrose@silvertone.princeton.edu

--
 --- Joe M.

                            THE AUDIENCE IS NOW DEAF

------------------------------
Date:         Fri, 21 Aug 1992 19:47:36 -0400
From:         NLEONARD@RCNVMS.RCN.MASS.EDU
Subject:      Performer DTLe problem

I have experienced a number of glitches using Performer/MTP with
SMPTE.  The worst of which seems to be errors in the reading of
time code which cause performer to jump from record to play mode.

I recently stopped using DTLe, which seems to have been part of the
problem.  Using performer/MTP and MIDI Time Code I am getting
better results EXCEPT for the first 2-3 seconds after I press the
record button:  Performer jumps into play mode, then a second or third
press of the record button puts it back into record where it stays
for the rest of the take.

This problem has been occuring with a second master tape made at
a professional studio.  I am beginning to wonder if Performer/MTP and
DTLe or MTC are inherently unreliable when using them with a consumer
deck.

Has anyone had this problem and managed to have fixed it?

Thank you in advance.

Neil Leonard
nleonard@ecn.mass.edu


------------------------------
Date:         Mon, 24 Aug 1992 10:38:31 EST
From:         Larry Larraga 
Subject:      Re: Performer DTLe problem

>I am beginning to wonder if Performer/MTP and
>DTLe or MTC are inherently unreliable when using
>them with a consumer deck.

I've been using an MTP and Performer (now 4.0) with a Tascam 38 since
the MTP was fgirst released and have used DTLe exclusively.  I've
had maybe 5 trivial glitches in 2(?) years.  Nothing that restarting
a tape wouldn't solve.  I'm in a middle of a project now where I need every
track I can get, so there's no dummy audio track of the MIDI stuff and
I roll the sequence every single time I play the tape - every punch,
every roll back, lot of shuttling back and forth.  Not a glitch from
the MTP.  I'm a happy camper and a MOTU devotee because of this.

------------------------------
Date:         Tue, 18 Aug 1992 09:37:06 -0400
From:         Barry Kirsch 
Subject:      Sound Designer format needed

	Can someone please tell me where I can get the Sound Designer
data file format.

Thank you,
Barry Kirsch
bkirsch@nadc.navy.mil

------------------------------
Date:         Mon, 24 Aug 1992 18:12:35 EDT
From:         "Joseph D. McMahon" 
Subject:      Technical article on implementing a sequencer

[This article appeared in comp.music the other ay and I thought it might be
of interest to EMUSIC-L readers. Please pass on any comments to
eker@loria.crin.fr (Steven Eker). I have made some minor punctuation changes
for clarity. --- Joe M.]

>Subject: Sequencer algorithm article (long)
>Date: 19 Aug 92 19:41:39 GMT

I'm posting this article which I wrote for a MIDI mag a while ago in the hope
that MIDI programmers will find it useful (I saw a posting a week ago asking
about how to write a sequencer).

Appologies in advance to music reseach people:
This article is (very) "dumbed down" because it is written for an audience
who were (for eg) treated to a lengthy explaination of binary and hex notation
in a previous issue.

A couple of questions:

(1)	How is the "one point" vs "two point" representation of on/off pairs
handled in top pro/reseach music software? Do you use binary heaps or something
more advanced (eg f-heaps)?

(2)	I've cross posted to comp.music & rec.music.synth (followups to
comp.music) but considering the recent discussion, which group is most
appropriate for MIDI programming articles? I know this is MIDI
and hence an anathema to some (most?) music research people but
rec.music.synth strikes me as user/musician orientated rather than programmer
orinetated.

Steven


MIDI I/O ALGORITHMS
===================

by Steven Eker (eker@loria.fr)


To a musician, a note is an single object possessing (among other
characteristics) a starting point and a length. However to MIDI equipment, a
note consists of two distinct events - a Note On message and a Note Off
message. It is easy to see why MIDI had to be implemented this way: suppose
you press a key on a synth, then the synth must immediately transmit a
message telling  any connected modules to play a note, however there is
no way the synth could transmit the length of the note as it hasn't
been determined until you release the key.

This dichotomy causes a real headache for sequencer designers: how best
to store sequences of notes inside the sequencer? The most obvious
answer is the so called "two point" format where the notes are stored
as a sequence of Note On and Off events, in the order they arrive from
the synth. This format is fine when you simply want to store and replay
sequences unmodified and is the format chosen for the MIDI file standard -
presumably to make life easy for simple-minded sequencers. The problems
start when you want to edit sequences.

Whenever you move insert or delete a Note On event you have to move, insert,
or delete the corresponding Note Off event; otherwise you will end up with
the notes which change length unexpectedly or even worse hang indefinitely.
Of course a decent sequencer should keep track of the Note On/Off pairs and
present the user with notes as single entities. With the two point format a
Note On event and its matching Note Off event may be separated by arbitrarily
many other events and manipulating such a sequences consistently requires a
lot of searching for matching Note On/Off pairs.

It is much simpler if sequences of notes are stored in the "one point"
format where each Note On/Off pair is combined as a single item in a sequence.
This format also saves memory. The big drawback of the one point format
is that it has to be converted to and from the two point format for input
and output. This has to be done in real time and any lengthly computations
will reduce the accuracy of the sequencer.

In his book "MIDI sequencing in C", Jim Conger suggests storing MIDI sequences
in two point format and then converting them to and from one point format
as required for note level editing by the user. This solution has a number of
disadvantages. Firstly, block move/copy routines (and any other routines that
have to manipulate sequences in the two point format) are complicated by the
the need to avoid separating Note On and Note Off events. Secondly,
there is now way the user can edit events during playback and hear the
changes as they are being made. Thirdly, there is no saving in memory
as is possible with the one point format.

The method I will explain in this article allows you to have the best of
all worlds and even solves two other MIDI I/O headaches at the same time:

(1)	When a sequencer is replaying a large number of tracks simultaneously,
	the naive approach of sequentially scanning the active tracks to see
	which one has an event to output can cause timing inaccuracies and
	(if interrupts are blocked during this process) cause incoming MIDI
	messages to be lost.

(2)	When the user clicks on the stop button, all currently playing notes
	must be terminated. One naive method is to send an All Notes Off message
	on each MIDI channel. This method fails when the receiving MIDI device
	does not implement All Notes Off. Another naive method is to send Note
	Off messages for every pitch on every channel. Apart from taking a
	little over 1.3 seconds (with running status) this method can also
	cause problems if the sequencer output is being merged with another
	MIDI source. A rather clever idea used by one well-known sequencer
	vendor is to send a single Active Sensing message causing the
	receiving device to reset itself when no further Active Sensing
	messages arrive. Unfortunately even this method causes problems with
	certain synths. The right thing to do is to transmit Note Off messages
	for just those notes that are actually playing, but this means keeping
	track of which these are which; this can be very time consuming
	(affecting sequencer accuracy) if done a naive way.

Overview of the solution
========================

The basic idea is to keep the sequence(s) in one-point format and use fast
algorithms to convert to and from two-point format in real time for
input and output.

Actually converting incomming data from two-point format into one-point format
is fairly straightforward. We simply keep a 128x16 entry table. There
is one entry for every pitch/channel combination. When a Note On message
arrives, it is stored in a record in the appropriate sequence and a pointer to
this record is stored in the corresponding table entry. When a Note Off message
arrives, we look at the appropriate entry in the table. If it is null, then we
have a stray Note Off event and we discard it. Otherwise, we have a pointer to
the record containing the matching Note On event and we add the extra
information, such as release time and release velocity to this record; then
we place a null in the table entry.

There are a couple of subtle points to cope with missing Note Off messages.
If when we come to write a pointer in to the table we find that the entry
is already filled by a non-null pointer, then this pointer points to
a record containing a Note On message which (for some reason) has lost its
Note Off message.  In this case we can use the current time as the release
time and 64 as the default release velocity to replace the missing information.
At the end of recording, we check through the table looking for non-null
entries. If we find any, then these are pointers to records containing Note On
messages without Note Off messages. This can easily happen if the user clicks
on the stop button without releasing all the synth keys. Once again, we can use
the current time and the release velocity 64 to fill in the missing data.

The reverse process, converting from one-point format into two-point format
for playback, is not so simple. We need to use a computer-science concept
called a priority queue.

Priority Queues
===============

A priority queue is a collection of items ordered by some property - in our
case, time. There are several operations that may be performed on a priority
queue - for our purposes the following four are sufficient.

(1)	Find the least item
(2)	Remove the least item
(3)	Insert a new item
(4)	Flush the queue - remove all items.

For playback we keep two priority queues: The first contains the
next note/event for each active track; the second contains all of the
pending Note Off events.

When we are ready to transmit an event, we compare the time stamps of
the least items in the two priority queues. There are two possibilities/steps:

(1)	If the time stamp on the least item in the note/event queue was
	the lesser (or the Note Off queue was empty) we output this event.
	We then remove this item from the note/event queue and insert the
	next item on the same track into the note/event queue. If this item
	was a note, we insert a corresponding Note Off event into the Note Off
	queue.

(2)	If the time stamp on the least item in the Note Off queue was the
	lesser (or equal), we output this Note Off event and remove this
	Note Off event from the Note Off queue.

Actually, this explanation is oversimplified, since we also should take into
account the sequencer clock, but I'll come to that later.  The reason for
giving Note Off events precedence when the least items in each queue have the
same time stamp is simply that MIDI devices have limited polyphony and this
reduces the likelihood of the polyphony limit being exceeded and notes being
arbitrarily cut off.

When the user presses the stop button, the Note Off queue contains a Note Off
event for every note playing. We can simply flush this queue (i.e. remove and
transmit all the Note Off events, in any convenient order) to stop all
currently-playing notes.

Binary Heaps
============

Up to now I haven't said anything about how the priority queues are
actually implemented. An obvious solution is to store them as arrays.
There is a snag however: typically the number of tracks in a sequencer
that could be active will be rather large - perhaps 64. Each will have
an event in the note/event queue. Also the number of pending Note Offs
that might have to be stored in the Note Off queue could be equal to the
total polyphony of all the user's synths/modules.

When we have to find the least item in a queue, in the worst case we
might have to check all the items. This is not a good solution.
Suppose we kept the array in sorted order - now getting at the least
element is easy. However, in this case we might have to move all the items
already in the queue whenever we insert a new item. A sorted linked
list is also a poor implementation of a priority queue because
we might have to check every item already in the queue to find
out where to insert a new item.

A better way to implement priority queues is a data structure called a
binary heap. This is an array which is "half-sorted" in a very special
way that allows both the removal of the least item and the insertion
of new items to be performed efficiently. Binary heaps are explained
in detail in any decent book on data structures so I will not go into
technical details here. A particularly good account of binary heaps
for the practising programmer is Chapter 12 of "Programming Pearls"
by Jon Bentley.

If sequences are stored in one point format, reading and writing them to and
from MIDI files (which, you will remember, use the two-point format) requires
the same sort of conversion as that required for MIDI I/O and similar
algorithms can be used.  The situation for one-point-to-two-point format
conversion is somewhat simpler since only one track is written at
a time; only a Note Off heap is required. Speed is not as critical, but
a binary heap is still a good way to organise the conversion.

To illustrate how easily binary heaps can be programmed, Figure 1 contains the
heap manipulation code (written in 'C') from the MIDI file-save module of my
own sequencer.

-------------------------------------------------------------------------------

typedef struct heap_struct {
	long time;
	char byte1, byte2, byte3;
} HEAP;

static HEAP midi_heap[256];
static int heap_size;

ins_heap(time, byte1, byte2, byte3)
register long time;
char byte1, byte2, byte3;
{
	register int empty = ++heap_size, new;

	for(;;){
		new = empty / 2;
		if(new == 0 || midi_heap[new].time <= time)
			break;
		midi_heap[empty] = midi_heap[new];
		empty = new;
	}
	midi_heap[empty].time = time;
	midi_heap[empty].byte1 = byte1;
	midi_heap[empty].byte2 = byte2;
	midi_heap[empty].byte3 = byte3;
}

del_heap()
{
	register int empty = 1, new;
	register long time = midi_heap[heap_size--].time;

	for(;;){
		new = 2 * empty;
		if(new > heap_size)
			break;
		if(new < heap_size &&
			midi_heap[new + 1].time < midi_heap[new].time)
				new++;
		if(midi_heap[new].time >= time)
			break;
		midi_heap[empty] = midi_heap[new];
		empty = new;
	}
	midi_heap[empty] = midi_heap[heap_size + 1];
}

			Figure 1: Heap manipulation code
-------------------------------------------------------------------------------

How the code is used is as follows. Initially, the heap is empty and
heap_size = 0. The least element (if the heap is not empty) in the heap is
always in midi_heap[1].  (Yes - I know 'C' arrays start at 0 but here it is
convenient to not use the first element.) Each event in the sequence being
written to a MIDI file has its time stamp compared with that of the Note Off
event in midi_heap[1] (if the heap is not empty).  If the Note Off event in
midi_heap[1] has the lesser time stamp, it is written to the MIDI file and
del_heap() is called to remove it from the heap. The comparison step is then
repeated with the new occupant of midi_heap[1] (assuming the heap is still not
empty).

Whenever the current event in the sequence has the lesser time stamp
(or the heap is empty) this event is written to the MIDI file. If this event
was a Note On event, ins_heap is called to put the corresponding Note Off event
in the Note Off heap.

At the end of the sequence, the Note Off events remaining in the heap are
written to the MIDI file and removed from the heap in order, least time stamp
first.  In this way the Note Off events are slotted into their correct places
in the MIDI file.

Subtle points
=============

There are a number of subtle points and refinements when it comes to
implementing the above ideas.

First off, during playback we need to compare time stamps of events against the
current sequencer clock to see if they are due to be output as well as against
each other to determine the order.

One way of organising this is that we first compare the least element of the
Note Off heap against the sequencer clock - if it is less than or equal we take
step (2) above. Otherwise, we compare the least element of the note/event heap
against the sequencer clock - if it is less than or equal we take step (1)
above. Otherwise, we know that the time stamps on all the next events in all
the active tracks and all the pending Note Off events are greater than the
current clock time and nothing is due to be output at this time.

Doing the tests this way around means that later Note Off events can actually
be transmitted before other events with earlier time stamps. However, this can
only happen when there is a backlog of events due to be transmitted and
prioritising Note Off messages under these circumstances may be a good thing.

The alternative arrangement is to compare the time stamps of the least elements
on the two heaps first and then compare the lesser of these against the
sequencer clock.

Notice that during playback, the Note Off heap starts off as empty and is
filled on the fly. To set up the note/event heap at the beginning of playback,
we simply call the heap insert item routine to insert the first event
of each track (or more efficiently a pointer to the first event on each track)
into the note/event heap.

Also notice that testing the least item in a heap just means testing the item
in the first location of the array used to store the heap. So no real
work has to be done rearranging the heaps unless a MIDI message is actually
transmitted and items have to be inserted and/or deleted from the heaps.

Now in a professional sequencer, the MIDI output code is interrupt-driven
and written in assembler both for accuracy and to allow it to run as a
background task. The heap insert and delete item algorithms are very fast and
can be coded in very tight assembler (the division and multiplication in the
above code are done by shifting) it is possible for that for very large heaps
they may not complete their task in the 320us between MIDI output bytes (or
input bytes).  Thus MIDI bandwidth could be wasted and accuracy impaired (and
incomming MIDI data could be lost).

A neat (but tricky) way of getting around this problem is allow the
code that rearranges the heaps (running in an interrupt routine)
to itself be interrupted by other interrupt routines to output and input
MIDI bytes. In this way incoming MIDI data will not be lost, and we
have complete timing accuracy (up to sequencer clock resolution and MIDI
bandwidth) as long as the heap rearrangement can be done in the 640us or 960us
between output messages (okay, some messages Can be transmitted in one byte
using running status - but these are not Note On messages so we only have to
rearrange one heap).

Needless to say there has be be some kind of synchronisation between the
various layers of interrupts and this is a tricky topic which I will not go
into here.

A nice refinement is to allow the user to activate and deactivate tracks
while the sequencer is playing. This is done using slightly modified
versions of the heap insert and delete item routines to insert(remove)
the next event of the activated(deactivated) track in the note/event heap.
Another refinement is to allow the user to edit (or block copy/move) sequences
while they are being played. Both of these refinements require synchronisation
between the main program code which is making the change and the interrupt
routines that are modifying the heaps and accessing the track sequences.

------------------------------
End of the EMUSIC-L Digest
******************************