Problems with audio.seek() immediately after an audio.start() on the iPad

Hello,

I’m having a problem playing back audio at a specific location. My initial tactic was to start the audio playback, then seek to the correct playback position, like so:

 audio\_channel = audio.play(sound)  
 audio.seek(seek\_position, { channel = audio\_channel }  

However, in both the simulator and on the iPad, the audio would start playing back at the beginning for a split second, then seek to the correct playback position. The result was that you could hear a little “blip” or “hiccup” at the beginning of the playback.

So, I updated my code like so:

 audio.setVolume( 0 )  
 audio\_channel = audio.play(sound)  
 audio.seek(seek\_position, { channel = audio\_channel })  
 audio.setVolume( 1 )  

On the simulator this works great, but on the iPad it didn’t make any difference at all. Any suggestions?

Thanks,

  • Bret [import]uid: 168791 topic_id: 30266 reply_id: 330266[/import]

Hi clone45,

I’d suggest that you get the sound channel or handle via a different API that doesn’t require playing it first. “audio.loadSound” or “audio.loadStream” might be valid for this. Once the sound is loaded into memory (or the stream is set up to play), then seek the proper point in that file.

Of course, there are different methods if you’re loading a sound or a stream. But essentially, I’d suggest that you avoid playing the file first, then seeking a position within it. Try to locate the position before the file or stream begins playing.

Brent
[import]uid: 9747 topic_id: 30266 reply_id: 121312[/import]

Hi Brent,

Thanks a ton for the feedback. I am using audio.loadSound() before calling audio.seek() already. In my example…

audio.setVolume( 0 )  
audio\_channel = audio.play(sound)  
audio.seek(seek\_position, { channel = audio\_channel })  
audio.setVolume( 1 )  

… the variable “sound” here…

audio\_channel = audio.play(sound)  

… is an audioHandle returned by audio.loadSound(). I like your idea of seeking the audio before playing it, but audio.seek() requires a channel as an argument, and the channel is returned by the call to audio.play(). Therefore, I can’t really call audio.seek() using the channel until after I call audio.play()

I can’t use an audioHandle in the call to audio.seek() unless I load the sound using audio.loadStream(), which I hope to avoid.

I might try calling audio.seek() without specifying a channel before calling audio.play, but I feel like I tried that already and it didn’t make a difference. I’ll give it another shot tonight, but I’m pessimistic.

Thanks!

  • Bret [import]uid: 168791 topic_id: 30266 reply_id: 121393[/import]

Bret: You are at an edge case that I was hoping nobody would actually need. I think the ‘proper’ solution is to have an API that allows you to occupy a channel without actually playing it. But I was hoping to avoid introducing additional APIs for this. (Trying to keep a good balance of simplicity vs. capabilities.)

I see 2 possible workarounds for you.

  1. Try audio.play immediately followed by audio.pause. Then do audio.seek as you were followed by audio.resume. Maybe this will be fast enough that you don’t hear the blip.

  2. Use a sound with a silent lead in of a known amount of time. Then you can seek over this lead-in time.
    [import]uid: 7563 topic_id: 30266 reply_id: 121400[/import]

Thanks for the response ewing. I’ll definitely try your workarounds. Luckily, it’s not really a show stopper for my application which is a bit glitchy by design.

I admit knowing nothing of the underlying code, but perhaps another tactic would be to add an (optional) parameter for the starting playback position to audio.play()…

audio.play( audioHandle [, { [channel=c] [, loops=l] [, duration=d] [, fadein=f] [, onComplete=o] [, seek=ms] } ] )
Thanks again,

  • Bret
    [import]uid: 168791 topic_id: 30266 reply_id: 121407[/import]

ewing,

Wooo… Surprisingly, that didn’t work at all! In fact, it cause all sorts of mayhem. To be more specific, if I start a sample playing like you suggested:

 print("playback started")  
 audio\_channel = audio.play(sound)  
 audio.pause({ channel = audio\_channel })  
 audio.seek(seek\_position, { channel = audio\_channel })  
 audio.resume({ channel = audio\_channel })   

Then any subsequent call to audio.seek on that playing sound is all messed up. It sounds like the subsequent seeks aren’t really seeking, plus the seeks causes short pauses in the playback. Quite unexpected! Is there something about pause() and resume() that cause seek() to freak out?

I’ve temporarily reverted back to my old code, which sounds a lot better but still has the issue where you can hear the beginning of the sample start to playback before the seek happens:

audio.setVolume( 0 )  
audio\_channel = audio.play(sound)  
audio.seek(seek\_position, { channel = audio\_channel })  
audio.setVolume( 1 )  

Any help would be much appreciated,

  • Bret [import]uid: 168791 topic_id: 30266 reply_id: 121429[/import]

Interesting. Is it freaking out on both the Corona Mac simulator and iPad? (Does it also freakout on Windows or Android?)

The volume thing you originally did should have worked but it sounds like it is an iOS bug (especially if it works on Mac). I would encourage you to file a bug with Apple.

Another trick you might try is to set the channel volume in addition to or in replacement of your setVolume.

audio_channel = audio.findFreeChannel()
audio.setVolume(0, {channel=audio_channel})
audio.play(sound {channel=audio_channel})

[import]uid: 7563 topic_id: 30266 reply_id: 121432[/import]

I confirmed that the pause/resume is an Apple bug that affects Mac and iOS. It does not affect Android and presumably Windows (OpenAL Soft).

I filed a bug with Apple on this one: rader://12194320.

Please file a duplicate with Apple on this. (The more people that complain, the faster it gets fixed.) Do it ASAP if you want to see it get fixed before iOS 6 ships.

I haven’t had time to look at the volume iPad bug. I encourage you to file a bug with Apple and post the bug number here.

[import]uid: 7563 topic_id: 30266 reply_id: 121586[/import]

Oh wow, thanks for going to extra mile for me! I’ll file a bug as soon as possible. I really appreciate your support. :slight_smile:

  • Bret [import]uid: 168791 topic_id: 30266 reply_id: 121601[/import]

Hi clone45,

I’d suggest that you get the sound channel or handle via a different API that doesn’t require playing it first. “audio.loadSound” or “audio.loadStream” might be valid for this. Once the sound is loaded into memory (or the stream is set up to play), then seek the proper point in that file.

Of course, there are different methods if you’re loading a sound or a stream. But essentially, I’d suggest that you avoid playing the file first, then seeking a position within it. Try to locate the position before the file or stream begins playing.

Brent
[import]uid: 9747 topic_id: 30266 reply_id: 121312[/import]

Hi Brent,

Thanks a ton for the feedback. I am using audio.loadSound() before calling audio.seek() already. In my example…

audio.setVolume( 0 )  
audio\_channel = audio.play(sound)  
audio.seek(seek\_position, { channel = audio\_channel })  
audio.setVolume( 1 )  

… the variable “sound” here…

audio\_channel = audio.play(sound)  

… is an audioHandle returned by audio.loadSound(). I like your idea of seeking the audio before playing it, but audio.seek() requires a channel as an argument, and the channel is returned by the call to audio.play(). Therefore, I can’t really call audio.seek() using the channel until after I call audio.play()

I can’t use an audioHandle in the call to audio.seek() unless I load the sound using audio.loadStream(), which I hope to avoid.

I might try calling audio.seek() without specifying a channel before calling audio.play, but I feel like I tried that already and it didn’t make a difference. I’ll give it another shot tonight, but I’m pessimistic.

Thanks!

  • Bret [import]uid: 168791 topic_id: 30266 reply_id: 121393[/import]

Bret: You are at an edge case that I was hoping nobody would actually need. I think the ‘proper’ solution is to have an API that allows you to occupy a channel without actually playing it. But I was hoping to avoid introducing additional APIs for this. (Trying to keep a good balance of simplicity vs. capabilities.)

I see 2 possible workarounds for you.

  1. Try audio.play immediately followed by audio.pause. Then do audio.seek as you were followed by audio.resume. Maybe this will be fast enough that you don’t hear the blip.

  2. Use a sound with a silent lead in of a known amount of time. Then you can seek over this lead-in time.
    [import]uid: 7563 topic_id: 30266 reply_id: 121400[/import]

Thanks for the response ewing. I’ll definitely try your workarounds. Luckily, it’s not really a show stopper for my application which is a bit glitchy by design.

I admit knowing nothing of the underlying code, but perhaps another tactic would be to add an (optional) parameter for the starting playback position to audio.play()…

audio.play( audioHandle [, { [channel=c] [, loops=l] [, duration=d] [, fadein=f] [, onComplete=o] [, seek=ms] } ] )
Thanks again,

  • Bret
    [import]uid: 168791 topic_id: 30266 reply_id: 121407[/import]

ewing,

Wooo… Surprisingly, that didn’t work at all! In fact, it cause all sorts of mayhem. To be more specific, if I start a sample playing like you suggested:

 print("playback started")  
 audio\_channel = audio.play(sound)  
 audio.pause({ channel = audio\_channel })  
 audio.seek(seek\_position, { channel = audio\_channel })  
 audio.resume({ channel = audio\_channel })   

Then any subsequent call to audio.seek on that playing sound is all messed up. It sounds like the subsequent seeks aren’t really seeking, plus the seeks causes short pauses in the playback. Quite unexpected! Is there something about pause() and resume() that cause seek() to freak out?

I’ve temporarily reverted back to my old code, which sounds a lot better but still has the issue where you can hear the beginning of the sample start to playback before the seek happens:

audio.setVolume( 0 )  
audio\_channel = audio.play(sound)  
audio.seek(seek\_position, { channel = audio\_channel })  
audio.setVolume( 1 )  

Any help would be much appreciated,

  • Bret [import]uid: 168791 topic_id: 30266 reply_id: 121429[/import]

Interesting. Is it freaking out on both the Corona Mac simulator and iPad? (Does it also freakout on Windows or Android?)

The volume thing you originally did should have worked but it sounds like it is an iOS bug (especially if it works on Mac). I would encourage you to file a bug with Apple.

Another trick you might try is to set the channel volume in addition to or in replacement of your setVolume.

audio_channel = audio.findFreeChannel()
audio.setVolume(0, {channel=audio_channel})
audio.play(sound {channel=audio_channel})

[import]uid: 7563 topic_id: 30266 reply_id: 121432[/import]

I confirmed that the pause/resume is an Apple bug that affects Mac and iOS. It does not affect Android and presumably Windows (OpenAL Soft).

I filed a bug with Apple on this one: rader://12194320.

Please file a duplicate with Apple on this. (The more people that complain, the faster it gets fixed.) Do it ASAP if you want to see it get fixed before iOS 6 ships.

I haven’t had time to look at the volume iPad bug. I encourage you to file a bug with Apple and post the bug number here.

[import]uid: 7563 topic_id: 30266 reply_id: 121586[/import]

Oh wow, thanks for going to extra mile for me! I’ll file a bug as soon as possible. I really appreciate your support. :slight_smile:

  • Bret [import]uid: 168791 topic_id: 30266 reply_id: 121601[/import]