iOS - how to play sound file using avfoundation - ios

I want to play a sound file (which I have dragged into xcode and copy to the project) using av foundation with the following code but fail.
I think NSURL *url = [[NSURL alloc] initWithString:#"sound.caf"]; this is where it goes wrong, but I have no idea other than this way, how I could instantiate an AVAsset with this the sound file (of course, it would be other place that goes wrong). Anyway, can someone offer me some helps? thanks
AVMutableComposition *composition = [AVMutableComposition composition];
CMPersistentTrackID trackID = kCMPersistentTrackID_Invalid;
AVMutableCompositionTrack *compositionTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:trackID];
NSURL *url = [[NSURL alloc] initWithString:#"sound.caf"];
AVAsset *songAsset = [AVURLAsset URLAssetWithURL:url options:nil];
AVAssetTrack *assetTrack = [[songAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
CMTime startTime = CMTimeMakeWithSeconds(0, 1);
CMTime endTime = songAsset.duration;
CMTimeRange tRange = CMTimeRangeMake(startTime, endTime);
NSError *error = nil;
[compositionTrack insertTimeRange:tRange ofTrack:assetTrack atTime:CMTimeMake(0, 44100) error:&error];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:composition];
self.player = [[AVPlayer alloc] initWithPlayerItem:playerItem];
[self.player play];

This code should help you:
NSString *soundPath = [[NSBundle mainBundle] pathForResource:#"myfile" ofType:#"wav"];
NSURL *soundURL = [NSURL fileURLWithPath:soundPath];
NSError *error = nil;
AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundURL error:&error];
if (error) {
NSLog(#"%#",[error localizedDescription]);
}
[player play];

Try this
NSString *shutterplayerPath =
[[NSBundle mainBundle] pathForResource:#"shutter" ofType:#"mp3"];
NSString *tickplayerPath =
[[NSBundle mainBundle] pathForResource:#"tick" ofType:#"wav"];
shutterAudioPlayer =
[[AVAudioPlayer alloc] initWithContentsOfURL:[[NSURL alloc]
initFileURLWithPath: shutterplayerPath] error:NULL];
tickAudioPlayer =
[[AVAudioPlayer alloc] initWithContentsOfURL:[[NSURL alloc];
initFileURLWithPath:tickplayerPath] error:NULL];
[shutterAudioPlayer play];
[tickAudioPlayer play];

Related

iPod touch not Playing sound

All device is playing the sound in foreground except iPod touch not playing the sound in foreground, When the app receive notification,
Below we have paste the exact code
NSString *playSoundOnAlert = #"Sound.wav";
NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/%#",[[NSBundle mainBundle] resourcePath],playSoundOnAlert]];
NSError *error;
aVAudioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
aVAudioPlayer.numberOfLoops = 0;
[aVAudioPlayer play];
check the code:
NSString *playSoundOnAlert = #"Sound";
AVAudioPlayer *audioPlayer;
NSString *audioPath = [[NSBundle mainBundle] pathForResource: playSoundOnAlert ofType:#".wav"];
NSURL *audioURL = [NSURL fileURLWithPath:audioPath];
NSError *audioError = [[NSError alloc] init];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:&audioError];
if (!audioError) {
[audioPlayer play];
NSLog(#"playing!");
}
else {
NSLog(#"Error!");
}

tracksWithMediaType returns 0 tracks sometimes

In my app I combine several .m4a audio files. For combining audio files I use below code.
CMTime nextClipStartTime = kCMTimeZero;
AVMutableComposition *composition = [[AVMutableComposition alloc] init];
AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
for(NSString * str in filesNamesArray)
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:str];
NSURL *url = [[NSURL alloc] initFileURLWithPath:path];
AVAsset *avAsset = [[AVURLAsset alloc] initWithURL:url options:nil];
NSArray *tracks = [avAsset tracksWithMediaType:AVMediaTypeAudio];
if ([tracks count] == 0)
{
NSLog(#"Tracks = %lu",(unsigned long)[tracks count]);
return;
}
NSLog(#"%#",avAsset);
CMTimeRange timeRangeInAsset = CMTimeRangeMake(kCMTimeZero, [avAsset duration]);
AVAssetTrack *clipAudioTrack = [[avAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
ok = [compositionAudioTrack insertTimeRange:timeRangeInAsset ofTrack:clipAudioTrack atTime:nextClipStartTime error:&error];
if (!ok) {
NSLog(#"Current Video Track Error: %#",error);
}
nextClipStartTime = CMTimeAdd(nextClipStartTime, timeRangeInAsset.duration);
}
Sometimes 'tracksWithMediaType' returns empty array. Why is this happening and any help would be greatly appreciated.
When you create AVAsset with:
AVAsset *avAsset = [[AVURLAsset alloc] initWithURL:url options:nil];
asset must have loaded its tracks before ready for use:
[avAsset loadValuesAsynchronouslyForKeys:#"tracks" completionHandler: ^{
AVKeyValueStatus status = [avAsset statusOfValueForKey:#"tracks" error:nil];
if (status == AVKeyValueStatusLoaded) {
// Asset is ready now
}
}];

Memory Increases When Merging and Playing Audio

I'm trying to merge multiple pieces of audio into one simultaneous sound and then play it. I can merge and play, but my app's memory usage keeps increasing over time.
Looking online, it seems like there's ARC/memory issues with AVPlayer.
I've added all relevant code below for setting up the files, merging them and then playing them.
Setting up sound files
- (void) setUpSoundFiles {
AVURLAsset *songAsset = nil;
AVAssetTrack *sourceAudioTrack = nil;
for (int i = 0; i < numberOfSoundsToMerge; i++){
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:[#(i) stringValue] ofType:#"mp3"]];
songAsset = [AVURLAsset URLAssetWithURL:url options:nil];
sourceAudioTrack = [[songAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
[songTracks insertObject:sourceAudioTrack atIndex:i];
[songAssets insertObject:[AVURLAsset URLAssetWithURL:url options:nil] atIndex:i];
//[sourceAudioTrack.asset cancelLoading];
}
}
Merging Sound Files
- (void) mergeAudio: (AVMutableComposition *)composition{
for(int i = 0; i < numberOfSoundsToMerge; i++) {
AVMutableCompositionTrack *track = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
NSError *error = nil;
BOOL ok = NO;
CMTime startTime = CMTimeMakeWithSeconds(0, 1);
CMTime trackDuration = ((AVURLAsset *)[songAssets objectAtIndex:i]).duration;
CMTimeRange tRange = CMTimeRangeMake(startTime, trackDuration);
//Set Volume
AVMutableAudioMixInputParameters *trackMix = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:track];
[trackMix setVolume:0.8f atTime:startTime];
[audioMixParams addObject:trackMix];
//Insert audio into track
ok = [track insertTimeRange:tRange ofTrack:(AVAssetTrack *)[songTracks objectAtIndex:i] atTime:CMTimeMake(0, 1) error:&error];
[((AVAssetTrack *)[songTracks objectAtIndex:i]).asset cancelLoading];
}
}
Playing Sound Files
- (void) playSounds {
AVMutableComposition *composition = [AVMutableComposition composition];
audioMixParams = [[NSMutableArray alloc] initWithObjects:nil];
[self mergeAudio:composition];
AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix];
audioMix.inputParameters = [NSArray arrayWithArray:audioMixParams];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:composition];
AVPlayer *player = [[AVPlayer alloc] initWithPlayerItem:playerItem];
[playerItem setAudioMix:audioMix];
[player play]; }

+ exportSessionWithAsset:presetName: returning nil on iOS7

I'm using the following code:
- (AVAssetExportSession *)testRecording
{
AVMutableComposition *composition = [[AVMutableComposition alloc] init];
NSURL *url = [[NSBundle mainBundle] URLForResource:kTestSongName withExtension:#"mp3"];
AVAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil];
CMTimeRange range = CMTimeRangeMake(CMTimeMake(0, 600), asset.duration);
NSError *editError;
BOOL result = [composition insertTimeRange:range ofAsset:asset atTime:kCMTimeZero error:&editError];
if (!result) {
NSLog(#"Error inserting timerange");
}
AVAssetExportSession *exportSession = [AVAssetExportSession
exportSessionWithAsset:composition
presetName:AVAssetExportPresetAppleM4A];
return exportSession;
}
This does what it's supposed to on iOS8 but on iOS7 exportSession is always nil at the end of the method. I tried using assets with different formats (mp3, caf) but the result was the same.
If I play the composition instead of exporting it the sound is fine:
AVPlayerItem * item = [[AVPlayerItem alloc] initWithAsset:composition];
AVPlayer * player = [AVPlayer playerWithPlayerItem:item];
[player play];
Any idea about what might be wrong?
exportSession = [[AVAssetExportSession alloc]
initWithAsset:songAsset
presetName:AVAssetExportPresetAppleM4A];
exportSession.outputFileType = #"com.apple.m4a-audio";
filePath = [[docDir stringByAppendingPathComponent:fileName] stringByAppendingPathExtension:#"m4a.mov"]
exportSession.outputURL = [NSURL fileURLWithPath:filePath];
[exportSession exportAsynchronouslyWithCompletionHandler:^{
if (exportSession.status == AVAssetExportSessionStatusCompleted) {
NSString *newPath = [NSString stringWithFormat:#"%#/%#", documentDirectory, [[[filePath lastPathComponent] substringToIndex:[[filePath lastPathComponent] length]-5] stringByAppendingString:#"a"]];
[[NSFileManager defaultManager] removeItemAtPath:newPath error:nil];
NSError *error = nil;
[[NSFileManager defaultManager] moveItemAtPath:filePath toPath:newPath error:&error];
}
if (exportSession.status == AVAssetExportSessionStatusCancelled) {
}
if (exportSession.status == AVAssetExportSessionStatusExporting) {
}
if (exportSession.status == AVAssetExportSessionStatusFailed) {
NSLog(#"erros:%#",exportSession.error);
}
if (exportSession.status == AVAssetExportSessionStatusUnknown) {
}
if (exportSession.status == AVAssetExportSessionStatusWaiting) {
}
}];
If you want to save in mp3 format, use ffmpeg.

Click on Multiple UIButton how to Play multiple sound at same time duration?

I am new in Objective-C. Please help me for this.
I have one viewController which contains scrollview.
scrollView are paging enabled so i have 10 pages on each page i have 30 buttons .
My problem is when click on multiple button i want to play multiple sound..
My code : -
-(void)buttonClicked:(UIButton *)sender{
if (sender.tag == 1) {
NSString *audioPath = [[NSBundle mainBundle]pathForResource:#"v1" ofType:#"mp3"];
NSURL *url = [NSURL fileURLWithPath:audioPath];
audioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:nil];
audioPlayer.delegate = self;
[audioPlayer play];
}
if (sender.tag == 2) {
NSString *audioPath = [[NSBundle mainBundle]pathForResource:#"v2" ofType:#"mp3"];
NSURL *url = [NSURL fileURLWithPath:audioPath];
audioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:nil];
audioPlayer.delegate = self;
[audioPlayer play];
}
if (sender.tag == 3) {
NSString *audioPath = [[NSBundle mainBundle]pathForResource:#"v3" ofType:#"mp3"];
NSURL *url = [NSURL fileURLWithPath:audioPath];
audioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:nil];
audioPlayer.delegate = self;
[audioPlayer play];
}
problem is when i pressed on buttons only one sound is enable. how to enable multiple sounds ??
please help me...
thanks in advance
First import #import <AudioToolbox/AudioServices.h>
NSString *path = [[NSBundle mainBundle] pathForResource:#"soundeffect" ofType:#"m4a"];
NSURL *pathURL = [NSURL fileURLWithPath : path];
SystemSoundID audioEffect;
AudioServicesCreateSystemSoundID((CFURLRef) pathURL, &audioEffect);
AudioServicesPlaySystemSound(audioEffect);
In each UIButton you need change the path with the sound that you need play.
Hope this help :)

Resources