AudioBufferList 的 AurioTouch 用途

Posted

技术标签:

【中文标题】AudioBufferList 的 AurioTouch 用途【英文标题】:AurioTouch purpose of AudioBufferList 【发布时间】:2015-12-30 08:03:00 【问题描述】:

在苹果提供的aurioTouch项目中,听说performRender()函数下AudioController文件中的AudioBufferList ioData是把麦克风的音频数据传送到音频播放器的?谁能证实这一点?代码如下:

// Render callback function
static OSStatus performRender (void                         *inRefCon,
                           AudioUnitRenderActionFlags   *ioActionFlags,
                           const AudioTimeStamp         *inTimeStamp,
                           UInt32                       inBusNumber,
                           UInt32                       inNumberFrames,
                           AudioBufferList              *ioData)

OSStatus err = noErr;
if (*cd.audioChainIsBeingReconstructed == NO)

    // we are calling AudioUnitRender on the input bus of AURemoteIO
    // this will store the audio data captured by the microphone in ioData
    err = AudioUnitRender(cd.rioUnit, ioActionFlags, inTimeStamp, 1, inNumberFrames, ioData);

    // filter out the DC component of the signal
    cd.dcRejectionFilter->ProcessInplace((Float32*) ioData->mBuffers[0].mData, inNumberFrames);

    // based on the current display mode, copy the required data to the buffer manager
    if (cd.bufferManager->GetDisplayMode() == aurioTouchDisplayModeOscilloscopeWaveform)
    
        cd.bufferManager->CopyAudioDataToDrawBuffer((Float32*)ioData->mBuffers[0].mData, inNumberFrames);
    

    else if ((cd.bufferManager->GetDisplayMode() == aurioTouchDisplayModeSpectrum) || (cd.bufferManager->GetDisplayMode() == aurioTouchDisplayModeOscilloscopeFFT))
    
        if (cd.bufferManager->NeedsNewFFTData())
            cd.bufferManager->CopyAudioDataToFFTInputBuffer((Float32*)ioData->mBuffers[0].mData, inNumberFrames);
    

    // mute audio if needed
    if (*cd.muteAudio)
    
        for (UInt32 i=0; i<ioData->mNumberBuffers; ++i)
            memset(ioData->mBuffers[i].mData, 0, ioData->mBuffers[i].mDataByteSize);
    


return err;

【问题讨论】:

【参考方案1】:

RemoteIO 音频单元是一个能够访问音频硬件输入(麦克风)和输出(扬声器)的组件。

输入从麦克风或缓冲区获取数据。输出将音频数据放入扬声器或缓冲区。

由于输入是从麦克风获取数据的,因此您可以对它进行任何操作。您可以将其保存到文件中。您可以将其发送到网络流。你可以把它留在记忆中。

对于输出,音频输出设备和扬声器正在请求播放数据。

因此,在您提供的软件中,他们所做的只是将麦克风连接到扬声器作为直接音频传递。

音频系统会定期调用函数performRender(),它会显示“给我一些音频样本来播放”。在该函数内部,它从以下行中的麦克风生成的数据中读取:AudioUnitRender(cd.rioUnit, ioActionFlags, inTimeStamp, 1, inNumberFrames, ioData);

您可以替换 performRender() 的内部并以编程方式制作自己的音频数据,从文件或缓冲区中读取等。他们所做的只是从麦克风数据中读取。

至于您关于 AudioBufferList 的用途的问题。这只是提供了一个缓冲区列表,其中每个缓冲区都是一个通道。有时您有多个音频通道,具体取决于格式(单声道、立体声、立体声交错、混音器通道等)和单元类型。

【讨论】:

感谢您如此详细的回复,这真的让事情变得清晰了。这是一个非常广泛的问题,但我真的很难使用这个名为 Multipeer Connectivity 的框架将麦克风数据发送到另一部手机,而且我一直觉得音频内容不够深入,所以我不得不问它。我尝试初始化 NSStream 并将“iodata”发送到另一部手机。虽然它收到了数据,但它什么也没做,这现在是有道理的,因为我没有向它发送完整的麦克风数据。我的问题是如何将麦克风数据流实时发送到另一部手机? 是的,非常广泛的问题。我对你提到的框架了解不多。但是,当您进行流式传输时,您需要解决以下问题和限制:1) 带宽限制? (例如 LAN 与 WAN ) 2)您的网络通信协议是可靠的还是不可靠的(rg tcp vs udp)?如果不可靠,您将如何处理数据丢失? 3) 定义您的实时延迟约束。 (30 毫秒、100 毫秒、2 秒?)没有系统作为 0 延迟。 4) 你将如何压缩数据? (Opus 非常适合低延迟流式传输) 5)您是向一个人还是多个人发送数据? 但是我不能在函数 AudioUnitRender(cd.rioUnit, ioActionFlags, inTimeStamp, 1, inNumberFrames, ioData); 中发送参数换个手机不行吗?不知何故,它需要被制成该数据的压缩版本,然后一起发送。 您关心的信息在ioData中。那就是原始流所在的位置。如果您愿意,可以将其压缩并通过网络发送。音频流不是一项简单的任务。您需要考虑很多额外的事情:缓冲、溢出、欠载、边缘情况、网络带宽、压缩、丢失、丢失隐藏、网络抖动。看到这个帖子***.com/questions/30948346/… @jaybers 你能帮我用我自己的音频数据填充麦克风缓冲区吗?我该怎么办?我基本上是在尝试为虚拟输入设备填充音频缓冲区

以上是关于AudioBufferList 的 AurioTouch 用途的主要内容,如果未能解决你的问题,请参考以下文章

将 AudioBufferList 转换为 CMSampleBuffer 会产生意外结果

如何在渲染回调中交错非交错的 AudioBufferList?

AudioUnit inputCallback 与 AudioUnitRender -> audioBufferList.mBuffers[0].mDataByteSize 之间不匹配!= in

aurioTouch2 录音问题。我需要将数据从一个 AudioBufferList 添加到另一个

用于AUHAL单元的AudioBufferList,其输出流格式被压缩。

如何将该 UnsafeMutablePointer<UnsafeMutablePointer<Float>> 变量转换为 AudioBufferList?