AVAudioSession manipulate sound output - ios

I'm using AVSoundSession to configure sound, and AVAudioPlayer to play different sounds.
I searched a lot and couldn't find anything. How can I manipulate output sources?
I need a method in my SoundManager where I could switch output between phone speaker and loudspeaker.
success = [session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker
error:&error];
Using this I can route sound to loudspeaker, but there is no method to move it to phone speaker. Can anybody help me with it?

So, I found solution for manipulating with sound output.
You could initialize sound settings with AVAudioSession
Something like this:
session = [AVAudioSession sharedInstance];
BOOL success;
NSError* error;
success = [session setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];
if (!success) NSLog(#"AVAudioSession error setting category:%#",error);
success = [session setMode:AVAudioSessionModeVoiceChat error:&error];
if (!success) NSLog(#"AVAudioSession error setting mode:%#",error);
success = [session overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:&error];
[session setPreferredOutputNumberOfChannels:0 error:nil];
if (!success) NSLog(#"AVAudioSession error overrideOutputAudioPort:%#",error);
success = [session setActive:YES error:&error];
if (!success) NSLog(#"AVAudioSession error activating: %#",error);
else NSLog(#"audioSession active");
With
[session overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:&error];
You set don't override output port. And your app playing with default speaker. As I understand for mode AVAudioSessionModeVoiceChat used phone speaker. It's directly what I need for my SIP caller app.
Then you can override output port with
[session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:&error];
I do it so:
- (void) loudSpeakerOn:(BOOL)isLoudSpeaker{
[session setActive:NO error:nil];
BOOL success;
NSError* error;
success = [session overrideOutputAudioPort:isLoudSpeaker?AVAudioSessionPortOverrideSpeaker:AVAudioSessionPortOverrideNone error:&error];
if (!success) NSLog(#"AVAudioSession error setting category:%#",error);
[session setActive:YES error:nil];
}

Related

iOS: AVAudioSession sample rate is not changing when playing a sound from speaker

When setting the preferred sample rate to 16000 it is working fine. However, when I want to play the sound from the speaker and print the sample rate I find it 48000.
I tried to set the sample rate again after playing from the speaker, but it is not working.
NSError *err = nil;
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setActive:NO error:&err];
BOOL successfullySatSampleRate = [session setPreferredSampleRate:SAMPLING_FREQUENCY error:&err];
if(err != nil)
{
NSLog(#"Error in setting up audio: %#", err);
}
if(!successfullySatSampleRate)
{
NSLog(#"Error in setting up sample rate");
}
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error: nil];
[session setActive:YES error:&err];
NSLog(#"initialize Session preferredSampleRate = %f, hardware sampleRate = %f",[session preferredSampleRate],[session sampleRate]);
What should I do to keep the sample rate 16000?

How to play audio from earpiece in iPhone?

I want to play audio from earpiece . I tried the solution provided in this : Play Audio but it is not working. I also tried
NSError *error = nil;
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];
[session setActive: YES error:nil];
AVAudioSessionPortDescription *routePort = session.currentRoute.outputs.firstObject;
[session overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:&error];
I play audio from earpiece by writing these lines in my ViewController's viewDidLoad method:
NSError *error = nil;
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];
[session setActive: YES error:nil];
[session overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:&error];

Can we enable iPhone Speaker On before Calling using NSUrl("tel:") scheme

Can we enable iPhone speaker on before calling using NSUrl("tel:") scheme in objective c and Xamarin.iOS? If so then how we can achieve this? Thanks.
I don't believe Apple exposes any public API to do this. The user must choose the audio out channel.
To enable speaker while calling for open in Objective C, you can do something like this :
- (void)setAudioOutputSpeaker:(BOOL)enabled
{
AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *error;
[session setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];
[session setMode:AVAudioSessionModeVoiceChat error:&error];
if (enabled) // Enable speaker
{
[session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:&error];
}
else // Disable speaker
{
[session overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:&error];
}
[session setActive:YES error:&error];
}

AVAudioSession for Audio Video call

I am implementing Audio Video Call like feature. I am using AVAudioSession for Voice feature. I want to configure the AVAudioSession such that it should work on the receive speaker and loud speaker as well as the headphones.I am using the following initialisation for AVAudioSession:
NSError *err = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord
withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:&err];
[[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:&err];
[[AVAudioSession sharedInstance] setMode:AVAudioSessionModeVideoChat error:&err];
[[AVAudioSession sharedInstance] setActive: YES error: NULL];
The above code works fine for loud speaker and headphones but the voice quality from loud speaker is very low.
I have tried the code below for switching the audio route to receiver speaker. But it doesn't work.
NSError *err = nil;
[[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:&err];
Can somebody please help me with this?
I got similar problem.i solve it by
[[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:nil];
NSArray *outputs =[[[AVAudioSession sharedInstance] currentRoute] outputs];
BOOL haveSpeaker = NO;
for (AVAudioSessionPortDescription *currentPut in outputs) {
if ([currentPut.portType isEqualToString:#"Speaker"]) {
haveSpeaker = YES;
break;
}
}
if (haveSpeaker) {
NSError *error;
[[AVAudioSession sharedInstance]setCategory:AVAudioSessionCategoryRecord error:nil];
[[AVAudioSession sharedInstance]setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
[[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:&error];
[[AVAudioSession sharedInstance]setActive:YES error:nil];
}
In my opinion AVAudioSessionCategoryOptionDefaultNone is not reciver,it's default route. so u hava changed the default route for this mode;

Switching audio output between Receiver and Speaker in iOS7 and above?

I have an audio player which has an option of switching the Audio Output from Speaker to Receiver/Earpiece (irrespective of whether headset is connected) when proximity sensor notifies 1. The following is my code for doing so.
- (void) switchAudioOutput:(NSString*)output{
AVAudioSession* audioSession = [AVAudioSession sharedInstance];
BOOL success;
NSError* error;
if([output isEqualToString:keAudioOutputReciever]){
//Force current audio out through reciever
//set the audioSession override
success = [audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideNone
error:&error];
if (!success)
NSLog(#"AVAudioSession error overrideOutputAudioPort:%#",error);
//activate the audio session
success = [audioSession setActive:YES error:&error];
if (!success)
NSLog(#"AVAudioSession error activating: %#",error);
else
NSLog(#"AVAudioSession active with override: AVAudioSessionPortOverrideNone");
}else if([output isEqualToString:keAudioOutputSpeaker]){
//set the audioSession override
success = [audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker
error:&error];
if (!success)
NSLog(#"AVAudioSession error overrideOutputAudioPort:%#",error);
//activate the audio session
success = [audioSession setActive:YES error:&error];
if (!success)
NSLog(#"AVAudioSession error activating: %#",error);
else
NSLog(#"AVAudioSession active with override: AVAudioSessionPortOverrideSpeaker");
}
}
This was based on the answer Toggle Button route audio to speaker and receiver and enter link description here. I noticed that this only forces the Audio to Speaker alone but does not ensure that the route goes to receiver alone. Moreover while shifting to speaker I get the following error:
AVAudioSession error overrideOutputAudioPort:Error Domain=NSOSStatusErrorDomain Code=-50 "The operation couldn’t be completed. (OSStatus error -50.)"
I figured out the answer by avoiding overrides for Receiver
- (void) setAudioSession:(NSString*)audioOutput{
NSError* error;
if([audioOutput isEqualToString:audioOutputSpeaker.lowercaseString]){
//set the audioSession override
if(![self setCategory:AVAudioSessionCategoryPlayAndRecord
withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker|AVAudioSessionCategoryOptionAllowBluetooth
error:&error])
NSLog(#"AVAudioSession error AVAudioSessionCategoryPlayAndRecord:%#",error);
//activate the audio session
if (![self setActive:YES error:&error])
NSLog(#"AVAudioSession error activating: %#",error);
else
NSLog(#"AVAudioSession active with override: AVAudioSessionPortOverrideNone");
}else if ([audioOutput isEqualToString:audioOutputReciever.lowercaseString]){
//Force current audio out through reciever
//set the audioSession override
if(![self setCategory:AVAudioSessionCategoryPlayAndRecord
withOptions:AVAudioSessionCategoryOptionAllowBluetooth
error:&error])
NSLog(#"AVAudioSession error AVAudioSessionCategoryPlayAndRecord:%#",error);
if (![self overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:&error])
NSLog(#"AVAudioSession error overrideOutputAudioPort to Reciever:%#",error);
//activate the audio session
if (![self setActive:YES error:&error])
NSLog(#"AVAudioSession error activating: %#",error);
else
NSLog(#"AVAudioSession active with override: AVAudioSessionPortOverrideNone");
}
}
I was struggling with this too and was trying to set the mode parameter so something potentially appropriate, e.g.
try AVAudioSession.sharedInstance().setCategory(.playAndRecord,
mode: .voicePrompt,
options: .defaultToSpeaker)
And that would just throw me an error:
Error Domain=NSOSStatusErrorDomain Code=2003329396 "(null)"
The audio was routing to the receiver rather than speaker with just the category parameter and with the mode, but when I randomly decided to try without the mode parameter but with the options parameter it worked fine!
So give this code a try if you struggle:
try AVAudioSession.sharedInstance().setCategory(.playAndRecord,
options: .defaultToSpeaker)

Resources