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 ******************************