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];
}
}
Related
I am able to record video and output the movie to a file correctly. However, I have a problem with video recording (no video ouput) when trying to use AVAudioPlayer to play some audio. Does it mean that I cannot use AVCaptureSession and AVAudioPlayer at the same time? Here is my code to create the capture session and to play the audio. The video capture is started first, then during the capturing, I want to play some audio. Thanks so much for any help.
Code to create the capture session to record video (with audio) - output to a .mov file:
- (void)addVideoInput
AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
//... also some code for setting up videoDevice/frontCamera
NSError *error;
AVCaptureDeviceInput *videoIn = [AVCaptureDeviceInput
deviceInputWithDevice:frontCamera error:&error];
AVCaptureDeviceInput *audioIn = [AVCaptureDeviceInput
deviceInputWithDevice:audioDevice error:&error];
if (!error) {
if ([captureSession canAddInput:audioIn])
[captureSession addInput:audioIn];
else
NSLog(#"Couldn't add audio input.");
if ([captureSession canAddInput:videoIn])
[captureSession addInput:videoIn];
else
NSLog(#"Couldn't add video input.");
}
- (void)addVideoOutput
{
AVCaptureMovieFileOutput *m_captureFileOutput = [[AVCaptureMovieFileOutput alloc] init];
[captureSession addOutput:m_captureFileOutput];
[captureSession startRunning];
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSMutableString *filePath = [NSMutableString stringWithString:#"Movie.mov"];
NSString* fileRoot = [docDir stringByAppendingPathComponent:filePath];
NSURL *fileURL = [NSURL fileURLWithPath:fileRoot];
AVCaptureConnection *videoConnection = NULL;
for ( AVCaptureConnection *connection in [m_captureFileOutput connections] )
{
for ( AVCaptureInputPort *port in [connection inputPorts] )
{
if ( [[port mediaType] isEqual:AVMediaTypeVideo] )
{
videoConnection = connection;
}
}
}
[videoConnection setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
[m_captureFileOutput startRecordingToOutputFileURL:fileURL recordingDelegate:self];
[m_captureFileOutput release];
}
Code to play the audio, this function is call during the video capture session. If I don't call this function, the video is recorded and I am able to save to the .mov file. However, if I call this function, there's no output .mov file.
- (void)playAudio
{
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:#"AudioFile" ofType:#"mp3"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:soundFilePath];
AVAudioPlayer *newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil];
[fileURL release];
self.audioPlayer = newPlayer;
[newPlayer release];
[audioPlayer setDelegate:self];
[audioPlayer prepareToPlay];
[audioPlayer play];
}
I fixed the problem by setting up the audio session. I called the following function before creating the audio player object to play the audio. That way, I was able to record video (with audio) and play audio at the same time.
- (void)setupAudioSession {
static BOOL audioSessionSetup = NO;
if (audioSessionSetup) {
return;
}
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: nil];
UInt32 doSetProperty = 1;
AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof(doSetProperty), &doSetProperty);
[[AVAudioSession sharedInstance] setActive: YES error: nil];
audioSessionSetup = YES;
}
- (void)playAudio
{
[self setupAudioSession];
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:#"AudioFile" ofType:#"mp3"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:soundFilePath];
AVAudioPlayer *newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil];
[fileURL release];
self.audioPlayer = newPlayer;
[newPlayer release];
[audioPlayer setDelegate:self];
[audioPlayer prepareToPlay];
[audioPlayer play];
}
I browsed through all kinds of post related to this topic but the answers just do not really help. I used this tutorial to implement recording of audio files and playback. What seems to be missing is how to save the record permanently. When I exit my app the sound file is there but nothing is in it. I don't even know if it is saving the rocerd or just creating the file.
Here is a code sample:
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir = [dirPaths objectAtIndex:0];
NSString *soundFilePath = [docsDir
stringByAppendingPathComponent:#"tmpSound.caf"];
tempRecFile = [NSURL fileURLWithPath:soundFilePath];
NSDictionary *recSettings = [NSDictionary
dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:AVAudioQualityMin],
AVEncoderAudioQualityKey,
[NSNumber numberWithInt:16],
AVEncoderBitRateKey,
[NSNumber numberWithInt: 2],
AVNumberOfChannelsKey,
[NSNumber numberWithFloat:44100.0],
AVSampleRateKey,
nil];
recorder = [[AVAudioRecorder alloc] initWithURL:tempRecFile settings:recSettings error:nil];
[recorder setDelegate:self];
[recorder prepareToRecord];
[recorder record];
I saw a possible solution to this problem here but since I'm new to iOS I do not really get it or it is just does not working for me.
Please help and provide a code example. I read the documentation about AVFoundation and other classes but with no positive results.
SOS :)
UPDATE
This is my recording method:
-(IBAction)recording{
//***** METHOD for recording
if(isNotRecording){
isNotRecording = NO;
[recButton setTitle:#"Stop" forState:UIControlStateNormal];
recStateLabel.text = #"Recording";
[recorder setDelegate:self];
[recorder prepareToRecord];
[recorder record];
}
else{
isNotRecording = YES;
[recButton setTitle:#"Rec Begin" forState:UIControlStateNormal];
playButton.hidden = NO;
recStateLabel.text = #"Not recording";
[recorder stop];
}
}
This is my viewDidLoad:
- (void)viewDidLoad
{
//record sound test code - start
isNotRecording = YES;
//playButton.hidden = YES;
recStateLabel.text = #"Not recording";
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
[audioSession setActive:YES error:nil];
//record sound test code - END
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
// code for generating the sound file that is to be saved
NSArray *dirPaths;
NSString *docsDir;
dirPaths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
NSString *soundFilePath = [docsDir
stringByAppendingPathComponent:#"sound.caf"];
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
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;
recorder = [[AVAudioRecorder alloc]
initWithURL:soundFileURL
settings:recordSettings
error:&error];
if (error)
{
NSLog(#"error: %#", [error localizedDescription]);
} else {
[recorder prepareToRecord];
}
}
This is my playBack method:
-(IBAction)playback{
//AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:temporaryRecFile error:nil];
NSError *error;
// setting the uri of the formed created file
NSArray *dirPaths;
NSString *docsDir;
dirPaths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
NSString *soundFilePath = [docsDir
stringByAppendingPathComponent:#"sound.caf"];
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
AVAudioPlayer *player = [[AVAudioPlayer alloc]initWithContentsOfURL:soundFileURL error:&error];
[player setNumberOfLoops:0];
[player prepareToPlay];
[player setVolume:1];
[player play];
NSLog(#"URL je: %#", soundFileURL);
//method 2
if (error)
NSLog(#"Error: %#",
[error localizedDescription]);
else
{
[player play];
if(player.isPlaying==YES)
{
NSLog(#"It's playing");
}
}
}
I hopše this makes it clear what I do.
Any suggestions where I might be wrong?
You need to stop recording in order to save the data to the file permanently:
[recorder stop];
The problem is that when you tell XCode (in the viewDidLoad method) to [recorder prepareToRecord]; it gets rid of the previously recorded audio file. Eliminate that piece of code in the "if" statement and your audio file WILL be saved when you exit and come back in to the app.
FYI -- The "[recorder prepareToRecord]" method creates a fresh audio file, overwriting any previous recorded file.
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");
}
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;
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.