在 AudioUnit 播放回调中从 AudioBuffer->mdata 播放音频
Posted
技术标签:
【中文标题】在 AudioUnit 播放回调中从 AudioBuffer->mdata 播放音频【英文标题】:Playing audio from AudioBuffer->mdata in AudioUnit playback callback 【发布时间】:2016-08-22 14:23:01 【问题描述】:一整天以来,我一直在寻找并尝试解决以下问题。还没有成功
好的,所以我一直在使用苹果示例代码项目名称 WiTap
使用 NSInputStreams
和 NSOutputStreams
通过 wifi 与两个设备进行黑白通信我已经能够传输数据(音频数据)黑白设备成功。
但是在目标设备上我接收数据并将其填充到音频缓冲区中,如下所示:
bytesRead = [self.inputStream read:anAudioBuffer.mData maxLength:anAudioBuffer.mDataByteSize];
而anAudioBuffer
本身声明如下
anAudioBuffer.mNumberChannels = 1;
anAudioBuffer.mDataByteSize = 512 * 2;
anAudioBuffer.mData = malloc( 512 * 2 );
现在我在 Apple 示例代码的 AudioUnit 回调中以 someObject.anAudioBuffer
的身份访问此音频缓冲区
如下
static OSStatus playbackCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
// Notes: ioData contains buffers (may be more than one!)
// Fill them up as much as you can. Remember to set the size value in each buffer to match how
// much data is in the buffer.
for (int i=0; i < ioData->mNumberBuffers; i++) // in practice we will only ever have 1 buffer, since audio format is mono
AudioBuffer buffer = ioData->mBuffers[i];
// copy temporary buffer data to output buffer
UInt32 size = min(buffer.mDataByteSize, someObject.anAudioBuffer.mDataByteSize); // dont copy more data then we have, or then fits
memcpy(buffer.mData, someObject.anAudioBuffer.mData, size);
buffer.mDataByteSize = size; // indicate how much data we wrote in the buffer
// uncomment to hear random noise
/*
UInt16 *frameBuffer = buffer.mData;
for (int j = 0; j < inNumberFrames; j++)
frameBuffer[j] = arc4random();
*/
return noErr;
现在我想播放从someObject.anAudioBuffer
复制的字节到本地变量buffer
我确实注意到这部分代码与播放音频有关
/*
UInt16 *frameBuffer = buffer.mData;
for (int j = 0; j < inNumberFrames; j++)
frameBuffer[j] = arc4random();
*/
现在arc4random
用于播放静态噪音。尽我最大的努力并在整个互联网上搜索,我无法弄清楚如何播放我自己的字节以及这段代码 b/w /* */
例如,这条线的目的是什么?
UInt16 *frameBuffer = buffer.mData;
我如何用我自己的数据填充这个frameBuffer
来播放。
谁能指导我。我有太多时间浪费在这个看似微不足道的问题上。
如果需要,我可以提供更多详细信息。
期待中……
【问题讨论】:
【参考方案1】:您必须将 mBuffer.mData[0] 指向的内存(或数组)完全填充为 inNumberFrames 个音频样本帧(无论您是否有这些样本可用)。您可以在噪声生成器中执行此操作,而不是在您的 memcopy 代码中。
同样保持 mDataByteSize 不变,因为它是回调的输入,而不是输入输出。音频回调是一种需求,而不是可选的请求。
【讨论】:
我的源数据填写在someObject.anAudioBuffer
someObject.anAudioBuffer
你能指导我如何完成填写任务,即填写frameBuffer[j]
与您在 for 循环中所做的相同,除了使用来自 someObject 而不是 rnd() 的数据。
对不起,如果我听起来太新手,但我收集到你在循环中建议这个 frameBuffer[j] = someObject.anAudioBuffer.mData
如果是这样的话,我仍然不成功
您是否要复制 = ...mData[j] 中的样本?
as frameBuffer = buffer.mData;
所以我们需要在 frameBuffer[j] 中写入音频数据,不是吗?我在someObject.anAudioBuffer.mData
中有我的数据作为字节【参考方案2】:
所以我找到了答案
这很简单,但我不知道读取 C 指针数组。我所要做的就是:
UInt16 *frameBuffer = buffer.mData;
for (int j = 0; j < inNumberFrames; j++)
frameBuffer[j] = *(frameBuffer + j);
虽然这个UInt16 *frameBuffer = buffer.mData;
使frameBuffer
指向buffer.mData
的起始索引,但以下
*(frameBuffer + j);
是C读取next指针的方式。
在写完frameBuffer[j] = *(frameBuffer + j);
之后,我的流中的音频播放起来就像一个魅力。
很高兴知道这是否对其他人也有帮助。
从 here 找到 C 指针数组信息
【讨论】:
确实有帮助。起初对我来说没有意义,仍然不清楚发生了什么以及我是如何让它工作的。对我来说,当我把它切换到这个时它起作用了。帧缓冲[j] = 帧缓冲[+j];谢谢!以上是关于在 AudioUnit 播放回调中从 AudioBuffer->mdata 播放音频的主要内容,如果未能解决你的问题,请参考以下文章
启动 AVAssetReader 停止对远程 I/O AudioUnit 的回调
AudioUnit Render 回调中的 Objective-C/Swift 用法