iOS Audio/Media Player

I am writing an iOS app that requires to play some audio files. I have to control and set the position of the song. How can I do that?

You need to write declares into AVAudioPlayer. I plan to add classes to iOSKit to do this after XDC.

Thank you for the tip Jason, I forgot to add that it’s my first iOS app and I’m not very familiar with declares, what do you suggest me to study/do?

You should definitely study the documentation on it, although the way I learned was by looking at projects like MacOSLib or iOSKit to see how other devs had approached it. Feel free to ask questions and post progress here so that myself or others can try to help you.

I have an AVAudioPlayer implementation sitting here…
Need to release it soon.

Hi Christian,

I notice the announcement today about your AVAudioPlayer kit. Looks interesting! The announcement mentions a demo app, but I can’t see one to download anywhere. I might just be going blind though!

I was wondering what you are using internally for this? I need access to the PitchTime Audio Unit in iOS and have been playing around with Swift to do it. Would be great if your AVAudioPlayer kit could handle it in Xojo.

The easiest way in Swift is to use the AVAudioEngine and add an AVAudioUnitTimePitch node. It’s iOS 8 only, but that wouldn’t be an issue for me. In iOS 7 you can still use the AUNewTimePitch audio unit, but that’s a lot more complicated than the new AVAudioEngine stuff, so I would think it would be too tricky using declares.

Anyway, I’d be interested in a bit more information about your AV Player Kit for iOS and if it can handle any of the Pitch/Time manipulation mentioned above.

there is no demo app. I just forgot to remove that line from announcement.
(or make one) we’ll see.

and sorry, it’s just a wrapper for AVAudioPlayer.

Hi Christian,
I am very interested on your plugin, but when I click the button Buy Now it goes to “MBS Xojo Addressbook Kit”

Sorry. The link is fixed to have the right ID.

Can AVAudioPlayer play sounds syncronous instead of async? Yes I realize that would block the main thread… but I’m talking about sounds that are less that 1/2 second in length but need to be repeated… like beep beep beep (but the sound is not a vanilla beep), when played async I get one beep … as they don’t wait for each other to complete.

I doubt very much anything can be made synchronous in iOS, since Apple forbids anything that holds execution.

I see two approaches to beep beep :

  • concatenate the mp3, as it uses to work for identical sounds
  • use a timer. I just played with that. With some fine tuning based on the length of the beep, it works.

you can get an event when playback finished.
I did that for my AudioPlayerKit.

[quote=198399:@Christian Schmitz]you can get an event when playback finished.
I did that for my AudioPlayerKit.[/quote]

That would require a declare…

Yes, the Kit has the declares.
Or you write your own.

AVAudoPlayer has a “didComplete” delegate… but even using that would be a pain… It tells you when the sound completed… but doesn’t provide a method to WAIT… seeing as the program code would have already moved to the next statement after “play”. The only way I could see to use that (assuming one had the right declares) would be to set a flag, and loop until the delegate flipped the flag. Apple expressly discourges POLLING…

So what I have done (so far) was create a timer the same duration as the sound…

Concat the sounds isn’t an option, as the number of times it plays varies, and sometimes it is a combination of multiple sounds in sequence… and some element of the UI is usually changing color with each sound

where is the problem?
When you get the didComplete call/event, you would simply start playing next sound.
Or you calculate in advance the end and start playing new sound a few seconds before old starts to fade over.

a) the sounds are between 0.2 and 0.4 seconds in length… so a “few seconds before” is out of the question… it is not like I am playing songs lasting minutes
b) as I mentioned … UI elements need to change in synch with the sounds …

So as I mentioned above… I have added a sleep timer that is 1/100th of second longer than the sound itself, and this seems to give the best (not perfect) results

In order to get two sound playing in sync Apple gives an advice here. I use it in my project and the sync is perfect (I use 32 instances of AVAudioPlayer playing in perfect sync a 32+ minutes-long track without any kind of UI hang or lag), maybe it can help you.

I appreciate the attempt to help, but this has nothing to do with the problem… as I mentioned, the sounds I am dealing with are less that 0.5 seconds in length, and the sequence is something like

for i=1 to 5
    play a ding type sound
    change the color of a ui element
next i

and since the sounds are normally played ASync, the first sound is still playing when the loop finishes, so the user only hears ONE sound (the last one, as the first four were aborted when the 2nd,3rd and 4th started).

So the only “band-aid” I have found is to insert a time delay (NSTimer) in the middle, where the duration of the timer is equal to the duration of sound

for i=1 to 5
    play a ding type sound
   sleep for duration of sound
    change the color of a ui element
next i

I’m just not sure what Apple’s reaction to using NSTimer like this

Seems like a queue of tasks would be an appropriate model here. Push the sequence one at a time into the queue and then execute them one at a time.

With the sounds the didComplete event would trigger the next item in the queue to be serviced.

Whether or not you would like that better than implementing a delay with a timer is probably a matter of preference.