Audio Normalize in xcode (iOS) - ios

I'm trying to build a music player for iPhone and iPad.
I've used AVFoundation for playback controls. But I'm trying to implement audio normalization as "Sound Check" in "Music" settings in my player, I couldn't find any helpful resource for the same. Any suggestion would be helpful.

Simple answer: This is not possible.
Expert answer: It is not possible with your chosen frameworks. You need to go down on the lower layer of Core Audio: Audio Units and AudioQueue. But here you will find C code and the need of some signal processing knowledge.
What you can easily do is to change the volume:
NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/audiofile.mp3", [[NSBundle mainBundle] resourcePath]]];
NSError *error = nil;
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
audioPlayer.volume = 0.5; // from 0.0 to 1.0
if(audioPlayer == nil)
NSLog([error description]);
else
[audioPlayer play];

Related

Play iOS built-in sounds with AVAudioPlayer

Is is possible to play built-in sounds with AVAudioPlayer, to get around the limitations of AudioServicesPlaySystemSound?
For example:
AudioServicesPlaySystemSound(1360);
vs.
AVAudioPlayer
NSURL* url = [[NSBundle mainBundle] URLForResource:#"???" withExtension:#"??"];
player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
[player play];
What would the path or code be (if possible)?

iOS Streaming mp3

I've been searching for a good tutorial for playing and streaming audio finally I found this which seems to offer an offline audio playing.
in the YMCAudioPlayer class I've commented loading a resource and provided NSURL* generated by a direct link instead like so.
- (void)initPlayer:(NSString*) audioFile fileExtension:(NSString*)fileExtension
{
//NSURL *audioFileLocationURL = [[NSBundle mainBundle] URLForResource:audioFile withExtension:fileExtension];
NSURL *audioFileLocationURL = [NSURL URLWithString:#"http://188.95.64.47/AghaninaDownload/Content/per_singer/JFire/Audios/J-FirE_and_Omar_khalid_wlaKelmeh-sample.mp3"];
NSError *error;
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioFileLocationURL error:&error];
}
And I've ensured that it's a valid link, but seems not to play on emulator. what have I missed there?
EDIT
It generates the following error
Error Domain=NSOSStatusErrorDomain Code=-43 "The operation couldn’t be completed. (OSStatus error -43.)
Might be a stupid question, but did you make it play ?
[self.audioPlayer play];
Then I would try this, to ensure your settings are correct :
[self.audioPlayer prepareToPlay];
[self.audioPlayer setCurrentTime:0.0];
[self.audioPlayer setVolume:1.0];
[self.audioPlayer play];
You can also use the delegate of AVAudioPlayer to check if something happens when you play.
Else it might be an URL of format issue.
I think you cannot play audio on EMULATOR, you have to test it on device.
Here mentioned on apple developer guid -
https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/iOS_Simulator_Guide/TestingontheiOSSimulator/TestingontheiOSSimulator.html#//apple_ref/doc/uid/TP40012848-CH4-SW1
I've found the answer in the accepted answer here
"I was able to fix the issue by loading the file first into an NSData element and then using that to initialize the AVAudioPlayer instead, like so:"
NSData *songFile = [[NSData alloc] initWithContentsOfURL:songCacheURL options:NSDataReadingMappedIfSafe error:&error1 ];
self.audioPlayer = [[AVAudioPlayer alloc] initWithData:songFile error:&error2];

Play audio after a Time Interval IOS7

Hi in my application, audio is playing when user press the button but now I have two audio buttons like audio1 and audio2, now I want to play second audio after a time interval once the audio1 is completed by clicking the same button.
- (IBAction)btn1:(id)sender {
NSString *audioPath = [[NSBundle mainBundle] pathForResource:#"audio" ofType:#"mp3" ];
NSURL *audioURL = [NSURL fileURLWithPath:audioPath];
NSError *error;
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:&error];
[self.audioPlayer play];
}
The above code I have used for play one audio now I want to play second audio once the first audio completed please tell me how to make it.
Thanks.
Try this:
You have to add a bool variable with the name 'firstAudioPlayed' on start the variable should be NO or FALSE.
- (IBAction)btn1:(id)sender {
if (![self.audioPlayer isPlaying]) {
NSString *audioPath;
if (self.firstAudioPlayed) {
audioPath = [[NSBundle mainBundle] pathForResource:#"audio2" ofType:#"mp3" ];
} else {
audioPath = [[NSBundle mainBundle] pathForResource:#"audio1" ofType:#"mp3" ];
}
NSURL *audioURL = [NSURL fileURLWithPath:audioPath];
NSError *error;
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:&error];
[self.audioPlayer play];
self.firstAudioPlayed = !self.firstAudioPlayed;
}
}
I'm not sure if it's working like this, else just ask with a comment...
Explication of the code:
First you check if the player is already playing a song, if he isn't, you check if the first audio already has played (self.firstAudioPlayed) with this you can give the correct path to load the audio file. Now you play this audio file.
(Sorry for my grammar and my english, corrections are welcome)
You probably should use player's delegate. Set audioPlayer.delegate=self; and implement audioPlayerDidFinishPlaying:successfully: method to see when a player finished playing.
Then you can do whatever you want in there, for example start the second audio.

Reduce / decrease background ipod sound in my App

I need to make an application in iOS who make different sound like "beep" during her fonctionnement.
I have implemented interaction to background ipod with MPMusicPlayerController.
The probleme:
I do not hear the "beep" due to the volume of music from ipod.
I need to reduce the volume of the ipod but NOT reduce the volume of my application.
The tomtom application make that when the speaker give information about the direction to take. But I do not know how.
I have try this code:
- (void)playSoundCountDown{
NSError *errorObject = nil;
[[AVAudioSession sharedInstance]setCategory:AVAudioSessionCategoryAmbient error:&errorObject];
if (errorObject) {
NSLog(#"Error setting category! %#",errorObject);
}
NSString *path = [[NSBundle mainBundle] pathForResource:#"countDownFiveToOne" ofType:#"caf"];
theSound = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:nil];
theSound.delegate = self;// (AVAudioPlayer *theSound;)
[theSound setVolume:0.4f];
[theSound play];
float volumeDecrease = 0.2f;
MPMusicPlayerController* iPodMusicPlayer = [MPMusicPlayerController iPodMusicPlayer];
[iPodMusicPlayer setVolume:volumeDecrease];
}
But "setVolume" reduce the volume of all sound of the device, included the sound of my app...
I need your help please.
Thanks.
Instead of decreasing the volume, try enabling ducking:
- (void)playSoundCountDown{
NSError *errorObject = nil;
[[AVAudioSession sharedInstance]
setCategory: AVAudioSessionCategoryAmbient
withOptions: AVAudioSessionCategoryOptionDuckOthers
error: nil];
NSString *path = [[NSBundle mainBundle] pathForResource:#"countDownFiveToOne" ofType:#"caf"];
theSound = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:nil];
theSound.delegate = self;
[theSound setVolume:0.4f];
[theSound play];
}

AVAudioPlayer initWithContentsOfURL returns nil for AAC/M4A files

I use the following code to play an audio file. It plays fine for MP3 files, but when I try to play an AAC file, the [[AVAudioPlayer alloc] initWithContentsOfURL:] returns nil and I get the following error:
Error Domain=NSOSStatusErrorDomain Code=1937337955 "The operation couldn’t be completed. (OSStatus error 1937337955.)"
The audio file plays fine on Mac and iPhone (when I email it to myself) and is here: https://dl.dropboxusercontent.com/u/2667666/song.aac
NSError *setCategoryError = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&setCategoryError];
// Create audio player with background music
NSString *backgroundMusicPath = [[NSBundle mainBundle] pathForResource:#"song" ofType:#"aac"];
NSURL *backgroundMusicURL = [NSURL fileURLWithPath:backgroundMusicPath];
NSError *error;
_backgroundMusicPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:backgroundMusicURL error:&error];
if (!_backgroundMusicPlayer) {
NSLog(#"_backgroundMusicPlayer pointer is null!!");
}
[_backgroundMusicPlayer setDelegate:self]; // We need this so we can restart after interruptions
[_backgroundMusicPlayer prepareToPlay];
[_backgroundMusicPlayer play];
Update: If I change the extension of the file from aac to m4a, the error code change to 1954115647 (whose four letter code is "tip?"). The four letter code for the error code that I get with the arc extension is "sync".
Initializing the audio player with initWithData:error: solves this.
For example:
NSData* data = [NSData dataWithContentsOfURL:url] ;
AVAudioPlayer* audioPlayer = [[AVAudioPlayer alloc] initWithData:data error:outError];
Disappointing that apple initializes their audio player based on extension, instead of looking at the binary data and trying to figure out which type of data they received.
Found the solution!
Turns out that if I simply use AVPlayer instead of AVAudioPlayer and if I use .acc as the extension of the file, then it plays just fine. now I can play both aac and mp3 files.
.aac file can be played,try to check whether the file exists?
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: backgroundMusicPath ] == YES)
{
NSLog(#"find file");
}

Resources