Older Version
Newer Version
JanetTerra
Dec 19, 2009
==Adding Music to Your Program with PLAYMIDI==
The PLAYMIDI command is a bit more complicated than the [[MediaPlaywave|PLAYWAVE]] command. Unlike the PLAYWAVE command, the programmer using PLAYMIDI must keep track of the playmidi progress.
(1) Whether a midi file is currently playing
(2) Whether the midi file has finished playing
To keep track, you must assign variables. Such variables are commonly referred to as flags. The programmer must also determine the length of the midi file. Fortunately, this value is extracted by Just BASIC as part of the PLAYMIDI command. The directions from the Help File
[[code]]
Description:
This plays a *.MIDI sound from a file on disk as specified in filename.
The length variable will hold the length of the MIDI file (not in seconds).
You can only play one file at a time. Periodically, you will need to use
the MIDIPOS( ) function to see if you've reached the end of the music:
Finally, use the STOPMIDI command to close the music file before you can
play a different one.
Usage:
'the playmidi command returns the length of the midi in
' the variable howLong
playmidi "c:\somedir\mymusic.midi", howLong
timer 1000, [checkPlay]
wait
[checkPlay]
if howLong = midipos( ) then [musicEnded]
wait
[musicEnded]
stopmidi
timer 0
wait
[[code]]
Liberty BASIC includes the midi file theme.mid in its MEDIA subfolder. This article assumes you are running the demo codes from your Liberty BASIC directory.
First, the code to begin playing the midi
[[code]]
Playmidi DefaultDir$;”\MEDIA\theme.mid”, midiLength
Print “It is important to press Enter BEFORE the music stops.”
Input “Press Enter at any time to stop the midi: “;any$
Stopmidi
End
[[code]]
Unfortunately, there is no automatic way of knowing whether the midi file has finished playing. And, unlike the PLAYWAVE “” command, if a STOPMIDI command is issued when no midi was playing, your program will crash. Run this Code
[[code]]
Playwave “”
Print “This works fine even if no wav file was being played.”
Print “But….”
STOPMIDI
End
[[code]]
A flag variable is required to keep track of whether a midi file is being played or not. In this demo, we’ll use midiFlag as that flag variable.
[[code]]
midiFlag = 0 ‘No midi file being played
midiFlag = 1 ‘yes a midi file is being played
[[code]]
But, how do we keep track of whether the midi file is finished or not? The PLAYMIDI command gets the length of that midi file and stores it in the variable you assign. In this demo, that variable is midiLength.
[[code]]
Playmidi DefaultDir$;”\MEDIA\theme.mid”, midiLength
Print “midiLength = “;midiLength
Stopmidi
End
[[code]]
If you’re using the theme.mid file, you might find that midiLength = 627. Knowing the full length of the file is only useful if the current position of the midi file is known. That position is made known by the command MIDIPOS(). Run this code to see MIDIPOS() in action. Note also the use of the midiFlag variable to indicate whether a midi file is being played or not.
[[code]]
Playmidi DefaultDir$;”\MEDIA\theme.mid”, midiLength
midiFlag = 1
For i = 1 to 300
Print “midiLength = “;midiLength
Print “midiPosition = “;Midipos()
Next i
Stopmidi
midiFlag = 0
End
[[code]]
The above code isn't very practical for use within a program. It would be better to check the position of the midi file being played and still continue on with the program. In this case, set up a timer. A timer is kind of an alarm clock that’s set not for a particular time, but for a particular time span. Everytime that time span has been reached, the timer executes the assigned block of code, then sits off to the side and waits for that time span to be reached again. In this next example, a timer will be used to check the position of the midi file every 1000 milliseconds (1 second). While that’s happening, the program goes on as usual.
[[code]]
Playmidi DefaultDir$;”\MEDIA\theme.mid”, midiLength
midiFlag = 1
Timer 1000, [checkPlay] ‘Every 1000 milliseconds, check the midi position
[doSomethingHere]
If midiFlag = 1 Then
msg$ = “Do you want to stop the music yet?”
Else
msg$ = “Press Enter to Quit”
End If
If midiFlag = 0 Then
Confirm msg$;any$ ‘Confirm is used here only to prevent the BEEP from Notice
End
End If
Confirm msg$;yn$
If midiFlag = 1 Then
If yn$ = “yes” Then
Timer 0 ‘Turn off the timer
Stopmidi ‘Stop the midi file
midiFlag = 0 ‘Set the midiFlag to 0 to indicate midi file is no longer being played
End If
End If
Goto [doSomethingHere]
[checkPlay]
If Midipos() = midiLength Then ‘If the position is at the total length then
Stopmidi ‘Stop playing the midi
midiFlag = 0 ‘Set the midiFlag to 0 to indicate midi file is no longer being played
Timer 0 ‘Stop the timer
End If
Wait
[[code]]
One last word of caution. When you end your program, don’t expect the midi that’s playing to be stopped automatically (as is the case with PLAYWAVE). If your midi file hasn’t reached the end of the file and you haven’t issued a STOPMIDI command, your music will continue even after the program has ENDed. Running the same or another program will encounter the Midi File already playing error message when you try to issue the PLAYMIDI command again. This will happen even if the music has finished playing and you no longer hear the music. So, you must use STOPMIDI before ENDING your program, but ONLY IF the STOPMIDI command wasn’t issued prior. This is another place the midiFlag variable becomes cruicial. It is always prudent to issue a Timer 0 command at the end of any program using a timer, whether the program has already shut the timer off or not.
[[code]]
[quit]
Timer 0
If midiFlag = 1 Then
Stopmidi
End If
Close #main
End
[[code]]
===Playmidi Demo===
[[code format="vbnet"]]
'Define the Menus
Menu #w, "&File","&Load Midi",[loadMusic], _
"&Play Midi",[playMusic],"&Stop Midi",[stopMusic],|, _
"E&xit",[endProgram]
'Open the Program's Main Window
WindowWidth = 320 'Sets Width of Main Window
WindowHeight = 220 'Sets Height of Main Window
UpperLeftX = Int((DisplayWidth-WindowWidth)/2) 'Centers Horizontally
UpperLeftY = Int((DisplayHeight-WindowHeight)/2) 'Centers Vertically
Nomainwin
Graphicbox #w.g, 5, 15, 300, 98
Button #w.b1, "LOAD", [loadMusic], UL, 35, 130, 60, 30
Button #w.b2, "PLAY", [playMusic], UL, 127,130, 60, 30
Button #w.b3, "STOP",[stopMusic], UL, 216, 130, 60, 30
fileFlag = 0 '0 = No File Loaded, 1 = File Loaded
midiFlag = 0 '0 = No Midi Playing, 1 = Midi Playing
shortName$ = "No Midi Loaded" 'Name of Current Loaded File
midiLength = 0 'Midi Length of Current Loaded File
Open "Liberty BASIC Midi Player" for Window as #w
#w, "Trapclose [endProgram]"
#w, "Font Times_New_Roman 12 Bold Italic"
#w.g, "Down; Fill 0 211 155"
#w.g, "BackColor 0 211 155"
#w.g, "Font Times_New_Roman 12 Bold"
Call grayBorder 298, 96
#w.g, "Flush"
Call displayMidiLength shortName$, midiLength, midiFlag
Wait
[endProgram]
If midiFlag = 1 Then
StopMidi
End If
Timer 0
Close #w
End
[loadMusic]
'File Dialog to Load New File
FileDialog "Open Midi File", "*.mid", fileName$
'If No File Selected, Then Go Back to [awaitUserInput]
If fileName$ = "" Then
Call displayMidiLength shortName$, midiLength, midiFlag
Wait
End If
'Get Extension Type
fileExtension$ = fileExtension$(fileName$)
shortName$ = shortName$(fileName$)
'Is File a Valid Midi File? valid extensions = .mid, .midi
If validExt(fileExtension$) = 0 Then
msg$ = msgInvalidFile$(shortName$)
Notice msg$
End If
If validExt(fileExtension$) = 0 Then
Call displayMidiLength shortName$, midiLength, midiFlag
Wait
End If
'If Valid File, then Check to See if Midi Already Playing
'End Midi if Playing
Timer 0
If midiFlag = 1 Then
StopMidi
midiFlag = 0
End If
'If Valid File, Display Name of New File
fileFlag = 1 'Midi File has been Loaded
PlayMidi, fileName$, midiLength
StopMidi
Call displayMidiLength shortName$, midiLength, midiFlag
Wait
[playMusic]
If midiFlag = 1 Then
Timer 0
StopMidi
midiFlag = 0
End If
If fileFlag = 0 Then
msg$ = msgNoMidiLoaded$()
Notice msg$
Else
Playmidi fileName$, midiLength
midiFlag = 1
Timer 500, [checkPlay]
End If
Call displayMidiLength shortName$, midiLength, midiFlag
Wait
[stopMusic]
If midiFlag = 0 Then
msg$ = msgNoMidiPlaying$()
Notice msg$
Else
Timer 0
StopMidi
midiFlag = 0
End If
Call displayMidiLength shortName$, midiLength, midiFlag
Wait
[checkPlay]
If midiFlag = 1 Then
If midiLength = MidiPos() Then
StopMidi
Timer 0
midiFlag = 0
End If
End If
Call displayMidiLength shortName$, midiLength, midiFlag
Wait
Function placeZero$(n, z)
placeZero$ = Str$(n)
If Len(placeZero$) = 0 Then
placeZero$ = "0"
End If
z = Abs(z)
If z < 0 Then
z = 0
End If
If Len(placeZero$) > 8 Then
placeZero$ = Right$(placeZero$,8)
End If
While Len(placeZero$) <> z
placeZero$ = "0";placeZero$
Wend
End Function
Function validExt(fileExtension$)
validExt = 0
fileExtension$ = UPPER$(fileExtension$)
If fileExtension$ = "MID" Then
validExt = 1
End If
If fileExtension$ = "MIDI" Then
validExt = 1
End If
End Function
Function shortName$(fileName$)
c$ = ""
c = Len(fileName$)
While c$ <> "\"
c = c - 1
c$ = Mid$(fileName$, c, 1)
Wend
shortName$ = Right$(fileName$, Len(fileName$)-c)
End Function
Function fileExtension$(fileName$)
c$ = ""
c = Len(fileName$)
While c$ <> "."
c = c - 1
c$ = Mid$(fileName$, c, 1)
Wend
fileExtension$ = Right$(fileName$, Len(fileName$)-c)
End Function
Sub displayMidiLength shortName$, midiLength, midiFlag
midiLength$ = placeZero$(midiLength, 8)
If midiFlag = 1 Then
musicPosition$ = placeZero$(MidiPos(), 8)
Else
musicPosition$ = placeZero$(0, 8)
End If
nSpaces = 32 - Len(shortName$)
If nSpaces < 0 Then
nSpaces = 0
End If
#w.g, "Color DarkPink"
#w.g, "Place 100 30"
#w.g, "\";shortName$;Space$(nSpaces)
#w.g, "Place 100 54"
#w.g "\";midiLength$;Space$(4)
#w.g, "Place 100 78"
#w.g, "\";musicPosition$;Space$(4)
#w.g, "Discard"
End Sub
Sub grayBorder w, h
hue = 0: hueInc = 32: start = 0
For box = 0 to 10
#w.g, "Color ";hue;" ";hue;" ";hue
#w.g, "Place ";start;" ";start
#w.g, "Box ";start + w;" ";start + h
start = start + 1
w = w - 2: h = h - 2
If hue = 160 Then
hueInc = (-32)
End If
hue = hue + hueInc
Next box
#w.g, "Color DarkCyan"
#w.g, "Place 40 30"
#w.g, "\Midi:"
#w.g, "Place 40 54"
#w.g, "\Length:"
#w.g, "Place 40 78"
#w.g, "\Position:"
#w.g, "Flush; Discard"
#w.g, "Getbmp midiBox 0 0 w h"
#w.g, "Drawbmp midiBox 0 0"
#w.g, "Flush; Discard"
End Sub
Function msgInvalidFile$(shortName$)
msgInvalidFile$ = "No Midi File Loaded . . . ";Chr$(13)
msgInvalidFile$ = msgInvalidFile$;shortName$;Chr$(13)
msgInvalidFile$ = msgInvalidFile$;"does not appear to be a";Chr$(13)
msgInvalidFile$ = msgInvalidFile$;"valid midi file."
End Function
Function msgNoMidiLoaded$()
msgNoMidiLoaded$ = "No Midi File To Play . . . ";Chr$(13)
msgNoMidiLoaded$ = msgNoMidiLoaded$;"There does not appear to be";Chr$(13)
msgNoMidiLoaded$ = msgNoMidiLoaded$;"a valid midi file loaded."
End Function
Function msgNoMidiPlaying$()
msgNoMidiPlaying$ = "No Midi File To Stop . . . ";Chr$(13)
msgNoMidiPlaying$ = msgNoMidiPlaying$;"There does not appear to be";Chr$(13)
msgNoMidiPlaying$ = msgNoMidiPlaying$;"a valid midi file playing."
End Function
[[code]]
By the way, although you can’t play multiple wav files or multiple midi files simultaneously, you can PLAYWAVE a wav file even while a midi file is playing. In this way, you don’t have to interrupt background music to hear those blood curdling sound effects.
----