How to play audio received in didOutputSampleBuffer:? - iphone

I am working on conference related application, i have first capture audio with CaptureSession, now I want to play the audio data dynamically without saving into file. I have tried with AVQueue it seems both CaptureSession and AVQueue won't work together when I starts queue it stops capture, so What can I do now to play audio captured through CaptureSession?
thanks for your helps

You will need to convert your audioData into NSData:
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer: (CMSampleBufferRef)sampleBuffer
fromConnection:(AVCaptureConnection *)connection {
NSData *audioData = yourFunction here to convert//[self audioFromSampleBuffer:sampleBuffer];
dispatch_async(dispatch_get_main_queue(), ^{
NSError *e;
AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithData:data error:&e];
NSLog(#"%#",[e description]);
[player setDelegate:self];
[player play];
}
}
EDIT : refer Recording_Audio_on_an_iPhone_with_AVAudioRecorder link.

I have fixed the problem using AudioUnit method, Note: when we process audio data captured in AVCapturesession using AudioUnit, we need to ensure AudioUnit is not trying to access capture devices (Mic in my case), that is the reason it stopped capture call back.

Related

Play audio when iPhone is muted [duplicate]

This question already has answers here:
iPhone - Is it possible to override silent mode or have a recursive alert sound with push notification? [closed]
(3 answers)
Closed 4 years ago.
I want to make an application which creates sound, music, or system sound when an iPhone is in silent mode. Is it possible to play any type of sound whether music or system tones when it is silent mode?
It's not advisable, but who am I to say you can't do it. You may have a good reason to be playing sound.
If you are using Audio Sessions, then include <AVFoundation/AVFoundation.h> at the start of your file and
[[AVAudioSession sharedInstance]
setCategory: AVAudioSessionCategoryPlayback
error: nil];
should do the trick. Note if you play music or sounds, then iPod playback will be paused.
Once this has been done, probably somewhere in the initialization of one of your classes that plays the sounds, you can instantiate sounds like this:
// probably an instance variable: AVAudioPlayer *player;
NSString *path = [[NSBundle mainBundle] pathForResource...];
NSURL *url = [NSURL fileURLWithPath:path];
player = [[AVAudioPlayer alloc] initWithContentsOfURL:url];
When that's done, you can play with it any time you want with:
[player play]; // Play the sound
[player pause]; // Pause the sound halfway through playing
player.currentTime += 10 // skip forward 10 seconds
player.duration // Get the duration
And other nice stuff. Look up the AVAudioPlayer Class reference.
And for Swift 2, 3, 4.2
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)
} catch {
print(error)
}
Yes you can play sound when the phone is set to vibrate.
Simply use the AVAudioPlayer class.
By default, playing an Audio Session
sound will ~not~ respect the setting
of the mute switch on the iPhone. In
other words, if you make a call to
play a sound and the silent (hardware)
switch on the iPhone is set to silent,
you’ll still hear the sound.
This is what you want. So now you know that playing an Audio Session when your phone is in silent mode will still play the sound you just need to know how to create an audio session to play the sound, like so:
taken from this website: http://iosdevelopertips.com/audio/playing-short-sounds-audio-session-services.html
SystemSoundID soundID;
NSString *path = [[NSBundle mainBundle]
pathForResource:#"RapidFire" ofType:#"wav"];
AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:path],&soundID);
AudioServicesPlaySystemSound (soundID);
For this to work, you will need to import header file, and also add the AudioToolbox.framework to your project.
And that's it.
So from this answer you now know that you can play sound while the phone is on vibrate.
You don't need extra or special code to allow you to do this functionality as it already does that by default.
Pk
Works on iOS 6 and above
NSError *setCategoryErr = nil;
NSError *activationErr = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&setCategoryErr];
[[AVAudioSession sharedInstance] setActive:YES error:&activationErr];
Just put this in your viewDidLoad:
UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
AudioSessionSetProperty (kAudioSessionProperty_AudioCategory,
sizeof(sessionCategory), &sessionCategory);
For playing a sound in silent mode and even when it goes to background, try this:
Put this code in application:didFinishLaunchingWithOpitons:
[[AVAudioSession sharedInstance] setDelegate:self];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive:YES error:nil];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
and this code in applicationDidEnterBackground:
[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
Also setup a background mode of Playing Audio/Air Play and include AVFoundation header.
for Objective C, you could play system sound with following code:
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
*The system path could be modified.*
NSString *path = #"/System/Library/Audio/UISounds/begin_record.caf";
NSURL *url = [NSURL fileURLWithPath:path];
player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[player play];
Swift - Call this function before playing your audio/video to force playback when the phone is on silent. This also silences other audio that is currently playing.
You can change .duckOthers to .mixWithOthers if you don't want to silence other audio.
func setupAudio() {
let audioSession = AVAudioSession.sharedInstance()
_ = try? audioSession.setCategory(AVAudioSessionCategoryPlayback, with: .duckOthers)
_ = try? audioSession.setActive(true)
}

How to easily play back to back .m4a files programmatically on an iOS iPhone app

How can I play more than one .m4a file consecutively?
Presently, my function starts playing one, using AudioServicesPlaySystemSound etc., uses AudioServicesAddSystemSoundCompletion to select a callback, and then returns. When the sound is done, the callback lets my software continue.
This is a LOT of coding whenever there is back to back sound.
Can my software start a .m4a playing, and SOMEHOW wait for it to complete, waiting waiting for its callback to set a flag? Can I use pthread software to do a wait loop with a multitasking pause?
Here's my code so far...
// Restore game_state to continue game after playing sound file.
int game_state_after_sound;
void play_sound_file_done (
SystemSoundID ssID,
void calling_class
)
{
printf("\n play_sound_file_done.");
// Sound is now done, so restore game_state and continue to manage_game from where left off:
game_state = game_state_after_sound;
[ (GeController)calling_class manage_game];
}
// Plays sound_file_m4a and returns after playing has completed.
-(void) play_sound_file: (NSString *) sound_file_m4a
{
printf("\n play_sound_file '%s' ", [sound_file_m4a UTF8String] );
NSString *soundPath = [[NSBundle mainBundle] pathForResource:sound_file_m4a ofType:#"m4a"];
SystemSoundID soundID;
AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath: soundPath], &soundID);
AudioServicesPlaySystemSound (soundID);
AudioServicesAddSystemSoundCompletion ( soundID, NULL, NULL, play_sound_file_done, (void*)self );
game_state_after_sound = game_state;
game_state = DELAY_WHILE_PLAYING_SOUND;
}
********************************** AVPlayer work-in-progress...
But this produces no sound.
#import <AVFoundation/AVFfoundation.h>
-(void) play_queued_sounds: (NSString *) sound_file_m4a
{
printf("\n queue_sound_file: '%s' ", [sound_file_m4a UTF8String] );
AVPlayerItem *sound_file = [[AVPlayerItem alloc] initWithURL:[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:sound_file_m4a ofType:#"m4a"]]];
AVQueuePlayer *player = [AVQueuePlayer queuePlayerWithItems:[NSArray arrayWithObjects:sound_file, nil]];
[player play];
return;
}
This can be achieved quite easily in AVQueuePlayer. You don't have to handle completion or anything, you just give it the AVPlayerItems that you want to play in sequence and call play. Here's an example:
#import <AVFoundation/AVFfoundation.h>
//AVPlayerItem *item1 = [[AVPlayerItem alloc] initWithURL:[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:#"myFileName" ofType:#"m4a"]]];
EDIT: Use this instead
AVPlayerItem *item1 = [[AVPlayerItem alloc] initWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:[[NSString alloc] initWithFormat:#"2"] ofType:#"mp3"]]];
AVQueuePlayer *player = [AVQueuePlayer queuePlayerWithItems:[NSArray arrayWithObjects:item1, nil]];
[player play];
Just as an addition, this can also be achieved with items from the users iPod library using a MPMusicPlayerController queued from the didPickMediaItems delegate method of MPMediaPickerController
- (void)mediaPicker:(MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection
{
MPMusicPlayerController *player = [MPMusicPlayerController applicationMusicPlayer];
[player setQueueWithItemCollection:mediaItemCollection];
[player play];
}
I could not get the AVQueuePlayer solution to work.
GREAT SOLUTION:
For each sound to play, spin up a thread that awaits then locks a mutex, then does AudioServicesPlaySystemSound. Just spin up a thread for each successive sound to play, and use the pthread mutex to delay each successive thread until the AudioServicesAddSystemSoundCompletion function unlocks the mutex. Works like a champ.
This is 21st century embedded programming: Throw threads at the problem!

MPMoviePlayerController playing YouTube video

How can I play a YouTube video in an MPMoviePlayerController on the iPhone while avoiding going into fullscreen mode?
This question has been raised here: MPMoviePlayerController is playing YouTube video? and here: Play Youtube video in MPMoviePlayerController or play RTSP - 3GP link with answers claiming such functionality was impossible.
Yet this app, Deja, has exactly the functionality I would like: a seamless MPMoviePlayerController whose frame I have explicit control over. http://itunes.apple.com/app/deja/id417625158
How is this done!?
add this sample into you project
instantiate YoutubeStreamPathExtractorTest
invoke test method of YoutubeStreamPathExtractorTest instance.
Follow logs and be happy
#import "AFHTTPRequestOperationManager.h"
#import <MediaPlayer/MediaPlayer.h>
typedef void (^CallbackBlock)(NSArray* result, NSError* error);
static NSString* const kYouTubeStreamPathPattern = #"\\\"url_encoded_fmt_stream_map\\\\\":.*?url=(.*?)\\\\u0026";
#interface YoutubeStreamPathExtractorTest : NSObject
- (void)test;
- (void)youtubeURLPath:(NSString*)youtubeURLPath extractStreamURLPathsWithCallback:(CallbackBlock)callback;
#end
#implementation YoutubeStreamPathExtractorTest
- (void) test {
NSString* path = #"http://www.youtube.com/watch?v=TEV5DZpAXSw";
[self youtubeURLPath:path extractStreamURLPathsWithCallback:^(NSArray *result, NSError *error) {
if (error){
NSLog(#"extracting error:%#",[error localizedDescription]);
}
for(NSString* streamURLPath in result) {
NSLog(#"streamURLPath:%#",streamURLPath);
/*
NSURL* url = [NSURL URLWithString:streamURLPath];
MPMoviePlayerController* mpMoviePlayerController_ = [[MPMoviePlayerController alloc] initWithContentURL:url];
mpMoviePlayerController_.controlStyle = MPMovieControlStyleDefault;
[mpMoviePlayerController_ play];
*/
}
}];
}
- (void)youtubeURLPath:(NSString*)youtubeURLPath extractStreamURLPathsWithCallback:(CallbackBlock)callback {
__block NSMutableArray* resultArray = [NSMutableArray new];
AFHTTPRequestOperationManager* manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:nil];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:#"text/html", nil];
[manager GET:youtubeURLPath
parameters:nil
success:^(AFHTTPRequestOperation* operation, id responseObject) {
NSData* data = (NSData*)responseObject;
NSString* string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSError* error = nil;
NSRegularExpression* expression = [NSRegularExpression regularExpressionWithPattern:kYouTubeStreamPathPattern
options:NSRegularExpressionCaseInsensitive
error:&error];
NSRange range = NSMakeRange(0,[string length]);
NSArray* matches = [expression matchesInString:string options:0 range:range];
for(NSTextCheckingResult* checkingResult in matches) {
if ([checkingResult numberOfRanges]>1){
NSString* resultStr = [string substringWithRange:[checkingResult rangeAtIndex:1]];
//remove extra slashes
[resultArray addObject:[resultStr stringByReplacingOccurrencesOfString:#"\\" withString:#""]];
}
}
if (callback) {
callback(resultArray,error);
}
} failure:^(AFHTTPRequestOperation* operation, NSError* error) {
if (callback) {
callback(resultArray, error);
}
}];
}
#end
MPMoviePlayerController does not support the playback of YouTube SWF (Flash) video, period.
That app you are mentioning actually plays progressively downloaded files in MP4 format which YouTube also offers for some of its content. This actually is a violation of Apple's guidelines as it will (and does) exceed the maximum amount of progressive download per app per timeframe. I am surprised it got through the iTunes approval.
Warning: iOS apps submitted for distribution in the App Store must
conform to these requirements. If your app delivers video over
cellular networks, and the video exceeds either 10 minutes duration or
5 MB of data in a five minute period, you are required to use HTTP
Live Streaming. (Progressive download may be used for smaller clips.)
If your app uses HTTP Live Streaming over cellular networks, you are
required to provide at least one stream at 64 Kbps or lower bandwidth
(the low-bandwidth stream may be audio-only or audio with a still
image).
These requirements apply to iOS apps submitted for distribution in the
App Store for use on Apple products. Non-compliant apps may be
rejected or removed, at the discretion of Apple.
So your task boils down to the question on how to get the MP4 URL of a video offered through YouTube. That part is really tricky and nicely solved by Deja. Just use a packet sniffer and you will see that it actually creates a local server that feeds MPMoviePlayerController.
try this code:
NSString *urlStr=[Your url is here];
NSURL *url = [NSURL fileURLWithPath:urlStr];
MPMoviePlayerController* moviePlayer = [[MPMoviePlayerController alloc]initWithContentURL:url];
[self.view addSubview:moviePlayer.view];
moviePlayer.view.frame = CGRectMake(set frame is here);
[moviePlayer play];
[moviePlayer setFullscreen:NO animated:YES];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish)
name:MPMoviePlayerPlaybackDidFinishNotification
object:nil];
I guess it is against Youtube ToS but you can use this code here:
https://github.com/larcus94/LBYouTubeView
It is simple to use and works like a charm!
Use UIWebView. Copy HtML code video in youtube.
UIWevView* movie = [UIWebView alloc] initWithFrame:CGRectMake(0,0,320,460)];
NSString* urlString = #"past HTML code";
[self.webView loadHTMLString:urlString baseURL:nil];
[self.view addSubview:movie];

objective c play audio as it is downloading

I have an iphone design question regarding downloading and playing an audio file. Thanks to Matt Gallagher's AudioStreamer sample I can stream audio and play it back, bu that does not save it locally on the phone for later. Using an NSURLConnection I can download and save the audio files, but I have to wait until I have downloaded them to init my AVAudioPlayer given the data property is read only. I can not add to the buffer.
My question is how can I start the download, but then start playing the file after "enough" of it is downloaded, but before it is finished? Is there another audio player other then AVAudioPlayer that I can feed data into as it is being downloaded.
The only way I can see to do it now would be to do both in different threads, but then of course I would be pulling down the data twice.
Thoughts?
I thought you could do it with AVAudioPlayer but I havent tested it. I believe I have played audio without it loading fully with AVPlayer like so:
self.player = [AVPlayer playerWithURL:assetUrl];
[player play];
I would use an AVAudioSession along with a MPMoviePlayerViewController.
/**
* Play audio session
*
* #version $Revision: 0.1
*/
- (void)playAudioWithURL:(NSString *)audioURL {
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *setCategoryError = nil;
[audioSession setCategory:AVAudioSessionCategoryPlayback error:&setCategoryError];
if (setCategoryError) {
}
NSError *activationError = nil;
[audioSession setActive:YES error:&activationError];
if (activationError) {
}
MPMoviePlayerViewController *tempPlayer = [[MPMoviePlayerViewController alloc]initWithContentURL:[NSURL URLWithString:[audioURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
// Make sure we have airplay
if([tempPlayer.moviePlayer respondsToSelector:#selector(setAllowsAirPlay:)]) {
tempPlayer.moviePlayer.allowsAirPlay = YES;
}
tempPlayer.moviePlayer.shouldAutoplay = YES;
tempPlayer.moviePlayer.useApplicationAudioSession = NO;
[self presentMoviePlayerViewControllerAnimated:tempPlayer];
[tempPlayer.moviePlayer play];
[tempPlayer release];
}//end

How to use MPMusicPlayerController with AVAudioPlayer

I am trying to play an in app audio with ipod the code I am using to play the audio file is:
Code:
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: nil];
UInt32 doSetProperty = 1;
AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof(doSetProperty), &doSetProperty);
[[AVAudioSession sharedInstance] setActive: YES error: nil];
if(error)
{
NSLog(#"Some error happened");
}
NSString *path = [[NSBundle mainBundle] pathForResource:effect ofType:type];
myPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
myPlayer.delegate = self;
myPlayer.numberOfLoops = -2;
myPlayer.volume = 1.0f;
[myPlayer play];
and to play the ipod music I am using
Code:
player = [MPMusicPlayerController iPodMusicPlayer];
My ipod plays fine until the audio starts playing but once the audio stops I am not able to get back to the ipod to play. I am using
Code:
NSString *value = [[NSUserDefaults standardUserDefaults] stringForKey:#"sound"];
if([value compare:#"ON"] == NSOrderedSame && myPlayer != nil)
{
[myPlayer stop];
[myPlayer release];
myPlayer = nil;
}
NSError *error = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&error];
if(error)
{
NSLog(#"Some error happened");
}
to stop the audio and then just call
Code:
[player play];
to play the ipod music but it does not play the music, it says the title to be null.
I would really appreciate if some one could help me with this.
Regards,
Ankur
I suggest moving the audio session setup (including the Ambient category) to your application delegate's didFinishLaunchingWithOptions and not using the Playback category at all. You can still play AVAudio sounds just fine with the Ambient setting.
If you want to kill iPod music whenever you play AV sounds, then you should only be using the Playback category. (I'm not exactly sure what you're trying to do.)
The error that you're getting when you try to resume the iPod music suggests that your MPMusicPlayerController object resets its song queue when it is stopped by the AVAudio sounds, and that you'll have to set up the MP player again. "Title is null" definitely sounds like a dangling pointer or the like in the MP player.
It's not possible to play iPod audio in AVAudioPlayer. You need to convert the library Asset link from ipod, using *AVURLAsset to an mp3 or wav and save it to the documents library. IOS.5 currently has a bug in the conversion (AudioExportSession) from ipod to mp3 file, so it's NOT POSSIBLE. Sorry.
You need to resume iPod player after myPlayer finish playing.
-(void) audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
[player play];
}