I use the following code for music, loops, one shot and sfx queuing. Hope it helps. It based on some old code that I think was written by Eikon.
DebugLog "MOD_SFX_Engine.bmx"
Const CH_ANY = -1
Const CH_1 = 1 'Brick Sounds
Const CH_2 = 2 'Score Sounds
Const CH_3 = 3 'Powerup Sounds
Const CH_4 = 4 'Incidential Sounds
Const CH_5 = 5
Const CH_6 = 6 ' Diamond Sounds
Const CH_7 = 7 ' Chords
Const CH_8 = 8 ' Vox
Const CH_9 = 9 ' GUI Sounds
Const CH_10 = 10 ' BG Music
Const CH_11 = 11 ' Score Sounds
' ---------------------------------------------------------------------
Global ChannelTList:TList = New TList
Type ActiveChannel
Field SampleID :Int
Field Address :TChannel
Field FadeTime :Double
Field FadeStart :Double
Field CreateTime:Int
Field Volume :Double
Field VolumeS :Double
Field Queue :TSound[8]
Field VolQ :Double[8]
Field Qcount :Double
Method New ()
If ChannelTList = Null Then ChannelTList = New TList
ChannelTList.AddLast Self
End Method
'----------------------------------------------------------------
Function Destroy (a:ActiveChannel)
Local b:Int
a.Address = Null
For b = 0 To 7
a.Queue[b] = Null
Next
ChannelTList.Remove a
a = Null
End Function
'----------------------------------------------------------------
Function MusicQueueState(ID:Int)
Local c:ActiveChannel
For c:ActiveChannel = EachIn ChannelTList
If c.SampleID = ID Then Return Int(c.QCount)
Next
End Function
'----------------------------------------------------------------
Function PlaySample(add:TSound,ID:Int=-1,Vol:Double=1,Queue:Byte=False,overlap:Byte=False,rate:Double=1)
Local Channel:ActiveChannel
Local Simultaneous:Byte = False
Local Playing:Byte = False
If ID <0 Then Simultaneous = True
For Channel:ActiveChannel = EachIn ChannelTList
If Channel.SampleID = ID
If Queue = True
Channel.Qcount = Channel.Qcount + 1
If Channel.Qcount > 1 Then
Channel.QCount = 1
DebugLog "**SFX Queue Overload!"
Return
EndIf
Channel.Queue[Channel.Qcount] = add
Channel.VolQ[Channel.Qcount] = vol
Playing = True
Else
Playing = True
EndIf
If overlap And (MilliSecs() - Channel.Createtime > 100) Then Playing = False
EndIf
If Not ChannelPlaying(Channel.Address) Then
StopChannel(Channel.Address)
Destroy(Channel)
EndIf
Next
If Not (Simultaneous = False And Playing = True)
Channel:ActiveChannel = New ActiveChannel
Channel.SampleID = ID
Channel.Address = AllocChannel()
Channel.Volume = Vol
Channel.VolumeS = Vol
SetChannelVolume(Channel.Address,Channel.Volume)
PlaySound(Add,Channel.Address)
Channel.FadeTime = 0
Channel.CreateTime = MilliSecs()
SetChannelRate(Channel.Address,rate)
EndIf
End Function
'----------------------------------------------------------------
Method Update()
Local a:Int
If Not ChannelPlaying(self.Address)
If self.Qcount = 0
StopChannel(self.address)
Destroy(Self)
Return
Else
SetChannelVolume(self.address,self.volQ[1])
PlaySound(self.queue[1],self.address)
For a = 1 To self.qCount - 1
self.queue[a] = self.queue[a+1]
self.volQ[a] = self.volQ[a+1]
Next
self.Queue[self.Qcount] = Null
self.Qcount = self.Qcount - 1
EndIf
EndIf
If Self.FadeTime
If self.Volume <= 0 Then
If self.Qcount = 0
StopChannel(self.address)
Destroy(Self)
Else
Self.FadeTime = 0
Self.Volume = self.volQ[1]
SetChannelVolume(self.address,self.volQ[1])
PlaySound(self.queue[1],self.address)
For a = 1 To self.qCount - 1
self.queue[a] = self.queue[a+1]
self.volQ[a] = self.volQ[a+1]
Next
self.Queue[self.Qcount] = Null
self.Qcount = self.Qcount - 1
EndIf
Else
Self.Volume = self.VolumeS - Float(MilliSecs() - self.FadeStart) / self.fadetime
SetChannelVolume(self.address,self.volume)
EndIf
EndIf
End Method
'----------------------------------------------------------------
Function UpdateAll()
Local c:ActiveChannel
For c:ActiveChannel = EachIn ChannelTList
c.Update()
Next
End Function
'----------------------------------------------------------------
Function SoundOff()
Local c:ActiveChannel
For c:ActiveChannel = EachIn ChannelTList
StopChannel(c.address)
Destroy(c)
Next
End Function
'----------------------------------------------------------------
Function SetVolume(ID:Int,Vol:Double)
Local c:ActiveChannel
For c:ActiveChannel = EachIn ChannelTList
If c.SampleID = ID Then SetChannelVolume(c.address,vol)
Next
End Function
'----------------------------------------------------------------
Function Playing(ID:Int)
Local c:ActiveChannel
For c:ActiveChannel = EachIn ChannelTList
If c.SampleID = ID And ChannelPlaying(c.address) Then Return True
Next
Return False
End Function
'----------------------------------------------------------------
Function ReleaseSample(ID:Int,Timeout:Double)
Local c:ActiveChannel
For c:ActiveChannel = EachIn ChannelTList
If Not c.FadeTime
If c.SampleID = ID Then
If Timeout
c.FadeTime = Timeout
c.FadeStart = MilliSecs()
Else
StopChannel(c.Address)
Destroy(c)
EndIf
EndIf
EndIf
Next
End Function
'----------------------------------------------------------------
Function NextTrack()
MusicTrack:+1
If MusicTrack > MusicTracks Then MusicTrack = 1
ActiveChannel.ReleaseSample(CH_10,4000)
DebugLog "Music Track : "+MusicTrack
ActiveChannel.Playsample(MainSkin.BGMusic[MusicTrack],CH_10,MusicVolume,True,False)
Return True
End Function
End Type
|