iPhone Allow Other App to Play Audio While Recording Audio / Shazam

ort11 picture ort11 · May 11, 2012 · Viewed 16k times · Source

Looking to do pretty much what Shazam is doing as far as recording audio while another app is playing audio.

1) Recording audio fine, no problem here

2) When app starts and starts recording, the music from another app stops (itunes, etc).

3) I have played with all of the incantations of the AV Audio settings with no luck in having the audio continue / resume.

4) When Shazam starts, the audio stop for a bit, and then resumes. I assume that Shazam is doing something to restart the audio with the music player? I searched and could not find if there is a way to do this.

So if anyone has the proper settings to get this to work, it would be appreciated.

Also, Saying, please read the AV docs, is not an answer, I have looked these over with no luck.

I have tried found here

http://developer.apple.com/library/ios/#documentation/Audio/Conceptual/AudioSessionProgrammingGuide/AudioSessionCategories/AudioSessionCategories.html

Have tried both the AV and K type of settings. I do see a difference in the settings as far as how exactly the MIC works, but in all cases when my app gets the mic, it stops the audio from the other app.

If I have to sacrifice a chicken standing in the direction of Apple, this is fine, just let me know what type of chicken :-)

Answer

ort11 picture ort11 · Jun 4, 2012

After some back and forth, it looks like using the MixWithOthers is the key. You have to also make sure that the audio route is set to the last / current audio route...

FYI This is with the AudioQueue interface

So we ...

/ Start Music with iPod / Start our app with

  • AudioQueueNewInput
  • AudioQueueAddPropertyListener
  • AudioQueueAllocateBuffer(s)
  • AudioQueueEnqueueBuffer(s)
  • setupCat
  • setupDuck
  • setupAudioRoute
  • setupMixing
  • AudioSessionSetActive (true)
  • AudioQueueStart

typedef union 
{
    OSStatus propertyResult;
    char a[4];
} unionstatus;

unionstatus u2;

typedef union 
{
    UInt32 UI32sessionCat;
    char a[4];
} unionuint32;

unionuint32 usc2;

bool setAudioUInt32 ( UInt32 property, UInt32 value )
{
    bool result = true;

    UInt32 UI32 = value;
    UInt32 UI32size = sizeof(UI32);

    u2.propertyResult = AudioSessionSetProperty (property, UI32size , &UI32 );

    if ( u2.propertyResult )
    {
        printf("Error Set %ld %lx %c%c%c%c\n",u2.propertyResult,u2.propertyResult,u2.a[3],u2.a[2],u2.a[1],u2.a[0]);
        result = false;
    }
    return result;
}

UInt32 getAudioSettingInt ( UInt32 value )
{
    UInt32  I32;
    UInt32  I32size = sizeof(I32);

    u2.propertyResult = AudioSessionGetProperty ( value , &I32size, &I32 );

    if ( u2.propertyResult )
        printf("Error Get %ld %lx %c%c%c%c\n",u2.propertyResult,u2.propertyResult,u2.a[3],u2.a[2],u2.a[1],u2.a[0]);

    return (I32);
}

/// checking taken out

bool otherPlaying = getAudioSettingInt ( kAudioSessionProperty_OtherAudioIsPlaying );
if ( otherPlaying )
{
    setAudioUInt32 (kAudioSessionProperty_OtherMixableAudioShouldDuck, false);
    // this returns a string, arg, have to look for string values, etc.
    UInt32 audioRoute = getAudioSettingInt ( kAudioSessionProperty_AudioRoute );

    CFStringRef ar = (CFStringRef) audioRoute;
    CFStringEncoding encodingMethod = CFStringGetSystemEncoding();
    const char *car = CFStringGetCStringPtr(ar,encodingMethod);
    CFRange range = CFStringFind(ar,CFSTR("Headphones"),kCFCompareCaseInsensitive);

    if ( range.length == 0 ) // we have speakers
        result = setAudioUInt32 (kAudioSessionProperty_OverrideAudioRoute, kAudioSessionOverrideAudioRoute_Speaker);
    else // we have headphones
        {}
}