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];
Related
I am building up a APP on iOS by AudioKit(version 4.5.3), and I find out the AKTimePitch class does not work for me, here is my code(objective-c xcode 10):
(IBAction)startButton:(id)sender {
NSURL *url = [[NSBundle mainBundle] URLForResource:#"burncalory" withExtension:#"m4a"];
AKAudioFile *file = [[AKAudioFile alloc] initForReading:url error:nil];
AKAudioPlayer *player = [[AKAudioPlayer alloc] initWithFile:file looping:NO lazyBuffering:YES error:nil completionHandler:^{
NSLog(#"Finished!");
}];
AKTimePitch *akTimePitch = [[AKTimePitch alloc] init:player rate:2.0 pitch:1600 overlap:8];
AudioKit.output = akTimePitch;
[akTimePitch start];
[AudioKit startAndReturnError:nil];
[player playFrom:0.0];
}
I check out the playground(4.5.3), and the sample of "Time Stretching and Pitch Shifting" works well.
Is there something wrong in my code to use AKTimePitch or something wrong with my audio file example.m4a? By the way, this audio file can be loaded and play well by AKAudioPlayer.
After some testing I found that the parameter in the init method does not work, but after I add akTimePitch.pitch=1600 before [player playFrom:0.0], then the AKTimePitch effects works!! I don't know why the AKTimePitch *akTimePitch = [[AKTimePitch alloc] init:player rate:2.0 pitch:1600 overlap:8]; just does not work...
I am using an AVAudioPlayer to play audio in my app, and it worked for a while. Suddenly, it just stopped working and I cannot figure out why. I created the AVAudioPlayer at the class level in the .h file. This is the code I use to init the player
-(void)initAudio
{
NSURL *song = [[NSBundle mainBundle] URLForResource:#"Prelude" withExtension:#"m4a"];
NSError *error = nil;
_audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:song error:&error];
[_audioPlayer prepareToPlay];
}
I call this method in the initWithSize function. error is nil, and I have verified that the player object contains the actual audio file. The audio file plays back fine in my OS environment and I have tried adding it to the build phase compile sources just to be safe, even though beforehand it worked fine without it explicitly there. When I trigger the play event, it will play the first snippet of the audio and then nothing. I log the current time of the player and it is 0. Everything else about the app is continuing on and functions without issue. I do not interfere with the avaudioplayer object in any way except to play/pause/preparetoplay.
I am completely stumped as it worked fine and then suddenly no longer works. I have tried to clean the project, I have even dumped the derivedData.
Any ideas?
I think your player has an error when you try to play the song.
You need to check the error first.
In my opinion, it seems like OSStatus error -43.
When you update an app, file path can be changed.
For example,
old path : /var/mobile/Applications/F28E0C2C-4AE2-4C9D-906F-414AE1669D90/Documents/AAA.mp3
new path: var/mobile/Applications/6086783B-A410-42C3-9BAE-7BA755D0E528/Documents/AAA.mp3
Try this code instead:
NSError *error;
NSURL *song = [[NSBundle mainBundle] URLForResource:#"Prelude" withExtension:#"m4a"];
_audioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:song error:&error];
if(error){
NSLog(#"[error localizedDescription] %#", [error localizedDescription]);
NSString *fileName = [[song absoluteString] lastPathComponent]; //this code is just example. get your fileName like "AAA.m4a"
NSString *docDirPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/%#", docDirPath , fileName];
_audioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL URLWithString:filePath] error:&error];
}
_audioPlayer.delegate = self;
[_audioPlayer prepareToPlay];
[_audioPlayer play];
}
I hope this will help you.
Cheers
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];
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");
}
I can't play mp3 audio file.
URL_PATH = #"http://...../.…./A1.mp3";
NSError *error;
player = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL URLWithString:URL_PATH] error:&error];
if (error)
{
NSLog(#"error:%#",error.localizedDescription);
}
if (player ==nil)
{
NSLog(#"nil");
}
else
{
NSLog(#"playing");
[player play];
}
error code :
error:The operation couldn’t be completed. (OSStatus error -43.)
nil
How can I do?
Please tell me hint. pre-Thanks!
You are using the wrong player to play audio captured from a network stream. See Apple's documentation on AVAudioPlayer:
Apple recommends that you use this class for audio playback unless you
are playing audio captured from a network stream or require very low
I/O latency. For an overview of audio technologies, see Audio & Video
Starting Point and “Using Audio” in Multimedia Programming Guide.
One work around way to use AVAudioPlayer is to fetch the audio's data and put it in a NSData. Then you can init your AVAudioPlayer by initWithData:error:. Also, don't put the code in your main queue. Else it will block your user interface from reacting to user's input.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURL *mp3URL = [NSURL URLWithString:#"http://zhangmenshiting.baidu.com/data2/music/44799433/4479927746800128.mp3?xcode=dbff90a141d5d136fdc7275fdc3fae126077a44adc974ad8"];
NSData *data = [NSData dataWithContentsOfURL:mp3URL];
self.audioPlayer = [[AVAudioPlayer alloc] initWithData:data error:NULL];
[self.audioPlayer play];
});
sunkehappy is right, AVAudioPlayer isn't meant for streaming audio. It is meant for playing audio files and for data that is already in memory. That's why you need to init it with the data and not with the URL.
Here's the apple answer (which you can find here http://developer.apple.com/library/ios/#qa/qa1634/_index.html ):
The AVAudioPlayer class does not provide support for streaming audio
based on HTTP URL's. The URL used with initWithContentsOfURL: must be
a File URL (file://). That is, a local path.
If you look for an audio streamer, you can test that audio streamer.