play sounds in sequence

Posted by open768, Posted on January 22, 2012

0 votes

Hope this helps someone :-)

syntax

1
cSoundPlayer:play(paFiles, poListener)

plays a sequence of sounds and takes a tablelistener as a param
tableListener must implement function onComplete()

example

1
2
3
4
5
6
myObj = {}
function myObj.onComplete()
print ("hey you played all the sounds")
end
 
cSoundPlayer:play({"snd1.mp3", "snd2.mp3"},  myObj)

code for player object:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
cSoundPlayer =  {}
 
function cSoundPlayer:play(paFiles, poListener)
        local oInstance = {}
        setmetatable( oInstance, { __index = cSoundPlayer } )  -- arcane lua for OO
        
        oInstance.files=paFiles
        oInstance.nowPlaying = 0
        oInstance.handle = nil
        oInstance.listener = poListener 
        
        oInstance:playInSeq(1)
 
        return oInstance
end
 
--*******************************************************
function cSoundPlayer:playInSeq(piIndex)
        print ("playing sound: "..piIndex)
        self.handle = audio.loadSound(self.files[piIndex])
        self.nowPlaying = piIndex
        
        fnCallback = function(poEvent)  self:onComplete(poEvent) end
        audio.play(self.handle, {onComplete=fnCallback})
end
 
--*******************************************************
function cSoundPlayer:onComplete(poEvent)
        local oListener
        -- clear out the previous audio
        audio.dispose(self.handle)
        self.handle = nil
        print ("finished " .. self.nowPlaying)
        
        --
        if (self.nowPlaying < table.maxn(self.files)) then
                self:playInSeq(self.nowPlaying + 1 )
        else
                oListener = self.listener
                self.files=nil
                self.listener = nil
                oListener:onComplete()
        end
end


Replies

RegieC's picture
RegieC
User offline. Last seen 1 week 2 days ago. Offline
Joined: 27 Jan 2012

Thank you, this works great!

open768's picture
open768
User offline. Last seen 1 week 5 days ago. Offline
Joined: 6 Jul 2011

no problem! could be improved by preloading all the sounds before playing them, but its a tradeoff between length to load, memory use and gap between playing.

Pasz72's picture
Pasz72
User offline. Last seen 3 hours 26 min ago. Offline
Joined: 13 Jul 2011

Great snippet. Is there a way to cancel the sequence ?

open768's picture
open768
User offline. Last seen 1 week 5 days ago. Offline
Joined: 6 Jul 2011

heres the updated with a stop() function.
though mind you'll need to take out my debug code.

I've extended this further into a animation class that
coordinates sounds and transitions which I plan to upload separately.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
cSoundPlayer =  { eventName = "onComplete"}
 
--TBD remove listener and use events
 
function cSoundPlayer:play(paFiles, poListener, pbLooped)
        local oInstance = {}
        setmetatable( oInstance, { __index = cSoundPlayer } )  -- arcane lua for OO
        
        oInstance.files=paFiles
        oInstance.nowPlaying = 0
        oInstance.handle = nil
        oInstance.listener = poListener 
        oInstance.stopped = false
        oInstance.channel = nil
        oInstance.looped = pbLooped
        
        oInstance:_playInSeq(1)
 
        return oInstance
end
 
--*******************************************************
function cSoundPlayer:_playInSeq(piIndex)
        local fnCallback
        
        if not self.files then
                error("no Files to play")
        end
        
        if self.stopped then return end
 
        self.channel = audio.findFreeChannel()
        self.handle = audio.loadStream(self.files[piIndex])
        self.nowPlaying = piIndex
        
        fnCallback = function(poEvent)  self:onComplete(poEvent) end
        self.alChannel, self.alSource = audio.play(self.handle, {onComplete=fnCallback, channel=self.channel})
end
 
--*******************************************************
function cSoundPlayer:onComplete(poEvent)
        local oListener
        -- clear out the previous audio
        audio.dispose(self.handle)
        self.handle = nil
        self.channel = nil
        self.alChannel = nil
        self.alSource = nil
        
        -- bomb out if stopped
        if self.stopped then return end
        
        --
        if (self.nowPlaying < table.maxn(self.files)) then
                self:_playInSeq(self.nowPlaying + 1 )
        else
                if self.looped then
                        self:_playInSeq(1)
                        return
                else
                        -- tbd 
                        if (self.listener ) then
                                self.files=nil
                                if type(self.listener) == "function" then
                                        self.listener(poEvent)
                                else
                                        self.listener:onComplete()
                                end
                                self.listener = nil
                        end
 
                        -- clear out the 
                        self.files = nil
                end
        end
end
 
--*******************************************************
function cSoundPlayer:stop()
        if self.channel then
                cDebug:print(DEBUG__INFO, "stopping sounds on channel "..self.channel)
                self.stopped = true
                audio.stop(self.channel)
        end
end