2012-04-13 7 views
2

모노 오디오 이벤트 (다양한 주파수에서 짧은 경고음)를 재생하는 코드가 있습니다. AudioOutputUnit을 만들고, 중지하고, 오디오를 재생해야 할 때마다 만듭니다. 나는 그것을 시작한다. 내가 필요한 시간 동안 그것을했을 때, 나는 그것을 멈춘다.AudioOutputUnitStart very slow

소리가 충분히 간단합니다.

그러나 AudioOutputUnitStart는 내 iPhone 4S (iOS 5.1 사용)에서 돌아 오는 데 보통 180 밀리가 걸릴 것으로 예상됩니다. 여기

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; 
} 

그것을 시작하려면 AudioOutputUnit의 생성/초기화, 나는 단순히 부를 것이다 :

OSErr err = AudioOutputUnitStart(m_toneUnit); 

을 수행 할 때 :

OSErr err = AudioOutputUnitStop(m_toneUnit); 

나는 시도했다 다양한 것들 : kAudioSessionProperty_PreferredHardwareIOBufferDuration 속성을 만드는 중 t 오 (5ms의 같은) 매우 작은 값에 상관없이 내가 뭘 프레임 속도 (시도 48kHz의, 44.1kHz로, 8kHz의)

을 줄일 수 없다 ...의 AudioUnit가 시작 처음 AudioOutputUnitStart은 160-180ms 후 반환합니다. 내가 멈추고 바로 시작하면 약 5m가 더 잘 받아 들여집니다.

내 응용 프로그램의 지연 시간은 중요하며 180ms는 확실히 허용되지 않습니다.

제안 사항? 나는 비슷한 질문을하는 사람들을 보았지만 대개 답을 얻지 못했습니다.

나는이 시간 일을 오디오 장치 시동 지연 시간을 다루는 다른 :

+0

이미 생각해 봤 겠지만 여기에 renderCallback 작업을 추가/제거합니까? 또한 이것을 보았다 (귀하의 버퍼가 작음) : http://stackoverflow.com/questions/5690460/objective-c-audiooutputunitstart-takes-a-long-time-to-start-possible-workaroun –

+0

콜백 제거 생각; 콜백에서 사운드 웨이브가 실제로 생성되므로 오디오 버퍼가 작아 질 수 있습니다. – jyavenard

답변

2

방법이 될 것입니다 희망하고있어 앞으로 필요한 시간의 오디오 장치를 시작하고 중지하지 않는 것입니다. 대신 짧은 버퍼에 대한 오디오 세션을 구성한 다음 원하는 사운드를 채울 때까지 오디오 장치 렌더링 콜백 버퍼를 무음으로 채 웁니다. 그런 다음 소리를 내고 나서 멈추지 않고 침묵으로 완충액을 채우십시오.

+0

을 시도 할 것입니다. 제가 염려했던 문제는 두 번째 스레드가 항상 실행 중이며 대기 시간을 줄이기 위해 짧은 오디오 버퍼를 사용한다는 것이 성능에 상당한 영향을 미칠 것이라는 것입니다. – jyavenard

+1

@jyavenard : IIRC, 매우 짧은 버퍼를 가진 지속적으로 실행되는 RemoteIO 오디오 장치는 iPhone 4에서 CPU주기의 1 % 미만을 사용합니다. 성능에 미치는 영향은 거의 눈에 띄지 않습니다. – hotpaw2