3

モノラル オーディオ イベント (さまざまな周波数で短いビープ音) を再生するコードがあります。AudioOutputUnit を作成して停止し、オーディオを再生する必要があるときはいつでも。始めます。必要な時間再生したら、停止します。

シンプルに聞こえます。

ただし、私の iPhone 4S (iOS 5.1 を使用) では AudioOutputUnitStart が返されるまでに通常 180 ミリ秒かかります。これは長すぎます。

これが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 プロパティを非常に小さい値 (5ms など) にする フレームレートを下げる (48kHz、44.1kHz、8kHz を試した)

私が何をしても... audiounitが初めて開始されたとき、AudioOutputUnitStartは160-180ms後にのみ返されます。停止してすぐに開始すると、約 5 メートルしかかからず、はるかに許容範囲内です。

私のアプリケーションのレイテンシはかなり重要であり、180 ミリ秒は絶対に受け入れられません。

助言がありますか?似たような質問をする人を何人か見たことがありますが、通常は答えがありません。

今回は状況が違うことを願っています:)

4

1 に答える 1

3

Audio Unit の起動遅延に対処する方法は、Audio Unit を停止するのではなく、必要な時間よりも前に起動することです。代わりに、短いバッファー用にオーディオ セッションを構成し、Audio Unit レンダー コールバック バッファーを目的のサウンドで満たすまで無音で満たしてください。次に、サウンドの後、停止するのではなく、バッファーを無音で満たすことに戻ります。

于 2012-04-13T22:20:51.500 に答える