home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 25 / AACD 25.iso / AACD / Sound / MSE / docs / MSE-Compiler.Tutorial1 < prev   
Encoding:
Text File  |  2000-03-23  |  16.6 KB  |  469 lines

  1. So you're feeling a bit overwhelmed!  MIDI has a lot of powerful
  2. features, and so MSE needs a lot of powerful commands to access
  3. everything that MIDI is capable of doing.  It's true this can be a bit
  4. overwhelming.  This tutorial will hopefully ease you into the process of
  5. defining MSE modules.
  6.  
  7. In the following tutorial you do not need to actually create a
  8. definition file, we have already included them to save you the time.
  9. Use them for reference as you proceed through the tutorial, if
  10. necessary.  They are a good guide for proper stucture and ordering.
  11.  
  12.  
  13.  1: First things first
  14. =======================
  15.  
  16. The first step is to name our module.  Normally, you would name the
  17. module according to the device you wanted it to control.  Let's call it
  18. "Tutorial1".
  19.  
  20. General information about a module is defined with the command structure
  21. 'Define Device'.  It has two required parameters: 'Manufacturer' and
  22. 'Device'.  We will use these two parameters to name our module.  Here is
  23. how it would look:
  24.  
  25.   Define Device (
  26.     Manufacturer "Test"
  27.     Device "Tutorial1"
  28.   )
  29.  
  30. Notice the brackets that enclose the 'Define Device' structure.  Several
  31. commands have parameters with the same name, such as 'Position'.  These
  32. brackets ensure that the compiler can tell where one command ends and the
  33. next one begins.  Brackets must always appear in pairs '(' for starting
  34. (opening) and ')' for ending (closing) a structure.  We have also
  35. indented the two parameters, so that it is easier to see that they are
  36. part of the 'Define Device' structure.
  37.  
  38. Now we need to tell the compiler what fonts we want to use in this
  39. module.  We just need one right now.  The compiler also needs to know how
  40. we want to refer to this font later, we will just use the label "Font1".
  41. We want to use the Topaz2 font with a size of 8.  Here is how it would
  42. look:
  43.  
  44.   Define Font "Font1" (
  45.     Name "Topaz2.font"
  46.     Size 8
  47.   )
  48.  
  49. 'Define Font' has two requirements, a label "Font1" and the 'Name'
  50. parameter.  The 'Size' parameter is actually optional.  The compiler will
  51. default to a size of 8 if it is not told specifically to use a different
  52. size.  We have included it here to make things more understandable.
  53.  
  54. The next thing to do is to define a window for our gadgets and text to
  55. appear in.  Windows are defined like this:
  56.  
  57.   Define Window "Main" (
  58.     Position 10 20
  59.     Size 400 200
  60.     Border
  61.   )
  62.  
  63. We have given this one the label "Main", so that we can refer to it
  64. later.  The two required parameters, 'Position' and 'Size' tell the
  65. compiler where we want the window to appear on the screen.  In this case,
  66. the upper left hand corner of the window should be at the coordinates:
  67. x=10, y=20 and it should be 400 pixels wide and 200 pixels tall.  The
  68. optional parameter 'Border' indicates that we want the window to have a
  69. border drawn around it.
  70.  
  71. Finally, we need to reference the defined window or the compiler will
  72. complain that it hasn't been used.  For now, we will just use an empty
  73. window structure which we will explain later.
  74.  
  75.   Window "Main" (
  76.   )
  77.  
  78.  
  79.  
  80.  2: Compiling a module
  81. =======================
  82.  
  83. At this point, we have enough information to compile a module.  We have
  84. included the file "Test/Tutorial1-A.def" which includes the commands we
  85. have used so far.
  86.  
  87. Start the compiler by double clicking the "MSE-Compiler" icon.  When you
  88. are prompted with the file requester, enter the "Test" directory and
  89. select the file "Tutorial1-A.def".
  90.  
  91. Once you have selected the definition file to be compiled the compiler
  92. begins its job.  This is not a very big definition yet, so you likely
  93. will not get to see any of the information the compiler displays as it
  94. compiles.  Basically, all you missed is the compiler counting lines,
  95. fonts, windows, etc.  If there had been any errors, the compiler would
  96. have told you and stopped.  Note that you do not have to quit the
  97. compiler, it quits when it is finished.
  98.  
  99.  
  100.  3: Viewing the module
  101. =======================
  102.  
  103. In that couple of seconds the compiler generated our tutorial module.
  104. Let's have a look and see what we have so far.  Start "MSE" by clicking on
  105. its icon.  When you are prompted with the file requester, enter the "Test"
  106. directory and select the file "Tutorial1.mse".  MSE will load the module
  107. and display the defined window.  Our module does not do anything yet, so
  108. enjoy the little bordered window and then quit MSE.
  109.  
  110.  
  111.  4: Displaying text
  112. ====================
  113.  
  114. We have not used the font we defined, so let's dislay some text with it.
  115. First, we need to the tell the compiler what window we want to display
  116. the text in.  All of the commands that apply to windows, 'Text', 'Gadget',
  117. 'Border', etc. are contained within a window structure.  Simply, a window
  118. structure looks like this:
  119.  
  120.   Window "Main" (
  121.   )
  122.  
  123. That will not actually do anything on its own.  It simply tells the
  124. compiler which window we are going to work with.  We need to put
  125. something inside that structure for it to be of any real use.
  126.  
  127.   Window "Main" (
  128.     Text "ABCDEFGHIJK" (
  129.       Position 10 15
  130.     )
  131.   )
  132.  
  133. The text command has two required parameters: a text string and a
  134. 'Position'.  Here we have told the compiler to place the text
  135. "ABCDEFGHIJK" at x=10, y=15.  'x' refers to the left edge of the text and
  136. 'y' refers to the baseline of the font.  The baseline is the point at
  137. which a letter meets the ground, so to speak.  Letters such as
  138. "abcdefhiklmnorstuvwxz" all sit on the baseline.  But "gjpqy" have
  139. descenders, which drop below the baseline.  With a standard size 8 font
  140. you have something like this:
  141.  
  142.       01234567     01234567
  143.  
  144.     0 **         0
  145.     1 **         1
  146.     2 ******     2 **    **
  147.     3 **   **    3  **  **
  148.     4 **   **    4   ****
  149.     5 **   **    5    **
  150.     6 o*****     6 o  **
  151.     7            7  ***
  152.  
  153. Where the baseline is at row 6.  When defining the position text, you
  154. have to keep the baseline in mind when indicating coordinates.  If you
  155. wanted the upper left hand corner of the letter 'b' to appear at x=5,
  156. y=10 you would use 'Position 5 16'.  In the above examples, 'o' indicates
  157. the point at which coordinates refer (at 0,6).
  158.  
  159.  
  160. We will display two different texts in our previously defined window:
  161.  
  162.   Window "Main" (
  163.     Text "Plain Text" (
  164.       Position 20 25
  165.     )
  166.     Text "Shadow Text" (
  167.       Position 20 40
  168.       Color 2
  169.       Shadow
  170.     )
  171.   )
  172.  
  173.  
  174. Refer to MSE-Compiler.guide for more information about the extra
  175. parameters, 'Color' and 'Shadow', used here and others that can also be
  176. used.
  177.  
  178. Compile "Test/Tutorial1-B.def" and open the 'Tutorial1.mse' module in MSE
  179. to see the results.
  180.  
  181.  
  182.  4: Adding borders
  183. ===================
  184.  
  185. Let's make things a little prettier and add a border around the text.
  186. Note that the Border option in 'Define Window' is actually a quick form
  187. of this command.  When used in 'Define Window', the 'Position' and 'Size'
  188. are determined by the size of the window and no other options are
  189. allowed.  The 'Border' command allows some additional features.  Borders
  190. are defined like this:
  191.  
  192.   Border (
  193.     Position 10 10
  194.     Size 107 40
  195.     Fill 3
  196.   )
  197.  
  198. Remember that, although we have not shown it this way, this command and
  199. others like it must be contained within a 'Window' structure.
  200.  
  201. The 'Position' parameter, as with 'Define Window', refers to the
  202. coordinates of the upper left hand corner of the border.  Again, 'Size'
  203. refers to the width and height in pixels.  Note that there is an
  204. alternative to using the 'Size' command anywhere it is used.  'Position2'
  205. sets the position of the lower right hand corner.  In the above example,
  206. we could have used 'Position2 117 50' instead of 'Size 107 40' and would
  207. have gotten the same result.  When using a paint program to do intial
  208. layout designs, the 'Position2' alternative can save you some calculation
  209. since most paint programs only give x/y coordinates.
  210.  
  211. The 'Fill' option tells the compiler that we want the border filled with
  212. color 3.  It is important to realize that sometimes the order that
  213. commands appear within the definition file needs to be considered.  If we
  214. added this 'Border' definition in AFTER the 'Text' commands, the text
  215. would be overdrawn by the fill option we have used.  Because we want the
  216. text to appear over the filled border, we have to order it BEFORE.
  217. Something like this:
  218.  
  219.   Window "Main" (
  220.     Border (
  221.       Position 10 10
  222.       Size 107 40
  223.       Fill 3
  224.     )
  225.     Text "Plain Text" (
  226.       Position 20 25
  227.     )
  228.     Text "Shadow Text" (
  229.       Position 20 40
  230.       Color 2
  231.       Shadow
  232.     )
  233.   )
  234.  
  235. Compile "Test/Tutorial1-C.def" and open the 'Tutorial1.mse' module in MSE
  236. to see the results.
  237.  
  238.  
  239.  5: Adding gadgets
  240. ===================
  241.  
  242. To interact with MSE we have to add gadgets.  Although MSE supports
  243. several different kinds, we will begin with a simple slider gadget
  244. example:
  245.  
  246.   Gadget "Notes" (
  247.     Position 140 140
  248.     Type Slider (
  249.       Range 0 127
  250.       Size 100 10
  251.       Direction HORIZONTAL
  252.     )
  253.   )
  254.  
  255. This defines a gadget with the label "Notes".  Currently, gadget labels
  256. are not used but because future features will need them, they are
  257. required.  The gadget command has two additional required parameters:
  258. 'Position' and 'Type'.  As with other commands, 'Position' defines the
  259. upper left hand coordinate of the gadget.  'Type' is used to define the
  260. kind of gadget and its parameters.  Note that 'Type' is also a structure
  261. imbedded (or nested) within the Gadget command with its own structure
  262. bracketing pair.
  263.  
  264. The 'Type Slider' structure has three required parameters.  'Range' sets
  265. the minimum and maximum values for the gadget.  'Size' sets the width
  266. (100) and height (10) of the gadget.  'Direction' determines the
  267. orientation of the gadget.
  268.  
  269. Note that 'Gadget' is a window command and like others must be placed
  270. within a window structure.
  271.  
  272. Compile "Test/Tutorial1-D.def" and open the 'Tutorial1.mse' module in MSE
  273. to see the results.
  274.  
  275.  
  276.  6: Displaying gadget values
  277. =============================
  278.  
  279. Our gadget does not do much, yet.  Let's enhance it a little by adding a
  280. couple optional parameters to the 'Type Slider' structure:
  281.  
  282.       LevelPlace ABOVE
  283.       Default 63
  284.  
  285. This tells the compiler that we want the value (or level) of the gadget
  286. to be displayed above the gadget and that we what the gadget's intial
  287. level to be set at 63.  Once an editor contains midi patch data, the
  288. 'Default' value can usually be determined from the default patch data, so
  289. this parameter would normally not be included.  If it was, it would
  290. override the value contained in the patch data.  This is not what we
  291. normally want to happen.
  292.  
  293. Note that different gadget types have different parameters, they can not
  294. be interchanged.
  295.  
  296. We would like to see some text to remind us what the gadget is for, so we
  297. have also added a new 'Text' structure.
  298.  
  299.   Text "Note #" (
  300.     Position 167 159
  301.     Color 3
  302.   )
  303.  
  304. Compile "Test/Tutorial1-E.def" and open the 'Tutorial1.mse' module in MSE
  305. to see the results.
  306.  
  307.  
  308.  7: Understanding how MSE handles MIDI
  309. =======================================
  310.  
  311. Our module is not very useful, yet.  Let's teach it about MIDI.  For this
  312. example, we will use a feature of MIDI that will work with almost any
  313. MIDI sound module... note playing.  This is not a great application of
  314. MSE but is easy enough to get started.
  315.  
  316. The are several parts to defining MIDI information.  First, the compiler
  317. needs to know what MIDI channel the device is operating on and where it
  318. should send the MIDI data.  These parameters should be included within
  319. the 'Define Device' structure.
  320.  
  321.     Channel 1
  322.     Handler MIDI
  323.  
  324. This tells the compiler to use the public domain MIDI.library for
  325. controlling your MIDI devices.  If you do not have it installed, install
  326. it in your LIBS: directory now -OR- consult the MSE-Compiler.guide for
  327. other 'Handler' options.  If the device you want to control is set to a
  328. channel other than 1 or OMNI, this should be changed too.
  329.  
  330. Secondly, we need to tell the compiler what the MIDI message looks like.
  331. This is done with the 'Define Midi' command.  The MIDI specification
  332. defines the note message as such:
  333.  
  334.   $9n ## vv
  335.  
  336.   where:   n = MIDI Channel (0-15)
  337.           vv = velocity (NOTE ON vv = 1-127, NOTE OFF vv = 0)
  338.  
  339. In midi communication, channels are numbered 0-15 not 1-16 like we
  340. usually see them displayed.
  341.  
  342. For this message, channels work like this: A value of $90 represents MIDI
  343. Channel 1, $91 = 2, $92 = 3, ... $9F = 16.  If we ALWAYS wanted to use
  344. channel 5 here we could use $94.  However, one of the features of MSE is
  345. the ability to override the channel at anytime.  If we force this to be
  346. $94, that feature will not work with this module.  For now we will use
  347. $90 and add the channel # to it later.  Technically we are still forcing
  348. this message to use channel 1, but this will make more sense later, when
  349. we discuss this further.
  350.  
  351. For now, let's not concern ourselves with the velocity.  Instead we will
  352. force it to 64.
  353.  
  354. Here, we will actually define two note messages: NOTE ON followed by NOTE
  355. OFF.  As far as MIDI is concerned, this is not greatly useful, but serves
  356. this tutorial purpose.
  357.  
  358. In the MSE definition language the message can be defined like this:
  359.  
  360.   Define Midi "Notes" (
  361.     Data (
  362.       $90  '            0 = Offset
  363.       Byte 'Note #      1
  364.       64   'Velocity    2
  365.     )
  366.   )
  367.  
  368. * The apostrophe is a special marker that can be used to tell the
  369.   compiler that we are just making a note to ourselves.  When the
  370.   compiler encounters this character, it ignores everything on the
  371.   remainder of that line.
  372.  
  373. * As with other commands, '"Notes"' is simply a label for later
  374.   referencing of this definition.
  375.  
  376. * 'Byte' as used here, serves only as a place holder.  The compiler
  377.   actually stores this as 0 when it creates the module.  More
  378.   importantly, it serves as a reminder to us that these are values that
  379.   need to be inserted later.  You can put anything you want here, really,
  380.   because it will be overwritten anyway.
  381.  
  382. So, now that we have the general structure of the message defined, we
  383. need to consider how the missing values get put into the message.  A
  384. couple things are still missing: Midi Channel and Note #.
  385.  
  386. We will use the slider gadget we defined previously to control the Note
  387. #.  So we will handle that later.
  388.  
  389. 'Define Midi' has a special parameter, 'Midi', that is used to tell the
  390. compiler what values need to be inserted in the midi message before it
  391. gets sent.  This is a good place to tell it about the Midi Channel.
  392.  
  393. We will use this feature to tell the compiler where in the message the
  394. channel is to be stored, so that MSE can change it when we want it to.
  395. Because we are sending two note message, we actually need to store it in
  396. two places.  This parameter needs to be added to the already defined
  397. 'Define Midi' structure.
  398.  
  399.   Midi (
  400.     Data (
  401.       0 CHANNEL
  402.     )
  403.   )
  404.  
  405. * '0' represents a byte offset from the beginning of the message.
  406.   Refer back to the definition.
  407.  
  408. * 'CHANNEL' is a special indicator to MSE that we want to add the current
  409.   MIDI channel number to the value at the given offset.  Remember that we
  410.   initialized this value to $90.  so, if the current channel was 5,
  411.   $90 + 4 (remember channels are numbered 0-15) would be $94.
  412.  
  413.  
  414.  8: Making gadgets send midi data
  415. ==================================
  416.  
  417. Now that we have told the compiler about the midi messages that we want
  418. to use, it's time to tell our previously defined slider gadget about it.
  419.  
  420. Though, the MIDI note message supports a range of 128 notes, most sound
  421. modules do not.  So, our gadget has too large a range.  We need to change
  422. that first.
  423.  
  424.       Range 36 96
  425.  
  426. The 'Default' setting and and other parameters are okay the way they are.
  427.  
  428. The gadget command also has a 'Midi' parameter, similar to the one used
  429. with 'Define Midi' but much more powerful.  There are some differences,
  430. see the MSE-Compiler.guide for more details.
  431.  
  432.   Midi "Notes" (
  433.     Data (
  434.       1 VALUE Byte
  435.     )
  436.     Send
  437.   )
  438.  
  439. * Here's where the label we defined earlier with 'Define Midi' comes in
  440.   handy.  We use it to reference the already defined message.
  441.  
  442. * '1' represents a byte offset from the beginning of the message.
  443.  
  444. * 'VALUE' is a special indicator to MSE that we want to store the current
  445.   value of the gadget.
  446.  
  447. * 'Byte' tells MSE how the value should be stored.  This is the normal
  448.   method of storage, and the simplest.
  449.  
  450. * 'Send' is an option that tells MSE that it should send the midi
  451.   message. If you do not include this, MSE will construct the midi
  452.   message but will not send it.  Why doesn't MSE just send the message
  453.   all the time?  Sometimes it is necessary to maintain several messages
  454.   simultaneously and it is not necessary to send both so 'Send' is an
  455.   option.
  456.  
  457.  
  458.  9: Hearing the results
  459. ========================
  460.  
  461. Compile "Test/Tutorial1-F.def" and open the 'Tutorial1.mse' module in MSE
  462. to see the results.  Visually, everything should look the same as the
  463. last time.
  464.  
  465. However, if everything is properly connected to your sound module, when
  466. you change the slider value, you should hear notes play.
  467.  
  468. Because we have not sent a note off message, the sound will play forever.
  469.