HI,
Is there any way to adjust the speed of the song being played by the MPMusicPlayerController?
I've searched everywhere but didn't find anything useful. If there is no way to do it where can I find an example which does it with other components? Some say OpenAL, but I can't find any clear way to use the iPod library with this and change the speed of the song...
Mainly the thing I need is:
The user chooses a song from the iPod library trough MPMusicPlayerController
You have 2 buttons: Slow Down & Speed Up
If the user presses "Slow Down" the speed of the song is slowed down by lets say 5% or something. "Speed Up" visa-versa.
I really hope someone can help me with this!
Thanks in advance!
You could do this as of iOS 3.2 and later -
[musicPlayer play];
[musicPlayer setCurrentPlaybackRate:2.0];
Ref: https://developer.apple.com/library/ios/documentation/mediaplayer/reference/MPMediaPlayback_protocol/Reference/Reference.html#//apple_ref/occ/intfp/MPMediaPlayback/currentPlaybackRate
You can use AVAudioPlayer and AVPlayer for the above purpose.
They have a rate property which can set the speed of the song.
[AVPlayer setRate:1.25]; // 25% faster
However, AVPlayer cannot change the speed by 5% but 25% and AVAudioPlayer works for iOS 5 and above.
If you wish to go for other alternative then Dirac is the best option. Try DIRAC 3 LE which is free.
Use this Link to get an idea on how to use Dirac. For more information, let me know.
#girish_vr
No, you can't do this using only the MPMusicPlayerController.
If you don't mind the pitch going up and down proportional to the speed changes, then you can use the OpenAL resampler after converting your sound file to raw PCM sample files or buffers.
If you don't want the pitch to change, what you are looking for is DSP time pitch stretching/modification/correction techniques. OpenAL can't do this, but there are commercial DSP libraries (DIRAC may be one) available that can do this on iOS. You could also try writing your own phase vocoder, but this is non-trivial digital signal processing code.
Related
I need to play sounds (~5 seconds each) throughout my iphone application. When they're triggered, they need to play immediately.
For the moment I'm using AudioServices and (as you probably know) the first time you play a sound it lags, then every time there after it's perfect. Is there some code available that's clever enough to preload an AudioServices sound (by playing it silently maybe?). I've read adjusting the system volume programmatically will get your app rejected, so that's not an option. Seems AudioServices isn't made for volume correction from what I can see.
I've looked into OpenAL and while feasible seems a little over kill. AVAudioPlayer seems like a little bit of a better option, I'm using that for background music at present. Extending my music player to handle a 'sound board' might be my last resort.
On the topic of OpenAL, does anyone know of a place with a decent (app store friendly) OpenAL wrapper for the iPhone?
Thanks in advance
Finch could be perfect for you. It’s a tiny wrapper around OpenAL with very low latency and simple API. See also all SO questions tagged ‘Finch’.
If you use an AVAudioPlayer, you can call prepareToPlay when you initialize the object to reduce the delay between calling play and having the audio start.
I'd like to be able to play back audio I've recorded using AVAudioRecorder # 1.5x or 2.0x speed. I don't see anything in AVAudioPlayer that will support that. I'd appreciate some suggestions, with code if possible, on how to accomplish this with the iPhone 3.x SDK. I'm not overly concerned with lowering the pitch to compensate for increased playback speed, but being able to do so would be optimal.
Changing the sample rate should work just like a tape recorder would if you played it faster. Everything becomes higher in pitch. To keep the pitch the same, you would need to set up an Audio Unit graph that includes the AUPitch effect, and lower the pitch by the same ratio that you increase the sample rate by.
See this question. In other words, you'll have to use a different API like Audio Queue Services. If you want to try a simple hack, you can try doubling the sample rate property of the audio file. It probably won't work though. Also, be warned that it is fairly CPU demanding to adjust the playback speed while keeping the same pitch. You'll need to use a one of the available techniques called "time stretching". Also, in case you haven't realized it by now, doing complicated things with audio on the iPhone is a major pain because Apple's documentation is generally either very bad or nonexistent.
If you want to play audio faster or slower, there is a build-in method in avAudioPlayer. Have you tried AudioPlayer Rate property ? in Swift it will be like this -
audioP = try! AVAudioPlayer(contentsOf: URL(fileURLWithPath: selectedPath), fileTypeHint: "caf")
audioP.enableRate = true
audioP.prepareToPlay()
audioP.rate = 1.5
audioP.play()
I'm using Media Player Framework to access the user's music library on iPhone. I would like to set the playback starting position so that I can start playing a song from 30 second mark, for example.
I have trouble finding out how to do this. The MPMediaPlayerController only offers beginSeekingForward but that's not quite what I'm looking for as it simply accelerates the playback speed.
There is probably something really simple that I'm missing.
MPMusicPlayerController's property currentPlaybackTime is a writeable property, so adjusting the playback starting point can be done with player.currentPlaybackTime = 30.0
You can use player.currentPlaybackTime to set the time, before you start playing and playback will start at your desired point.
UPDATE
2009 me had some real problems. He didn't really understand properties and missed the fact that MPMusicPlayerController.currentPlaybackTime is writable! And he was angry. Angry because iOS3.0 had promised iPod Library "Access" and instead delivered MPMusicPlayerController. He had been hoping for speedy access to the music packet data upon which he would have built many fascinating and magical audio applications. Luckily, iOS4.1's AVAssetReader came along 1 year later and he was finally able to stop hating.
WRONG 2009 ANSWER
Nope, this API is deliberately crippled, which is why you don't see any functions for
opening, or streaming from, the media file.
Your only hope is lowering the volume and calling beginSeekingForward until currentPlaybackTime returns >= 30s.
Enjoy!
I have a performance-intensive iPhone game I would like to add sounds to. There seem to be about three main choices: (1) AVAudioPlayer, (2) Audio Queues and (3) OpenAL. I’d hate to write pages of low-level code just to play a sample, so that I would like to use AVAudioPlayer. The problem is that it seems to kill the performace – I’ve done a simple measuring using CFAbsoluteTimeGetCurrent and the play message seems to take somewhere from 9 to 30 ms to finish. That’s quite miserable, considering that 25 ms == 40 fps.
Of course there is the prepareToPlay method that should speed things up. That’s why I wrote a simple class that keeps several AVAudioPlayers at its disposal, prepares them beforehand and then plays the sample using the prepared player. No cigar, still it takes the ~20 ms I mentioned above.
Such performance is unusable for games, so what do you use to play sounds with a decent performance on iPhone? Am I doing something wrong with the AVAudioPlayer? Do you play sounds with Audio Queues? (I’ve written something akin to AVAudioPlayer before 2.2 came out and I would love to spare that experience.) Do you use OpenAL? If yes, is there a simple way to play sounds with OpenAL, or do you have to write pages of code?
Update: Yes, playing sounds with OpenAL is fairly simple.
AVAudioPlayer is very marginal for game audio. Tackling AudioQueue or OpenAL by adapting one of the examples is definitely the way to go. latency is much more controllable that way.
If you're calling play on the main thread, try running it on a separate thread. What I ended up doing is:
#include <dispatch/dispatch.h>
dispatch_queue_t playQueue = dispatch_queue_create("com.example.playqueue", NULL);
AVAudioPlayer* player = ...
dispatch_async(playQueue, ^{
[player play];
});
which fixed the worst of the framerate stuttering I was experiencing.
I use OpenAL and the classes that came with the CrashLanding sample code. It's worked fine so far to play samples and play looped music all at the same time. I'm currently learning how to release the memory I've allocated for a sound (.wav file) when, for example, I want to play some intro music just once.
Use CocosDenshion – it’s free, easy, and works. It wraps AVAudioPlayer for background tracks and OpenAL for sounds.
Do you want to check the buffering with the implementation you're using? It might be somehow related to the 20ms delay you're experiencing. i.e., try to play around with the buffer size.
Is there an easy way to control the playback speed/tempo of a sound file loop played using Audio Queue Services? For example, if a game is playing background music, I want to make the BGM speed up as time runs out, but without changing the pitch of the music. Thx!
There's no trivial way to do this that I know of. On the Mac, you'd presumably use Audio Units to do this, but I think the support for those is limited on the iPhone SDK.
You can do some processing during your AudioQueue playback callback, between AudioFileReadPackets() and AudioQueueEnqueueBuffer() but I think speed-shifting without changing the tone will require rather a lot of CPU time.
It'd probably be easier to have more than one recording of the music, and switch files during a silent passage of the music.