Possible to generate a tone/noise and send to a particular speaker?

I have an app for the Apple TV that tests the users surround sound system ("Theater Test"). Currently, I encode all of my audio in Dolby Digital Plus, and play back using the decoder on the Apple TV, which sends PCM to the users receiver. I would love to be able to generate these test tones on the fly, and send them to a user specified channel (speaker). Can this be done using TAAE2? I know you have the tone generation available, but I'm just not sure about TAAE and tvOS's ability to send audio to a specific speaker.

Comments

  • Hey @pboden - yep, sure can! AERenderContextOutputToChannels is what you want. Generate the tone (maybe with an AEOscillatorModule), then output to whatever channel you choose.

    I've not worked with the Apple TV, so I'm not quite certain of the finer points (like how to make sure the output is 5.1/etc), though. I suspect you'll need to interact with AVAudioSession.

    Check out this video for details: https://developer.apple.com/videos/wwdc/2015/?id=507

  • Excellent Michael! Yes, on the Apple TV, you can query the number of available channels, and then ask the session to use that channel count. I will let you know how it goes. Thanks!

  • I finally got around to playing with this. So, I have my Apple TV connected to a 7.1 channel system (only using 5.1 at the moment). I found that I was able to play a test tone on up to any two speakers I want, including Center, LFE and surround channels. The firstChannel and lastChannel values of the AEChannelSet had to be 1 apart for it to play on both of the channels. I wasn't able to say, play on all 6 channels at once (0 to 5). Here's an example snippet of my code to get it working:

        AERenderer *renderer = [AERenderer new];
        renderer.numberOfOutputChannels = 8;
    
        AEOscillatorModule *oscillator = [[AEOscillatorModule alloc] initWithRenderer:renderer];
        oscillator.frequency = 400;
        AEChannelSet channels;
        /*
         0 left
         1 right
         2 lfe
         3 center
         4 back/side left
         5 back/side right
         6 back/side left
         7 back/side right
         */
        channels.firstChannel = 2; //lfe
        channels.lastChannel = 3;  //center
    
        renderer.block = ^(const AERenderContext *context) {
            AEModuleProcess(oscillator, context);
            AERenderContextOutputToChannels(context,0,channels);
        };
        self.output = [[AEAudioUnitOutput alloc] initWithRenderer:renderer];
    

    Thanks Michael!

  • That's right - if your current content is only 2 channels, if you try to write to more than 2, it'll just write to the first 2. What you want is to use OutputToChannels for every pair (or single channel) you want to output to.

    In this case, you'd call it once for LR, once for RL/RR, once for LFE, once for C. Or whatever =)

  • Ah, that makes sense! Thanks again.

Sign In or Register to comment.