2012-04-13 2 views
2

У меня есть код, который воспроизводит монофоническое событие (короткие звуковые сигналы на разных частотах). Создаю AudioOutputUnit, остановите его и всякий раз, когда мне нужно воспроизвести аудио. Я начинаю. Когда я сыграл его в течение необходимого времени, я останавливаю его.AudioOutputUnitStart очень медленный

Звучит достаточно просто.

Однако AudioOutputUnitStart займет обычно 180 мс, чтобы вернуться на мой iPhone 4S (с iOS 5.1), это слишком много.

Вот создание/инициализация AudioOutputUnit

void createAOU() 
{ 
    m_init = false; 
    // find the default playback output unit 
    AudioComponentDescription defaultOutputDescription; 
    defaultOutputDescription.componentType = kAudioUnitType_Output; 
    defaultOutputDescription.componentSubType = kAudioUnitSubType_RemoteIO; 
    defaultOutputDescription.componentManufacturer = kAudioUnitManufacturer_Apple; 
    defaultOutputDescription.componentFlags = 0; 
    defaultOutputDescription.componentFlagsMask = 0; 

    // Get the default playback output unit 
    AudioComponent defaultOutput = AudioComponentFindNext(NULL, &defaultOutputDescription); 
    if (defaultOutput == NULL) 
     return; 

    OSErr err = AudioComponentInstanceNew(defaultOutput, &m_toneUnit); 
    if (err != noErr) 
     return; 

    // single channel, floating point, linear PCM 
    AudioStreamBasicDescription streamFormat; 
    streamFormat.mSampleRate = m_framerate; 
    streamFormat.mFormatID = kAudioFormatLinearPCM; 
    streamFormat.mFormatFlags = 
    kLinearPCMFormatFlagIsFloat | 
    kAudioFormatFlagsNativeEndian | kLinearPCMFormatFlagIsPacked; 
    streamFormat.mBytesPerPacket = sizeof(float); 
    streamFormat.mFramesPerPacket = 1; 
    streamFormat.mBytesPerFrame = sizeof(float); 
    streamFormat.mChannelsPerFrame = 1; 
    streamFormat.mBitsPerChannel = sizeof(float) * 8; 
    err = AudioUnitSetProperty (m_toneUnit, 
           kAudioUnitProperty_StreamFormat, 
           kAudioUnitScope_Input, 
           0, 
           &streamFormat, 
           sizeof(AudioStreamBasicDescription)); 
    if (err != noErr) 
     return; 

    // Attach callback to default output 
    AURenderCallbackStruct input; 
    input.inputProc = RenderTone; 
    input.inputProcRefCon = this; 
    err = AudioUnitSetProperty(m_toneUnit, 
           kAudioUnitProperty_SetRenderCallback, 
           kAudioUnitScope_Input, 
           0, 
           &input, 
           sizeof(input)); 
    if (err != noErr) 
     return; 

    float aBufferLength = 0.001; // In seconds 
    AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, 
          sizeof(aBufferLength), &aBufferLength); 

    err = AudioUnitInitialize(m_toneUnit); 
    if (err != noErr) 
     return; 
    reset(); 
    m_init = true; 
} 

Чтобы начать, я бы просто позвонить:

OSErr err = AudioOutputUnitStart(m_toneUnit); 

Когда сделано:

OSErr err = AudioOutputUnitStop(m_toneUnit); 

Я пробовал различные вещи: , что делает свойство kAudioSessionProperty_PreferredHardwareIOBufferDuration t о очень малое значение (например, 5мс) Уменьшите частоту кадров (пытался 48кГц, 44,1, 8kHz)

Независимо от того, что я делаю ... первый раз запускается AudioUnit, AudioOutputUnitStart возвращается только после того, как 160-180ms. Если я остановлюсь и начну сразу, тогда это займет всего около 5 м, что гораздо более приемлемо.

Задержка в моей заявке весьма важна, и 180 мс определенно неприемлемо.

Любые предложения? Я видел, как несколько человек задавали подобные вопросы, но у них обычно не было ответа.

Я надеюсь, что на этот раз все будет по-другому :)

+0

Возможно, вы уже об этом подумали - но добавляет/удаляет работу renderCallback здесь? Также видел это (хотя ваш буфер крошечный): http://stackoverflow.com/questions/5690460/objective-c-audiooutputunitstart-takes-a-long-time-to-start-possible-workaroun –

+0

У меня на самом деле нет подумал об удалении обратного вызова; в обратном вызове звуковая волна фактически генерируется, поэтому звуковой буфер может быть крошечным. попробует – jyavenard

ответ

2

Чтобы справиться с блоком аудио пуска задержки, чтобы начать Аудиоблок впереди времени, необходимого, а не остановить его. Вместо этого просто настройте сеанс аудио для коротких буферов, а затем залейте буферизацию обратного вызова Audio Unit, пока не настанет время заполнить их желаемым звуком. Затем, после вашего звука, вернитесь, чтобы заполнить буферы молчанием, а не останавливаться.

+0

, проблема, о которой я беспокоился, заключается в том, что вы знаете, что во всем мире работает 2-й поток, а с моим коротким звуковым буфером (чтобы уменьшить латентность) это наверняка повлияет на производительность честного бита. – jyavenard

+1

@jyavenard: IIRC, постоянно работающий RemoteIO Audio Unit с очень короткими буферами использует менее 1% циклов процессора на iPhone 4. Любое влияние на производительность, вероятно, будет совершенно незаметным. – hotpaw2

Смежные вопросы