菜鸟教程小白 发表于 2022-12-12 18:00:07

ios - 在附加到 remoteio 音频单元的输入范围的渲染回调中使用循环缓冲区中的音频数据


                                            <p><p>标题几乎概括了我想要实现的目标。我正在尝试在渲染回调中使用 Michael Tyson 的 TPCircularBuffer,而循环缓冲区正在填充传入的音频数据。我想将渲染回调中的音频发送到 RemoteIO 音频单元的输出元素,以便我可以通过设备扬声器听到它。 </p>

<p>音频是交错的 16 位立体声,以 2048 帧的数据包形式传入。以下是我设置 Audio Session 的方式:</p>

<pre><code>#define kInputBus 1
#define kOutputBus 0
NSError *err = nil;
NSTimeInterval ioBufferDuration = 46;
AVAudioSession *session = ;
;
;
;
AudioComponentDescription defaultOutputDescription;
defaultOutputDescription.componentType = kAudioUnitType_Output;
defaultOutputDescription.componentSubType = kAudioUnitSubType_RemoteIO;
defaultOutputDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
defaultOutputDescription.componentFlags = 0;
defaultOutputDescription.componentFlagsMask = 0;

AudioComponent defaultOutput = AudioComponentFindNext(NULL, &amp;defaultOutputDescription);
NSAssert(defaultOutput, @&#34;Can&#39;t find default output.&#34;);

AudioComponentInstanceNew(defaultOutput, &amp;remoteIOUnit);
UInt32 flag = 0;

OSStatus status = AudioUnitSetProperty(remoteIOUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kOutputBus, &amp;flag, sizeof(flag));
size_t bytesPerSample = sizeof(AudioUnitSampleType);
AudioStreamBasicDescription streamFormat = {0};
streamFormat.mSampleRate = 44100.00;
streamFormat.mFormatID = kAudioFormatLinearPCM;
streamFormat.mFormatFlags = kAudioFormatFlagsCanonical;
streamFormat.mBytesPerPacket = bytesPerSample;
streamFormat.mFramesPerPacket = 1;
streamFormat.mBytesPerFrame = bytesPerSample;
streamFormat.mChannelsPerFrame = 2;
streamFormat.mBitsPerChannel = bytesPerSample * 8;
streamFormat.mReserved = 0;

status = AudioUnitSetProperty(remoteIOUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &amp;streamFormat, sizeof(streamFormat));

AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc = render;
callbackStruct.inputProcRefCon = self;
status = AudioUnitSetProperty(remoteIOUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Global, kOutputBus, &amp;callbackStruct, sizeof(callbackStruct));
</code></pre>

<p>这里是音频数据被加载到循环缓冲区并在渲染回调中使用的地方:</p>

<pre><code>#define kBufferLength 2048
-(void)loadBytes:(Byte *)byteArrPtr{
TPCircularBufferProduceBytes(&amp;buffer, byteArrPtr, kBufferLength);
}

OSStatus render(
                void *inRefCon,
                AudioUnitRenderActionFlags *ioActionFlags,
                const AudioTimeStamp *inTimeStamp,
                UInt32 inBusNumber,
                UInt32 inNumberFrames,
                AudioBufferList *ioData)
{
AUDIOIO *audio = (__bridge AUDIOIO *)inRefCon;
AudioSampleType *outSample = (AudioSampleType *)ioData-&gt;mBuffers.mData;
//Zero outSample
memset(outSample, 0, kBufferLength);
int bytesToCopy = ioData-&gt;mBuffers.mDataByteSize;
SInt16 *targetBuffer = (SInt16 *)ioData-&gt;mBuffers.mData;
//Pull audio
int32_t availableBytes;
SInt16 *buffer = TPCircularBufferTail(&amp;audio-&gt;buffer, &amp;availableBytes);
memcpy(targetBuffer, buffer, MIN(bytesToCopy, availableBytes));
TPCircularBufferConsume(&amp;audio-&gt;buffer, MIN(bytesToCopy, availableBytes));
return noErr;
}
</code></pre>

<p>此设置有问题,因为我没有通过扬声器获得任何音频,但我在设备上进行测试时也没有收到任何错误。据我所知,TPCircularBuffer 正在被正确填充和读取。我已按照 Apple 文档设置 Audio Session 。我正在考虑下一步尝试设置 AUGraph,但我想看看是否有人可以为我在这里尝试做的事情提出解决方案。谢谢!</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>对于立体声(每帧 2 个 channel ),每帧的字节数和每数据包的字节数必须是样本大小的两倍(以字节为单位)。就比特而言,每个 channel 的比特数相同。</p>

<p>添加:如果 availableBytes/yourFrameSize 几乎不总是与 inNumberFrames 一样大或更大,您将不会获得太多连续的声音。</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 在附加到 remoteio 音频单元的输入范围的渲染回调中使用循环缓冲区中的音频数据,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/21032267/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/21032267/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 在附加到 remoteio 音频单元的输入范围的渲染回调中使用循环缓冲区中的音频数据