Routing audio input to receive from TOP microphone on iPhone - iphone

I am writing a little app to record multiple tracks and play them back over one another.
I am using the PlaybackAndRecord mode and i am routing my output to the main speakers.
Problem is that the bottom microphone is still being used for input as well so now I when I record I get the output from the other tracks really loud on the new track.
Here is what I have so far:
audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
OSStatus propertySetError = 0;
UInt32 allowMixing = true;
propertySetError = AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof(allowMixing), &allowMixing);
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,sizeof (audioRouteOverride),&audioRouteOverride);
[audioSession setActive:YES error:nil];

Use AVAudioSession to get available inputs. On my iPhone 5 it looks like this.
NSLog(#"%#", [AVAudioSession sharedInstance].availableInputs);
"<AVAudioSessionPortDescription: 0x14554400, type = MicrophoneBuiltIn; name = iPhone Microphone; UID = Built-In Microphone; selectedDataSource = Back>"
Then use one of these inputs to get availableDataSources, like this.
NSLog(#"%#", [AVAudioSession sharedInstance].availableInputs[0].dataSources);
"<AVAudioSessionDataSourceDescription: 0x145afb00, ID = 1835216945; name = Bottom>",
"<AVAudioSessionDataSourceDescription: 0x145b1870, ID = 1835216946; name = Front>",
"<AVAudioSessionDataSourceDescription: 0x145b3650, ID = 1835216947; name = Back>"
We can see that there are actually THREE microphones on this iPhone: top front, top back, and bottom. Now you can set your preferred data source.
AVAudioSessionPortDescription *port = [AVAudioSession sharedInstance].availableInputs[0];
for (AVAudioSessionDataSourceDescription *source in port.dataSources) {
if ([source.dataSourceName isEqualToString:#"Back"]) {
[port setPreferredDataSource:source error:nil];
}
}

Related

Audio played using AVAudioPlayer is working in iPhone Simulator but not in the Device

I need to play a video along with a small 2 sec audio play. Everything works fine in iPhone simulator but not in the Device. I am storing my audio file in the project bundle and playing the audio from there.
NSString *gotItsoundFilePath = [[NSBundle mainBundle] pathForResource:#"gotit" ofType:#"mp3"];
NSData *gotItsampleData = [[NSData alloc] initWithContentsOfFile:gotItsoundFilePath];
NSError *gotItaudioError = nil;
gotItAudioPlayer = [[AVAudioPlayer alloc] initWithData:gotItsampleData error:&gotItaudioError];
gotItAudioPlayer.numberOfLoops = 0;
This code works fine in iPhone Simulator when i use [gotItAudioPlayer play]; but the same build is not working in the device. Am i doing wrong somewhere? Can someone please help on this?
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayAndRecord error: nil];
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,sizeof (audioRouteOverride),&audioRouteOverride);
Put this code. before you make player object.

Control AudioSession from code

In my project i have a function that play music
-(void)playPlin {
AudioSessionSetActive(true);
// Set up audio session, to prevent iPhone from deep sleeping, while playing sounds
UInt32 category = kAudioSessionCategory_MediaPlayback;
AudioSessionSetProperty (
kAudioSessionProperty_AudioCategory,
sizeof (category),
&category
);
//UInt32 category = kAudioSessionCategory_MediaPlayback;
OSStatus result = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory,
sizeof(category), &category);
if (result){
NSLog(#"ERROR SETTING AUDIO CATEGORY!\n");
}
result = AudioSessionSetActive(true);
if (result) {
NSLog(#"ERROR SETTING AUDIO SESSION ACTIVE!\n");
}
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:#"chimes" ofType:#"wav"];
NSData *sampleData = [[NSData alloc] initWithContentsOfFile:soundFilePath];
NSError *audioError = nil;
AVAudioPlayer *alarmAudioPlayer = [[AVAudioPlayer alloc] initWithData:sampleData error:&audioError];
[sampleData release];
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: nil];
if(audioError != nil) {
NSLog(#"An audio error occurred: \"%#\"", audioError);
}
else {
[alarmAudioPlayer play];
} }
The file play ok but i have three issue:
1.how can I make that the audio file starts not from the beginning but from the number of second that i pass? for example, if i step value 300 audio file should start from the second 300 of it
2.How can i set volume of audio file?
3.How can i set loop property of it?
thank in advance
This is all pretty clearly laid out in the documentation.
1) Use the playAtTime: method call instead of play. Pass the time in seconds.
2) Set the volume property on the AVAudioPlayer. Note that this is the gain of the player, and will be modulated with the current system volume.
3) Set the numberOfLoops property. Assign a huge value like NSIntegerMax to keep looping indefinitely.

iPhone SdK: AVPlayer will not play a composition after adding a audio track

