home *** CD-ROM | disk | FTP | other *** search
- So you're feeling a bit overwhelmed! MIDI has a lot of powerful
- features, and so MSE needs a lot of powerful commands to access
- everything that MIDI is capable of doing. It's true this can be a bit
- overwhelming. This tutorial will hopefully ease you into the process of
- defining MSE modules.
-
- In the following tutorial you do not need to actually create a
- definition file, we have already included them to save you the time.
- Use them for reference as you proceed through the tutorial, if
- necessary. They are a good guide for proper stucture and ordering.
-
-
- 1: First things first
- =======================
-
- The first step is to name our module. Normally, you would name the
- module according to the device you wanted it to control. Let's call it
- "Tutorial1".
-
- General information about a module is defined with the command structure
- 'Define Device'. It has two required parameters: 'Manufacturer' and
- 'Device'. We will use these two parameters to name our module. Here is
- how it would look:
-
- Define Device (
- Manufacturer "Test"
- Device "Tutorial1"
- )
-
- Notice the brackets that enclose the 'Define Device' structure. Several
- commands have parameters with the same name, such as 'Position'. These
- brackets ensure that the compiler can tell where one command ends and the
- next one begins. Brackets must always appear in pairs '(' for starting
- (opening) and ')' for ending (closing) a structure. We have also
- indented the two parameters, so that it is easier to see that they are
- part of the 'Define Device' structure.
-
- Now we need to tell the compiler what fonts we want to use in this
- module. We just need one right now. The compiler also needs to know how
- we want to refer to this font later, we will just use the label "Font1".
- We want to use the Topaz2 font with a size of 8. Here is how it would
- look:
-
- Define Font "Font1" (
- Name "Topaz2.font"
- Size 8
- )
-
- 'Define Font' has two requirements, a label "Font1" and the 'Name'
- parameter. The 'Size' parameter is actually optional. The compiler will
- default to a size of 8 if it is not told specifically to use a different
- size. We have included it here to make things more understandable.
-
- The next thing to do is to define a window for our gadgets and text to
- appear in. Windows are defined like this:
-
- Define Window "Main" (
- Position 10 20
- Size 400 200
- Border
- )
-
- We have given this one the label "Main", so that we can refer to it
- later. The two required parameters, 'Position' and 'Size' tell the
- compiler where we want the window to appear on the screen. In this case,
- the upper left hand corner of the window should be at the coordinates:
- x=10, y=20 and it should be 400 pixels wide and 200 pixels tall. The
- optional parameter 'Border' indicates that we want the window to have a
- border drawn around it.
-
- Finally, we need to reference the defined window or the compiler will
- complain that it hasn't been used. For now, we will just use an empty
- window structure which we will explain later.
-
- Window "Main" (
- )
-
-
-
- 2: Compiling a module
- =======================
-
- At this point, we have enough information to compile a module. We have
- included the file "Test/Tutorial1-A.def" which includes the commands we
- have used so far.
-
- Start the compiler by double clicking the "MSE-Compiler" icon. When you
- are prompted with the file requester, enter the "Test" directory and
- select the file "Tutorial1-A.def".
-
- Once you have selected the definition file to be compiled the compiler
- begins its job. This is not a very big definition yet, so you likely
- will not get to see any of the information the compiler displays as it
- compiles. Basically, all you missed is the compiler counting lines,
- fonts, windows, etc. If there had been any errors, the compiler would
- have told you and stopped. Note that you do not have to quit the
- compiler, it quits when it is finished.
-
-
- 3: Viewing the module
- =======================
-
- In that couple of seconds the compiler generated our tutorial module.
- Let's have a look and see what we have so far. Start "MSE" by clicking on
- its icon. When you are prompted with the file requester, enter the "Test"
- directory and select the file "Tutorial1.mse". MSE will load the module
- and display the defined window. Our module does not do anything yet, so
- enjoy the little bordered window and then quit MSE.
-
-
- 4: Displaying text
- ====================
-
- We have not used the font we defined, so let's dislay some text with it.
- First, we need to the tell the compiler what window we want to display
- the text in. All of the commands that apply to windows, 'Text', 'Gadget',
- 'Border', etc. are contained within a window structure. Simply, a window
- structure looks like this:
-
- Window "Main" (
- )
-
- That will not actually do anything on its own. It simply tells the
- compiler which window we are going to work with. We need to put
- something inside that structure for it to be of any real use.
-
- Window "Main" (
- Text "ABCDEFGHIJK" (
- Position 10 15
- )
- )
-
- The text command has two required parameters: a text string and a
- 'Position'. Here we have told the compiler to place the text
- "ABCDEFGHIJK" at x=10, y=15. 'x' refers to the left edge of the text and
- 'y' refers to the baseline of the font. The baseline is the point at
- which a letter meets the ground, so to speak. Letters such as
- "abcdefhiklmnorstuvwxz" all sit on the baseline. But "gjpqy" have
- descenders, which drop below the baseline. With a standard size 8 font
- you have something like this:
-
- 01234567 01234567
-
- 0 ** 0
- 1 ** 1
- 2 ****** 2 ** **
- 3 ** ** 3 ** **
- 4 ** ** 4 ****
- 5 ** ** 5 **
- 6 o***** 6 o **
- 7 7 ***
-
- Where the baseline is at row 6. When defining the position text, you
- have to keep the baseline in mind when indicating coordinates. If you
- wanted the upper left hand corner of the letter 'b' to appear at x=5,
- y=10 you would use 'Position 5 16'. In the above examples, 'o' indicates
- the point at which coordinates refer (at 0,6).
-
-
- We will display two different texts in our previously defined window:
-
- Window "Main" (
- Text "Plain Text" (
- Position 20 25
- )
- Text "Shadow Text" (
- Position 20 40
- Color 2
- Shadow
- )
- )
-
-
- Refer to MSE-Compiler.guide for more information about the extra
- parameters, 'Color' and 'Shadow', used here and others that can also be
- used.
-
- Compile "Test/Tutorial1-B.def" and open the 'Tutorial1.mse' module in MSE
- to see the results.
-
-
- 4: Adding borders
- ===================
-
- Let's make things a little prettier and add a border around the text.
- Note that the Border option in 'Define Window' is actually a quick form
- of this command. When used in 'Define Window', the 'Position' and 'Size'
- are determined by the size of the window and no other options are
- allowed. The 'Border' command allows some additional features. Borders
- are defined like this:
-
- Border (
- Position 10 10
- Size 107 40
- Fill 3
- )
-
- Remember that, although we have not shown it this way, this command and
- others like it must be contained within a 'Window' structure.
-
- The 'Position' parameter, as with 'Define Window', refers to the
- coordinates of the upper left hand corner of the border. Again, 'Size'
- refers to the width and height in pixels. Note that there is an
- alternative to using the 'Size' command anywhere it is used. 'Position2'
- sets the position of the lower right hand corner. In the above example,
- we could have used 'Position2 117 50' instead of 'Size 107 40' and would
- have gotten the same result. When using a paint program to do intial
- layout designs, the 'Position2' alternative can save you some calculation
- since most paint programs only give x/y coordinates.
-
- The 'Fill' option tells the compiler that we want the border filled with
- color 3. It is important to realize that sometimes the order that
- commands appear within the definition file needs to be considered. If we
- added this 'Border' definition in AFTER the 'Text' commands, the text
- would be overdrawn by the fill option we have used. Because we want the
- text to appear over the filled border, we have to order it BEFORE.
- Something like this:
-
- Window "Main" (
- Border (
- Position 10 10
- Size 107 40
- Fill 3
- )
- Text "Plain Text" (
- Position 20 25
- )
- Text "Shadow Text" (
- Position 20 40
- Color 2
- Shadow
- )
- )
-
- Compile "Test/Tutorial1-C.def" and open the 'Tutorial1.mse' module in MSE
- to see the results.
-
-
- 5: Adding gadgets
- ===================
-
- To interact with MSE we have to add gadgets. Although MSE supports
- several different kinds, we will begin with a simple slider gadget
- example:
-
- Gadget "Notes" (
- Position 140 140
- Type Slider (
- Range 0 127
- Size 100 10
- Direction HORIZONTAL
- )
- )
-
- This defines a gadget with the label "Notes". Currently, gadget labels
- are not used but because future features will need them, they are
- required. The gadget command has two additional required parameters:
- 'Position' and 'Type'. As with other commands, 'Position' defines the
- upper left hand coordinate of the gadget. 'Type' is used to define the
- kind of gadget and its parameters. Note that 'Type' is also a structure
- imbedded (or nested) within the Gadget command with its own structure
- bracketing pair.
-
- The 'Type Slider' structure has three required parameters. 'Range' sets
- the minimum and maximum values for the gadget. 'Size' sets the width
- (100) and height (10) of the gadget. 'Direction' determines the
- orientation of the gadget.
-
- Note that 'Gadget' is a window command and like others must be placed
- within a window structure.
-
- Compile "Test/Tutorial1-D.def" and open the 'Tutorial1.mse' module in MSE
- to see the results.
-
-
- 6: Displaying gadget values
- =============================
-
- Our gadget does not do much, yet. Let's enhance it a little by adding a
- couple optional parameters to the 'Type Slider' structure:
-
- LevelPlace ABOVE
- Default 63
-
- This tells the compiler that we want the value (or level) of the gadget
- to be displayed above the gadget and that we what the gadget's intial
- level to be set at 63. Once an editor contains midi patch data, the
- 'Default' value can usually be determined from the default patch data, so
- this parameter would normally not be included. If it was, it would
- override the value contained in the patch data. This is not what we
- normally want to happen.
-
- Note that different gadget types have different parameters, they can not
- be interchanged.
-
- We would like to see some text to remind us what the gadget is for, so we
- have also added a new 'Text' structure.
-
- Text "Note #" (
- Position 167 159
- Color 3
- )
-
- Compile "Test/Tutorial1-E.def" and open the 'Tutorial1.mse' module in MSE
- to see the results.
-
-
- 7: Understanding how MSE handles MIDI
- =======================================
-
- Our module is not very useful, yet. Let's teach it about MIDI. For this
- example, we will use a feature of MIDI that will work with almost any
- MIDI sound module... note playing. This is not a great application of
- MSE but is easy enough to get started.
-
- The are several parts to defining MIDI information. First, the compiler
- needs to know what MIDI channel the device is operating on and where it
- should send the MIDI data. These parameters should be included within
- the 'Define Device' structure.
-
- Channel 1
- Handler MIDI
-
- This tells the compiler to use the public domain MIDI.library for
- controlling your MIDI devices. If you do not have it installed, install
- it in your LIBS: directory now -OR- consult the MSE-Compiler.guide for
- other 'Handler' options. If the device you want to control is set to a
- channel other than 1 or OMNI, this should be changed too.
-
- Secondly, we need to tell the compiler what the MIDI message looks like.
- This is done with the 'Define Midi' command. The MIDI specification
- defines the note message as such:
-
- $9n ## vv
-
- where: n = MIDI Channel (0-15)
- vv = velocity (NOTE ON vv = 1-127, NOTE OFF vv = 0)
-
- In midi communication, channels are numbered 0-15 not 1-16 like we
- usually see them displayed.
-
- For this message, channels work like this: A value of $90 represents MIDI
- Channel 1, $91 = 2, $92 = 3, ... $9F = 16. If we ALWAYS wanted to use
- channel 5 here we could use $94. However, one of the features of MSE is
- the ability to override the channel at anytime. If we force this to be
- $94, that feature will not work with this module. For now we will use
- $90 and add the channel # to it later. Technically we are still forcing
- this message to use channel 1, but this will make more sense later, when
- we discuss this further.
-
- For now, let's not concern ourselves with the velocity. Instead we will
- force it to 64.
-
- Here, we will actually define two note messages: NOTE ON followed by NOTE
- OFF. As far as MIDI is concerned, this is not greatly useful, but serves
- this tutorial purpose.
-
- In the MSE definition language the message can be defined like this:
-
- Define Midi "Notes" (
- Data (
- $90 ' 0 = Offset
- Byte 'Note # 1
- 64 'Velocity 2
- )
- )
-
- * The apostrophe is a special marker that can be used to tell the
- compiler that we are just making a note to ourselves. When the
- compiler encounters this character, it ignores everything on the
- remainder of that line.
-
- * As with other commands, '"Notes"' is simply a label for later
- referencing of this definition.
-
- * 'Byte' as used here, serves only as a place holder. The compiler
- actually stores this as 0 when it creates the module. More
- importantly, it serves as a reminder to us that these are values that
- need to be inserted later. You can put anything you want here, really,
- because it will be overwritten anyway.
-
- So, now that we have the general structure of the message defined, we
- need to consider how the missing values get put into the message. A
- couple things are still missing: Midi Channel and Note #.
-
- We will use the slider gadget we defined previously to control the Note
- #. So we will handle that later.
-
- 'Define Midi' has a special parameter, 'Midi', that is used to tell the
- compiler what values need to be inserted in the midi message before it
- gets sent. This is a good place to tell it about the Midi Channel.
-
- We will use this feature to tell the compiler where in the message the
- channel is to be stored, so that MSE can change it when we want it to.
- Because we are sending two note message, we actually need to store it in
- two places. This parameter needs to be added to the already defined
- 'Define Midi' structure.
-
- Midi (
- Data (
- 0 CHANNEL
- )
- )
-
- * '0' represents a byte offset from the beginning of the message.
- Refer back to the definition.
-
- * 'CHANNEL' is a special indicator to MSE that we want to add the current
- MIDI channel number to the value at the given offset. Remember that we
- initialized this value to $90. so, if the current channel was 5,
- $90 + 4 (remember channels are numbered 0-15) would be $94.
-
-
- 8: Making gadgets send midi data
- ==================================
-
- Now that we have told the compiler about the midi messages that we want
- to use, it's time to tell our previously defined slider gadget about it.
-
- Though, the MIDI note message supports a range of 128 notes, most sound
- modules do not. So, our gadget has too large a range. We need to change
- that first.
-
- Range 36 96
-
- The 'Default' setting and and other parameters are okay the way they are.
-
- The gadget command also has a 'Midi' parameter, similar to the one used
- with 'Define Midi' but much more powerful. There are some differences,
- see the MSE-Compiler.guide for more details.
-
- Midi "Notes" (
- Data (
- 1 VALUE Byte
- )
- Send
- )
-
- * Here's where the label we defined earlier with 'Define Midi' comes in
- handy. We use it to reference the already defined message.
-
- * '1' represents a byte offset from the beginning of the message.
-
- * 'VALUE' is a special indicator to MSE that we want to store the current
- value of the gadget.
-
- * 'Byte' tells MSE how the value should be stored. This is the normal
- method of storage, and the simplest.
-
- * 'Send' is an option that tells MSE that it should send the midi
- message. If you do not include this, MSE will construct the midi
- message but will not send it. Why doesn't MSE just send the message
- all the time? Sometimes it is necessary to maintain several messages
- simultaneously and it is not necessary to send both so 'Send' is an
- option.
-
-
- 9: Hearing the results
- ========================
-
- Compile "Test/Tutorial1-F.def" and open the 'Tutorial1.mse' module in MSE
- to see the results. Visually, everything should look the same as the
- last time.
-
- However, if everything is properly connected to your sound module, when
- you change the slider value, you should hear notes play.
-
- Because we have not sent a note off message, the sound will play forever.
-