Son2D Volume / Pan & Doppler Effect
Publié : mar. 29/oct./2013 8:08
Y a quelques mois, j'avais codé un petit moteur de son 2D, ce moteur gère le volume & le pan de manière automatique en fonction de la position de celui qui l'écoute
mais en plus il prend en compte la vélocité du mouvement pour simulé l'effet doppler, pour faire cours sur l'effet doppler :

http://youtu.be/eo_owZ2UK7E?t=15s
et le code , multiplate-forme, offcourse...
exemple en pied de code commenté.
mais en plus il prend en compte la vélocité du mouvement pour simulé l'effet doppler, pour faire cours sur l'effet doppler :

http://youtu.be/eo_owZ2UK7E?t=15s
et le code , multiplate-forme, offcourse...
exemple en pied de code commenté.
Code : Tout sélectionner
; /////////////////////////////////////////////////////////////////////////////
;
; Sound Effect by G-Rom
; ---------------------
; This file provide function for simulate doppler effect in 2D environement
;
;
;
; /////////////////////////////////////////////////////////////////////////////
; /////////////////////////////////////////////////////////////////////////////
;
; /////////////////////////////////////////////////////////////////////////////
#SOUND_SPEED_PIXEL_PER_SECOND = 340
Structure sSound
mSoundID.i
mChannel.i
mPositionX.i
mPositionY.i
mRadius.i
mListenerX.i
mListenerY.i
mFrequency.i
mVolume.i
mPlay.b
mDopplerTime.i
mOldX.i
mOldY.i
mSpeedX.i
mSpeedY.i
mOldLenght.d
mLenght.d
mValid.l
EndStructure
Global NewList *soundPlaying.sSound()
; /////////////////////////////////////////////////////////////////////////////
;
; /////////////////////////////////////////////////////////////////////////////
Procedure.i LoadSoundFromFile(filename.s, radius.l)
*s.sSound = AllocateMemory(SizeOf(sSound))
If *s
*s\mSoundID = LoadSound(#PB_Any,filename)
*s\mFrequency = GetSoundFrequency( *s\mSoundID)
*s\mRadius = radius
ProcedureReturn *s
EndIf
EndProcedure
; /////////////////////////////////////////////////////////////////////////////
;
; /////////////////////////////////////////////////////////////////////////////
Procedure.i LoadSoundFromMemory(soundID.l, radius.l)
*s.sSound = AllocateMemory(SizeOf(sSound))
If *s
*s\mSoundID = soundID
*s\mFrequency = GetSoundFrequency(*s\mSoundID)
*s\mRadius = radius
ProcedureReturn *s
EndIf
EndProcedure
; /////////////////////////////////////////////////////////////////////////////
;
; /////////////////////////////////////////////////////////////////////////////
Procedure deleteSound(*s.sSound)
If *s
FreeSound(*s\mSoundID)
FreeMemory(*s)
EndIf
EndProcedure
; /////////////////////////////////////////////////////////////////////////////
;
; /////////////////////////////////////////////////////////////////////////////
Procedure playSoundAtPosition(*s.sSound,x.i, y.i ,flag.l)
If *s
*s\mChannel = PlaySound(*s\mSoundID, #PB_Sound_MultiChannel | flag)
*s\mPositionX = x
*s\mPositionY = y
*s\mValid = #True
AddElement(*soundPlaying())
*soundPlaying() = *s
EndIf
EndProcedure
; /////////////////////////////////////////////////////////////////////////////
;
; /////////////////////////////////////////////////////////////////////////////
Procedure computeSound(*s.sSound, listenerX.i, listenerY.i)
If *s
dx.i = listenerX-*s\mPositionX
dy.i = listenerY-*s\mPositionY
d.q = (dx*dx) + (dy*dy)
rMax.i = *s\mRadius * *s\mRadius
;
; Compute volume
;
If d < rMax
vs.i = d * 100 / rmax
Else
vs.i = 100
EndIf
If vs < 0
vs = 0
EndIf
If vs > 100
vs = 100
EndIf
SoundVolume(*s\mSoundID,100-vs,*s\mChannel)
;
; Compute pan
;
If vs < 100
; source sound is on left
If listenerX > *s\mPositionX
SoundPan(*s\mSoundID,-vs,*s\mChannel)
ElseIf listenerX < *s\mPositionX ; on right
SoundPan(*s\mSoundID,vs,*s\mChannel)
Else ; same position
SoundPan(*s\mSoundID,0,*s\mChannel)
EndIf
EndIf
;
; Doppler effect
;
If *s\mDopplerTime < ElapsedMilliseconds()
*s\mDopplerTime = ElapsedMilliseconds() + 10
dx.i = *s\mPositionX - listenerX
dy.i = *s\mPositionY - listenerY
*s\mSpeedX = dx - *s\mOldX
*s\mSpeedY = dy - *s\mOldY
*s\mOldX = dx
*s\mOldY = dy
*s\mOldLenght = *s\mLenght
*s\mLenght = Sqr(d)
EndIf
dirX.i = listenerX-*s\mPositionX
dirY.i = listenerY-*s\mPositionY
If l>0
dirX / l
dirY / l
EndIf
If *s\mLenght < *s\mOldLenght
v.f = -Sqr( ((*s\mSpeedX**s\mSpeedX) + (*s\mSpeedY**s\mSpeedY)) )
Else
v.f = Sqr( ((*s\mSpeedX**s\mSpeedX) + (*s\mSpeedY**s\mSpeedY)) )
EndIf
w1.i = *s\mFrequency * (1-v/#SOUND_SPEED_PIXEL_PER_SECOND)
SetSoundFrequency(*s\mSoundID,w1,*s\mChannel)
EndIf
EndProcedure
; /////////////////////////////////////////////////////////////////////////////
;
; /////////////////////////////////////////////////////////////////////////////
Procedure soundEngineRun(listenerX.i, listenerY.i)
ForEach *soundPlaying()
computeSound(*soundPlaying(),listenerX, listenerY)
status.l = SoundStatus(*soundPlaying()\mSoundID,*soundPlaying()\mChannel)
If status = #PB_Sound_Stopped
*soundPlaying()\mValid = #False
DeleteElement(*soundPlaying())
Continue
EndIf
Next
EndProcedure
; /////////////////////////////////////////////////////////////////////////////
;
; /////////////////////////////////////////////////////////////////////////////
Procedure soundIsValid(*s.sSound)
If *s
If *s\mValid
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndIf
EndProcedure
; /////////////////////////////////////////////////////////////////////////////
;
; /////////////////////////////////////////////////////////////////////////////
Procedure moveSound(*s.sSound, x.i, y.i)
If *s
*s\mPositionX = x
*s\mPositionY = y
EndIf
EndProcedure
; /////////////////////////////////////////////////////////////////////////////
;
; /////////////////////////////////////////////////////////////////////////////
Procedure resetAndPauseSound(*s.sSound)
If *s
PauseSound(*s\mSoundID,*s\mChannel)
SetSoundPosition(*s\mSoundID,0,#PB_Sound_Millisecond,*s\mChannel)
EndIf
EndProcedure
; /////////////////////////////////////////////////////////////////////////////
;-EXAMPLE
; /////////////////////////////////////////////////////////////////////////////
; InitSound()
;
; SoundRadius = 7000
;
; ; by this way
; *buffer = CatchSound(#PB_Any, ?memory)
; *sound = LoadSoundFromMemory(*buffer,SoundRadius)
;
; ;or by file
; *snd = LoadSoundFromFile("file",SoundRadius)
;
; ; position of listener (you) and the sound in 2D space
; ListenerX = 0
; ListenerY = 0
; SoundX = 0
; SoundY = 0
;
;
;
; Repeat
;
; ; move listener
; ListenerX = 5000 * Cos(ElapsedMilliseconds() / 500)
;
; moveSound(*snd,SoundX,SoundY)
; soundEngineRun(ListenerX,ListenerY)
;
; Until whatever