Hey folks...was messing around with 3D sounds for my game the other day and I got a little fustrated that the sounds had to be all converted to mono, and I wasn't really sure how volume equated to the range of the sound.
This, for some reason, was enough to trigger my brain into making my own system...and here it is.
`==========================================================================================================`
`Setup`
`=====`
SetupBagSound:
nill=make vector3(111111)
nill=make vector3(111112)
nill=make vector3(111113)
Type BagSound
Active as boolean
FileName as string
Range as Float
DropOffStart as Float
X as Float
Y as Float
Z as Float
XDir as Float
YDir as Float
ZDir as Float
PanStart as Float
PanEnd as Float
DefSpeed as Float
Speed as Integer
State as Integer
Volume as integer
PlayPos as float
Length as float
ByteNum as float
Endtype
Type BagListenerT
X
Y
Z
XDir as Float
YDir as Float
ZDir as Float
Endtype
Global BagListener as BagListenerT
Global BStart=100
Global BEnd=200
Global BSTime#
a=BEnd-BStart
if a<1 then exit prompt "Invalid sound range given to SetupBagSound","BagSound Error" : end
Dim BagSounds(a) as BagSound
Dim BagSoundActive(a)
Return
`==========================================================================================================`
`Listener`
`========`
Function PositionBagListener(X#,Y#,Z#)
BagListener.X=X#
BagListener.Y=Y#
BagListener.Z=Z#
Endfunction
Function PositionBagListenerToCam()
BagListener.X=Camera position x()
BagListener.Y=Camera position y()
BagListener.Z=Camera position z()
Endfunction
Function SetBagListenerDirection(X#,Y#,Z#)
BagListener.XDir=X#
BagListener.YDir=Y#
BagListener.ZDir=Z#
Endfunction
Function SetBagListenerDirectionToCam()
VectorToCamera(111111)
BagListener.XDir=x vector3(111111)
BagListener.YDir=y vector3(111111)
BagListener.ZDir=z vector3(111111)
Endfunction
`==========================================================================================================`
`Load & Delete Sounds`
`====================`
Function LoadBagSound(file$,Numb)
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "Program has tried to load BagSound outside specified range","BagSound Error" : end
Load Sound File$,Num
set sound volume num,0
Bagsounds(numb).Active=1
Bagsounds(numb).FileName=File$
Bagsounds(numb).Range=100
Bagsounds(numb).DropOffStart=0.0
Bagsounds(numb).X=0.0
Bagsounds(numb).Y=0.0
Bagsounds(numb).Z=0.0
Bagsounds(numb).XDir=0.0
Bagsounds(numb).YDir=0.0
Bagsounds(numb).ZDir=1.0
Bagsounds(numb).PanStart=180
Bagsounds(numb).PanEnd=180
Bagsounds(numb).DefSpeed=sound speed(num)
Bagsounds(numb).Speed=sound speed(num)
Bagsounds(numb).State=0
Bagsounds(numb).Volume=100
done=0
for i=1 to (BEnd-Bstart)
if done=0 and BagSoundActive(i)=0 then BagSoundActive(i)=Numb : exit
next i
`Grab Sound Info`
if memblock exist(1) then delete memblock 1
make memblock from sound 1,num
Bagsounds(numb).Bytenum=(get memblock size(1)-12)
Bagsounds(numb).Length=(Bagsounds(numb).Bytenum/int(memblock dword(1,12)))
if memblock exist(1) then delete memblock 1
Endfunction
Function DeleteBagSound(Numb)
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "Program has tried to load BagSound outside specified range","BagSound Error": end
if Bagsounds(numb).Active=0 then exit prompt "BagSound specified for deletion does not exist","BagSound Error": end
Delete Sound Num
Bagsounds(numb).Active=0
Bagsounds(numb).FileName=""
Bagsounds(numb).Range=0
Bagsounds(numb).DropOffStart=0
Bagsounds(numb).X=0.0
Bagsounds(numb).Y=0.0
Bagsounds(numb).Z=0.0
Bagsounds(numb).XDir=0.0
Bagsounds(numb).YDir=0.0
Bagsounds(numb).ZDir=0.0
Bagsounds(numb).PanStart=0
Bagsounds(numb).PanEnd=0
Bagsounds(numb).Speed=0
Bagsounds(numb).State=0
for i=(numb+1) to (BEnd-BStart)
if BagSoundActive(i)<>0
BagSoundActive(i-1)=BagSoundActive(i)
else
exit
endif
next i
Endfunction
`==========================================================================================================`
`Range`
`=====`
Function SetBagSoundRange(Numb,Range#)
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "BagSound specified is outside range","BagSound Error": end
Bagsounds(numb).Range=Range#
Endfunction
Function GetBagSoundRange(Numb)
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "BagSound specified is outside range","BagSound Error": end
Range#=Bagsounds(numb).Range
Endfunction Range#
`==========================================================================================================`
`Drop-Off`
`========`
Function SetBagSoundDropOffStart(Numb,Start#)
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "BagSound specified is outside range","BagSound Error": end
Bagsounds(numb).DropOffStart=Start#
Endfunction
Function GetBagSoundDropOffStart(Numb)
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "BagSound specified is outside range","BagSound Error": end
start#=Bagsounds(numb).DropOffStart
Endfunction start#
`==========================================================================================================`
`Positioning`
`===========`
Function PositionBagSound(Numb,X#,Y#,Z#)
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "BagSound specified is outside range","BagSound Error": end
Bagsounds(numb).X=x#
Bagsounds(numb).Y=y#
Bagsounds(numb).Z=z#
Endfunction
Function BagSoundPositionX(numb)
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "BagSound specified is outside range","BagSound Error": end
x#=Bagsounds(numb).x
Endfunction x#
Function BagSoundPositionY(numb)
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "BagSound specified is outside range","BagSound Error": end
y#=Bagsounds(numb).y
Endfunction y#
Function BagSoundPositionZ(numb)
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "BagSound specified is outside range","BagSound Error": end
z#=Bagsounds(numb).z
Endfunction z#
`==========================================================================================================`
`Direction`
`=========`
Function SetBagSoundDirection(numb,x#,y#,z#)
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "BagSound specified is outside range","BagSound Error": end
Bagsounds(numb).XDir=x#
Bagsounds(numb).YDir=y#
Bagsounds(numb).ZDir=z#
Endfunction
Function SetBagSoundDirectionFromVector(numb,vecnum)
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "BagSound specified is outside range","BagSound Error": end
Bagsounds(numb).XDir=x vector3(vecnum)
Bagsounds(numb).YDir=y vector3(vecnum)
Bagsounds(numb).ZDir=z vector3(vecnum)
Endfunction
Function BagSoundDirectiontoVector(numb,vecnum)
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "BagSound specified is outside range","BagSound Error": end
Set vector3 vecnum, Bagsounds(numb).XDir, Bagsounds(numb).YDir, Bagsounds(numb).ZDir
Endfunction
Function BagSoundDirectionX()
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "BagSound specified is outside range","BagSound Error": end
x#=Bagsounds(numb).XDir
Endfunction x#
Function BagSoundDirectionY()
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "BagSound specified is outside range","BagSound Error": end
y#=Bagsounds(numb).YDir
Endfunction y#
Function BagSoundDirectionZ()
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "BagSound specified is outside range","BagSound Error": end
z#=Bagsounds(numb).ZDir
Endfunction z#
`==========================================================================================================`
`Panning`
`=======`
Function SetBagSoundPanStart(Numb,Angle#)
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "BagSound specified is outside range","BagSound Error": end
Bagsounds(numb).PanStart=Angle#
Endfunction
Function SetBagSoundPanEnd(Numb,Angle#)
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "BagSound specified is outside range","BagSound Error": end
Bagsounds(numb).PanEnd=Angle#
Endfunction
Function GetBagSoundPanStart(Numb,Angle#)
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "BagSound specified is outside range","BagSound Error": end
Angle#=Bagsounds(numb).PanStart
Endfunction Angle#
Function GetBagSoundPanEnd(Numb,Angle#)
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "BagSound specified is outside range","BagSound Error": end
Angle#=Bagsounds(numb).PanEnd
Endfunction Angle#
`==========================================================================================================`
`Speed`
`=====`
Function SetBagSoundSpeed(Numb,Speed)
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "BagSound specified is outside range","BagSound Error": end
Bagsounds(numb).Speed=Speed
set sound speed num,speed
Endfunction
Function GetBagSoundSpeed(Numb)
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "BagSound specified is outside range","BagSound Error": end
Speed=Bagsounds(numb).Speed
Endfunction Speed
`==========================================================================================================`
`Playing, Looping and Stopping`
`=============================`
Function PlayBagSound(Numb)
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "BagSound specified is outside range","BagSound Error": end
Bagsounds(numb).State=1
Bagsounds(numb).Playpos=0.0
Play Sound Num
Endfunction
Function LoopBagSound(Numb)
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "BagSound specified is outside range","BagSound Error": end
Bagsounds(numb).State=2
Bagsounds(numb).Playpos=0.0
Loop Sound Num
Endfunction
Function StopBagSound()
Num=(numb+BStart)
if Num>BEnd or num<Bstart then exit prompt "BagSound specified is outside range","BagSound Error": end
Bagsounds(numb).State=0
Bagsounds(numb).Playpos=0.0
stop sound num
Endfunction
`==========================================================================================================`
`Update`
`======`
Function UpdateBagSounds()
BSTime#=(Timer()-BSTime#)
for i=1 to (BEnd-BStart)
if BagSoundActive(i)=0
exit
else
numb=BagSoundActive(i)
if Bagsounds(numb).State>0
skip=0
Bagsounds(numb).Playpos=Bagsounds(numb).Playpos+((1.0/screen fps())* ((1.0/Bagsounds(numb).DefSpeed)*Bagsounds(numb).Speed) )
if Bagsounds(numb).Playpos>Bagsounds(numb).Length
Bagsounds(numb).Playpos=(Bagsounds(numb).Playpos-Bagsounds(numb).Length)
if Bagsounds(numb).State=1 then StopBagSound() : skip=1
endif
if skip=0
VolPer#=100.0
`If listener outside endpan then volume=0%
set vector3 111111,Bagsounds(numb).XDir,Bagsounds(numb).YDir,Bagsounds(numb).ZDir
set vector3 111112,(BagListener.X-Bagsounds(numb).X),(BagListener.Y-Bagsounds(numb).Y),(BagListener.Z-Bagsounds(numb).Z)
DirToLisAng#=getvecangle(111111,111112)
if DirToLisang#<Bagsounds(numb).PanEnd
SndToLis#=GetPPDist(BagListener.X,BagListener.Y,BagListener.Z,Bagsounds(numb).X,Bagsounds(numb).Y,Bagsounds(numb).Z)
if SndToLis#<Bagsounds(numb).DropOffStart
VolPer#=100.0
else
DropOffDist#=(Bagsounds(numb).Range-Bagsounds(numb).DropOffStart)
DistIn#=(SndToLis#-Bagsounds(numb).DropOffStart)
Per#=(100.0-((DistIn#/DropOffDist#)*100.0))
if SndToLis#>Bagsounds(numb).Range then Per#=0.0
VolPer#=((VolPer#/100.0)*Per#)
endif
If DirToLisang#>Bagsounds(numb).PanStart
DropOffAng#=(Bagsounds(numb).PanEnd-Bagsounds(numb).PanStart)
AngIn#=DirToLisang#-Bagsounds(numb).PanStart
Per#=(100.0-((AngIn#/DropOffAng#)*100.0))
VolPer#=((VolPer#/100.0)*Per#)
else
Endif
Else
VolPer#=0.0
Endif
Set Sound Volume (i+BStart),int((Bagsounds(numb).Volume/100.0)*VolPer#)
if volper#=0.0
stop sound (i+BStart)
else
if sound playing((i+BStart))=0 and Bagsounds(numb).state=1 then play sound (i+BStart),((Bagsounds(numb).Bytenum/Bagsounds(numb).Length)*Bagsounds(numb).Playpos)
if sound playing((i+BStart))=0 and Bagsounds(numb).state=2 then loop sound (i+BStart),12,Bagsounds(numb).Bytenum,((Bagsounds(numb).Bytenum/Bagsounds(numb).Length)*Bagsounds(numb).Playpos)
endif
set vector3 111111, BagListener.XDir, BagListener.YDir, BagListener.ZDir
set vector3 111112,(BagListener.X-Bagsounds(numb).X),(BagListener.Y-Bagsounds(numb).Y),(BagListener.Z-Bagsounds(numb).Z)
MakeSecondVec(111111)
Side=CheckHeadSide()
Ang#=getvecangle(111111,111112)
if Ang#>90 then Ang#=(90.0-(Ang#-90.0))
`pan#=side*((10000.0/90.0)*Ang#)
pan#=side*((abs(sin((ang#/6.0)+180))*100.0)*100.0)
set sound pan (i+BStart),pan#
endif
endif
endif
next i
Endfunction
function getvecangle(vec1,vec2)
var#=dot product vector3(vec1,vec2)
var#=var#/(length vector3(vec1)*length vector3(vec2))
angle#=ACOS(var#)
endfunction angle#
function GetPPDist(x#,y#,z#,q#,w#,e#)
dist#=sqrt(((q#-x#)*(q#-x#)) + ((w#-y#)*(w#-y#)) + ((e#-z#)*(e#-z#)))
endfunction dist#
Function MakeSecondVec(vecnum)
a#=x vector3(vecnum)
o#=z vector3(vecnum)
angle#=atan(a#/o#)
if a#>0.0
if o#<0.0 then angle#=(180.0+angle#)
else
if o#<0.0 then angle#=(180.0+angle#)
if o#>0.0 then angle#=(360.0+angle#)
endif
set vector3 111113, newxvalue(0.0,(angle#+90.0),1.0), 0.0, newzvalue(0.0,(angle#+90.0),1.0)
endfunction
Function CheckHeadSide()
y#=y vector3(111112)
set vector3 111112,x vector3(111112),0,z vector3(111112)
angle2#=getvecangle(111113,111112)
if angle2#>90
side=1
else
side=-1
endif
set vector3 111112,x vector3(111112),y#,z vector3(111112)
Endfunction side
Function VectorToCamera(vec)
oldx#=camera position x()
oldy#=camera position y()
oldz#=camera position z()
move camera 10
x#=camera position x()
y#=camera position y()
z#=camera position z()
move camera -10
set vector3 vec,(x#-oldx#),(y#-oldy#),(z#-oldz#)
normalize vector3 vec,vec
endfunction
And here are the commands
Gosub SetupBagSound: This sets up the vectors and arrays used by the system.
`========`
`Listener`
`========`
PositionBagListener(X#,Y#,Z#): Positions your 'ears' in the game.
PositionBagListenerToCam(): Positions your "ears" at the position of the camera.
SetBagListenerDirection(X#,Y#,Z#):Sets the direction your listener is facing in the game.
SetBagListenerDirectionToCam():points your listener in the direction the camera is facing.
`====================`
`Load & Delete Sounds`
`====================`
LoadBagSound(File$,Number): Loads your sound. You specify the filename and number as usual.
DeleteBagSound(Number): Deletes the specified sound
`=====`
`Range`
`=====`
SetBagSoundRange(Number,Range#): Sets the total range of the sound. By this distance the sound will be totaly in-audible
GetBagSoundRange(Number): Returns the range of the sound
SetBagSoundDropOffStart(Numb,Start#): Now this is new to you. This is the distance from the sounds origin that the sound will start fading, being inaudible by the range value (see above)
GetBagSoundDropOffStart(Numb): Gets the Drop off range#
`===========`
`Positioning`
`===========`
PositionBagSound(Number,X#,Y#,Z#): Positions the sound in 3D space
BagSoundPositionX(number): Gets the X position of the sound
BagSoundPositionY(number): Gets the Y position of the sound
BagSoundPositionZ(number): Gets the Z position of the sound
`=========`
`Direction`
`=========`
SetBagSoundDirection(number,x#,y#,z#): Sets the direction of the sound. X#, Y# & Z# specify the componants of a vector.
SetBagSoundDirectionFromVector(number,vectornum): Sets the direction of the sound to the contents of the specified vector
BagSoundDirectiontoVector(numb,vecnum): Puts the direction of the sound into the specified vector
BagSoundDirectionX(): Gets the X componant of the sound direction
BagSoundDirectionY(): Gets the Y componant of the sound direction
BagSoundDirectionZ(): Gets the Z componant of the sound direction
`=======`
`Panning`
`=======`
SetBagSoundPanStart(Numb,Angle#): The Pan is the angle the listner must be to the sound to hear it. The Pan start is the angle that the, until which the soundwill be perfectly clear. after this until Pan end the sound will fade.
SetBagSoundPanEnd(Numb,Angle#): specifies the end of the pan range. By this angle the sound is in audible.
GetBagSoundPanStart(Numb,Angle#):Gets the angle of the pan start
GetBagSoundPanEnd(Numb,Angle#):gets the angle of the pan end
`=====`
`Speed`
`=====`
SetBagSoundSpeed(Numb,Speed): sets the playing speed of the sound
GetBagSoundSpeed(Numb): gets the current speed the sound is playing at
`=============================`
`Playing, Looping and Stopping`
`=============================`
PlayBagSound(Numb)
LoopBagSound(Numb)
StopBagSound
`======`
`Update`
`======`
UpdateBagSounds(): You put this in your main loop to update the sound system. Remember this one!
Ok so I hope this helps someone. I am more than happy to explain any part of the code or to add extra functions.
Please report any problems as it helps me as much as you. Thanks again folks and sorry in advance for any unfound bugs.
Oh and please have a we look at the demo below...i'm affraid its a bit crappy but It gives a vague idea of how thigs work...please play with it as you will.
As usual all this is royalty free, just please update me with any problems you find or features you need. Also a wee mention in credits if it is used would be lovely.
Thanks people
Chris
p.s.
Oh you will need to know that this system uses normal sounds to emulate 3D sound effects.
It uses the sounds between BStart and BEnd which can be specified by you in the Setup gosub.
http://forum.thegamecreators.com/xt/xt_apollo_download.php?i=796616
p.p.s.
This bit is for those who may have lost me on the Pan start Pan end bit..I hope here I can explain.
This terrible image is how the sounds can work.
The sound itself is the red dot with the orange line showing the direction in which the sound is facing.
We have the pink line showing where the sound starts to fade off and the dirty green line showing where the sound finally is in-audible...between the points the volume of the sound fades away smoothly.
The blue line shows the start of the volume fade based on the angle from the sound's direction and the green lines showing where the volume finally dissipates.
As default both the startpan and endpan are set to 180 so the effect is that it behaves as a point sound.
e.g.
Some may have seen this on DBP discussion a little while back...however it didnt get much feedback so I'm reposting in the hope it will generate more interest and reach more people.
I'm completly open to any feature requests and would be very interested on expanding this.
Thanks people !
M.I.A is pending