How to fix audio distortion issue in iPhone 6s/iPhone 6s - ios

I'm developing a live streaming app. I have an issue with audio distortion on both the iPhone 6s and 6s Plus. I know that Apple has changed the audio hardware sample rate (to 48000Hz).
I have tried following code, but still audio gets distorted:
-(void) setupAudioSpeaker
{
NSError * audioSessionError = nil;
[[AVAudioSession sharedInstance] setCategory:
AVAudioSessionCategoryPlayback error: &audioSessionError];
if (audioSessionError) {
DLog(#"AVAudioSession Error %ld, %#",
(long)audioSessionError.code,
audioSessionError.localizedDescription);
}
NSTimeInterval bufferDuration =0.01;
[[AVAudioSession sharedInstance]
setPreferredIOBufferDuration:bufferDuration
error:&audioSessionError];
if (audioSessionError) {
DLog(#"Error %ld, %#", (long)audioSessionError.code,
audioSessionError.localizedDescription);
}
double sampleRate = 48000.0;
[[AVAudioSession sharedInstance] setPreferredSampleRate:sampleRate
error:&audioSessionError];
if (audioSessionError) {
DLog(#"AVAudioSession Error %ld, %#",
(long)audioSessionError.code,
audioSessionError.localizedDescription);
}
[[AVAudioSession sharedInstance] setActive:YES
error:&audioSessionError];
if (audioSessionError) {
DLog(#"AVAudioSession Error %ld, %#", (long)audioSessionError.code,
audioSessionError.localizedDescription);
}
sampleRate = [AVAudioSession sharedInstance].sampleRate;
bufferDuration = [AVAudioSession sharedInstance].IOBufferDuration;
DLog(#"Sampe Rate:%0.0fHZ I/O Buffer Duration:%f", sampleRate,
bufferDuration);
}

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 disable proximity when AVPlayer stop playing

In my app i have to record audio and play this audio and add proximity when play this audio near your ear so for this i have to do this code when play button click:
- (IBAction)btnPlayPauseTapped:(id)sender {
UIDevice *device = [UIDevice currentDevice];
[device setProximityMonitoringEnabled: YES];
if (device.proximityMonitoringEnabled == YES) {
[[NSNotificationCenter defaultCenter] removeObserver:APP_DELEGATE name:#"UIDeviceProximityStateDidChangeNotification" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:APP_DELEGATE selector:#selector(proximityChanged:) name:#"UIDeviceProximityStateDidChangeNotification" object:device];
//other code
}
Notification call this method when proximity enable:
- (void) proximityChanged:(NSNotification *)notification {
NSLog(#"proximity changed called");
UIDevice *device = [notification object];
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
if(device.proximityState == 1){
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
[audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:nil];
[audioSession setActive:YES error:nil];
}
else{
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
[audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];
[audioSession setActive:YES error:nil];
}
}
when player stop playing or pause i add this:
UIDevice *device = [UIDevice currentDevice];
[device setProximityMonitoringEnabled: NO];
but when i again start playing audio and put device near ear that time it called notification method(proximityChanged) and at that time proximity state also get 1 and audio session category also set as playandrecord but it did not play this audio in ear speaker . it play audio in main speaker.
please help me in this.
Thank you in Advance.
I Solved my problem after 2 days in that when player stop player as I disable proximity is correct but I changed audiosession category in proximitychange method.
- (void) proximityChanged:(NSNotification *)notification {
UIDevice *device = [notification object];
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
BOOL success;
success = [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
if(device.proximityState == 1){
NSLog(#"bool %s", success ? "true" : "false");
[audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:nil];
[audioSession setActive:YES error:nil];
}
else{
NSLog(#"bool %s", success ? "true" : "false");
[audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];
[audioSession setActive:YES error:nil];
}

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;

Why does averagePowerForChannel always return -160?

I have these code and both method call are SUCCESS.
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory: AVAudioSessionCategoryPlayAndRecord error: NULL];
[audioSession setActive: YES error: NULL];
And these code to start recording:
[self.recorder prepareToRecord];
[self.recorder recordForDuration: 60];
I have a timer function to update meters
- (void)updateMeters
{
[self.recorder updateMeters];
float peakPower = [self.recorder averagePowerForChannel: 0];
double ALPHA = 0.05;
double peakPowerForChannel = pow(10, (ALPHA * peakPower));
self.recordView.progress = peakPowerForChannel;
NSLog(#"%f", peakPower);
}
But I do not know why peakPower is always 160. I have another demo(from web) can work well, but I can not find any difference between them.
Just try to set:
recorder.meteringEnabled = YES;
Set the category to AVAudioSessionCategoryPlayAndRecord and check
NSError *error;
[[AVAudioSession sharedInstance]
setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];
if (error) {
NSLog(#"Error description: %#", [error description]);
}
It is strange that [audioSession setCategory: AVAudioSessionCategoryPlayAndRecord error: &err] and [[AVAudioRecorder alloc] initWithURL: [NSURL fileURLWithPath: self.recordPath] settings: recordSetting error: NULL] must in the same function...It is the answer of this question.

How to programmatically mute video

How to play a video without sound?
I have tried these options but neither of them worked:
1) Setting the MPMusicPlayerController player to ipodMusicPlayer and disabling the application audio.
musicPlayer = [MPMusicPlayerController iPodMusicPlayer];
[[MPMusicPlayerController applicationMusicPlayer] setVolume:0];
2) Forcing the app to run the audio
NSError *error = nil;
if ([[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error:&error]) {
NSLog(#"Error setting audio session: %#", error);
}
Use this codebase to mute.
NSError *errorFeedBack = nil;
if (![[AVAudioSession sharedInstance] setActive:NO error:&errorFeedBack] )
{
NSLog(#"Error encountered: %#", [errorFeedBack localizedDescription]);
}

Resources