Технические вопросы и ответы QA1606

Когда экран заблокирован, график Обработки Аудиоустройства - Гарантирующий воспроизведение аудио продолжается

Q: Я использую AUGraph, и я хотел бы, чтобы мое аудио продолжало играть во время экранной блокировки. Есть ли что-либо еще, что я должен сконфигурировать в дополнение к Аудио Сеансу kAudioSessionCategory_MediaPlayback категорию, чтобы позволить моему AURenderCallback продолжать вызываться?

A: Я использую AUGraph, и я хотел бы, чтобы мое аудио продолжало играть во время экранной блокировки. Есть ли что-либо еще, что я должен сконфигурировать в дополнение к Аудио Сеансу kAudioSessionCategory_MediaPlayback категорию, чтобы позволить моему AURenderCallback продолжать вызываться?

Когда График Обработки Аудиоустройства используется для Вывода только, размер рендеринга I/O по умолчанию изменяется от 22 миллисекунд (1 024 выборки 44.1 кГц) к 88 миллисекундам (4 096 выборок 44.1 кГц), когда заблокирован экран. Это сделано для сохранения питания, так как нет никакого взаимодействия с пользователем с экраном, как только экран идет темный.

Если приложение не составляет это изменение, любое Аудиоустройство попросило обеспечивать, 4 096 выборок возвратят ошибку начиная с kAudioUnitProperty_MaximumFramesPerSlice установка будет меньше, чем это значение.

Удаленное Аудиоустройство I/O по умолчанию уже сконфигурировано для 4 096 максимальных кадров на часть, проблема влияет на все другие Аудиоустройства, используемые в графике.

Если приложение намеревается продолжать воспроизведение, когда экран заблокирован, это - клиентская ответственность измениться kAudioUnitProperty_MaximumFramesPerSlice свойство соответственно для каждого Аудиоустройства, используемого для обрабатывания запросов для 4 096 выборок.

Перечисление 1  Типичная установка Графика Аудиоустройства, конфигурирующая kAudioUnitProperty_MaximumFramesPerSlice свойство для микшера.

// audio render procedure
static OSStatus renderProc(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags,
                           const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber,
                           UInt32 inNumberFrames, AudioBufferList *ioData)
{
    // your audio render code here

    return noErr;
}

AUGraph   mGraph;
AudioUnit mMixer;

- (void)initializeAUGraph
{
    // create two AudioComponentDescriptions for the AUs we want in the graph
    // output unit
    AudioComponentDescription output_desc = {kAudioUnitType_Output, kAudioUnitSubType_RemoteIO,
                                             kAudioUnitManufacturer_Apple, 0, 0};
     // multichannel mixer unit
    AudioComponentDescription mixer_desc = {kAudioUnitType_Mixer, kAudioUnitSubType_MultiChannelMixer,
                                            kAudioUnitManufacturer_Apple, 0, 0};
    AUNode outputNode;
    AUNode mixerNode;
    CAStreamBasicDescription desc;

    // create a new AUGraph
    NewAUGraph(&mGraph);

    // create a node in the graph that is an AudioUnit, using the supplied AudioComponentDescription
    // to find and open that unit
    AUGraphAddNode(mGraph, &output_desc, &outputNode);
    AUGraphAddNode(mGraph, &mixer_desc, &mixerNode);

    // connect a node's output to a node's input
    AUGraphConnectNodeInput(mGraph, mixerNode, 0, outputNode, 0);

    // open the graph AudioUnits are open but not initialized (no resource allocation occurs here)
    AUGraphOpen(mGraph);

    // get the mixer audio unit since we need to configure it
    AUGraphNodeInfo(mGraph, mixerNode, NULL, &mMixer);

    // set bus count
    UInt32 numbuses = 1;

    AudioUnitSetProperty(mMixer, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &numbuses,
                         sizeof(numbuses));

    // setup render callback struct
    AURenderCallbackStruct rcbs;
    rcbs.inputProc = &renderProc;
    rcbs.inputProcRefCon = self;

    // Set a callback for the specified node's specified input
    AUGraphSetNodeInputCallback(mGraph, mixerNode, 0, &rcbs);

    // set input stream format to what we want
    UInt32 size = sizeof(desc);
    AudioUnitGetProperty(mMixer, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &desc, &size);

    desc.ChangeNumberChannels(2, false); 
    desc.mSampleRate = 44100.0;

    AudioUnitSetProperty(mMixer, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &desc,
                         sizeof(desc));

    // set output stream format to what we want
    AudioUnitGetProperty(mMixer, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &desc, &size);

    desc.ChangeNumberChannels(2, false); 
    desc.mSampleRate = 44100.0;

    AudioUnitSetProperty(mMixer, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &desc,
                         sizeof(desc));

    // set the mixer unit to handle 4096 samples per slice since we want to keep rendering during screen lock
    UInt32 maxFPS = 4096;
    AudioUnitSetProperty(mMixer, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0,
                         &maxFPS, sizeof(maxFPS));

    // now that we've set everything up we can initialize the graph, this will also validate the connections
    AUGraphInitialize(mGraph);
}


История версии документа


ДатаПримечания
15.03.2010

Передовая статья.

14.01.2010

Исправленное значение для максимума AU по умолчанию структурирует на часть.

14.12.2009

Передовая статья

09.12.2009

Новый документ, обсуждающий, как гарантировать воспроизведение аудио, в то время как телефон заблокирован при использовании многократных Аудиоустройств.