In my app i record and play audio at the same time. The app is almost finished. But there is one thing, that annoying me. When audio session is set to PlayAndRecord, sounds become quiet in comparison with the same sounds with the SoloAmbient category. Is there any way to make sound louder using PlayAndRecord?
when you use the session for play and record, the playback comes out of the speaker used for the phone, otherwise it comes out the speaker located at the bottom of the phone. this is to prevent feedback. you can override this like so (but watch out for feedback, not an issue if you aren't doing both at once)
//when the category is play and record the playback comes out of the speaker used for phone conversation to avoid feedback
//change this to the normal or default speaker
UInt32 doChangeDefaultRoute = 1;
AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryDefaultToSpeaker, sizeof (doChangeDefaultRoute), &doChangeDefaultRoute);
this code works on 3.1.2, earlier sdk's you have to do differently.
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
status = AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute, sizeof (audioRouteOverride), &audioRouteOverride);
you have to be careful with this method, it will override even if you have headphones plugged in, you have to monitor interruptions and change the routes accordingly. much better now using 3.1.2
Ask the user to plug in headphones?
The headphone + mic combination doesn't suffer from this problem.
I don't know if it's a bug, a consequence of the audio hardware,
or if the quiet playback is just an intentional and hamfisted
way of getting cleaner recordings.
UPDATE
I found out that setting the PlayAndRecord session changes your audio route to the receiver.
Apparently the use case is for telephony applications where the user holds the device up to his ear.
If that doesn't violate the Principle of Least Surprise, I don't know what does.
Related
I'm making kind of voip app, so I have to be able to play and record sound at the same time.
But.. when I play and record at same time, iphone's volume was very low.
I used
//kAudio
UInt32 audioCategory = kAudioSessionCategory_PlayAndRecord;
AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof(audioCategory), &audioCategory);
and
I try to
UInt32 audioRoute = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, sizeof(audioRoute), &audioRoute);
but.. still volume is very low..
please help..!
P.S
I'm using playing sound by audioQueue and recording sound by audioUnit.
Have you set your volume using kAudioSessionProperty_InputGainScalar property prior to recording ?
BTW, this input gain property is only available from iOS5.
I'm developing an interactive storybook type application for the iPhone and I've recently encountered a frustrating bug concerning audio mixing on the device.
Firstly, I setup an audio session. I set the category to AVAudioSessionCategoryAmbient and then init and play my AVAudioPlayer instance. Now, in the background whilst the audio is playing I'm pre-loading a video to play using an MPMoviePlayerController followed by a call to prepareToPlay. The reason I pre-load the video this way is because I need it to play instantly later on cue with fairly strict timing.
In this configuration, the audio/movie works fine and they mix and do not interrupt each other. However, this particular audio session category does not permit audio to continue playing while the device is locked, a feature I really need. As a result I'm forced to consider a different category: AVAudioSessionCategoryPlayback.
By default this category does not permit mixing with other audio, according to the Apple docs. To enable mixing with other audio I am overriding the relevant category:
OSStatus propertySetError = 0;
UInt32 setProperty = 1;
propertySetError = AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof(setProperty), &setProperty);
assert(propertySetError == 0);
Unfortunately, this solves my playing whilst locked issue but introduces another issue: the AVAudioPlayer audio is interrupted briefly as the video loads with a minor stutter. The stutter is small, perhaps less than a second but is enough to disrupt the user experience. I've read this related post which enabled me to pre-load the video with the AVAudioSessionCategoryAmbient, but unfortunately the same approach doesn't seem to work with the new category.
The audio session category is applied successfully, according to the return code. Does anyone know why enabling audio mixing with this category is not the same as the mixing facility provided by ambient category?
The best way I've found working a similar problem is to use the newer AVPlayer (+1 #adam) and set your app to enable background audio and receive remote control notifications. I was tipped off to this by #MarquelV following How can you play music from the iPod app while still receiving remote control events in your app?
If you can get backgrounding working properly, that should enable you to continue playing while the device is locked. Oh, and don't forget to add keys to info.plist, its easy to do and then have no idea why it isn't working.
What do you think is the best (i.e. most memory efficient) way of playing a few 30 second audio files (m4v) from the bundle within an app to the external speaker? The audio files have to play automatically as soon a specific view appears.
There is no mixing, etc. going on. However I'm listening to the microphone at the same time via AVAudioRecorder to measure a few noise levels/peak sounds etc. and react to them.
Thanks!
m4v are video files. Did you mean m4p?
Assuming you did, I'd say start with AVAudioPlayer
Since you're using input at the same time as playback, you'll want to set your Audio Session's category appropriately:
[AVAudioSession sharedInstance].category = AVAudioSessionCategoryPlayAndRecord;
// note that on the iPhone that category will send audio output to the
// phone earpiece rather than the speaker, so you have to redirect the output
// like so:
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty (
kAudioSessionProperty_OverrideAudioRoute,
sizeof (audioRouteOverride),
&audioRouteOverride
);
Does anyone know if it is possible to implement playback of an audio file through the internal speaker even if the headphones are plugged in?
I'm not sure how you are doing your audio playback, but try having a look at the "Redirecting Output Audio" section of the Audio Session Programming Guide
It looks something like this:
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker; // 1
AudioSessionSetProperty (
kAudioSessionProperty_OverrideAudioRoute, // 2
sizeof (audioRouteOverride), // 3
&audioRouteOverride // 4
);
Actually i think this is not possible, as there seems to be some kind of mechanical switch, which indicates a plugged in headset thus preventing speaker output when this is the case.
(read here)
Some other hints can be found in the description of kAudioSessionProperty_OverrideCategoryDefaultToSpeaker:
"Specifies whether or not to route audio to the speaker (instead of to the receiver) when no other audio route, such as a headset, is connected."
I am using Stephen Celis' SCListener class to record iPhone microphone audio levels. I also am playing audio through the use of AVAudioPlayer. For example, the user presses 'Play' to kick off a sound playing in the background and then has the option to blow into the microphone to play additional, shorter sounds. The code all works fine, playing all the sounds when they should be played, however, the AVAudioPlayer sound volume greatly decreases when you begin listening with the SCListener. I have narrowed down the culprit to this line in the SCListener source code:
AudioQueueNewInput(&format, listeningCallback, self, NULL, NULL, 0, &queue);
I have racked my brain and can not find out how to keep the playback volume at it's highest level once this line has executed. I have spoken with Stephen Celis, too, and he does not know what is happening. It is possible, I suppose, that the iPhone turns down the output volume when the microphone is being used so that feedback isn't introduced, but it seems like there should be a way to disable that.
In summary:
Start playing long audio file with AVAudioPlayer - 100% volume (loud).
Enable SCListener and begin listening (which calls AudioQueueNewInput).
The output volume on the AVAudioPlayer sound greatly decreases
Call [[SCListener sharedListener] stop] to dispose of the queue
AVAudioPlayer sound resumes higher playback volume
Has anyone seen anything like this or have any ideas on how to keep the playback volume higher? I have explicitly set the volume parameter to 1.0f to ensure that the gain is at it's highest level.
you can try this:
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,sizeof (audioRouteOverride),&audioRouteOverride);
I'm not familiar with Stephen Celis's work, but if tposchel's suggestion does not work, it might be of some value to look at the InputQueue's values versus the OutputQueue's audio values in debug mode (this is tricky, though, since the callbacks for these methods are realtime threads).
This may be informative in that it will tell you what the OS believes it is sending to your output device (headphone, or built-in speaker).
The brute force way to fix this problem is to manually normalize (or scale up, as it were) the values within your OutputQueue's callback. This doesn't address your root problem, perhaps, but may be a hack until you find the answer.