DirectMusic:
Modifying Music
By: Jack Hoxley
Written: June 2000
Download:
DM_Modify.Zip
(10kb) DM_DLSFX.zip (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
Dim noteMsg As DMUS_NOTE_PMSG
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.
|