Question

How can I implement seeking (timeline feature) in a streamed audio on the iPhone?

The AudioFileStreamSeek method takes in the byte offset from which I want to start seeking. I want to be able to get the current position of the mp3 which is playing and let the user come back (seek) to the same position at a later point in time.

But I could not find any way of knowing the number of bytes which have already played. I can find out the number of bytes which have been streamed. But cannot find out how many bytes have been played. I am using Matt Gallagher's audio streaming example as the base.

Any help is greatly appreciated.

Thanks.

Might just be able to find a solution. AudioFileStreamSeek documentation says

After you call this function, the parser assumes the next data passed to the AudioFileStreamParseBytes function starts from the byte offset returned in the outAbsoluteByteOffset parameter.

How do we do that? Should we be using the Http Range parameter? If we send the byte offset to Range, will it work as expected? And how should I clear the existing bytes in the buffer to avoid two streams to play together?

Any help greatly appreciated. Thanks.

Was it helpful?

Solution

AudioFileStreamSeek works with packets, not number of bytes. So, what you really need to track is the packet count.

The MyEnqueueBuffer method in Matt's code is where the buffers are sent to AudioQueue for playback. Grab packetsfilled and increment your index variable before packetsfilled is reset to 0:

myData.absolutePackets = myData.absolutePackets + myData->packetsFilled;

My problem is that I cannot AudioFileStreamSeek implemented correctly even with this value. So if you have some sample code of a working seek with Matt's code please share.

Thanks!

OTHER TIPS

I haven't really tried AudioFileStream API for this (we rolled our own internally), but here's a few things you have to take care of.

Asssuming you have no problem random-seeking the byte stream, then you have to keep tracking the relationship between MP3 frame number and the absolute byte stream location, just as Paul says. I assume you can do that in your AudioFileStream_PacketsProc by calling AudioFileStreamSeek along the way.

Here's the trickier part. When you do random seek, you have to reset the internal states of AudioFileStream. Because it might be in some intermediate state expecting the next incoming bytes to complete the current frame. I'm not sure if you can just feed zeros to have it skip the current frame, and start over (that you have to try, as I don't see anything like AudioFileStreamReset in the API; the audio queue itself, however, does have reset function that you can clean up already-queued frame). At any rate you have to take care of your AudioFileStream_PacketsProc too because you're going to parse a part of the byte stream which you already have kept track of.

Note you can't just find the start of a MP3 frame by relying on the second and the bitrate. Even with non-variable rate MP3 stream, there can be paddings every other few frames. So the most accurate information still comes from the parser.

I should quickly add that another way to do random seeking is simply "cache" (store) the parsed packets if you're not playing a really long and large stream. Frame index can be calculated from the frame header info. For non VBR MP3s, frames per second is a constant (e.g. it's 44100/1152 = 38.28125 frames per sec for 44.1 kHz stereo non-VBR MP3; check out MP3 spec for why it's so).

can you use AudioQueueStart with the mSampletime of the place you want to seek to?

so just stop the play.... and start at a different sample time? [just take the current sample time and manipulate it by what you need to?]

inDeviceStartTime The time at which the audio queue should start.

To specify a start time relative to the timeline of the associated audio device, use the mSampleTime field of the AudioTimeStamp structure. Use NULL to indicate that the audio queue should start as soon as possible.

Return Value A result code. See “Audio Queue Result Codes.”

Discussion If the associated audio device is not already running, this function starts it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top