[TAAE2] Background playing of audio

Could anyone point me to the proper pattern for leveraging TAAE2 for background audio?

I was hoping to move away from AudioQueue to TAAE2 for a music app i'm refactoring, but it seems that i've lost my ability to play music in the background.

For my AudioQueue Implementation, I spawned off a separate thread to render the audio, then AudioQueue's callback mechanism would read from an array of buffers.

Do i need to do something similar with TAAE2?

FWIW, my block of code is here, in case anyone can spot what i'm doing wrong. Thanks :)

<br />- (NSDictionary *) initializeSound:(NSString *)path {

    if (self.modPlayer) {
        [self pause];
    }
    else {
        self.modPlayer = [[MC_OMPT alloc] init];
    }

    AVAudioSession * audioSession = [AVAudioSession sharedInstance];
    [audioSession setPreferredIOBufferDuration:audioSession.sampleRate error:NULL];
    [audioSession setActive:YES error:nil];
    NSError *activationError = nil;

    BOOL success = [audioSession setActive:YES error:&activationError];
    if (!success) {
        /* handle the error condition */
        NSLog(@"Dafuq?");
    }

    self.modInfo = [self.modPlayer loadFile:path];

    NSArray *pathParts = [path componentsSeparatedByString:@"/"];

    self.loadedFileName = [pathParts objectAtIndex:[pathParts count] - 1];


    AERenderer *renderer = [AERenderer new];
    self.output = [[AEAudioUnitOutput alloc] initWithRenderer:renderer];

    lastPattern = -1;
    lastRow = -1;

    renderer.block = ^(const AERenderContext * _Nonnull context) {

        AEBufferStack *bufferStack = context->stack;

        const AudioBufferList * bufferList = AEBufferStackPushWithChannels(bufferStack, 1, 2);

        if ( !bufferList ) {
            return;
        }

        float *leftBuffer  = (float*)bufferList->mBuffers[0].mData,
              *rightBuffer = (float*)bufferList->mBuffers[1].mData;

        int32_t *currentStep = [self.modPlayer fillLeftBuffer:leftBuffer
                                              withRightBuffer:rightBuffer
                                                withNumFrames:context->frames];

        int currentPattern = currentStep[1],
            currentRow     = currentStep[2];

        if (lastPattern != currentPattern || lastRow != currentRow) {

            int32_t playerState[4];

            playerState[0] = currentStep[0];
            playerState[1] = currentStep[1];
            playerState[2] = currentStep[2];
            playerState[3] = currentStep[3];

            [self notifyInterface:playerState];
        }



        AERenderContextOutput(context, 1);
    };




    return self.modInfo;
}

Comments

  • Ugh. forgot to add:

        [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
    

    Issue resolved. :disappointed:

  • That'll do it =)

    For the record, if anyone else is curious: you need to make sure background audio is enabled via the Info.plist (select app target in Xcode, Capabilities tab, Background Modes, check Audio). If at some point you actually want to stop the audio, you need to stop the output when moving into the background, from either the app delegate or via a UIApplicationWillEnterBackgroundNotification handler.

  • Also, in case anyone runs into this similar issue,

    The "Play" button on CommandCenter won't show up when you have TAAE2 write to the sound card. So, you have to tell InfoCenter that you're playing audio.

    For me, setting MPNowPlayingInfoPropertyPlaybackRate to @1.0f when audio is playing worked.

    <br />- (void) updateInfoCenter {
    
        MPNowPlayingInfoCenter *infoCenter = [MPNowPlayingInfoCenter defaultCenter];
        NSDictionary *modInfo = self.modInfo;
    
        if (! modInfo) {
            return;
        }
    
        NSDictionary *nowPlayingInfo = @{
            MPMediaItemPropertyAlbumArtist       : [modInfo valueForKey:@"artist"],
            MPMediaItemPropertyGenre             : [modInfo valueForKey:@"type"],
            MPMediaItemPropertyTitle             : [modInfo valueForKey:@"name"] ?: @"Mod file",
            MPMediaItemPropertyPlaybackDuration  : [modInfo valueForKey:@"length"],
            MPMediaItemPropertyBeatsPerMinute    : [modInfo valueForKey:@"bpm"],
            MPMediaItemPropertyAlbumTitle        : self.loadedFileName,
            MPNowPlayingInfoPropertyPlaybackRate : isPaused ? @0.0f : @1.0f
        };
    
        [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
    
        infoCenter.nowPlayingInfo = nowPlayingInfo;
        [[AVAudioSession sharedInstance] setActive:YES error:nil];
    }
    
    
  • The solution for me was to stop TAAE before activating AVAudioSession.

    I thought I could just set TAAE's setAudioSessionCategory to AVAudioSessionCategoryPlayback and setAllowMixingWithOtherApps to NO but that doesn't seem to be enough!

Sign In or Register to comment.