Detect when audio has stopped playing, then start new audio from same point

It seems to be working, thank you! However, the documentation states

Audio loaded with audio.loadSound() may only seek using the channel parameter. You may not seek using the audioHandle.

which is why I only referred to the channel not the handle. Is this not actually the case?

My understanding is that this is only an issue if you are playing the same sound/audioHandle on multiple channels at the same time.  I don’t believe this will ever be an issue in your app.

Hi,

Resurrecting this topic because I’m now at the point where I’ve recreated the entire interface using your structure and am completely stuck on how to calculate the start/stop time using the new logic.

The relevant bit of my code looks like this:

-- Creates a plate table/object. local function newPlate() local self = {} self.onTouch = function(event) audio.play(self.sound, { channel = self.audioChannel, duration = 2000 }) self.startTime = system.getTimer() end return self end -- Create all plates an store them to a table. local plates = {} for plateNumber=1,24 do plates[plateNumber] = newPlate() plates[plateNumber].audioChannel = plateNumber + 1 end function playC(event) audio.stop({channel=1}) audio.play(chords[4], { channel=1, loops=-1 }) plates[1].sound = strum[3] plates[2].sound = strum[7] plates[3].sound = strum[3] plates[4].sound = strum[7] plates[5].sound = strum[3] plates[6].sound = strum[7] plates[7].sound = strum[3] plates[8].sound = strum[7] plates[9].sound = strum[3] plates[10].sound = strum[7] plates[11].sound = strum[3] plates[12].sound = strum[7] plates[13].sound = strum[3] plates[14].sound = strum[7] plates[15].sound = strum[3] plates[16].sound = strum[7] plates[17].sound = strum[3] plates[18].sound = strum[7] plates[19].sound = strum[3] plates[20].sound = strum[7] plates[21].sound = strum[3] plates[22].sound = strum[7] plates[23].sound = strum[3] plates[24].sound = strum[7] for plateNumber=1,24 do if audio.isChannelPlaying ( plateNumber + 1 ) then stopTime = system.getTimer() currentTime = stopTime - self.startTime print("plate " .. plateNumber .. currentTime) if currentTime \< 5000 then audio.stop ( platenumber + 1 ) audio.play(plates[plateNumber], { channel = plateNumber + 1}) audio.seek(currentTime, { channel = plateNumber + 1}) end end end end

However, when I change chords before the end of the 5000ms time frame, I get the following error: ‘Attempt to index global ‘self’ (a nil value).’ The error references the line where I’ve attempted to subtract self.startTime from stopTime.

Where is self.startTime being stored for each plate, and how do I access it?

That error is likely happening in your playC() function on the following line…

   currentTime = stopTime - self.startTime

The “self” variable is not defined that function.  If I’m understanding your code correctly, that line of code should be this…

   currentTime = stopTime - plates[plateNumber].startTime

Hmm. I’m trying this method but it doesn’t seem to be working and I’m not sure what the problem is.

The correct values of startTime, stopTime and currentTime are being printed, but when the chord is changed while the strumming note is still ringing out, it stops all the notes and the active plates fall silent. I can’t figure out why this is. It’s like the audio.stop call is working but then not the subsequent audio.seek and audio.play. Why would this be?

When this wasn’t working with the old code structure it was because I had called play before seek, but that isn’t the case this time so I’m a bit lost.

EDIT: I’m an idiot. Changed the below to

 audio.play(plates[plateNumber].sound, { channel = plateNumber + 1})

and now it works. Thanks!

-- Creates a plate table/object. function newPlate() local self = {} self.onTouch = function(event) audio.play(self.sound, { channel = self.audioChannel, duration = 2000 }) self.startTime = system.getTimer() end return self end -- Create all plates and store them to a table. local plates = {} for plateNumber=1,24 do plates[plateNumber] = newPlate() plates[plateNumber].audioChannel = plateNumber + 1 end function playC(event) audio.stop({channel=1}) audio.play(chords[4], { channel=1, loops=-1 }) plates[1].sound = strum[3] plates[2].sound = strum[7] plates[3].sound = strum[3] -- etc for plateNumber=1,24 do if audio.isChannelPlaying ( plateNumber + 1 ) then plates[plateNumber].stopTime = system.getTimer() print("start time" .. plates[plateNumber].startTime) print("stop time" .. plates[plateNumber].stopTime) plates[plateNumber].currentTime = plates[plateNumber].stopTime - plates[plateNumber].startTime print("current time " .. plates[plateNumber].currentTime) if plates[plateNumber].currentTime \< 8000 then audio.stop ( plateNumber + 1 ) audio.seek(plates[plateNumber].currentTime, { channel = plateNumber + 1}) audio.play(plates[plateNumber], { channel = plateNumber + 1}) end end end end function playG(event) audio.stop({channel=1}) audio.play(chords[5], { channel=1, loops=-1 }) plates[1].sound = strum[5] plates[2].sound = strum[8] plates[3].sound = strum[5] --etc for plateNumber=1,24 do if audio.isChannelPlaying ( plateNumber + 1 ) then plates[plateNumber].stopTime = system.getTimer() print("start time" .. plates[plateNumber].startTime) print("stop time" .. plates[plateNumber].stopTime) plates[plateNumber].currentTime = plates[plateNumber].stopTime - plates[plateNumber].startTime print("current time " .. plates[plateNumber].currentTime) if plates[plateNumber].currentTime \< 8000 then audio.stop ( plateNumber + 1 ) audio.seek(plates[plateNumber].currentTime, { channel = plateNumber + 1}) audio.play(plates[plateNumber], { channel = plateNumber + 1}) end end end end strumplate[1]:addEventListener("touch", plates[1].onTouch) strumplate[2]:addEventListener("touch", plates[2].onTouch) strumplate[3]:addEventListener("touch", plates[3].onTouch)