A Scripting Sample


To really understand programming with scripting, it helps to mess around with the scripting side of things too. To that end, I created a wacky little script called SimpleScript.spt.

Bad Dream

SimpleScript endeavors to provide a soundtrack to a very strange scene. Imagine a mechanical world filled with moving metal parts, and large train-like objects fly by at random intervals with a spray of steam and grinding metal. You are being hunted by a very annoying translucent wasp made of cellophane. As the story progresses, there are more and more mechanical objects to dodge, and as you find yourself increasingly cornered, your level of hysteria increases. Occasionally, you have a good idea that causes time to stand still, but then chaos falls back around your ears and the chase ensues. Eventually, you wake up in a cold sweat, and it's over. To build this soundscape, we need the following:

  • Theme music that plays forever and responds to both changes in "activity" and "hysteria"

  • A routine to start the music

  • Variables and routines for updating the activity and hysteria

  • A routine to play when the wasp flies by

  • A routine to play when a train is encountered

  • A routine to play when there is a "really good idea"

  • A routine to finish the music when the scene is over

The SimpleScript example incorporates solutions for all of these. Load it into Jones, so you can call each routine as we discuss it. If you are feeling adventurous, open it directly in DirectMusic Producer and study it in greater depth as we go along.

Before declaring any routines, SimpleScript declares two variables that will be used to set the Activity and Hysteria levels as the scene plays.

 ' Variables set by the application: dim Activity    ' Game supplied Activity level dim Hysteria    ' Game supplied Hysteria level 

Theme Music

