Liberty BASIC Default Variables
Internet - Downloading a File to Disk
API Corner - Easy Font Manipulations
Mapping Real World Coordinates
My knowledge of API calls is rather limited, so I rely heavily on help form others in the egroup. The following program is based on the clever Piano.bas originally provided by Alyce Watson with each new release of LB.
Many may not be fully aware of the considerable API routines held in winmm.dll provided with many versions of Windows. Apart form it's use enabling us to play MP3, MIDi, WAV and Video files such as MPEG and AVI, as Piano.bas demonstrates, it has 128 voices installed. No doubt these voices are need to play the MIDi files etc. What I would like to emphasize is the great value these voices can have in producing games, to avoid the use of space consuming WAV files, so popular among many games.
The following program demonstrates how to test any of the voices in a variety of ways, and should provide the ground work to allow you to call up a voice anytime. At the start of your program you need to activate winmm.dll etc by inserting gosub [sblast] . Then whenever you wish to produce a sound insert the following...
instrum = 1 : sndlen = 300 : note = 48 : gosub [newNote]
where instrum is the voice/instrument, sndlen is the length of the note in microseconds, and note is the frequency, with 48 producing the note of C. If you use a sndlen of 1 it will default to the natural length. You can of course repeat notes by doing this:
' START A RACE WITH PEPEATING TINKER BELL sndlen = 20 : note = 90 : instrum = 113 for n = 1 to 40 gosub [newNote] next n
' If sounds fail after any program changes,
' then abort LB and rerun the program. Ver. 3.02 & 3.03
nomainwin
dx = 1 : dy = 1
if DisplayWidth > 1000 then dx = 120 : dy = 90
UpperLeftX = dx : UpperLeftY = dy
WindowWidth = 800 : WindowHeight = 600
button #s, "Fast Range", [fast], LL 160, 140
button #s, "Slow Range", [slow], LL 280, 140
button #s, "Single Note", [single], LL 400, 140
button #s, "Music Scale", [scale], LL , 530, 140
button #s, "Doh Rae Mee", [doh], LL 160, 80
button #s, "Mee Rae Doh", [mee], LL 280, 80
button #s, "Voice List ", [list], LL 400, 80
button #s, "*** QUIT **", [quit], LL 530, 80
open "Instruments and Sounds" for graphics_nsb as #s
#s "trapclose [quit]; fill 100 100 1; backcolor 100 100 1"
#s "font arial 24 bold; color white; place 130 80"
#s "\Intrumental Voices and Sound Effects."
#s "font arial 10; place 220 100"
#s "\produced by Gordon Sweet ver. 2.2 July 2003 using Liberty Basic"
#s "font arial 18 bold; place 240 140"
#s "\Select a voice then the effects"
#s "color yellow; place 220 200; flush"
instrum = 1 : voice$ = "Grand Piano"
'read instrument names into array for combobox
Dim ins$(128) : Dim voice(128) : Dim tone(20)
restore [info] : For vc = 1 to 128
Read data$ : voice(vc)=vc : ins$(vc)=data$
Next vc
restore [notes] : for n = 1 to 15
read dat : tone(n) = dat
Next n
gosub [sblast] 'initialise winmm.dll
choice = 1 : instrum = 1 'first data
msg$=space$(20)+"Select an Instrument or Sound."
msg$=msg$+" If necessary turn up your speakers."
[which]
#s "place 200 200" : #s "\";space$(80)
#s "place 200 200" : #s "\Current Voice No. ";choice;" ";voice$
WindowWidth=470:WindowHeight=100
UpperLeftX=dx+160:UpperLeftY=dy+240
Button #p.default, "Quit",[quit],UL,370,15,50,30
Statictext #p, "Select Voice or Internal Speaker",15,5,200,20
Combobox #p.ins, ins$(,[instrument],15, 25, 220,580
Graphicbox #p.g, 0, 0,0,0
Statictext #p.vol, msg$,15,60,550,40
Open "Select" For Window_nf As #p
print #p, "trapclose [quit]"
Print #p.ins, "select ";voice$
Print #p.g, "trapclose [quit]"
mainH=hWnd(#p) : gosub [boxhold]
boxp = 1 : wait
[instrument]'user selected an instrument voice
Print #p.ins, "selectionindex?"
Input #p.ins, choice
instrum = voice(choice)
voice$ = ins$(choice)
#s "place 200 200" : #s "\";space$(80)
#s "place 200 200" : #s "\Current Voice No. ";choice;" ";voice$
wait
[fast] sndlen = 1 : goto [range]
[slow] sndlen = 100
[range]
close #p : for note = 50 to 100
gosub [newNote]
next note : goto [which]
[single]
close #p : boxp = 0
if boxb = 1 then close #b
WindowWidth = 200: WindowHeight = 120
UpperLeftX = 300+dx : UpperLeftY = 240+dy
statictext #b "Length 1/10000", 10, 10, 100, 20
statictext #b, "Note 10/500", 120, 10, 100, 20
textbox #b.tbox1, 30, 30, 30, 25
textbox #b.tbox2, 130, 30, 30, 25
button #b.default, "Accept", [pass], UL, 60, 60, 42, 25
open "Enter or Accept" for dialog as #b
print #b, "trapclose [bfin]" : boxb = 1
[nopass]
mainH=hWnd(#b) : gosub [boxhold] ' Prevents loss of Box
wait
[pass]
print #b.tbox1, "!contents? A$" : sndlen = val(A$)
print #b.tbox2, "!contents? B$" : note = val(B$)
if snflen > 0 and sndlen < 11000 then [bfin]
if note > 1 and note < 501 then [bfin]
notice "Invalid Entry!" : goto [nopass]
[bfin] bx=0 : close #b : boxb = 0
gosub [newNote] : goto [which]
[scale]
sndlen = 300
start = 1 : last = 15 : stp = 1
goto [sels]
[doh]
sndlen = 600
start = 9 : last = 11 : stp = 1
goto [sels]
[mee]
sndlen = 600
start = 11 : last = 9 : stp = -1
[sels] close #p
for n = start to last step stp
note = tone(n)
gosub [newNote]
next n : goto [which]
[sblast]
'open midi device and obtain handle
'midi functions return 0 if successful
struct m, a$ As ptr
CallDLL #winmm, "midiOutOpen",_
m As struct,-1 As long,0 As long,_
0 As long,0 As long,ret As long
hMidiOut=m.a$.struct 'handle to midi device
return
[newNote]
gosub [stopPlay] 'stop previous note
gosub [doChange]
gosub [playNewNote]'play new note
return
[playNewNote]'play new note:
' gosub [stopNote]
event=144 'event 144 = play on channel 1
low=(note*256)+event
velocity=127
hi=velocity*256*256
dwMsg=low+hi
CallDLL #winmm, "midiOutShortMsg",hMidiOut As ulong,_
dwMsg As ulong, ret As ulong
' NOTE LENGTH
tim = time$("ms") : while time$("ms") < tim +sndlen : wend
[stopPlay]'stop all notes from playing
event=128 'event 128 = stop play
low=(note*256)+event
dwMsg=low+hi
CallDLL #winmm, "midiOutShortMsg",hMidiOut As ulong,_
dwMsg As ulong, ret As ulong
timer 0
RETURN
[doChange]'signal a voice change:
event=192 'event 192 = change
voice=instrum-1
velocity=127
low=(voice*256)+event
hi=velocity*256*256
dwMsg=low+hi
CallDLL #winmm, "midiOutShortMsg",hMidiOut As ulong,_
dwMsg As ulong, ret As ulong
RETURN
[boxhold]
open "user32" for dll as #user ' prevents losing box
toTop=(-1 or 0)
flags=_SWP_NOMOVE or _SWP_NOSIZE
calldll #user,"SetWindowPos",mainH as ushort,toTop as short,_
0 as short,0 as short,0 as short,0 as short,flags as ushort,_
result as void
close #user : return
[quit]'stop note, close midi device, DLLs, window
timer 0
gosub [stopPlay] 'stop all output
CallDLL #winmm, "midiOutClose", hMidiOut As ulong,_
ret As ulong
CallDLL#user32,"ReleaseDC",_
Wnd As long,hDC As long,result As long
if boxp = 1 then close #p
if boxb = 1 then close #b
Close #s ' CHANGE #s TO OTHER HANDLES
End
[list]
close #p : boxp = 0
texteditor #L.tb 20,20,0,0 'this is invisible
Menu #L, "&CONTINUE", "Continue", [cont], "&QUIT", [quitL]
open "Winmm.dll Voice list" for text_fs as #L
#L "!trapclose [quitL]"
#L "!font Courier 10"
colm = 1 : row = 1
For n = 1 to 128
#L.tb using("###",n);
#L.tb " ";ins$(n);
gosub [tbox]
row = row + 1
if row = 33 then row = 1 : colm = colm + 25
Next n
#L.tb "Note some programs allocate a number 1 less. Click on screen to use Print/Copy etc"
row = 33 : colm = 2 : gosub [tbox]
beep : wait
[cont] close #L : goto [which]
[tbox]
#L.tb "!selectall";
#L.tb "!cut";
#L "!select ";colm;" ";row;
#L "!paste";
return
[quitL]
close #L : goto [quit]
[info]
'list of 128 voices, in order of their MIDI indexes
Data "Grand Piano","Bright Grand","Electric Grand","Honky Tonk"
Data "Rhodes","Chorus Piano","Harpsichord","Clavinet"
Data "Celesta","Glockenspiel","Music Box","Vibraphone"
Data "Marimba","Xylophone","Tubular Bells","Dulcimer"
Data "Hammond Organ","Percussion Organ","Rock Organ"
Data "Church Organ","Reed Organ","Accordian","Harmonica"
Data "Tango Accordian","Accoustic Nylon Guitar"
Data "Accoustic Steel Guitar","Electric Jazz Guitar"
Data "Electric Clean Guitar","Electric Mute Guitar"
Data "Overdrive Guitar","Distorted Guitar","Guitar Harmonic"
Data "Accoustic Bass","Electric Bass Finger","Electric Bass Pick"
Data "Fretless Bass","Slap Bass One","Slap Bass Two"
Data "Synth Bass One","Synth Bass Two","Violin","Viola","Cello"
Data "Contrabass","Tremolo Strings","Pizzicato Strings"
Data "Orchestra Harp","Timpani","String Ensemble One"
Data "String Ensemble Two","Synth Strings One","Synth Strings Two"
Data "Choir Ahhs","Voice Oohs","Synth Voice","Orchestra Hit"
Data "Trumpet","Trombone","Tuba","Mute Trumpet","French Horn"
Data "Brass Section","Synth Brass One","Synth Brass Two"
Data "Soprano Sax","Alto Sax","Tenor Sax","Bari Sax","Oboe"
Data "English Horn","Bassoon","Clarinet","Piccolo","Flute"
Data "Recorder","Pan Flute","Bottle Blow","Shakuhachi","Whistle"
Data "Ocarina","Square Wave","Sawtooth","Caliope","Chiff Lead"
Data "Charang","Solo Synth VX","Brite Saw","Brass and Lead"
Data "Fantasia Pad","Warm Pad","Poly Synth Pad","Space Vox Pad"
Data "Bowd Glas Pad","Metal Pad","Halo Pad","Sweep Pad"
Data "Ice Rain","Sound Track","Crystal","Atmosphere","Brightness"
Data "Goblin","Echo Drops","Star Theme","Sitar","Banjo","Shamisen"
Data "Koto","Kalimba","Bagpipe","Fiddle","Shanai"
Data "Tinkle Bell","Agogo","Steel Drums","Wood Block","Taiko Drum"
Data "Melodic Tom","Synth Drum","Rev Cymbal"
Data "Guitar Fret Noise","Breath Noise","Sea Shore","Bird Tweet"
Data "Phone Ring","Helicopter","Applause","Gunshot"
[notes]
Data 48,50,52,53,55,57,59,60,62,64,65,67,69,71,72
REM C D E F G A B C D E F G A B C
Liberty BASIC Default Variables
Internet - Downloading a File to Disk
API Corner - Easy Font Manipulations
Mapping Real World Coordinates