Main Site Links Resources Tutorials
News VB Gaming Code Downloads DirectX 7
Contact Webmaster VB Programming Product Reviews DirectX 8
  General Multimedia Articles DirectX 9

DirectMusic: Modifying Music
By: Jack Hoxley
Written: June 2000

Download: DM_Modify.Zip (10kb) (485kb)

You can only go so far with the two previous tutorials; sooner or later you will need to learn how to change things. This is what this tutorial is about. There are only a few things that can be done to "normal" music; most of the interesting things can only be done when using DLS files.

I will be using a modified version of the DM_Midi program to demonstrate how to do these things; you can download it above, or you can download it fromt he downloads page.

Changing the Volume
This is quite important, and is very simple. Using this you can let your user set how loud he/she wants the music to be played; this can be very important as not everyone playing your game will want to hear your music. You could also program it so that you have fade-in's or fade-outs.

Sub SetVolume(nVolume As Byte)
'This formula allows you to specify a volume between
'0-100; similiar to a percentage

perf.SetMasterVolume (nVolume * 42 - 3000)
End Sub

'You can then call this procedure like so:

call SetVolume(100) 'Max volume
SetVolume 50 'Half Volume

Changing the Tempo
This isn't quite as useful or important as changing the volume, but it will probably be useful somewhere. So far the only use I've found for it is amusement (sped up Mozart mainly) :)

Sub SetTempo(nTempo As Single)
'the tempo must be between 0.25 and 2
'the default is 1; 2 would double this, 0.5 would half this

perf.SetMasterTempo nTempo
End Sub

'You can call this like so:
call SetTempo(0.9) 'Slightly Slow
SetTempo(2) 'Double speed

Done. Those are the two main effects that you can use with "normal" music.

DLS Effects
These are probably the better effects; but they're also harder to use - like most things in DirectX. Although strictly speaking these aren't effects; they're still different things to do with your music. The main problem (and what makes it difficult) is that you need to know what's in the DLS collection. Which will require software; some basic knowledge, and if you intend to make your own then you'll need musical knowledge.

The effect to be demonstrated here is playing notes - MIDI notes. A DLS collection with one instrument has a different tone for every entry on a normal keyboard. We just choose one of these notes to play. This is where the idea of DLS files comes in - a MIDI piece is no more than a set of notes to play; each one intended for a different instrument - the DLS provides the instruments; so what if the instruments are totally messed up - ie, not normal notes? You start getting interesting effects.

If you're sending notes it allows you to create dynamic music; you could have atmospheric music most of the time; and easily switch to heart-pounding action music, which adds a further dimension to gameplay. A good example of this is XCOM: Apocalypse (Should you have played it; if not, why not?) - the music in that changes from atmospheric creapy music to action-fighting music; although it doesn't actually use DirectMusic to do this.

Step1: Initialising everything.
To use a DLS collection for playing notes you dont need any music to actually play; but you need it just for the way that DirectMusic works. You need a segment in order to load/connect to a DLS collection - this segment can be complete silence, as you're never going to play it. It is advisable in this case to load the smallest possible file.

'After doing normal initialisation, put this line in:
Call perf.SendPatchPMSG(0, DMUS_PMSGF_REFTIME, 1, 127, 0, 0)

'This next part goes where you normally load your music:

'Load our DLS Collection

Set col = loader.LoadCollection(App.Path & "\boids.dls")

'This segment is never played; but we require a segment
'in order to use a DLS file. This could either be a segment
'or a MIDI file - it doesn't matter

Set seg = loader.LoadSegment(App.Path & "\sample.sgt")
Call seg.ConnectToCollection(col)
Call seg.Download(perf)

Step2: Playing a Note
Playing a note requires that we describe what it's going to be. DirectX has a built in type definition for this, called DMUS_NOTE_PMSG. We then fill this out with all the relevent details and pass it through to DirectMusic; which generates us a note. There are two ways of sending a note; in our own time, or within the time of the music playing. As we want the note to play immediately we want it to play in our own time; If you had ANY music playing at the same time you'd have to play it in the music's time. This would require that you worked out exactly where you were currently and then play it. Or; you could set it up so that certain notes are played at certain times throughout a piece of music.

'We fill out a description of the note to be played;
'then we play it. NOTE: If you play the same note
'before the previous note has finished you'll get weird
'results - mixing and frequency changes


noteMsg.velocity = 255 'Volume (or Velocity/speed of the sound)
noteMsg.flags = DMUS_NOTEF_NOTEON
noteMsg.midiValue = 100 'Change this value for different notes
noteMsg.mtDuration = 3000 'in ms
'We must have the first two flags as 0 and ......REFTIME
'otherwise we have to interact with the music time. As it is,
'the note will play immediately

Call perf.SendNotePMSG(0, DMUS_PMSGF_REFTIME, 1, noteMsg)

Finished. There is only a certain distance you can go using this without actually getting into the music making. To use this properly you will need to know what's inside the DLS file you're using. I recommend getting a copy of DierctMusic producer from Microsoft's developer site. This program is specifically designed for the task of creating, viewing and editing DLS collections and other DirectMusic mediums.

You can download a working example from the top of this page; or from my downloads page.

DirectX 4 VB 2000 Jack Hoxley. All rights reserved.
Reproduction of this site and it's contents, in whole or in part, is prohibited,
except where explicitly stated otherwise.
Design by Mateo
Contact Webmaster