new audioSession properties

@finefin: It’s a mad… eh, small world :slight_smile: [import]uid: 10666 topic_id: 10882 reply_id: 81523[/import]

I’m trying to play a sound while getting the tuner volume, so I’ve set the audio.mixMode to audio.PlayAndRecordMixMode.
The problem is that while using PlayAndRecordMixMode, the output audio is redirected to the small speaker on the iPhone, and the volume is very very low.

Is it possible to set the kAudioSessionProperty_OverrideAudioRoute to redirect the output audio to the speaker with the audioSession setProperty?
I’m talking about this http://developer.apple.com/library/ios/#documentation/Audio/Conceptual/AudioSessionProgrammingGuide/Cookbook/Cookbook.html#//apple_ref/doc/uid/TP40007875-CH6-SW13

Thanks for the info… I’m trying and trying but I can’t find a way to do it…
[import]uid: 9158 topic_id: 10882 reply_id: 82912[/import]

Possibly, but you are wandering into advanced, unsupported, and untested territory here. We provide support for the constants we defined like MixMode, but there are a ton more we didn’t do because there are so many.

However, I left a back door so you could reach most of them. But this is not for the timid and will require you to understand some things about C and Audio Session Services. It is good you started reading Apple’s docs, because you will need that information.
The AudioSession API we expose is almost a direct passthrough to Apple’s stuff. As long as they don’t require callback notifications, I think it will work, but they are in undocumented/unsupported territory now. The hard part is that you need to figure out the constants Apple uses for the values they want to set. This is the code Apple wants us to run:

UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute\_Speaker;   
AudioSessionSetProperty (  
 kAudioSessionProperty\_OverrideAudioRoute,  
 sizeof (audioRouteOverride),  
 &audioRouteOverride  
);  

In Corona, you see from the top of this thread, we provide:
audio.setSessionProperty(param1, param2)
param1 maps to Apple’s first parameter (kAudioSessionProperty_OverrideAudioRoute) and param2 maps to Apple’s 3rd parameter (kAudioSessionOverrideAudioRoute_Speaker).

But there are two problems. First, Apple has an additional 3rd (middle position) parameter (sizeof (audioRouteOverride)). Second, we do not provide the constants for kAudioSessionProperty_OverrideAudioRoute and kAudioSessionOverrideAudioRoute_Speaker.

To solve the first problem, I added two tricks to the code. One trick is that I try to guess the second parameter for you. So there is a chance you don’t need to use it. But in case that didn’t work, I have a second trick. Our Corona function takes an optional 3rd parameter. You may specify a string of: “Float32”, “Float64”, “bool”, or “UInt32”. In this case, kAudioSessionOverrideAudioRoute_Speaker is a UInt32 so you want to pass “UInt32”.
To solve the second problem, you will need to do some work. Apple uses integer values behind the scenes for these Audio Session constants. So we need to know the integer values of kAudioSessionOverrideAudioRoute_Speaker and kAudioSessionProperty_OverrideAudioRoute.

Unfortunately, if you look at Apple’s headers, you will see this:

 kAudioSessionProperty\_OverrideAudioRoute = 'ovrd'  
 kAudioSessionOverrideAudioRoute\_Speaker = 'spkr'  

This is a technique called FourCC (which I talk about in both my book and Cocoaheads/YouTube video). But it is not obvious how to convert ‘ovrd’ or ‘spkr’ into a 32-bit integer. I would normally write a native iPhone program to solve this:

printf("kAudioSessionProperty\_OverrideAudioRoute: %d\n", kAudioSessionProperty\_OverrideAudioRoute);  
printf("kAudioSessionOverrideAudioRoute\_Speaker: %d\n", kAudioSessionOverrideAudioRoute\_Speaker);  

This would print:

kAudioSessionProperty\_OverrideAudioRoute: 1870033508  
kAudioSessionOverrideAudioRoute\_Speaker: 1936747378  

Once you know the magic numbers, in Corona, you should be able to do:

audio.setSessionProperty(1870033508, 1936747378, "UInt32")  

or possibly just:

audio.setSessionProperty(1870033508, 1936747378)  

To make it a little more readable:

local kAudioSessionProperty\_OverrideAudioRoute = 1870033508  
local kAudioSessionOverrideAudioRoute\_Speaker = 1936747378  
  
audio.setSessionProperty(kAudioSessionProperty\_OverrideAudioRoute, kAudioSessionOverrideAudioRoute\_Speaker, "UInt32")  

Again, this API was not intended for the faint of heart. It was intended to be a last resort for people that needed really low level control over Apple’s Audio Session Services where defaults were insufficient.

I want to note that while this will give you 99% access to Audio Session properties, Audio Session properties that provide callbacks are not supported. Unfortunately, these are really hard to bind in a generic way.

For those that do understand this and figure this out, please help others that ask about this. Feel free to document the constants and the size types (e.g. UInt32) in this thread as you discover them.
[import]uid: 7563 topic_id: 10882 reply_id: 83047[/import]

Thanks a lot for the exhaustive explanation! Now, time to start coding.
By the way, which one is your book? [import]uid: 9158 topic_id: 10882 reply_id: 83048[/import]

Beginning iPhone Games Development
http://playcontrol.net/iphonegamebook/

Presentation at CocoaHeads (Silicon Valley) on iOS Audio & OpenAL (YouTube)
http://www.youtube.com/watch?v=6QQAzhwalPI [import]uid: 7563 topic_id: 10882 reply_id: 83049[/import]

