Code archives/Audio/Area Sound

This code has been declared by its author to be Public Domain code.

Download source code

Area Sound by BMA
(Posted 20 years ago)
This extension lets you control the volume of a specific sound according to the position of two entities aka. listener and emitter.
For looped sounds place 'AreaSound_update' into your main loop...
; ************************************************************************************************************
; AreaSound - BMA 2006
; ************************************************************************************************************

Type tAreaSound
  Field emitter%
  Field listener%
  Field sound%
  Field emitVolume#
  Field range#
  Field channel%
  Field volume#
End Type


Function AreaSound_create(emitter%, listener%, sound%, range#=10.0, emitVolume#=1.0, loop%=False, play%=True)
  Local s.tAreaSound  = New tAreaSound
  s\emitter     = emitter
  s\listener      = listener
  s\range       = range
  s\emitVolume    = emitVolume
  s\sound       = sound%
  If loop Then LoopSound(s\sound)
  If play Then s\channel = PlaySound(s\sound)
  AreaSound_calc(s)
  If Not loop Then Delete s
  Return Handle(s)
End Function

;call this method in your game loop, when using looped sounds
Function AreaSound_update()
  For s.tAreaSound = Each tAreaSound
    AreaSound_calc(s)
  Next
End Function

Function AreaSound_getCurrentVolume#(soundID%)
  s.tAreaSound = Object.tAreaSound(soundID)
  Return s\volume
End Function

Function AreaSound_setEmitVolume(soundID%, volume#)
  s.tAreaSound = Object.tAreaSound(soundID)
  s\emitVolume = volume
  AreaSound_calc(s)
End Function

Function AreaSound_setEmitterRange(soundID%, range#)
  s.tAreaSound = Object.tAreaSound(soundID)
  s\range = range
  AreaSound_calc(s)
End Function

Function AreaSound_play(soundID%, loop%=False)
  s.tAreaSound = Object.tAreaSound(soundID)
  If loop Then LoopSound(s\sound)
  s\channel = PlaySound(s\sound)
  AreaSound_calc(s)
End Function

Function AreaSound_stop(soundID%)
  s.tAreaSound = Object.tAreaSound(soundID)
  StopChannel(s\sound)
End Function

Function AreaSound_cleanUp()
  Delete Each tAreaSound 
End Function

; ************************************************************************************************************
; Private Method
; ************************************************************************************************************

Function AreaSound_calc(s.tAreaSound)
  d# = EntityDistance(s\listener, s\emitter)
  If d < s\range Then
    s\volume = s\emitVolume - d * s\emitVolume / (s\range)
    ChannelVolume s\channel, s\volume
  Else
    s\volume = 0.0
    ChannelVolume s\channel, 0.0
  EndIf
End Function




; ************************************************************************************************************
; ************************************************************************************************************
; Test Stuff
; ************************************************************************************************************
; ************************************************************************************************************

Graphics3D 640,480,32,2
SetBuffer BackBuffer()
SeedRnd MilliSecs()

camera=CreateCamera()
PositionEntity camera,0,20,-10

light=CreateLight()
RotateEntity light,90,0,0

listener  = CreateCube()
EntityColor listener,255,0,0

emitter   = CreateCube()
range   = CreateSphere(32,emitter)

EntityColor emitter,255,255,0
EntityColor range,0,255,255
EntityAlpha range,0.2

PointEntity camera,listener

PositionEntity listener,0,1,0
PositionEntity emitter,Rand(-10,10),1,Rand(-10,10)

;define emitter range
r# = 8.0

soundFile% = LoadSound("your_sound_here.mp3")

aSound% = AreaSound_create(emitter, listener, soundFile, r, 1.0, True)

While Not KeyHit(1)
   If KeyDown(205) Then TurnEntity listener,0,-1,0
   If KeyDown(203) Then TurnEntity listener,0,1,0
   If KeyDown(208) Then MoveEntity listener,0,0,-0.1
   If KeyDown(200) Then MoveEntity listener,0,0,0.1
   
   If KeyDown(49) Then
      r = r -0.05
      AreaSound_setEmitterRange(aSound, r)
   EndIf
   If KeyDown(50) Then
      r# = r# +0.05
      AreaSound_setEmitterRange(aSound, r)
   EndIf
   
   Xscale#  = ((100/1)  * r) / 100.0
   Yscale#  = ((100/1)  * r) / 100.0
   Zscale#  = ((100/1)  * r) / 100.0

   ScaleEntity range,Xscale#,Yscale#,Zscale#
   
   ;update looped sounds
   AreaSound_update()
   
   RenderWorld
   Text 0,0,"Move Listener with Cursor-Keys"
   Text 0,20,"Set Emitter Range with 'N' and 'M' Keys - Range: "+r
   Text 0,40,"Emitter Sound Volume: "+AreaSound_getCurrentVolume(aSound)
   Flip
Wend
End