I have developed an app that plays audio files with some voices recordings. When I debug it I have no problems with it, when I download it from the AppStore it works perfectly, my friends use it and they haven't got any problem with the app, but a few people from all over the world have contacted me to tell me that the app doesn't sound.
It is very strange because they tell me that the sound of the bell (mp3 44100Hz, mono, 128kbps) that plays first sounds but the voices (mp3 44100Hz, stereo, 96kbps) don't sound. The people that contact with me has different devices models and different versions of iOS 6.
I use AVAudioPlayer to play the files and I think that it work well.
Have you experienced the same problem?
Thank you
UPDATE
This is the Localizable.strings that I have
I load the file like this:
//
NSString *fileLang = NSLocalizedString(aItem.fileName, nil);
//more code ...
thePlayerURL = [[NSBundle mainBundle] URLForResource:fileLang withExtension:#"mp3"];
//more code ...
AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL: aItem.urlAudio error:&error];
player.delegate = self;
[player prepareToPlay];
This is an example of the Localizable.strings with the file keys and values, by default the name of the key is the spanish version of the file:
//AUDIO NAMES
"1_au_es" = "1_au_en";
"2_au_es" = "2_au_en";
"3_au_es" = "3_au_en";
"4_au_es" = "4_au_en";
"5_au_es" = "5_au_en";
"6_au_es" = "6_au_en";
"7_au_es" = "7_au_en";
"8_au_es" = "8_au_en";
"9_au_es" = "9_au_en";
"10_au_es" = "10_au_en";
"11_au_es" = "11_au_en";
"12_au_es" = "12_au_en";
"13_au_es" = "13_au_en";
"14_au_es" = "14_au_en";
"15_au_es" = "15_au_en";
"16_au_es" = "16_au_en";
"17_au_es" = "17_au_en";
"18_au_es" = "18_au_en";
"19_au_es" = "19_au_en";
Have you ensured that their vibrate button isn't flipped on? I wrote a translate app that had the users simply mute/put the vibrate button flipped on. It seems simple, but I've gotten almost 15 emails for that alone, saying the app had no audio.
It seems simple, but that solution is the easiest and quickest fix. Vibrate mode, turns off all audio, even for the apps.
My translate App used AVAudioPlayer, and there was nothing programmatically wrong. Just simply user error.
Maybe the audio bitrate could be the problem? I really don't know...
The bell, than works well has 128kbps and the audio files have 96kbps and sometimes don't work. The strange thing is that the audio works very well for the 90% of the uses but sometimes fail. The bell instead work well the 100% times.
:/
Is very difficult to find the precise solution to this problem without checking your Xcode project configuration. However, by the information that you mentioned in the comments, I suspect that the problem must be related with the Localization strings. Check your localization configuration, check that you are using the localization strings files correctly, check that you wrote a valid filename for each supported localization.
Also, checking your code:
NSString *fileLang = NSLocalizedString(aItem.fileName, nil);
//more code ...
thePlayerURL = [[NSBundle mainBundle] URLForResource:fileLang withExtension:#"mp3"];
//more code ...
AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL: aItem.urlAudio error:&error];
player.delegate = self;
[player prepareToPlay];
Why you are not using "thePlayerURL"?. Maybe that is the problem, since is the "Localized URL". I would expect:
NSString *fileLang = NSLocalizedString(aItem.fileName, nil);
//more code ...
thePlayerURL = [[NSBundle mainBundle] URLForResource:fileLang withExtension:#"mp3"];
//more code ...
AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:thePlayerURL error:&error];
player.delegate = self;
[player prepareToPlay];
I recently submitted an application that was having the same problems, but it was denied due to the fact that I hadn't setup "Inter-App Audio" in Xcode and in the Certificates pane under the app info. That may help.
In case you are wondering, the application was in violation of Section 2.13 of the App Store Guidelines.
Related
I managed to load an audio file onto a player and play it via the following method:
- (void) play:(NSString*)loop{
NSString* resourcePath = [[NSBundle mainBundle] pathForResource:loop
ofType:#"mp3"];
player = [[AVAudioPlayer alloc] initWithContentsOfURL:
[NSURL fileURLWithPath:resourcePath]];
player.delegate = self;
[player play];
player.numberOfLoops = 1;
player.currentTime = 0;
player.volume = 1.0;
}
}
(I removed a couple of lines in this post but the method itself works great)
The problem here is, that the sound only gets loaded when the method play() is being called which results in a little delay in between the button click that calls the method and the player actually playing it.
I have about 200 sounds in my app and one way would be to load each sound in its own AVAudioPLayer in the viewDidLoad, but I doubt that this is considered good code.
On Android, I am using the SoundPool for this concern and it works great but I don't think there is an equivalent for this on iOS.
I now managed to do it via AudioServicesPlaySystemSound()
I use a method that loads all the sounds in a giant array
- (void)prepSounds{
NSString *soundPath =
[[NSBundle mainBundle] pathForResource:#"bl3"
ofType:#"mp3"];
NSURL *soundPathURL = [NSURL fileURLWithPath:soundPath];
AudioServicesCreateSystemSoundID(
(__bridge CFURLRef)soundPathURL, &soundID[0]);
AudioServicesPlaySystemSound(soundID[0]);
}
where soundID[] is an array of SystemSoundID declared in the header.
Now, I can just easily fire the sound via AudioServicesPlaySystemSound(soundID[0]) where 0 relates to the first sound I loaded. The latency is close to 0 (I would guess 5ms)
However, this only works for sounds no longer than about 30 seconds.
If you need any assistance with that, just comment here, I'm glad to help.
The app must to play a sound when it is in background. In the capabilities background fetch and audio & airplay are checked.
The method called for play the sound is that
-(void)playSound
{
NSString* str = [[NSBundle mainBundle] pathForResource:#"alarm4" ofType:#"wav"];
NSURL* url = [NSURL fileURLWithPath:str];
NSError* erreur;
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&erreur];
if(!erreur)
{
[self.audioPlayer setVolume:1];
[self.audioPlayer setNumberOfLoops:-1];
[self.audioPlayer prepareToPlay];
[self.audioPlayer play];
}
else
NSLog(#"erreur de chargemnt %#", [erreur localizedDescription]);
}
Can you give me some advice, please?
My advice is: Don't even dream of such a thing. In general, you can't do it.
You can continue playing a sound as you go into the background, but you cannot spontaneously produce a sound out of the blue in an already backgrounded app. It would be terrible if this could happen, because the user would not know where the sound is coming from, the sound could mess up the user's music listening experience, etc.
You should ask yourself why you think you need to do such a thing in the first place. You probably don't need to.
(Some Apple apps can do it. For example, the Clock app produces a repeating alarm sound out of the blue, in the background. But you, as you have probably noticed by now, are not Apple.)
I have an app that uses AVAudioPlayer to play sound effects, music, etc. It works fine for just about every user (100,000+ users), but I've had several reports of sound not playing at all even though sound effects are working on other apps on the same device. The bug has gone away for some users after an app restart/device reboot, but for others it continues to persist. AVSpeechSynthesizer isn't working for these users either.
I haven't been able to reproduce the bug to see if the AVAudioPlayer is throwing an error, so I'm not sure if it is - but I don't see why it would be working fine for 99.9% of users and not this tiny subset.
Has anyone else run into something like this?
Here's the code I'm using to set up the player:
[[AVAudioSession sharedInstance] setCategory:#"AVAudioSessionCategoryAmbient" error:nil];
NSString *file = [filename stringByDeletingPathExtension];
NSString *extension = [filename pathExtension];
NSURL *soundFileURL = [[NSBundle mainBundle] URLForResource:file withExtension:extension];
self.soundPlayer1 = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:&error];
[self.soundPlayer1 prepareToPlay];
I use AVAudioPlayer for playing audio file and UISlider to show user current time. Firstly, it looked that everything is fine but I noticed that audio player returns wrong file duration. For example it returns me duration equals to 3.5sec but file durations is equal to 6 sec. in reality.
Do you know What can cause this problem?
Below you can see my code which return file duration:
- (NSTimeInterval)audioDurationAtURL:(NSURL *)url
{
NSError *error;
NSData *data = [NSData dataWithContentsOfURL:url];
_audioPlayer = [[AVAudioPlayer alloc] initWithData:data error:&error];
return _audioPlayer.duration;
}
To add a bit to TonyMkenu's answer, AVAsset is an alternative with the ability to give you a more accurate duration.
https://developer.apple.com/library/mac/documentation/AVFoundation/Reference/AVAsset_Class/Reference/Reference.html#//apple_ref/occ/instp/AVAsset/duration
If you specify providesPreciseDurationAndTiming = YES, then AVAsset will decode the file if needed to determine its duration with accuracy. If the decode time is too long for your use, you can disable it.
In my situation, I use the AVURLAsset subclass:
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:localURL options:[NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES], AVURLAssetPreferPreciseDurationAndTimingKey, nil]];
float t = CMTimeGetSeconds(asset.duration);
AVAudioPlayer appears to only returns the correct duration of a file when it is ready for play it, so try to check the length of the audio file after [_audioPlayer play];
Under certain compression formats, the audio player may change its estimate of the duration as it learns more and more about the song by playing (and hence decoding) more and more of it - https://stackoverflow.com/a/16265186
In my case, having added an audio file to a project then editing (making it longer or shorter) and then deleting and re-adding the file to the Xcode project was the problem.
Essentially the project is caching the old file. To debug this I renamed the audio file to something else, added the new audio file to the project after which the duration reported by the player was always correct, before and after calling play.
I have tried everything I can find to try and get my app to play an mp3. I have a few 2-3 second mp3s that play as sound effects that work, but I am trying to play a 15s mp3 without any luck.
NSError *error;
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[[NSBundle mainBundle] URLForResource: #"test" withExtension: #"mp3"] error:&error];
if (error) {
NSLog(#"Error creating audio player: %#", [error userInfo]);
} else {
if([audioPlayer play] == FALSE) {
NSLog(#"Fail %#", error);
}
}
NSTimer* myTimer = [NSTimer scheduledTimerWithTimeInterval: 15.0 target: self
selector: #selector(stopMusic) userInfo: nil repeats: NO];
I doubt the timer has anything to do with it but thought I would include it just in case. Basically my error checks are not getting triggered at all. It "should" be playing properly but no sound is coming out, and no errors are being displayed.
I have tried a few other things to try and get this working, and I have tried without the timer. I can't find a decent guide. I don't need a full blown media player, just some background music for an UIScreenViewController.
I have also tried the following code, which works good with short MP3s, not with the longer MP3 I want to play.
NSString *path = [[NSBundle mainBundle] pathForResource:#"bgmusic" ofType:#"mp3"];
NSURL *pathURL = [NSURL fileURLWithPath : path];
AudioServicesCreateSystemSoundID((__bridge CFURLRef)pathURL, &audioEffect);
AudioServicesPlaySystemSound(audioEffect);
Please help, I have spent hours trying to sort this. It seems apple re-jig their audio every time they release an OS.
I did a little testing for you: It turned out that music files aren't added to target by default in Xcode 5. Therefore URLForResource:error: likely returns nil.
Try removing the mp3 from your project. Then add it again and this time make shure you add it to your target:
The other thing is: It seems like you're defining the AVAudioPlayer inside a method. You normally set up a #property for your audio player because otherwise its life is limited to the method - and the music stops playing after you reach the end of the method.