home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 640a.lha / NotePlayer_v1.0 / NotePlayer.doc.pp / NotePlayer.doc
Text File  |  1992-05-17  |  19KB  |  424 lines

  1.                                 NotePlayer
  2.                            Standard description
  3.                          Copyright 1992 Bryan Ford
  4.                                  Version 1
  5.  
  6.  
  7.  
  8.                                Distribution
  9.                                ~~~~~~~~~~~~
  10.  
  11.     This package is provided "as is" without warranty of any kind, either
  12. expressed or implied, including, but not limited to, the implied warranty
  13. of fitness for a particular purpose.  All risks associated with the use of
  14. this package are assumed by you.
  15.  
  16.     This package is freely redistributable as long as none of its contents
  17. are modified, added, or removed.  You may not charge more for distributing
  18. it than a small fee to cover the disk copying expenses.  It may not be used
  19. in or distributed with any commercial program without my written
  20. permission.  (If you want to use anything in a commercial program, just ask
  21. me - I probably won't charge anything; I mainly just want to know who is
  22. using it for what.)  The distribution must contain the following files:
  23.  
  24.     NotePlayer.doc      This document
  25.     note.i              Include file used to accessing a NotePlayer
  26.     notesys.asm         System-friendly audio.device NotePlayer
  27.     notehard.asm        Simple hardware-banging NotePlayer
  28.     note.lib            Link library containing assembled versions of
  29.                         notesys.asm and notehard.asm
  30.     ptplay.asm          Example music player which uses a NotePlayer
  31.  
  32.  
  33.  
  34.                                Introduction
  35.                                ~~~~~~~~~~~~
  36.  
  37.     This document describes the NotePlayer standard.  The NotePlayer
  38. standard is an application interface specification designed to be
  39. compatible across all 680x0-based computers.  Its purpose is to allow
  40. hardware-independent music players to be written which can be used in a
  41. variety of environments, operating systems, and even on completely
  42. different computers.  It also makes it easier to simply write music players
  43. for the Amiga.
  44.  
  45.     Note that while this document defines note players rather than music
  46. players, one of the goals is NOT to make NotePlayers interchangeable with
  47. each other.  (This would be pretty much impossible.)  The goal is to make
  48. the interface to a note player standardized, so music players can be
  49. made interchangeable.
  50.  
  51.     A NotePlayer module is a module written to this standard, which
  52. provides facilities to music players for playing notes.  These calls, along
  53. with some timing facilities provided in some other way (such as through the
  54. GMOD standard), provide everything a music player needs to play music. The
  55. interface is very powerful, but at the same time very easy to use for a
  56. music player.
  57.  
  58.  
  59.  
  60.                              Client interface
  61.                              ~~~~~~~~~~~~~~~~
  62.  
  63.     The only part of a NotePlayer module visible to the music player is a
  64. short jump table.  A particular NotePlayer module is referred to by a
  65. pointer to its jump table.  For example, in a portable GMOD module, a
  66. pointer to the NotePlayer's jump table is given to the module.  The module
  67. then performs all of its low-level note playing through entrypoints in this
  68. jump table.
  69.  
  70.     NotePlayer entrypoints are intended to be called from assembly
  71. language.  Calling them from C or another high-level language may require
  72. some kind of stub routines written in assembly language.  (But who wants to
  73. write music players in C, anyway?)
  74.  
  75.     The parameters to each of the functions in the jump table entries
  76. listed below are passed in registers, as indicated on the second line of
  77. each entry description.  The suffix '.b', '.w', and '.l' indicates which
  78. part of that register the NotePlayer looks at.  For '.b' and '.w', the
  79. NotePlayer ignores the top part of the register - it does not have to
  80. contain zero.
  81.  
  82.     The NotePlayer routines have pretty much standard calling conventions.
  83. They may destroy registers D0-D1/A0-A1, but will save all other registers.
  84. Return codes are returned in D0 where appropriate.
  85.  
  86.     The entries in the jump table are each four bytes long.  The number of
  87. entries in the jump table depends on the version number of the NotePlayer.
  88. The version number of a particular NotePlayer corresponds to the version
  89. number of the NotePlayer.doc (this document) according to which the
  90. NotePlayer was written.  The first eight entrypoints are present in all
  91. NotePlayers.  The currently defined entrypoints are:
  92.  
  93.  
  94. NotePlayer+$00: info = NoteInfo()
  95.                 D0.l
  96.  
  97.     Returns a pointer to an information structure in D0.  The structure's
  98. size depends on the version number in the structure.  The part of the
  99. structure defined in this version of the standard is:
  100.  
  101.     info+$00 (byte) Version number of NotePlayer standard used
  102.     info+$01 (byte) Revision number of this particular NotePlayer
  103.     info+$02 (byte) General-purpose flags:
  104.         bit 0: All sound samples must be in MEMF_CHIP
  105.         bit 1: Amiga "period" extension supported (described later)
  106.     info+$03 (byte) Maximum number of channels this NotePlayer supports
  107.     info+$04 (long) Pointer to name of this particular NotePlayer module
  108.  
  109.  
  110. NotePlayer+$04: errmsg = NoteInit(channels,stereoarray)
  111.                  D0.l               D0.b       A0.l
  112.  
  113.     Gets the NotePlayer ready to play notes.  This must be called before
  114. any other entrypoints are called.  (Exceptions:  NoteInfo and NoteFinish
  115. may be called before NoteInit.)
  116.  
  117.     The client passes the number of (monophonic) channels it will need in
  118. D0, and an array describing the preferred stereo orientation of each
  119. channel in A0.  The client can ask for between 1 and 128 channels, but if
  120. it asks for more channels than the NotePlayer supports, NoteInit will fail
  121. and the client will not be able to use this NotePlayer to play its music.
  122.  
  123.     The stereoarray, if supplied, must contain as many bytes as the number
  124. of channels requested. The first byte describes channel 0, the second byte
  125. channel 1, and so on.  Each byte contains a signed value from -127 to 127
  126. (-128 is reserved and should not be used) describing "where" this channel
  127. is supposed to play.  A value of -127 indicates far left; 127 indicates far
  128. right; 0 indicates center (no stereo).  Other values in this range may be
  129. used as a balance control, indicating the position on a gradient between
  130. left and right, although most NotePlayers will simply look at whether the
  131. byte is negative, positive, or zero.  (Future hot-shot NotePlayers running
  132. on advanced sound hardware can use two hardware channels per client-visible
  133. channel to achieve smooth stereo panning; a future version of this standard
  134. will provide for this situation when it arises.)  If the client passes NULL
  135. for the stereoarray, an array full of zeros is assumed.
  136.  
  137.     NoteInit returns zero if the NotePlayer was successfully initialized;
  138. it returns a pointer to a null-terminated error message if initialization
  139. failed for some reason or another.  If the call is successful, the client
  140. may commence playing notes with the NotePlayer, and must call NoteFinish
  141. when it is done.  If the call fails, the client must not call any other
  142. NotePlayer entrypoints except the first three, and it does not need to
  143. (though it may) call NoteFinish.
  144.  
  145.  
  146. NotePlayer+$08: NoteFinish()
  147.  
  148.  
  149.     This call stops all currently playing notes and performs whatever
  150. internal cleanup is necessary when note playing is finished.  If the
  151. NoteInit call succeeded, the client must call this entrypoint when it is
  152. finished with the NotePlayer.
  153.  
  154.  
  155. NotePlyaer+$0c: NoteStart(chan,oneshotdata,oneshotlen,repdata,replen,freq,vol)
  156.                           D2.b      A0.l       D0.l     A1.l   D1.l  D3.w D4.w
  157.  
  158.     This entrypoint is the workhorse of the NotePlayer system: it plays
  159. notes.  Any note previously playing in the channel is stopped, and a new
  160. note is started.
  161.  
  162.     The channel number must be between 0 and n-1, where n is the number of
  163. channels requested in (and granted by) the NoteInit call.  If bit 7 in the
  164. channel number is set, the NotePlayer takes the logical NOT of the
  165. parameter as the real channel number, and modifies the behavior of the call
  166. slightly.  In this case, instead of stopping any currently playing note and
  167. starting the new note immediately, the change is made after the currently
  168. playing note finishes its current cycle: when it is about to start the
  169. repeat part, either directly after the one-shot part finishes, or when the
  170. current repeat cycle is finished.  The new note will effectively be
  171. "joined" to the old note, making it possible to implement "release" phases
  172. of notes, among other things.
  173.  
  174.     If oneshotlen is nonzero, then it contains the number of 8-bit samples
  175. in the one-shot part of the note, and oneshotdata points to the sample
  176. data.  If oneshotlen is zero, the note has no one-shot part, and the repeat
  177. part (if it exists) is started immediately.
  178.  
  179.     The replen and repdata parameters work exactly like the one-shot
  180. parameters.  If repdata is zero, the note has no repeat part, and the
  181. channel will become silent as soon as the one-shot part is finished.
  182.  
  183.     If both oneshotlen and replen are zero, then any currently playing note
  184. is stopped without starting a new note.  This is equivalent in effect to
  185. the NoteStop entrypoint.
  186.  
  187.     The freq parameter contains the sampling frequency at which to play the
  188. note, in Hz.  The vol parameter contains the volume at which to play the
  189. note, ranging from $000 (silent) to $100 (maximum).
  190.  
  191.     If flag bit 1 in the Info structure returned by NoteInfo is set, then a
  192. special extension to the frequency specification is supported, to allow
  193. Amiga-based "tracker" players to be more easily accomodated.  If the client
  194. calls NoteStart with D3.w (freq) set to zero, then the frequency is defined
  195. by an Amiga period value in the high word of D3.  To calculate frequency
  196. from period, or vice versa, simply divide the known value into 3579545.
  197.  
  198.  
  199. NotePlayer+$10: NoteStop(chan)
  200.                          D2.b
  201.  
  202.     Stops any note currently playing in the specified channel, either
  203. immediately (if D2.b contains a normal channel number from 0-127), or after
  204. the current cycle of the currently playing note is finished (if D2.b
  205. contains a NOTed channel number).  This call is equivalent to calling
  206. NoteStart with zero in both oneshotlen and replen.
  207.  
  208.  
  209. NotePlayer+$14: NoteFreqVol(chan,freq,vol)
  210.                             D2.b D3.w D4.w
  211.  
  212.     Changes the frequency and volume of the currently playing note, either
  213. immediately (if D2.b contains a normal channel number from 0-127), or after
  214. the current cycle is finished (if D2.b contains a NOTed channel number).
  215. This entrypoint is used to implement slides and fades and such.  The freq
  216. and vol parameters work exactly as they do in the NoteStart entrypoint.
  217.  
  218.  
  219. NotePlayer+$18: NoteFreq(chan,freq)
  220.                          D2.b D3.w
  221.  
  222.     Changes the frequency of the currently playing note, without changing the
  223. volume.  Otherwise works exactly the same way as NoteFreqVol.
  224.  
  225.  
  226. NotePlayer+$1c: NoteVol(chan,vol)
  227.                         D2.b D4.w
  228.  
  229.     Changes the volume of the currently playing note, without changing the
  230. frequency.  Otherwise works exactly the same way as NoteFreqVol.
  231.  
  232.  
  233.  
  234.  
  235.               Amiga system-friendly NotePlayer (notesys.asm)
  236.               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  237.  
  238.     The file "notesys.asm" contains a sample NotePlayer module for the
  239. Amiga which uses the audio.device to play notes.  To use it, simply link
  240. "note.lib" with your program.  The symbol "NoteSys" then points to the
  241. NotePlayer jump table.  (The symbol "_NoteSys" also points to the jump
  242. table, for high-level language users.)
  243.  
  244.     Since this NotePlayer uses the audio.device for everything it does, it
  245. may be somewhat slower than a player that accesses the hardware directly.
  246. However, as the programmers at Commodore have pointed out many times, using
  247. the audio.device means there is no need for ugly DMA-delay loops and such,
  248. which often compensates for the slightly lower efficiency of the
  249. audio.device.  Moreover, this NotePlayer can give up audio channels as
  250. needed, and it automatically re-allocates them when they again become
  251. available, thus allowing beeps and such to be heard through the music.
  252.  
  253.     This NotePlayer includes a master volume/balance control which is
  254. completely independent of the main NotePlayer interface.  (In other words,
  255. the music player can't use it - instead, the main program that's
  256. responsible for putting the NotePlayer and the music player together uses
  257. it.)  To set the master volume, call the NoteSysMasterVol function:
  258.  
  259.     NoteSysMasterVol(volume)
  260.                       D0.w
  261.  
  262.     This function is available in both assembly ("NoteSysMasterVol") and C
  263. ("_NoteSysMasterVol" for stack args, "@NoteSysMasterVol" for register
  264. args).  The volume parameter must be between 0 and $100 (256).  If any
  265. music is currently playing, the volume changes immediately.  The master
  266. volume cannot be changed in any way through calls to the entrypoints in the
  267. normal (music player-visible) jump table.
  268.  
  269.     If you want separate control of the volume of the left and right
  270. channels (i.e. for a balance control), use the NoteSysMasterVolBal
  271. function:
  272.  
  273.     NoteSysMasterVolBal(leftvolume,rightvolume)
  274.                             D0.w       D1.w
  275.  
  276.     This function is also available in assembly and C forms.
  277.  
  278.     "notesys.asm" can be assembled with A68k version 2.71.
  279.  
  280.  
  281.  
  282.              Amiga hardware-banging NotePlayer (notehard.asm)
  283.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  284.  
  285.     For situations where the audio.device isn't available, is too slow, or
  286. simply isn't in style, "notehard.asm" can be used instead for 4-channel
  287. playing.  This module is much smaller and (if you arrange it so DMA delay
  288. loops aren't needed) faster, although not exactly system-friendly.
  289.  
  290.     The NotePlayer jump table in "notehard.asm" works exactly the same way
  291. as in "notesys.asm", except it's externally defined as "NoteHard" (and
  292. "_NoteHard") instead of "NoteSys".
  293.  
  294.     For simplicity, the NoteInit call in this NotePlayer does no error
  295. checking.  In particular, it doesn't check the number of channels requested
  296. by the music player.  If the music player requests more than four channels,
  297. NoteInit will succeed, but the first time the music player tries to use
  298. channel number 4 or higher, Bad Things will happen.
  299.  
  300.     This NotePlayer imposes a few restrictions, for the sake of simplicity.
  301. First, the sync-cycle feature (activated by NOTing the channel number) is
  302. not supported.  Do not hook a music player that uses it to this NotePlayer,
  303. or your results will be Not Good.
  304.  
  305.     Second, this NotePlayer doesn't handle samples more than 64K in size.
  306.  
  307.     Third, it assumes that the first four bytes in chip memory (at absolute
  308. address 0) contain zero.  This is normally the case anyway, and it is easy
  309. to enforce in a game or demo that takes over the machine either temporarily
  310. or permanently.
  311.  
  312.     Finally, unlike "notesys.asm" (and any other full-featured NotePlayer,
  313. "notehard.asm" does no mapping of channels; it does not attempt to match
  314. hardware channels with client channels according to the stereo preferences
  315. specified in the NoteInit call.  The client's channel 0 goes to hardware
  316. channel 0, etc.
  317.  
  318.     This NotePlayer does not need any of the audio interrupts, and you
  319. should have them all turned off (or redirected to a harmless routine) when
  320. you use it.
  321.  
  322.     The DMA delay, of course, is the bane of all Amiga players.
  323. "notehard.asm" requires that the client (not the music player, but the
  324. program that hooks the music player and the NotePlayer together) handle DMA
  325. waiting, for maximum flexibility.  After the music player finishes all its
  326. activity for a certain cycle (probably including calls to NoteStart) and
  327. returns to the client, the client must check the longword named
  328. "NoteHardDMACall" (or "_NoteHardDMACall"), which is defined in
  329. "notehard.asm".  If this longword is nonzero, it is a pointer to a routine
  330. which must be called after waiting an appropriate amount of time (usually
  331. about 7 scanlines).  The routine obeys standard Amiga calling conventions:
  332. it can munch d0-d1/a0-a1, but saves all other registers.  After the routine
  333. returns, the client must again check "NoteHardDMACall" and if it's still
  334. nonzero, wait again and call the new address, and so on until it returns
  335. zero.
  336.  
  337.     As an example, if you can't implement full interrupt-driven DMA
  338. waiting, this scrap of code could do the trick:
  339.  
  340.         bsr     musciplayer
  341. 1$      move.l  NoteHardDMACall,d0
  342.         bz      9$
  343.         move.l  d0,a0
  344.         moveq   #7-1,d1
  345. 2$      move.b  $dff006,d0
  346. 3$      cmp.b   $dff006,d0
  347.         beq.s   3$
  348.         dbra    d1,2$
  349.         jsr     (a0)
  350.         bra     1$
  351. 9$
  352.  
  353.     Of course, playing music will hog a lot less CPU time if you use a CIA
  354. timer interrupt for this purpose.
  355.  
  356.     As a final reminder, this NotePlayer never accesses the operating
  357. system or anything.  The only things it accesses (outside of some internal
  358. variables) are the DMACON register and the audio registers ($dff0a0 to
  359. $dff0d8).
  360.  
  361.     If you (heaven forbid!) want to use this routine while the OS is
  362. around, you'd better open the audio.device yourself and lock all the
  363. channels so things don't go haywire if someone else tries to access the
  364. audio hardware at the same.
  365.  
  366.     "notehard.asm" can be assembled with A68k version 2.71.
  367.  
  368.  
  369.  
  370.                      Example player code (ptplay.asm)
  371.                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  372.  
  373.     For your education and viewing pleasure, I've included a version of the
  374. Protracker 2.1 player code hacked up to use a NotePlayer.  Read it and
  375. weep.  (You'll see what I mean...)
  376.  
  377.  
  378.  
  379.                                Future plans
  380.                                ~~~~~~~~~~~~
  381.  
  382.     In the future I hope to write more NotePlayers to be distributed in
  383. this package.  Among them:
  384.  
  385.     * A better hardware NotePlayer that supports sound effects and such.
  386.  
  387.     * An 8-channel NotePlayer.
  388.  
  389.     * NotePlayers for the new sound boards for the Amiga.
  390.  
  391.     It would also be nice to see NotePlayers written for other 680x0-based
  392. computers besides the Amiga.  This could be very handy for games and other
  393. programs which are often written for several computers at once.
  394.  
  395.  
  396.  
  397.                               Contact Address
  398.                               ~~~~~~~~~~~~~~~
  399.  
  400.     I tend to move around a great deal, so mail sent directly to me
  401. sometimes has a hard time catching up.  If you want mail to reach me (it
  402. may take a while, but it WILL reach me), send it to this address:
  403.  
  404.         Bryan Ford
  405.         8749 Alta Hills Circle
  406.         Sandy, UT 84093
  407.  
  408.     I can be reached more quickly (for the time being anyway) on the phone
  409. or through one of the electronic mail addresses below:
  410.  
  411.         (801) 585-4619
  412.         bryan.ford@m.cc.utah.edu
  413.  
  414.     If you want to get something to me through the mail more quickly, FIRST
  415. call or E-mail me to make sure I'm still here, then send it to this
  416. address:
  417.  
  418.         Bryan Ford
  419.         27104 Ballif Hall
  420.         University of Utah
  421.         Salt Lake City, UT 84112
  422.  
  423.  
  424.