The Segment SkaNSeven.sgt supplies the theme music. It uses a Style for playback (thanks to Microsoft's Kelly Craven for creating a great Style), which has the advantage that Style Segments can respond to global groove level changes. Because Style Segments are chord based, other musical effects can track them harmonically. SkaNSeven.sgt is 42 measures long with measures 10 through 42 looping infinitely, so once it starts playing, it just loops and loops. In truth, you'd want more variety, but hey, this is called "SimpleScript" after all.

The first routine, StartLevel, is called by the application when we first enter the scene. StartLevel establishes the initial Activity and Hysteria levels by setting these values to zero and then calling the routine Update (more on that in a second.) Finally, StartLevel plays SkaNSeven.sgt to get the music looping.

 ' StartLevel is called when we enter the scene. sub StartLevel     Activity = 0  ' Init the Activity     OldActivity=0 ' Init the previous as well     Hysteria = 0  ' Init the Hysteria     Update        ' Now use these to set tempo and groove     ' Finally, play the music     SkanSeven.Play AtMeasure end sub 

Go ahead and click on the StartLevel command to hear the music start.

Setting Activity and Hysteria

Two variables, Activity and Hysteria, are used to control the overall groove level and tempo of the theme music as it plays. To change one of these, the application (or Jones) calls IDirectMusicScript:: SetVariableNumber() with the name of the variable (Activity or Hysteria) and that variable's new value.

But changing the variable is not enough. The script can't actively do anything with the new information unless one of its routines is called. So, the script has a routine, Update, that should be called whenever either variable has changed.

Update first makes sure that Activity and Hysteria are within reasonable ranges. Then, if it sees that the Activity increased, it plays a short secondary Segment, called Change.sgt, on a beat boundary. Then, Update applies formulas to translate the two variables into appropriate groove level and tempo modifiers.

Why does it play the Segment? When the groove level is changed, the effect doesn't take until the next pattern boundary within the Style, which is usually every measure. Since something just happened that is supposed to increase the musical activity, it would seem odd to wait up to a whole measure to hear the music react. Yet, cutting immediately would ruin the timing. So, we play the change Segment to add a flurry of activity while we wait for the groove level to hit at the next measure boundary.

 ' Every time the Activity or Hysteria variables are updated by ' the application, it needs to call Update so the script can act ' accordingly. sub Update     ' First, make sure everything is in range.     if (Hysteria < 0) then         Hysteria = 0     end if     if (Hysteria > 10) then         Hysteria = 10     end if     if (Activity < 0) then         Activity = 0     end if     if (Activity > 6) then         Activity = 6     end if     ' If the activity is increasing, play a motif.     if (OldActivity < Activity) then         Change.play IsSecondary+AtBeat     end if     ' Store the activity for next time around.     OldActivity = Activity     ' Then, set the levels     SetMasterGrooveLevel Activity*25 - 50     SetMasterTempo Hysteria*2 + 98 end sub 

To test this, first change the Activity or Hysteria variable, and then run the Update routine. In Jones, this means clicking on the variable name, editing its value, and then double-clicking on Update.

Wasp Flies By

When the wasp flies by, the routine Wasp can be called. Wasp plays a secondary Segment written with a Pattern Track, so it can transpose on top of the current chord and key. The Segment has many different variations so that the melody it plays is always a little different. This wasp has personality! On the other hand, when Activity is high, it seems intuitive that the wasp should be a little louder and little angrier. So, the Wasp routine checks the current Activity level before deciding which of two Segments to play.

 ' When a Wasp flies by in the game, call the Wasp routine which plays a secondary ' Segment. If the Activity is above 2, play a slightly louder and more intense Wasp. ' In either case, align with the beat. sub Wasp    if (Activity > 2) then       BigWasp.play IsSecondary+AtBeat    else       LittleWasp.play IsSecondary+ AtBeat    end if end sub 

Train

Now let's script the behaviors for the train. When a train lumbers by and the user gets close to the Tracks, the routine NearTracks is called to play something inspiring. This is a simple sequence with some weird train-like sound effects. Since this isn't musical at all, it can play immediately and not sound odd.

 ' When close to train tracks, call NearTracks. ' This isn't rhythmically attached to the music, so ' play it immediately. sub NearTracks     Train.play IsSecondary+AtImmediate end sub 

Thinking

I don't know about you, but when I have an original thought, the world stops and takes notice. Time stands still, multicolored flashing lights flutter around my head, and fog comes out of my nose. The Thinking routine attempts to recreate this otherworldly experience. It does so in an interesting way. It plays a Segment, Pause.sgt, that is a controlling Segment with a low groove level accompanied by break and fill embellishments. These alter the theme music by causing it to track to the low groove level and play the break and fill embellishments, while continuing with its own chord progression. Pause also plays a few drone-like notes and eerie sounds to telegraph the experience of having a head bursting full of profound, karmic thoughts.

But, again, with a groove change, we have a situation where the effect is delayed until the next measure boundary. We need to hear something sooner! Profound thoughts like mine can't wait. The Idea.sgt secondary Segment fills the breach with a brief chorus of angelic voices.

 ' When it's time to stop and think, call Thinking. sub Thinking     ' Play a small motif to carry us over since     ' the controlling Segment is aligned to a measure.     Idea.play IsSecondary+AtBeat     ' Now, the controlling Segment, which plays some     ' embellishments and drone sounds while altering     ' the groove level.     Pause.play IsControl+AtMeasure end sub 

Note

There are actually ways to force a groove level or embellishment to occur sooner. You can cause an immediate invalidation (see IDirectMusicPerformance::Invalidate), or you can transition to a new Segment on a beat boundary while making the groove change.

Enough Already!

When it's clear that the music itself is causing the hysteria, you can opt out by calling the EndLevel routine. This takes advantage of DirectMusic composition technology, which dynamically writes a transition Segment and plays it to lead into the final Segment, ScaNSevenEnd.sgt. It's worth listening to this a few times to see how it is able to pick chord progressions that wrap up the music quite handily, regardless of where the theme was at the moment you decided to leave.

 ' EndLevel is called when we are done. sub EndLevel     ' Play the finish Segment but precede it with a dynamically     ' composed transition with a fill and chords to modulate into it.     SkanSevenEnd.Play AtMeasure+PlayFill+PlayModulate end sub 

Note

If you are previewing in Jones, you will notice that the visual display temporarily shows nothing when the composed transition Segment plays. Magic? I like to think everything that comes out of the composition technology is magic, but there's a more grounded reason. Jones inserts a special display track in each Segment when it loads it. This special Track gives Jones the ability to follow the Segments as they play. The transition Segment is created on the fly within DirectMusic, so there is no opportunity for Jones to intercept it. But, if you want to believe it's magic

Enough of my foray into sound design. If nothing else, this exercise furthers the point that I should stick to programming and leave sound design to the pros. (And dream interpretation, too.)

If your project involves music and audio design that are done by somebody other than the programmer (read: YOU!), it pays to use scripting. It frees the participants to work more efficiently and faster, and there's no question that you will end up with a product that is significantly more sophisticated and well honed. Not to mention it will save you, as programmer, additional headaches!

On the rare occasion you are doing it all yourself, it might be a toss up only because scripting is harder to debug than straight C++ in that you can't single step through the code, but that's a minor point.




DirectX 9 Audio Exposed(c) Interactive Audio Development
DirectX 9 Audio Exposed: Interactive Audio Development
ISBN: 1556222882
EAN: 2147483647
Year: 2006
Pages: 170

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net