Thanks Eric,
it’s working perfectly, now I’m going to do some more tests just to be sure there are no bugs.
[import]uid: 9158 topic_id: 10882 reply_id: 83050[/import]

Just a warning to people trying to set this up for the first time. Do not modify your build.settings file as suggested above unless you intend for audio to continue playing from your app in the background. Apple will reject your app, as it did mine, expecting music to play in the background when the app is suspended. My intent was the opposite, to get music to continue playing from itunes as a player began playing my app. [import]uid: 10903 topic_id: 10882 reply_id: 83382[/import]

To support other audio like iTunes, you don’t need to modify build.settings. You only need code like the one shown as the very first example on this thread.
[import]uid: 7563 topic_id: 10882 reply_id: 83399[/import]

I would really like to have iTunes be able to play in the background but all I can achieve is:
Unsupported key: blah blah

In this thread I’ve seen both camel case and Pascal (ie. audio.kMixMode and audio.MixMode (without the k)). Which is it?

I’ve tried both. I am to the point of simply putting this line in at the VERY beginning of my code but no joy:

print(audio.getSessionProperty(audio.MixMode)) as well as the camel “kMixMode”, but still get the same Unsupported key error.

Could someone please tell me what I am missing here? [import]uid: 21331 topic_id: 10882 reply_id: 84563[/import]

Don’t use ‘k’. That was changed quite awhile back, very soon after the introduction. The very first post was corrected with the correct spelling. The others were not.

What does print(audio.MixMode) show?
And what does print(audio.getSessionProperty( audio.OtherAudioIsPlaying )) show?
[import]uid: 7563 topic_id: 10882 reply_id: 84568[/import]

duff333: Sorry, just noticed this. You’ll need to use the backdoor trick I describe with what’s documented here in the section ‘Supporting Bluetooth Audio Input’:

https://developer.apple.com/library/IOs/#documentation/Audio/Conceptual/AudioSessionProgrammingGuide/Cookbook/Cookbook.html [import]uid: 7563 topic_id: 10882 reply_id: 84571[/import]

print(audio.MixMode) produces:
Unsupported key: MixMode in audio librarynil (yes with the nil on the end like that)

print(audio.getSessionProperty(audio.OtherAudioIsPlaying)) produces:
Unsupported key: OtherAudioIsPlaying in audio library

Thanks for your time. [import]uid: 21331 topic_id: 10882 reply_id: 84574[/import]

You are actually testing on a real iOS device, right? Audio Sessions are iOS only. It won’t work on Mac.
[import]uid: 7563 topic_id: 10882 reply_id: 84576[/import]

I am currently running these tests that we are undergoing on PC/MAC.
I have tossed the code over to the device in each step of my testing (MixMode vs kMixMode) and was not able to set a flag when utilizing:

if(audio.getSessionProperty(audio.OtherAudioIsPlaying) == 1)then

If you think the problem is in my logic then I will keep plugging to see where I made a mistake.

I’m not sure how to witness a “print” statement on the device without writing some quick reporting Text to the screen. Is that how it’s done? Or is there something on the mac that i can catch that print with? [import]uid: 21331 topic_id: 10882 reply_id: 84579[/import]

Oh man… when I put it at the VERY beginning of my code, with proper key spellings, it seems to be working. I hate wasting peoples time. I did read it in this thread, but must’ve made a mistake when testing that reply.

Thank you so much for your time…you rock!! [import]uid: 21331 topic_id: 10882 reply_id: 84580[/import]

The code from the very top of this thread should work. Use audio.supportsSessionProperty to guard your code.

The Xcode Organizer has a console/log item for each device. Use it to watch for the print output.

By default stdout buffers output so you may not see it immediately. To disable it, try putting this at the top of your Lua code.
io.output():setvbuf(‘no’)

[import]uid: 7563 topic_id: 10882 reply_id: 84581[/import]

Awsome. Thanks for the added knowledge. Didn’t even know (or go look) to see if the Corona print went out like that. [import]uid: 21331 topic_id: 10882 reply_id: 84582[/import]

Just getting into this stuff myself. Here’s what I would like to be able to do:

Have the music player continue playing when my Corona app launches.
Be able to access the mic volume while the music player continues playing and be able to play my own sounds over top of this.

Is this currently possible? Is there source code available that does this?

Thanks for the help.

Pedro [import]uid: 115248 topic_id: 10882 reply_id: 92233[/import]

I think it is possible but never tried it with recording. You need to manually manage the Audio Session categories and manually set the mix mode setting when setting play and record. You really should read Apple’s documentation on Audio Sessions. You are getting into very platform specific and advanced areas.

[import]uid: 7563 topic_id: 10882 reply_id: 92828[/import]

OK, for right now I’m trying to just get the internal sounds and recording to work at the same time. At the top of my code I have:

if audio.supportsSessionProperty then
audio.setSessionProperty(audio.MixMode, audio.PlayAndRecordMixMode)
end

But the audio is getting cut off once I start the recorder. I also tried adding:

audio.setSessionProperty(audio.OverrideMixWithOthersMixMode, audio.PlayAndRecordMixMode)

Not sure if that’s the right way to call it, but it ddidn’t seem to have any effect.

Seems like turning on the recorder might be resetting the MixMode. I will continue playing around with it, but any further tips you might have would be appreciated.

Thanks [import]uid: 115248 topic_id: 10882 reply_id: 92892[/import]