How to record and play sound in iPhone app? - iphone

I tried using AVAudioSession and AVAudioPlayer to record and play sounds respectively but the sound volume is very low.
I tried putting volume value of AVAudioPlayer to 1.0 and more but didn't help much.
What could be my other options to record sound which can be loud enough to play back?

This code should be useful for you:
#import <AudioToolbox/AudioServices.h>
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,
sizeof (audioRouteOverride),&audioRouteOverride);
It will increase volume. The functionality of the code is to convert the ordinary sound to speaker sound on ur iPhone. That's why kAudioSessionOverrideAudioRoute_Speaker is used.

Since iOS7 you can fix this issue directly with AVAudioSession
The overrideOutputAudioPort method does the same than AudioSessionSetProperty
NSError *setOverrideError;
NSError *setCategoryError;
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayAndRecord error:&setCategoryError];
if(setCategoryError){
NSLog(#"%#", [setCategoryError description]);
}
[session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:&setOverrideError];
if(setOverrideError){
NSLog(#"%#", [setOverrideError description]);
}

Swift version :
import AVFoundation
var overrideError : NSError?
if AVAudioSession.sharedInstance().overrideOutputAudioPort(.Speaker, error: &error){
}else{
print("error in overrideOutputAudioPort " + overrideError!.localizedDescription)
}
Swift 2:
do {
try AVAudioSession.sharedInstance().overrideOutputAudioPort(AVAudioSessionPortOverride.Speaker)
} catch {
}

The following code fixed this issue for me:
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error: nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
UInt32 doChangeDefault = 1;
AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryDefaultToSpeaker, sizeof(doChangeDefault), &doChangeDefault);

MAN, try this.
AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *setCategoryError = nil;
if (![session setCategory:AVAudioSessionCategoryPlayback
withOptions:kAudioSessionOverrideAudioRoute_Speaker
error:&setCategoryError]) {
// handle error
}
NSError *error;
NSData * data = [NSData dataWithContentsOfURL:self.playlet.urlSound];
self.audioPlayer = [[AVAudioPlayer alloc] initWithData:data fileTypeHint:#"aac" error:&error];
self.audioPlayer.delegate = self;
if (error)
NSLog(#"Error: %#",
[error localizedDescription]);
else
[_audioPlayer play];

just set this
[session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:&setOverrideError];
It works for me.

Related

record input coming from bluetooth headset in iPhone

I have a project in which I have to record the voice coming from bluetooth headset and play with default iPhone speaker. I have searched a lot and got this code.
UInt32 allowBluetoothInput = 1;
AudioSessionSetProperty (
kAudioSessionProperty_OverrideCategoryEnableBluetoothInput,
sizeof (allowBluetoothInput),
&allowBluetoothInput
);
------------ CODE FOR AUDIO RECORDER START AND STOP ------------
- (IBAction)Record: (id)sender
{
UIButton *btn = (UIButton *)sender;
if([btn isSelected])
{
[audioRecorder stop];
[btn setSelected:NO];
[btn setTitle:#"Start Recording" forState:UIControlStateNormal];
}
else
{
[audioRecorder record];
[btn setSelected:YES];
[btn setTitle:#"Stop Recording" forState:UIControlStateNormal];
}
}
and i am using avaudiorecorder after this. There seems to be something else I am missing in here.
-------- Code for audio recorder ---------
NSURL *soundFileURL = [NSURL fileURLWithPath:AUDIO_FILE];
NSDictionary *recordSettings = [NSDictionary
dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:AVAudioQualityMin],
AVEncoderAudioQualityKey,
[NSNumber numberWithInt:16],
AVEncoderBitRateKey,
[NSNumber numberWithInt: 2],
AVNumberOfChannelsKey,
[NSNumber numberWithFloat:44100.0],
AVSampleRateKey,
nil];
NSError *error = nil;
audioRecorder = [[AVAudioRecorder alloc]
initWithURL:soundFileURL
settings:recordSettings
error:&error];
if (error)
{
NSLog(#"error: %#", [error localizedDescription]);
} else {
[audioRecorder prepareToRecord];
}
I think i am missing something else which needs to be added here. I just want the bluetooth headset input audio. Any help would be appreciated.
Thanks in Advance!!
i just review your issue and got nice answer something you want try with Bellow code:-
// create and set up the audio session
AVAudioSession* audioSession = [AVAudioSession sharedInstance];
[audioSession setDelegate:self];
[audioSession setCategory: AVAudioSessionCategoryPlayAndRecord error: nil];
[audioSession setActive: YES error: nil];
// set up for bluetooth microphone input
UInt32 allowBluetoothInput = 1;
OSStatus stat = AudioSessionSetProperty (
kAudioSessionProperty_OverrideCategoryEnableBluetoothInput,
sizeof (allowBluetoothInput),
&allowBluetoothInput
);
NSLog(#"status = %x", stat); // problem if this is not zero
// check the audio route
UInt32 size = sizeof(CFStringRef);
CFStringRef route;
OSStatus result = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &size, &route);
NSLog(#"route = %#", route);
// if bluetooth headset connected, should be "HeadsetBT"
// if not connected, will be "ReceiverAndMicrophone"
// now, play a quick sound we put in the bundle (bomb.wav)
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
SystemSoundID soundFileObject;
soundFileURLRef = CFBundleCopyResourceURL (mainBundle,CFSTR ("bomb"),CFSTR ("wav"),NULL);
NSError *error = nil;
audioRecorder = [[AVAudioRecorder alloc]
initWithURL:soundFileURLRef
settings:recordSettings
error:&error];
if (error)
{
NSLog(#"error: %#", [error localizedDescription]);
} else {
[audioRecorder prepareToRecord];
}
Credit goes to This
add the audio session to your code
// create and set up the audio session
AVAudioSession* audioSession = [AVAudioSession sharedInstance];
[audioSession setDelegate:self];
[audioSession setCategory:AVAudioSessionCategoryRecord error:nil];
[audioSession setActive:YES error:nil];
Try out this amazing piece of code. Will work for sure
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *err = nil;
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:NULL];
[audioSession setActive:YES error:NULL];
NSString *preferredPortType = AVAudioSessionPortBluetoothHFP;
for (AVAudioSessionPortDescription *desc in audioSession.availableInputs)
{
if ([desc.portType isEqualToString: preferredPortType])
{
[audioSession setPreferredInput:desc error:nil];
}
}

Playing a youtube video in Mpmovieplayer or Mpmusicplayer ios

I want to play a youtube video with Mpmovieplayer or Mpmusicplayer. I want to do this because i have a requirement to make the app keep playing the video in background mode and that is quite not possible in uiwebview. Kindly if you could answer keeping the background mode audio playing in mind. Thanks in advance :)
You can use MPMovieplayerviewcontroller & also it looks like default player of iPhone.
Here is my answer : how to play live streaming from url for a camera that broadcasting live
FOR BACKGROUND: For background play write below lines in ViewDidLoad method -
NSError *setCategoryErr = nil;
NSError *activationErr = nil;
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: &setCategoryErr];
[[AVAudioSession sharedInstance] setActive: YES error: &activationErr];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
UIBackgroundTaskIdentifier newTaskId = UIBackgroundTaskInvalid;
newTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];
And also make a small change in your info.plist like below image:
I successfully found a solution for the UIWebView, After see this hack https://gist.github.com/romainbriche/2308668
It's different on IO5/6 and IOS7.
The problem you will encounter will be to not stop the sound when the app enter in background.
We work on it here https://github.com/0xced/XCDYouTubeVideoPlayerViewController/issues/10#issuecomment-34252488
I found some solutions but not perfects.
Write Given Below code in didFinishLaunchingWithOptions
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *setCategoryError = nil;
BOOL success = [audioSession setCategory:AVAudioSessionCategoryPlayback error:&setCategoryError];
if (!success) { NSLog(#"Error"); } else {NSLog(#"Success");}
NSError *activationError = nil;
success = [audioSession setActive:YES error:&activationError];
if (!success) { NSLog(#"Error"); } else {NSLog(#"Success");}

AvAudiorecorder not functioning properly in iOS 5.1.1 and iPhone4

I am working on an audio recording feature in my app. I am using this code:
-(void)startAudioRecorder:(NSError**)error{
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *err = nil;
[audioSession setCategory :AVAudioSessionCategoryPlayAndRecord error:&err];
if(err){
NSLog(#"audioSession: %# %d %#", [err domain], [err code], [[err userInfo] description]);
return;
}
[audioSession setActive:YES error:&err];
NSMutableDictionary* recordSetting = [[NSMutableDictionary alloc] init] ;
[recordSetting setValue :[NSNumber numberWithInt:kAudioFormatMPEG4AAC] forKey:AVFormatIDKey];//kAudioFormatAppleIMA4,kAudioFormatAAC
[recordSetting setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey];
[recordSetting setValue:[NSNumber numberWithInt: 1] forKey:AVNumberOfChannelsKey];
NSString *absolutePath=[self getAbsoluteAudioFilePath];
if([[NSFileManager defaultManager] fileExistsAtPath:absolutePath]){
// [[NSFileManager defaultManager ] removeItemAtPath:absolutePath error:nil];
}
NSError *audioRecorderError=nil;
NSURL *absoluteUrl=[NSURL fileURLWithPath:absolutePath];
self.audioRecorder=[[[AVAudioRecorder alloc] initWithURL:absoluteUrl settings:recordSetting error:&audioRecorderError] autorelease];
NSLog(#"%s audioRecorder created=%#",__func__,self.audioRecorder);
[self.audioRecorder setDelegate: self];
BOOL prepared=[self.audioRecorder prepareToRecord];
BOOL record=[self.audioRecorder record];
if(!prepared || !record){
UIAlertView *alert=[[UIAlertView alloc] initWithTitle:#"message" message:#"something wrong" delegate:nil cancelButtonTitle:#"ok" otherButtonTitles: nil];
[alert show];
[alert release];
}
*error=audioRecorderError;
//[recordSetting release];
//recordSetting=nil;
}
From various blogs I found above code for recording and it's working as expected in all iOS devices, I have tested on the iPad, iPod, and iPhone. Unfortunately the above code recording with very less voice in iPhone 4, iOS 5.1.1 device rest all combinations are good, I have opened and recorded my voice in voice memos, SpeakEasy apps for the same hardware device those two apps working well which means hardware is working well.
Is there any modification that will solve my issue? What would be the best way to record the voice with high quality?
(Posted solution on behalf of the question author to move it to the answer section).
Added below lines in my method which solves problem
NSError *setCategoryErr = nil;
NSError *activationErr = nil;
//Set the general audio session category
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayAndRecord error: &setCategoryErr];
//Make the default sound route for the session be to use the speaker
UInt32 doChangeDefaultRoute = 1;
AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryDefaultToSpeaker, sizeof (doChangeDefaultRoute), &doChangeDefaultRoute);
//Activate the customized audio session
[[AVAudioSession sharedInstance] setActive: YES error: &activationErr];

Sound does not play while using AVAudioPlayer

Here is my code on button click
- (void)playButton:(id)sender
{
NSLog(#"Play Button Clicked!!!...");
audioPlayer = [self setUpAudioPlayer:[songs objectAtIndex:i]];
}
-(AVAudioPlayer *)setUpAudioPlayer:(NSString *)filename
{
NSLog(#"File name : %#",filename);
NSString *path = [[NSBundle mainBundle] pathForResource:filename ofType:#"caf"];
NSLog(#"File path = %#",path);
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:nil];
//audioPlayer.volume = 0.5;
[audioPlayer prepareToPlay];
[audioPlayer play];
NSLog(#"Song is playing....");
return [audioPlayer autorelease];
}
here songs is NSMutableArray which contains file name... All things go correct with NSLog... But no sound is coming and no error comes.. What is wrong with the code..???
Your audio player is probably getting released as soon as it starts playing. Try to retain it after setUpAudioPlayer is called.
Most probably you need to initialize an audio session, some like this
- (void)setupAudioSession
{
AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *error = nil;
[session setCategory: AVAudioSessionCategoryPlayback error: &error];
if (error != nil)
NSLog(#"Failed to set category on AVAudioSession");
// AudioSession and AVAudioSession calls can be used interchangeably
OSStatus result = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, RouteChangeListener, self);
if (result) NSLog(#"Could not add property listener! %d\n", result);
BOOL active = [session setActive: YES error: nil];
if (!active)
NSLog(#"Failed to set category on AVAudioSession");
}

playing audio while in background mode doesnt work

In my application audio is not being played when i put my application in background mode ..i have seen such issues in this site itself.it is mentioned that
1) in the app-info.plist add to background modes "audio"
2) in the code i added support for audio sessions
if([player isPlaying])
{
[player stop];
}
NSError *error=nil;
int trackid=arc4random()%10+1;
NSString *trackname=[NSString stringWithFormat:#"trk-%d",trackid];
NSLog(#"%#",trackname);
NSString *newAudioFile = [[NSBundle mainBundle] pathForResource:trackname ofType:#"mp3"];
player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:newAudioFile] error:NULL];
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *setCategoryError = nil;
[audioSession setCategory:AVAudioSessionCategoryPlayback error:&setCategoryError];
if (setCategoryError) { /* handle the error condition */ }
NSError *activationError = nil;
[audioSession setActive:YES error:&activationError];
if (activationError) { /* handle the error condition */ }
if(error) {
NSLog(#"%#",&error);
}
[player prepareToPlay];
[player play];
player.numberOfLoops=1;
but still it is not working when i put the application in backgroud mode.it resumes when i put the application back.have i missed something?
use this line in the - (void)viewDidLoad
[UIApplication sharedApplication].idleTimerDisabled = YES;