|
Post by Carl Gundel on Sept 3, 2018 9:21:57 GMT -5
A reusable library of music and sound code.
In the case of a music sequencer, we want the Liberty BASIC programmer to have a proof of concept example to draw from. In the case of a video game, let's take Donkey Kong as an example, there is background music during play (midi), and the sound of Mario walking (wav file). When he jumps it plays a musical phrase (midi or wav). When he picks something up or walks over a rivet you hear a sound effect (wav), and when he dies or succeeds in the level the music changes (midi) and then it starts over.
Let's start by creating a simple window.
The window will have:
1) Play midi loop button - clicking this will cause a midi track to loop, and will cause other music to stop 2) Play wav loop button - clicking this will cause a music or ambient wave file to loop, and will cause other music to stop 3) Play wav sound effect button - clicking this will play a wav sound effect once. It will not stop any other audio. 4) Play midi phrase button - clicking this will cause a brief midi phrase to place once without stopping any other audio
The first thing is to determine if exactly how to do exactly what I've submitted above in Liberty BASIC and using Windows APIs if necessary.
Ultimately it would be great for this to turn into a crazy music and sound demo window, and to have a library of code for use in other people's projects.
|
|
|
Post by Rod on Sept 10, 2018 7:38:47 GMT -5
|
|
|
Post by Rod on Sept 11, 2018 7:27:30 GMT -5
See above post for link to demo
|
|
|
Post by Carl Gundel on Sept 13, 2018 14:26:31 GMT -5
I will kick this off with an old demo of WaveMix dll. The native commands playmidi and play wave allow background music and sound effects simultaneously. The only catch is that Liberty allows only one sound effect at a time and any issued over one playing will silence and replace that sound. I needed a way to get round that limitation for games and started using WaveMix which I found at Alyce's Restaurant. It plays multi channel sound. WaveMix DemoHaving gone down that route I have since discovered that midi can be played multi channel so if you have the voices it would be possible to play multi channel sound using the midi mapper demo at the LBPE. Thanks for this example. It shows what can be done and how to do it. I am wondering though what can be done without the extra DLL. -Carl
|
|
|
Post by Rod on Sept 14, 2018 6:49:35 GMT -5
Well exploring the midi capabilities we can use API calls to play it directly. This is based on the LBPE tutorial.
'Based on Alyce Watson's excellent midi mapper demo from LBPE 'here we tease out the multi channel capability
hmidi=midiopen(hmidi) 'open the midi device if it is not already open vol=midivol(255,255,hmidi) 'set and remember the left and right volumes
'event 128 is stop note on channel 0-15 'event 144 is start note on channel 0-15 'event 192 is change instrument on channel 0-15
ret=message(192,1,44,0,hmidi) 'load whatever instrument 44 is to channel 2
'simply play a note five times on channel 1 and channel 2 using different instruments timer 500,[play] wait
[play] ret=message(128,0,60,0,hmidi) 'note off ch1 ret=message(144,0,60,127,hmidi) 'note on ch1 middle C ret=message(128,1,48,0,hmidi) 'note off ch2 ret=message(144,1,48,127,hmidi) 'note on ch2 count=count+1 if count >5 then [stop] wait
[stop] timer 0 nul=silence(hmidi) 'stop / silence all notes playing 0=success nul=midiclose(hmidi) 'close midi 0=sucess end
function message(event,channel,pitch,velocity,hmidi) status=event+channel low=(pitch*256)+status hi=velocity*256*256 dwMsg=low+hi CallDLL #winmm, "midiOutShortMsg",_ hmidi as ulong,_ 'handle to opened device dwMsg as ulong,_ 'message ret as ulong end function
function silence(hmidi) CallDLL #winmm, "midiOutShortMsg",_ hmidi as ulong,_ 'handle to opened device 128 as ulong,_ 'message ret as ulong silence=ret end function
function midivol(left,right,hmidi) '0 to 65535 or 0 to FFFF so FF=middle vol vol = (right * 256) + left calldll #winmm, "midiOutSetVolume",_ hmidi as ulong,_ vol as ulong,_ ret as ulong midivol=vol end function
function midiopen(hmidi) struct m, a$ As ptr if hmidi=0 then CallDLL #winmm, "midiOutOpen",_ m As struct,_ 'address of midiOut handle -1 As ulong,_ 'ID of MIDI output device 0 As ulong,_ 'callback, not used 0 As ulong,_ 'callback instance, not used 0 As ulong,_ 'callback event flag, not used ret As ulong '0=success (MMSYSERR_NOERROR = 0) if ret=0 then midiopen = m.a$.struct 'handle to midi device else midiopen = 0 end if end if end function
function midiclose(hmidi) if hmidi<>0 then CallDLL #winmm, "midiOutClose",_ hmidi as ulong,_ 'handle to opened device midiclose as ulong '0=success (MMSYSERR_NOERROR = 0) end if end function
|
|
|
Post by Rod on Sept 14, 2018 10:51:13 GMT -5
Well the sequencer is a sequencer and while it can play 127 voices over 16 channels simultaneously it is laborious and exacting to do so. I suppose what we really need to investigate is the MMI and MCISendString Using the MCI you can open multimedia devices and play almost anything. There are much fewer examples of this in action. Alyce had a few snippets in her API Book but not layering multiple sounds. I am guessing that behind the scenes Liberty uses MCISendString but it limits you to playmidi or playwave. It might be possible to load more than one .wav file and play them together. Needs some investigation
|
|
|
Post by Rod on Sept 15, 2018 3:13:42 GMT -5
Ok, having started researching mciSendStringA() function I recalled that I had seen a super flight sim from Chung. In it he had used MMI to play mpeg sounds in a variety of ways. The engine sound for example plays continuously but changes both volume and pitch. Other sounds are loaded and played at will. Just exactly what we are looking for.
I have still to find a comprehensive tutorial on using MMI but this is a extract of the sound code from Chung's flight sim. It surely points the way.
This code will not run, it simply shows the command sets he used.
'extracted from 'flight_chung 'a program by NGUYEN.Chung
[initsounds] fic$="sounds\pneu.mp3" r$ = mcisend$("open ";chr$(34);fic$;chr$(34);" type MpegVideo alias pneu") fic$="sounds\crash.mp3" r$ = mcisend$("open ";chr$(34);fic$;chr$(34);" type MpegVideo alias crash") fic$="sounds\explosion_2.mp3" r$ = mcisend$("open ";chr$(34);fic$;chr$(34);" type MpegVideo alias shoot") r$ = mcisend$("open ";chr$(34);fic$;chr$(34);" type MpegVideo alias shoot2") r$ = mcisend$("open ";chr$(34);fic$;chr$(34);" type MpegVideo alias shootavion") r$ = mcisend$("open ";chr$(34);fic$;chr$(34);" type MpegVideo alias shootavion2") r$ = mcisend$("open ";chr$(34);fic$;chr$(34);" type MpegVideo alias shootavion3") fic$="sounds\shoot.mp3" r$ = mcisend$("open ";chr$(34);fic$;chr$(34);" type MpegVideo alias shootboule") r$ = mcisend$("open ";chr$(34);fic$;chr$(34);" type MpegVideo alias shootboule2") r$ = mcisend$("open ";chr$(34);fic$;chr$(34);" type MpegVideo alias shootboule3") fic$="sounds\explosion_1.mp3" r$ = mcisend$("open ";chr$(34);fic$;chr$(34);" type MpegVideo alias explosion1 ") fic$="sounds\boom.mp3" r$ = mcisend$("open ";chr$(34);fic$;chr$(34);" type MpegVideo alias boom") return
[closesounds] r$ = mcisend$("close pneu") r$ = mcisend$("close crash") r$ = mcisend$("close shoot") r$ = mcisend$("close shoot2") r$ = mcisend$("close shootavion") r$ = mcisend$("close shootavion2") r$ = mcisend$("close shootavion3") r$ = mcisend$("close shootboule") r$ = mcisend$("close shootboule2") r$ = mcisend$("close shootboule3") r$ = mcisend$("close explosion1") r$ = mcisend$("close boom") return
[pneu] r$= mcisend$("setaudio pneu volume to "+str$(int(2000*soundvol))) r$ = mcisend$("seek pneu to 0") r$ = mcisend$("play pneu") return
[changevolume] print #win.volume,"selection? aux$" '"vol1" to "vol20" if aux$<>"" then volume$=aux$ soundvol=min(20,max(1,val(right$(volume$,len(volume$)-3))))/20 end if gosub [setvol] print #win.g,"setfocus" if editmap=1 then goto [nextmap2] print #win.g,"setfocus" goto [nexttime]
[setvol] prop=kprop*(volume-550) volume2=min(1000,int(volume*soundvol)) r$= mcisend$("setaudio fictoplay volume to "+str$(volume2)) r$= mcisend$("setaudio fictoplay2 volume to "+str$(volume2)) return
[initavion] fic$="sounds\";avion$;".mp3" r$ = mcisend$("open ";chr$(34);fic$;chr$(34);" type MpegVideo alias fictoplay") r$ = mcisend$("open ";chr$(34);fic$;chr$(34);" type MpegVideo alias fictoplay2") r$ = mcisend$("set fictoplay time format ms") r$ = mcisend$("set fictoplay2 time format ms") r$=mcisend$("set fictoplay speed "+str$(speed)) r$=mcisend$("set fictoplay2 speed "+str$(speed)) r$ = mcisend$("seek fictoplay to 4000") r$ = mcisend$("play fictoplay repeat") r$ = mcisend$("play fictoplay2 repeat") r$= mcisend$("setaudio fictoplay volume to "+str$(volume)) r$= mcisend$("setaudio fictoplay2 volume to "+str$(volume))
Function mcisend$(s$) buffer$=space$(256)+chr$(0) calldll #winmm,"mciSendStringA",s$ as ptr,buffer$ as ptr,_ 256 as long,0 as long,r as long if r>0 then mcisend$="error r="+str$(r)+" "+buffer$ else mcisend$=buffer$ end if End Function
|
|
|
Post by Carl Gundel on Sept 15, 2018 14:13:16 GMT -5
Oh that's exciting. Thanks a ton for that.
Very cool things can happen with this.
-Carl
|
|
|
Post by Rod on Sept 17, 2018 5:11:45 GMT -5
Right here is a demo of MMI. We can have a bank of sounds and play any or all at will. There are some quirks about volume setting and looping and playing async but all in all it offers better functionality than we have now. gamebin.webs.com/winmm.zip 'extracted from 'flight_chung 'a program by NGUYEN.Chung ' 'Use this resource to see the command list and what commands are appropriate for the device 'and media file type. Invalid commands return an error but do not stop playing. '(You cant break it) 'https://docs.microsoft.com/en-gb/windows/desktop/Multimedia/multimedia-command-strings
'rule one, all file paths must be wrapped in double quotes chr$(34)+pathtofile$+chr(34) 'rule two, .mid and .wav dont respond to volume messages, us waveoutsetvol() instead 'rule three, sounds are played asynchronously up to you to wait for a sound to finnish.
nomainwin
WindowWidth = 600 WindowHeight = 300 UpperLeftX = int((DisplayWidth-WindowWidth)/2) UpperLeftY = int((DisplayHeight-WindowHeight)/2) button #1.startmidi, "Start Midi", [themestart], UL, 10, 20, 100,20 button #1.endmidi, "Stop Midi", [themestop], UL, 10, 50,100, 20 button #1.saywoohoo, "Woo Hoo", [bwoho], UL, 10, 80, 100,20 button #1.sayhoohoo, "Hoo Hoo", [bhoho], UL, 10,110, 100,20 button #1.saythanks, "Thanks", [bthanks], UL, 10, 140,100,20 button #1.startmp3, "Start Mp3", [bgo], UL, 10,170,100,20 button #1.stopmp3, "Stop Mp3", [bstop], UL, 10,200,100,20 button #1.startloop, "Start Loop", [loopstart], UL, 10,230,100,20 button #1.volup, "Volume+", [volup], UL, 110,230,100,20 button #1.voldown, "Volume-", [voldown], UL, 210,230,100,20 button #1.speedup, "Speed+", [speedup], UL, 310,230,100,20 button #1.speeddown, "Speed-", [speeddown], UL, 410,230,100,20 button #1.stoploop, "Loop Stop", [loopstop], UL, 510,230,70,20 graphicbox #1.gb 110,20,400,200 open "Mario Sounds" for window as #1 print #1, "trapclose [quit]" loadbmp "mario","splash.bmp" #1.gb "down ; drawbmp mario 0 0 ; flush"
[loadwav] f$ = chr$(34) + "sounds\yes.wav" + chr$(34) r$ = mcisend$("open " + f$ + " type waveaudio alias yes") f$ = chr$(34) + "sounds\ok.wav" + chr$(34) r$ = mcisend$("open " + f$ + " type waveaudio alias ok") f$ = chr$(34) + "sounds\thanks.wav" + chr$(34) r$ = mcisend$("open " + f$ + " type waveaudio alias thanks") f$ = chr$(34) + "sounds\woho.wav" + chr$(34) r$ = mcisend$("open " + f$ + " type waveaudio alias woho") f$ = chr$(34) + "sounds\hoho.wav" + chr$(34) r$ = mcisend$("open " + f$ + " type waveaudio alias hoho") f$ = chr$(34) + "sounds\gameover.wav" + chr$(34) r$ = mcisend$("open " + f$ + " type waveaudio alias gameover")
[loadmpeg] f$ = chr$(34) + "sounds\go.mp3" + chr$(34) r$ = mcisend$("open " + f$ + " type mpegvideo alias go") f$ = chr$(34) + "sounds\blues.mp3" + chr$(34) r$ = mcisend$("open " + f$ + " type mpegvideo alias blues")
[loadmidi] f$ = chr$(34) + "sounds\theme.mid" + chr$(34) r$ = mcisend$("open " + f$ + " type sequencer alias theme") wait
[quit] timer 0 gosub [playgameover] timer 650,[q] wait [q] timer 0 r$ = mcisend$("close all") close #1 end
[themestart] gosub [playyes]
'find theme length in ms r$ =mcisend$("set theme time format ms") r$ = mcisend$("status theme length") midilength=val(r$)
'set theme volume to full r = vol(theme,100,100) '0-100 left right volume
'start theme playing from start r$ = mcisend$("play theme from 0") 'r$ = mcisend$("play theme repeat") 'r$ = mcisend$("play theme from 1000 to 2000")
'obtain / set theme.mid tempo 'r$ = mcisend$("status theme tempo") 'miditempo=val(r$) 'r$ = mcisend$("set theme tempo "+str$(miditempo)) 'r$ = mcisend$("pause theme") 'r$ = mcisend$("resume theme") 'r$ = mcisend$("close theme") timer 250,[themecheck] wait
[themecheck] 'check or position, jump if ended r$ = mcisend$("status theme position") midipos=val(r$) if midipos>=midilength then [themestop] wait
[themestop] 'pause the theme so it may be restarted 'if we close it it will need reloaded timer 0 gosub [playok] r$ = mcisend$("pause theme") 'r$ = mcisend$("close theme") wait
[bhoho] gosub [playhoho] wait [bwoho] gosub [playwoho] wait [bthanks] gosub [playthanks] wait [bgo] gosub [gostart] wait [bstop] gosub [gostop] wait
[playyes] r$ = mcisend$("play yes from 0") return
[playok] r$ = mcisend$("play ok from 0") return
[playthanks] r$ = mcisend$("play thanks from 0") return
[playwoho] r$ = mcisend$("play woho from 0") return
[playhoho] r$ = mcisend$("play hoho from 0") return
[playgameover] r$ = mcisend$("play gameover from 0") return
[gostart] r$ = mcisend$("setaudio go volume to 500") r$ = mcisend$("play go from 0") return
[gostop] r$ = mcisend$("pause go") return
[loopstart] 'find blues length in ms r$ =mcisend$("set blues time format ms") r$ = mcisend$("status blues length") looplength=val(r$) r$ = mcisend$("play blues from 0 repeat") wait
[loopstop] r$ = mcisend$("pause blues") wait
[volup] r$ = mcisend$("status blues right volume") vol=val(r$)+100 if vol>1000 then vol=1000 r$ = mcisend$("setaudio blues right volume to "+str$(vol)) r$ = mcisend$("setaudio blues left volume to "+str$(vol)) wait
[voldown] r$ = mcisend$("status blues right volume") vol=val(r$)-100 if vol<=0 then vol=0 r$ = mcisend$("setaudio blues right volume to "+str$(vol)) r$ = mcisend$("setaudio blues left volume to "+str$(vol)) wait
[speedup] r$ = mcisend$("status blues speed") sp=val(r$)+100 if sp>2000 then sp=2000 r$ = mcisend$("set blues speed "+str$(sp)) wait
[speeddown] r$ = mcisend$("status blues speed") sp=val(r$)-100 if sp<=0 then sp=0 r$ = mcisend$("set blues speed "+str$(sp)) wait
function mcisend$(s$) buffer$=space$(256)+chr$(0) calldll #winmm,"mciSendStringA",s$ as ptr,buffer$ as ptr,_ 256 as long,0 as long,r as long if r>0 then mcisend$="error r="+str$(r)+" "+buffer$ else mcisend$=buffer$ end if end function
function vol(device,left,right)'set left or right 0 - 100 % left=int(left*655.35) right=int(right*655.35) dwVol=right*65536+left calldll #winmm, "waveOutSetVolume", device as long, _ dwVol as long, vol as long end function
|
|
|
Post by Rod on Sept 17, 2018 9:22:42 GMT -5
The demo still needs work. The wav and midi volume control is not fully working. When you load a media file the mcsendstring() function returns an identifier. Simply a raising number for each resource loaded. I should be able to use this "device identifier" to adjust the volume for each .wav or .midi loaded. Not working just yet. I think what is happening is that by using the variable theme in the demo code I am just passing 0 which probably applies the change to all devices. Will experiment with more time.
Also when you play a resource it is possible to be notified of its termination. If Liberty was able to receive and act on those optional messages it would be possible to handle repeat playing and termination much more neatly. The timer/delay would not be needed.
|
|
|
Post by Rod on Sept 18, 2018 8:30:30 GMT -5
Not having much luck getting waveoutsetvolume and waveoutgetvolume working. I am getting error 2 which states bad handle for device. I am going to leave it aside for a while. If anyone has API skills and wants to show me how to get these API calls working that would be great.
However if you ignore volume change for .mid and .wav the demo code is still useable and the flexibility offered playing mp3 files is excellent. You can change volume and tempo on the fly.
|
|
|
Post by Rod on Sept 18, 2018 9:45:22 GMT -5
This is some code that uses waveoutset/getvolume. I can get it to work with device 0 but not when I use the deviceID returned by mcisendstring(). Perhaps I am misunderstanding what a deviceID is and what a handle is. So it works with this extract, the challenge is to get it working on individual wav files.
struct v, v$ as ptr
[openwavdevice] f$ = chr$(34) + "sounds\yes.wav" + chr$(34) r$ = mcisend$("open " + f$ + " type waveaudio alias yes") yes=val(r$) yes=0 'works if yes is 0 but not if yes is deviceid returned by mcisend$()
[playyes] r$ = mcisend$("play yes from 0")
for left=100 to 0 step -10 right=left vol=vol(yes,left,right) calldll #winmm, "waveOutGetVolume", 0 as long, v as struct, ret as long print v.v$.struct r$ = mcisend$("play yes from 0") timer 660,[done] wait [done] timer 0 next left
vol=vol(yes,100,100)
[quit] r$ = mcisend$("close all") end
function mcisend$(s$) buffer$=space$(256)+chr$(0) calldll #winmm,"mciSendStringA",s$ as ptr,buffer$ as ptr,_ 256 as long,0 as long,r as long if r>0 then mcisend$="error r="+str$(r)+" "+buffer$ else mcisend$=buffer$ end if end function
function vol(device,left,right)'set left or right 0 - 100 % left=int(left*655.35) right=int(right*655.35) dwVol=right*65536+left calldll #winmm, "waveOutSetVolume", device as long, _ dwVol as long, vol as long end function
'MMSYSERR_NOERROR = 0, ' MMSYSERR_ERROR = 1, ' MMSYSERR_BADDEVICEID = 2, ' MMSYSERR_NOTENABLED = 3, ' MMSYSERR_ALLOCATED = 4, ' MMSYSERR_INVALHANDLE = 5, ' MMSYSERR_NODRIVER = 6, ' MMSYSERR_NOMEM = 7, ' MMSYSERR_NOTSUPPORTED = 8, ' MMSYSERR_BADERRNUM = 9, ' MMSYSERR_INVALFLAG = 10, ' MMSYSERR_INVALPARAM = 11, ' MMSYSERR_HANDLEBUSY = 12, ' MMSYSERR_INVALIDALIAS = 13, ' MMSYSERR_BADDB = 14, ' MMSYSERR_KEYNOTFOUND = 15, ' MMSYSERR_READERROR = 16, ' MMSYSERR_WRITEERROR = 17, ' MMSYSERR_DELETEERROR = 18, ' MMSYSERR_VALNOTFOUND = 19, ' MMSYSERR_NODRIVERCB = 20, ' WAVERR_BADFORMAT = 32, ' WAVERR_STILLPLAYING = 33, ' WAVERR_UNPREPARED = 34
|
|
|
Post by Rod on Sept 19, 2018 4:36:45 GMT -5
Right this is waveoutgetvolume and waveoutsetvolume example code. It would appear that there is usually only one wave player device and that it is usually given deviceID 0. It also appears that you can only adjust the volume of the device and not individual .wav files. No big deal really. You can also pan in stereo as you have control of left and right volumes.
I will Insert this volume control in my previous demo but here is an extract.
struct v, v$ as ptr
[openwavdevice] f$ = chr$(34) + "sounds\yes.wav" + chr$(34) r$ = mcisend$("open " + f$ + " type waveaudio alias yes")
[loop] for level=100 to 0 step -10 nul=setwavvol(level,level)'left and right vol 0-100% vol=getwavvol(0) r$ = mcisend$("play yes from 0") timer 660,[done] wait
[done] timer 0 next
'restore the volume nul=setwavvol(100,100)
[quit] r$ = mcisend$("close all") end
function mcisend$(s$) buffer$=space$(256)+chr$(0) calldll #winmm,"mciSendStringA",s$ as ptr,buffer$ as ptr,_ 256 as long,0 as long,r as long if r>0 then mcisend$="error r="+str$(r)+" "+buffer$ else mcisend$=buffer$ end if end function
function getwavvol(device) calldll #winmm, "waveOutGetVolume", device as long, v as struct, ret as long getwavvol=v.v$.struct end function
function setwavvol(left,right)'set left or right 0 - 100 % left=int(left*655.35) right=int(right*655.35) dwVol=right*65536+left calldll #winmm, "waveOutSetVolume", 0 as long, _ dwVol as long, ret as long end function
|
|
|
Post by Rod on Sept 19, 2018 7:49:47 GMT -5
This is my final contribution. Everything works. More is possible because the MMI can play video as well as manage sound. Individual volume control is possible with mp3 and mpegvideo, it is also possible to alter tempo and speed. Chung uses this well with his aero engine noise which gets louder and faster in tempo when the throttle advances. The waveoutsetvol() function controls the overall volume so everything will get quieter or louder. The volume control is apparently logarithmic so the linear code I have written does not give best control. If you just want a bank of simple .wav files and to play any or all at will its possible and relatively easy make that happen. So all in all these API sound calls give us great functionality.
You will need the sound files from my previous .zip but use this .bas instead.
'extracted from 'flight_chung 'a program by NGUYEN.Chung ' 'Use this resource to see the command list and what commands are appropriate for the device 'and media file type. Invalid commands return an error but do not stop playing.(You cant break it) 'https://docs.microsoft.com/en-gb/windows/desktop/Multimedia/multimedia-command-strings
'rule one, all file paths must be wrapped in double quotes chr$(34)+pathtofile$+chr(34) 'rule two, .mid and .wav dont respond to volume messages, us waveoutsetvol() instead 'rule three, sounds are played asynchronously up to you to wait for a sound to finnish.
nomainwin struct v, v$ as ptr global wavVolLeft,wavVolRight
WindowWidth = 600 WindowHeight = 300 UpperLeftX = int((DisplayWidth-WindowWidth)/2) UpperLeftY = int((DisplayHeight-WindowHeight)/2) button #1.startmidi, "Start Midi", [themestart], UL, 10, 20, 100,20 button #1.endmidi, "Stop Midi", [themestop], UL, 10, 50,100, 20 button #1.saywoohoo, "Woo Hoo", [bwoho], UL, 10, 80, 100,20 button #1.sayhoohoo, "Hoo Hoo", [bhoho], UL, 10,110, 100,20 button #1.saythanks, "Thanks", [bthanks], UL, 10, 140,100,20 button #1.startmp3, "Start Mp3", [bgo], UL, 10,170,100,20 button #1.stopmp3, "Stop Mp3", [bstop], UL, 10,200,100,20 button #1.startloop, "Start Loop", [loopstart], UL, 10,230,100,20 button #1.volup, "Volume+", [volup], UL, 110,230,100,20 button #1.voldown, "Volume-", [voldown], UL, 210,230,100,20 button #1.speedup, "Speed+", [speedup], UL, 310,230,100,20 button #1.speeddown, "Speed-", [speeddown], UL, 410,230,100,20 button #1.stoploop, "Loop Stop", [loopstop], UL, 510,230,70,20 button #1.wavup, "Vol+",[waveup],UL,510,20,70,20 button #1.wavdown, "Vol-",[wavedown],UL,510,50,70,20
graphicbox #1.gb 110,20,400,200 open "Mario Sounds" for window as #1 print #1, "trapclose [quit]" loadbmp "mario","splash.bmp" #1.gb "down ; drawbmp mario 0 0 ; flush"
[loadwav] f$ = chr$(34) + "sounds\yes.wav" + chr$(34) r$ = mcisend$("open " + f$ + " type waveaudio alias yes") f$ = chr$(34) + "sounds\ok.wav" + chr$(34) r$ = mcisend$("open " + f$ + " type waveaudio alias ok") f$ = chr$(34) + "sounds\thanks.wav" + chr$(34) r$ = mcisend$("open " + f$ + " type waveaudio alias thanks") f$ = chr$(34) + "sounds\woho.wav" + chr$(34) r$ = mcisend$("open " + f$ + " type waveaudio alias woho") f$ = chr$(34) + "sounds\hoho.wav" + chr$(34) r$ = mcisend$("open " + f$ + " type waveaudio alias hoho") f$ = chr$(34) + "sounds\gameover.wav" + chr$(34) r$ = mcisend$("open " + f$ + " type waveaudio alias gameover")
[loadmpeg] f$ = chr$(34) + "sounds\go.mp3" + chr$(34) r$ = mcisend$("open " + f$ + " type mpegvideo alias go") f$ = chr$(34) + "sounds\blues.mp3" + chr$(34) r$ = mcisend$("open " + f$ + " type mpegvideo alias blues")
[loadmidi] f$ = chr$(34) + "sounds\theme.mid" + chr$(34) r$ = mcisend$("open " + f$ + " type sequencer alias theme") wait
[quit] timer 0 gosub [playgameover] timer 650,[q] wait [q] timer 0 r$ = mcisend$("close all") close #1 end
[themestart] gosub [playyes]
'find theme length in ms r$ =mcisend$("set theme time format ms") r$ = mcisend$("status theme length") midilength=val(r$)
'set volume to full wavVolLeft=65535 wavVolRight=65535 ret=setwavvol(0)
'start theme playing from start r$ = mcisend$("play theme from 0") 'r$ = mcisend$("play theme repeat") 'r$ = mcisend$("play theme from 1000 to 2000")
'obtain / set theme.mid tempo 'r$ = mcisend$("status theme tempo") 'miditempo=val(r$) 'r$ = mcisend$("set theme tempo "+str$(miditempo)) 'r$ = mcisend$("pause theme") 'r$ = mcisend$("resume theme") 'r$ = mcisend$("close theme") timer 250,[themecheck] wait
[themecheck] 'check or position, jump if ended r$ = mcisend$("status theme position") midipos=val(r$) if midipos>=midilength then [themestop] wait
[themestop] 'pause the theme so it may be restarted 'if we close it it will need reloaded timer 0 gosub [playok] r$ = mcisend$("pause theme") 'r$ = mcisend$("close theme") wait
[bhoho] gosub [playhoho] wait [bwoho] gosub [playwoho] wait [bthanks] gosub [playthanks] wait [bgo] gosub [gostart] wait [bstop] gosub [gostop] wait
[playyes] r$ = mcisend$("play yes from 0") return
[playok] r$ = mcisend$("play ok from 0") return
[playthanks] r$ = mcisend$("play thanks from 0") return
[playwoho] r$ = mcisend$("play woho from 0") return
[playhoho] r$ = mcisend$("play hoho from 0") return
[playgameover] r$ = mcisend$("play gameover from 0") return
[gostart] r$ = mcisend$("setaudio go volume to 500") r$ = mcisend$("play go from 0") return
[gostop] r$ = mcisend$("pause go") return
[loopstart] 'find theme length in ms r$ =mcisend$("set blues time format ms") r$ = mcisend$("status blues length") looplength=val(r$) r$ = mcisend$("play blues from 0 repeat") wait
[loopstop] r$ = mcisend$("pause blues") wait
[volup] r$ = mcisend$("status blues right volume") vol=val(r$)+100 if vol>1000 then vol=1000 r$ = mcisend$("setaudio blues right volume to "+str$(vol)) r$ = mcisend$("setaudio blues left volume to "+str$(vol)) wait
[voldown] r$ = mcisend$("status blues right volume") vol=val(r$)-100 if vol<=0 then vol=0 r$ = mcisend$("setaudio blues right volume to "+str$(vol)) r$ = mcisend$("setaudio blues left volume to "+str$(vol)) wait
[speedup] r$ = mcisend$("status blues speed") sp=val(r$)+100 if sp>2000 then sp=2000 r$ = mcisend$("set blues speed "+str$(sp)) wait
[speeddown] r$ = mcisend$("status blues speed") sp=val(r$)-100 if sp<=0 then sp=0 r$ = mcisend$("set blues speed "+str$(sp)) wait
[waveup] ret=getwavvol(0) wavVolLeft=wavVolLeft+655.35 '100 step vol control if wavVolLeft>65535 then wavVolLeft=65535 wavVolRight=wavVolRight+655.35 if wavVolRight>65535 then wavVolRight=65535 ret=setwavvol(0) wait
[wavedown] ret=getwavvol(0) wavVolLeft=wavVolLeft-655.35 if wavVolLeft<0 then wavVolLeft=0 wavVolRight=wavVolRight-655.35 if wavVolRight<0 then wavVolRight=0 ret=setwavvol(0) wait
function mcisend$(s$) buffer$=space$(256)+chr$(0) calldll #winmm,"mciSendStringA",s$ as ptr,buffer$ as ptr,_ 256 as long,0 as long,r as long if r>0 then mcisend$="error r="+str$(r)+" "+buffer$ else mcisend$=buffer$ end if end function
function getwavvol(device) calldll #winmm, "waveOutGetVolume", device as long, v as struct, getwavvol as long wavvol=v.v$.struct wavVolLeft=wavvol/65536 wavVolRight=wavvol-65535*wavVolLeft end function
function setwavvol(device) 'pack both values into doubleword dwVol=int(wavVolLeft*65536+wavVolRight) calldll #winmm, "waveOutSetVolume", 0 as long, _ dwVol as long, setwavvol as long end function
If you have any issues tell us and we shall see if it can be fixed.
|
|
|
Post by Rod on Sept 22, 2018 6:00:43 GMT -5
This is it distilled down to a few functions. The device id will be 0 for 99.9% of PCs. 0 is hard coded in the mcisend$() function.
'Use this resource to see the command list and what commands are appropriate for the device 'and media file type. 'https://docs.microsoft.com/en-gb/windows/desktop/Multimedia/multimedia-command-strings
'to set the master volume use getvol() setvol(), mp3 files can be controlled via mcisend$() 'function getvol() returns device volume 0-4294967296 'function setvol() sets device volume 'function vol() packs left and right volume to a doubleword (left*65536+right) 'function vleft() unpacks left volume 0-65535 'function vright() unpacks right volume 0-65535
'open and name all sound files prior to use, close all before quitting 'all file paths must be wrapped in double quotes so f$=chr$(34)+pathtofile$+chr(34) 'function mcisend$() sends media control message
'to open a .wav file send "open " + f$ + " type waveaudio alias name" 'to open a .mid file send "open " + f$ + " type sequencer alias name" 'to open a .mp3 file send "open " + f$ + " type mpegvideo alias name" ' 'example 'f$ = chr$(34) + "sounds\yes.wav" + chr$(34) 'r$ = mcisend$("open " + f$ + " type waveaudio alias yes") ' 'set time measure to ms "set name time format ms" 'get length of file in ms "status name length" 'get position in file in ms "status name position" ' 'example 'r$ ='mcisend$("set yes time format ms") 'r$ = mcisend$("status yes length") 'length=val(r$) ' 'set position in file in ms "seek name ms" 'play the named sound "play name" 'play sound and wait "play name wait" 'play mp3 repeatedly "play name repeat" 'play the named sound from ms "play name from ms", "play name from 0" always plays from start 'play a portion of the sound "play name from ms to ms" 'get mp3 left volume "status name left volume" 0-1000 logarithmic 'get mp3 right volume "status name right volume" 'set mp3 left volume "setaudio name left volume to x" 'set mp3 right volume "setaudio name right volume to x" 'get mid tempo "status name tempo" 'get mp3 speed "status name speed" 'speed up the midi tempo "set name tempo x" x = 0 to 2000 1000=normal 500=double 2000=half 'speed up mp3 playing "set name speed x" 'pause playing "pause name" 'resume playing "resume name" 'close sound "close name" all closes all
function mcisend$(s$) buffer$=space$(256)+chr$(0) calldll #winmm,"mciSendStringA",s$ as ptr,buffer$ as ptr,_ 256 as long,0 as long,r as long if r>0 then mcisend$="error r="+str$(r)+" "+buffer$ else mcisend$=buffer$ end if end function
function getvol(device) 'get packed volume struct v, v$ as ptr calldll #winmm, "waveOutGetVolume", device as long, v as struct, ret as long getvol=v.v$.struct end function
function setvol(device,vol) 'set packed volume calldll #winmm, "waveOutSetVolume", 0 as long, _ vol as long, ret as long setvol=vol end function
function vleft(vol) 'unpack left vleft=int(vol/65536) end function
function vright(vol) 'unpack right vleft=int(vol/65536) vright=vol-65536*vleft end function
function vol(l,r) 'pack left and right volumes vol=int(l*65536+r) end function
|
|