使用音频单元播放音频流,出现噼啪声

问题描述 投票:0回答:1

在 iOS 应用程序中,

使用

TPCircularBuffer
Audio Unit.

从 BLE 播放音频流

声音播放得很好,但是当缓冲区为空且没有字节可播放时,会产生噼啪声。

这是我的音频流配置,

  AudioStreamBasicDescription audioFormat;
        audioFormat.mSampleRate         = 8000.00;
        audioFormat.mFormatID           = kAudioFormatLinearPCM;
        audioFormat.mFormatFlags        = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsPacked;
        // || kAudioFormatFlagsNativeFloatPacked || kAudioFormatFlagIsSignedInteger
        //kAudioFormatFlagIsSignedInteger
        audioFormat.mFramesPerPacket    = 1;
        audioFormat.mChannelsPerFrame   = 1;
        audioFormat.mBitsPerChannel     = 32;// Update when required
        audioFormat.mBytesPerPacket     = 4; // Update when required
        audioFormat.mBytesPerFrame      = 4; // Update when required
    

下面是Audio Unit的播放功能

static OSStatus playbackCallback(void *inRefCon, 
                                 AudioUnitRenderActionFlags *ioActionFlags, 
                             const AudioTimeStamp *inTimeStamp, 
                             UInt32 inBusNumber, 
                             UInt32 inNumberFrames, 
                             AudioBufferList *ioData) {

//1
for (int i=0; i < ioData->mNumberBuffers; i++) { 

    IosAudioController *THIS = (__bridge IosAudioController *)inRefCon;

    int bytesAskingByPlayback = ioData->mBuffers[i].mDataByteSize;

    SInt16 *targetBuffer = (SInt16*)ioData->mBuffers[i].mData;

    // Pull audio from playthrough buffer
    int32_t availableBytesFromBuffer;

    SInt16 *sBuffer = TPCircularBufferTail(iosAudio.addressOfTPBuffer, &availableBytesFromBuffer);
    
    int willRemainBytes = availableBytesFromBuffer - bytesAskingByPlayback;

    if (willRemainBytes > 0) {
        memcpy(targetBuffer, sBuffer, bytesAskingByPlayback);
        TPCircularBufferConsume(iosAudio.addressOfTPBuffer,bytesAskingByPlayback);
        } else {


        //Note: Mostly need to update code here

                memcpy(targetBuffer, sBuffer, availableBytesFromBuffer);

            TPCircularBufferConsume(iosAudio.addressOfTPBuffer, availableBytesFromBuffer);

    }
}
    return noErr;
}

缓冲区大小为16384

一些解决方案说我会用 0 填充目标缓冲区以静音,但它不起作用。

一些解决方案说我可以用以前的值填充目标缓冲区以填补空白。

ios objective-c audio audio-streaming audiounit
1个回答
0
投票

但是当缓冲区为空且没有字节可播放时。

您需要从这里开始并确定为什么会发生这种情况。理想情况下,这种情况永远不应该发生。如果确实发生了,那么这种情况应该很少见,并且有明确的原因。如果上游已经暂停,那么您需要暂停下游。如果存在网络延迟,那么您需要增加缓冲区的大小。

任何时候你注入一个常数值,无论是零还是最后收到的值,你都会注入高频噪声。这听起来像一声小爆裂声。如果你经常这样做,那么它就会破裂。有一些技术可以解决这个问题,但它们相当复杂,在解决潜在的运行不足问题之前,您不应该采用这些技术。

如果您的上游有可变的延迟,那么您需要在统计下游之前缓冲一点(10ms、50ms、2000ms,这取决于它的可变程度)。如果您的缓冲区已耗尽,您需要暂停下游,直到可以再次建立缓冲区。

有时,偶尔“弹出”以避免暂停下游是值得的,这时就会出现“用零填充”或“用最后一个值填充”之类的建议。但是,如果您每秒弹出多次(那就是通常是什么“噼啪声”),这可能意味着您在开始下游之前没有足够的缓冲。

© www.soinside.com 2019 - 2024. All rights reserved.