Here's my modified Bass 3D demo.
1) The sound source position is attached to a moving 'character'.
2) Channel level is detected and used to open and close a 'mouth'.
I will be using two textures in my engine, one with mouth open, one with mouth closed, using EntityTexture() as appropriate.
In an ideal world I would attach a new bone to the neck of my character(s) to animate the jaw, but currently I'm using FPS Creator characters (good quality) and if I attach a new bone at all, even before I try to move it, it screws up the animation of the whole model.(?)
So for now I'll just make do with swapping the textures.
Thanks to all on this forum for pointing me in the right direction, and once again to Abrexxes for making free his brilliant work.
Here's the code:
Include "bass.bb"
Graphics3D 800,600,32,2
camera=CreateCamera()
PositionEntity camera,0,0,-10
TurnEntity camera,0,0,0
CameraRange camera,0.1,10000
AmbientLight 255,0,0
character = CreateSphere(32)
BASS_Init(-1,44100,BASS_DEVICE_3D,0,BASS_NULL)
file$ = "0.wav" ; <- your file here
; for this demo make sure it's a good 'speaking' file with lots of pauses.
channel = BASS_StreamCreateFile(0,file$,0,0,BASS_SAMPLE_3D)
BASS_ChannelPlay(channel,BASS_TRUE)
; BASS_Set3DFactors(0.9144, -1.0, -1.0) ; don't think this is needed.
BASS_Set3DPositionPos(EntityX(camera),EntityY(camera),EntityZ(camera)) ; set initial Listener pos
Repeat
; Move the character around the stereo field
deg# = deg# + 0.5
If deg# => 360 Then deg# = 0
cx# = Sin(deg#) * 7
cz# = Cos(deg#) * 7
PositionEntity character,cx#,0,cz#
UpdateWorld
RenderWorld
; Update where the character is speaking from
pos=CreateBank(12) : rot=CreateBank(12) : vel=CreateBank(12)
PokeFloat pos,0,EntityX(character,1) : PokeFloat pos,4,EntityY(character,1) : PokeFloat pos,8,EntityZ(character,1)
PokeFloat rot,0,0 : PokeFloat rot,4,0 : PokeFloat rot,8,0
PokeFloat vel,0,0 : PokeFloat vel,4,0 : PokeFloat vel,8,0
BASS_ChannelSet3DPosition(channel,pos,rot,vel)
FreeBank pos : FreeBank rot : FreeBank vel
; Update the Listener if camera moved.
If KeyDown(203)
MoveEntity camera,-0.1,0,0
BASS_Set3DPositionPos(EntityX(camera),EntityY(camera),EntityZ(camera))
Else If KeyDown(205)
MoveEntity camera,0.1,0,0
BASS_Set3DPositionPos(EntityX(camera),EntityY(camera),EntityZ(camera))
EndIf
If KeyDown(200)
MoveEntity camera,0,0,0.1
BASS_Set3DPositionPos(EntityX(camera),EntityY(camera),EntityZ(camera))
Else If KeyDown(208)
MoveEntity camera,0,0,-0.1
BASS_Set3DPositionPos(EntityX(camera),EntityY(camera),EntityZ(camera))
EndIf
If KeyDown(57) Then BASS_ChannelPlay(channel,BASS_TRUE) ; play again
BASS_Apply3D()
; Instructions
Color 255,255,255
Text 400,600-60,"Press Spacebar to restart sound", True, True
Text 400,600-40,"Use arrows to slide forward, backward, right, left", True, True
Text 400,600-20,"Camera "+EntityX(camera)+" "+EntityY(camera)+" "+EntityZ(camera), True, True
; Get the Level/Amplitude of the channel
; Maxumum should be 32767 on either left or right
vumono = BASS_ChannelGetLevel (channel)
vuleft = BASS_MakeLoWord (vumono)
vuright = BASS_MakeHiWord (vumono)
If vuright < 65535
Text 0,020,"Left channel : "+vuleft
Rect 0,050,vuleft/100,20,1
Rect 0,090,vuright/100,20,1
Text 0,120,"Right channel : "+vuright
Else
vuright = 0 ; ended, so close the mouth.
EndIf
; Simulated mouth response
Color 204,127,125
Rect 600,50,100,50,True
If vuright < 7500 ; adjust this for the threshold below which it's closed.
Color 0,0,0
Rect 605,75,90,1,True
Color 255,255,255
Text 600,30,"Closed"
Else
Color 255,255,255
Text 600,30,"Open"
Rect 610,65,80,20,True
Color 0,0,0
Rect 610,70,80,10,True
EndIf
Flip
Until KeyDown(1)
BASS_Stop()
BASS_Free()
End