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