After adding an audio track (recorded with AVAudioRecorder) to a composition AVPlayer will not play it. AVPlayer.status = 1 and AVPlayer.error = null.
I have looked at the WWDC10 AVEdit demo code and it's pretty much similar. Could it be an audio format incompatibility?
the original composition allready contains a video and audio track from a video asset.
after removing the newly added audio track the player still does not play
after removing the original audio track the player will play.
I'm also finding it hard to get debug information that would point me to the problem. If anyone has a suggestion it would be greatly appreciated.
Here is my code for adding the audio track
any help is most welcome
Jean-Pierre
-(void)editAudioViewController:(EditAudioViewController *)editAudioViewController didEditAudio:(NSURL *)url
{
[self dismissModalViewControllerAnimated:TRUE];
BOOL result;
NSError * error = nil;
if (url)
{
AVURLAsset * asset = [AVURLAsset URLAssetWithURL:url options:nil] ;
CMTimeRange audioTimeRange = CMTimeRangeMake(kCMTimeZero , asset.duration);
if (CMTIME_COMPARE_INLINE(CMTimeRangeGetEnd(audioTimeRange), >, [composition duration]))
audioTimeRange.duration = CMTimeSubtract([composition duration], audioTimeRange.start);
AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio
preferredTrackID:kCMPersistentTrackID_Invalid];
AVAssetTrack *audioTrack = [asset compatibleTrackForCompositionTrack:compositionAudioTrack];
result = [compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, audioTimeRange.duration) ofTrack:audioTrack atTime:audioTimeRange.start error:&error];
if (!result)
{
NSLog(#"%#", [error description]);
}
[mp replaceCurrentItemWithPlayerItem:[AVPlayerItem playerItemWithAsset:composition]];
[mp seekToTime:kCMTimeZero];
}
}
I had two separate sessions in my audio recorder code one for recording and one for playback.
I switched to a single record/play session and this somehow fixed the problem:
audioSession = [AVAudioSession sharedInstance];
if (!audioSession.inputIsAvailable)
{
NSLog(#"No input available");
}
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
NSError * error = nil;
[audioSession setActive:TRUE error:&error];
if (error)
{
NSLog(#"%#", [error description]);
}

how to route iPhone audio to the bluetooth headset

I'm attempting to output audio to the bluetooth headset (not A2DP) using AVAudioPlayer, AVAudioSession and AudioSessionSetProperty.
There seems to be functions to select the bluetooth headset as input (kAudioSessionProperty_OverrideCategoryEnableBluetoothInput), but no equivalent for setting the output. This is done in the Voicemail app, where you can select the headset, handset speaker or speaker phone. I've tried various combinations of SessionCategories and the AudioSession properties, but I just can't seem to hit on an approach that works.
I'm sure someone has figured this out, care to share an example?
This little test worked for me... it involves setting up the bluetooth headset as the input also (not sure if that's what you want). Sorry about the crappy formatting on the 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);
AudioServicesCreateSystemSoundID (soundFileURLRef,&soundFileObject);
AudioServicesPlaySystemSound (soundFileObject); // should play into headset
Hope that helps!
I was able to get this working, but it took some doing. I've pieced together the pertinent piece of code here:
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:&err];
UInt32 allowBluetoothInput = 1;
AudioSessionSetProperty(
kAudioSessionProperty_OverrideCategoryEnableBluetoothInput,
sizeof (allowBluetoothInput),
&allowBluetoothInput);
It is also possible to which sources are available and switch between bluetooth, a headset, handset or the speakerphone but things become very involved at that point. The audio source manager I ultimately wrote was over 700 lines.

iphone, how to play sound even in silent or mute mode?

as topic... is it possible ?
Thanks
again, I have attached the code as follows, please check which step is wrong .thanks.
//#step
AudioSessionInitialize (NULL, NULL, NULL, NULL);
AudioSessionSetActive(true);
UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
OSStatus error = AudioSessionSetProperty (kAudioSessionProperty_AudioCategory, sizeof(sessionCategory),&sessionCategory);
if (error)
printf("ERROR AudioSessionSetProperty ! %d\n", error);
//#step
NSString* filePath = #"AlarmClockBell.caf";
[Util restoreResourceFile:filePath];
filePath =[Util getFileFullPathFromSysDoc:filePath];
NSURL *soundFileURL = [NSURL fileURLWithPath:filePath];
NSError* error ;
AVAudioPlayer * audioPalyer = [[AVAudioPlayer alloc] initWithContentsOfURL: soundFileURL error: &error];
if (nil == audioPalyer)
{
AppTrace3(self, #"Faild to play", soundFileURL, error);
return FALSE;
}
[audioPalyer prepareToPlay];
[audioPalyer setVolume: 5 ];
[audioPalyer setDelegate: self];
audioPalyer.numberOfLoops = 10;
[audioPalyer play];
thanks...
If you look in the docs under Audio Session Categories, you'll find a number of modes that you can set to tell the system how your app plans to use audio. The default is AVAudioSessionCategorySoloAmbient which tracks the ring/silent switch and the screen lock.
To have your app ignore the ring/silent switch settings, you could try changing the category:
#import <AudioToolbox/AudioToolbox.h>
AudioSessionInitialize (NULL, NULL, NULL, NULL);
AudioSessionSetActive(true);
UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
AudioSessionSetProperty (kAudioSessionProperty_AudioCategory,
sizeof(sessionCategory),&sessionCategory);
If you want to allow iPod audio to continue playing in the background, you'll also want to check kAudioSessionProperty_OverrideCategoryMixWithOthers.
As of iOS 6, there is an alternative method that's more compact than Ramin's answer.
#import <AVFoundation/AVFoundation.h>
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback
error:nil];
To allow background audio from other apps to continue playing, add the AVAudioSessionCategoryOptionMixWithOthers option:
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback
withOptions:AVAudioSessionCategoryOptionMixWithOthers
error:nil];
There's further details in Apple's AVAudioSession Class Reference.
It must be, there's been a couple games I've had which (even when its in mute mode) will play sound. Unfortunately this was discovered whilst attempting to play games covertly in class.
As to how to actually do it, I really don't have any idea.