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