Direct Music Tutorial
Author: Jack Hoxley
Version Compatibility:
Instructions: Copy the declarations and code below and paste directly into your VB project.
How DirectMusic works, and other things you need to know... |
|
The Variables you will need... |
|
Making the form, adding controls and giving them the right names |
|
What code to put in the Form_Load event |
|
Loading the MIDI file |
|
Getting some output from your app. |
|
Getting the Program to pause the music. |
|
Making your program STOP! |
|
Make your program break the speakers....... |
|
This gives the user a guide as to how far through the file they are. |
THEORY AND GETTING STARTED
DirectMusic is fairly new in directX history, it only appeared in version 6 and 7, It is a good component though, and if you have the resources, a lot better than some other formats.
DirectMusic loads a .MID file into a buffer (similiar to DirectSound/Draw) and then modifies it and plays it back. There is another file format that can be used: Downloadable sounds, I might cover this later on, but for the casual game developer it's a bit over complicated.
For this tutorial you will need a .MID file, there are several supplied with Windows, but they are all rubbish. If you haven't got any, there is one supplied with the DirectMusic Project from my download page.
THE VARIABLES
These variables go into the (Declarations) section of your Main Form:
Option Explicit Dim dx As New DirectX7 'the root object, as seen in every DirectX application Dim perf As DirectMusicPerformance Dim perf2 As DirectMusicPerformance 'These 2 variables are the buffers, "perf" is the master, "perf2" is used to gather 'information about the MIDI file Dim seg As DirectMusicSegment Dim segstate As DirectMusicSegmentState 'Segments, these hold segments of the music! Dim loader As DirectMusicLoader 'This is an object that helps load the files into the buffers. Public GetStartTime As Long Public Offset As Long Public mtTime As Long Public mtLength As Double Public dTempo As Double Dim timesig As DMUS_TIMESIGNATURE 'This'll hold the time signiture that the MIDI is in. Dim IsPlayingCheck As Boolean 'A simple true/false statement as to whether or not it's playing. Dim msg As String 'Used in the error handler sub. Dim time As Double Dim fIsPaused As Boolean Dim ISITPAUSED As Boolean '--TIME-- These settings are sued in the progress bar section. Dim Total_Time As Double Dim Current_Time As Double Dim Percent_Time As Double |
The next bit of code is the error handler, a simple, almost pointless wrapper sub for generating error messages:
Sub localerror(ErrorNum As Long, ErrorDesc As String) 'Nothing much to explain here... msg = ErrorDesc msg = "(" & ErrorNum & ") - " & msg MsgBox msg End Sub |
MAKING THE INTERFACE
This section needs to be done before anything else. Refer to this picture for the basic layout:
Note, there is a timer on the form, and a Shape control hidden in the White PictureBox. (This picture was taken at run-time).
Just to make it simple for me, use this list as a reference for all the objects:
Form1 |
Now that's out of the way, we can get onto some code. If you find any problems with the above descriptions, download the working example from my "Downloads Page"
FORM LOAD: WHERE IT ALL STARTS
This is the first code that your program executes, so place this code in the "Form_Load":
Private Sub Form_Load() Set perf = dx.DirectMusicPerformanceCreate()'create the first Buffer. |
Most of this code is straight forward, and is explained in the Comments. Now we can move on
THE OPEN CODE
This code is where you prepare the buffer's to accept data, then load the Music into them. Copy the following code into the "cmdOpen" Command Button:
Private Sub cmdOpen_Click() On Error GoTo LocalErrors |
Now, when you run the application, and click on the load button, it should put some information into the labels. Now we need to get it to do something!
THE PLAY CODE
Now you'll get some output. Assuming that everything is working fine, this code should play the contents of the "perf" buffer. Dont try running it until you have the "Stop" code written in, as you may cause it to lock up if it isn't stopped. Copy the following code into the "Play" command button:
Private Sub cmdPlay_Click() |
THE PAUSE CODE
Next up, the pausing code. All three (Play/pause/stop) link together, so dont test the application until you have added all the bits of code. As above, place this code in the "Pause" Command button:
Private Sub cmdPause_Click() If seg Is Nothing Then 'If it hasn't been loaded yet, get out of here IsPlayingCheck = perf.IsPlaying(seg, segstate) |
THE STOP CODE
And finally, the stop code. Once this code is complete you can listen to the MIDI at your hearts content. (Should you want to) This code goes in the "Stop" button:
Private Sub cmdStop_Click() |
CHANGING THE VOLUME
The rest of the code from here is about optimizing, and getting more out of your current application. The above code is necessary in every application that uses DirectMusic; the following stuff is probably useful though. Changing the volume is very easy, paste these lines in the appropriate place:
Private Sub UpDown_Volume_Change() Private Sub Edit_Volume_Change() |
Experiment with the volume, it can be used during a game to signify key points (getting louder) or just to fade out at the end of a level.
THE PROGRESS BAR
This is the final piece to be added to your project. Although it isn't implemented in this project, this is how you can make the music loop. This code iutputs a percentage of the way through the music - you could modify this code so that, at 100% (finished) it stops the music, resets it back to the begginning, then starts playing it all over again.
Put the following code in the timer control:
If perf.IsPlaying(Nothing, segstate) = True Then 'Only update the display if there is music playing,,,
Current_Time = ((((perf.GetMusicTime() - (segstate.GetStartTime() - Offset)) / 768) * 60) / dTempo) 'get the current time
Percent_Time = Int((Current_Time / Total_Time) * 100) 'work out the percentage - you remember these?
'These bits are irrelevant - I left these lines in the code when i compressed it up
'so's not to confuse people, I left them here:
'Me.Caption = Percent_Time & "% {Playing}"
'Update User-Interface
'shape1 moves up the picture box as the MIDI file plays on....
'2 Pixels=1%
'END useless code!
Shape1.Top = 200 - (Percent_Time * 2) 'Because the shape starts at the bottom, it needs to work out from the bottom:
'Hence the 200-
lblPercentage = Percent_Time & "%" 'copy the result to the label
Else
'Me.Caption = "{Stopped}" another useless line.
End If