AudioUnit 输入示例
Posted
技术标签:
【中文标题】AudioUnit 输入示例【英文标题】:AudioUnit Input Samples 【发布时间】:2012-06-26 18:40:23 【问题描述】:因此,我的 AudioUnit 从 ios 中的麦克风/线路输入中获取数据时遇到了一些问题。我能够将所有内容设置为我认为可以的,并且它正在调用我的 recordingCallback,但是我从缓冲区中获取的数据不正确。它总是返回完全相同的东西,主要是零和随机大数。有谁知道这可能是什么原因造成的。我的代码如下。
设置音频单元
OSStatus status;
// Describe audio component
AudioComponentDescription desc;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_RemoteIO;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
// Get component
AudioComponent inputComponent = AudioComponentFindNext(NULL, &desc);
status = AudioComponentInstanceNew(inputComponent, &audioUnit);
// Enable IO for recording
UInt32 flag = 1;
status = AudioUnitSetProperty(audioUnit,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Input,
kInputBusNumber,
&flag,
sizeof(flag));
// Disable playback IO
flag = 0;
status = AudioUnitSetProperty(audioUnit,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Output,
kOutputBusNumber,
&flag,
sizeof(flag));
// Describe format
AudioStreamBasicDescription audioFormat;
audioFormat.mSampleRate = 44100.00;
audioFormat.mFormatID = kAudioFormatLinearPCM;
audioFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked |kAudioFormatFlagIsNonInterleaved;
audioFormat.mFramesPerPacket = 1;
audioFormat.mChannelsPerFrame = 1;
audioFormat.mBitsPerChannel = 32;
audioFormat.mBytesPerPacket = 4;
audioFormat.mBytesPerFrame = 4;
// Apply format
status = AudioUnitSetProperty(audioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
kInputBusNumber,
&audioFormat,
sizeof(audioFormat));
// Set input callback
AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc = recordingCallback;
callbackStruct.inputProcRefCon = (__bridge void*)self;
status = AudioUnitSetProperty(audioUnit,
kAudioOutputUnitProperty_SetInputCallback,
kAudioUnitScope_Global,
kInputBusNumber,
&callbackStruct,
sizeof(callbackStruct));
status = AudioUnitInitialize(audioUnit);
输入回调
static OSStatus recordingCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
AudioBufferList bufferList;
bufferList.mNumberBuffers = 1;
bufferList.mBuffers[0].mDataByteSize = 4;
bufferList.mBuffers[0].mNumberChannels = 1;
bufferList.mBuffers[0].mData = malloc(sizeof(float)*inNumberFrames); //
InputAudio *input = (__bridge InputAudio*)inRefCon;
OSStatus status;
status = AudioUnitRender([input audioUnit],
ioActionFlags,
inTimeStamp,
inBusNumber,
inNumberFrames,
&bufferList);
float* result = (float*)&bufferList.mBuffers[0].mData;
if (input->counter == 5)
for (int i = 0;i<inNumberFrames;i++)
printf("%f ",result[i]);
input->counter++;
return noErr;
任何人都曾遇到过类似的问题或在我的代码中看到明显错误的地方。提前感谢您的帮助!
我的所有内容都基于Michael Tysons Core Audio RemoteIO code
【问题讨论】:
这是不久前的,但以防有人看到并复制代码:您不应该在时间敏感的代码中使用 malloc。在别处分配缓冲区。 (或懒惰地分配一次。) 【参考方案1】:如果我没记错的话,您在回调中从音频缓冲区获取的样本不是浮点数,它们是 SInt16。尝试像这样铸造样本:
SInt16 *sn16AudioData= (SInt16 *)(bufferList.mBuffers[0].mData);
这些应该是最大值和最小值:
#define sn16_MAX_SAMPLE_VALUE 32767
#define sn16_MIN_SAMPLE_VALUE -32768
【讨论】:
我也是这样做的,只是在这个例子中我忘了把它改回 SInt16。似乎一直返回给我的只是我根本无法使用的垃圾数据。【参考方案2】:我基本上是尝试用非常相似的代码做同样的事情,但使用的是AudioGraph()
。我遇到了同样的问题,我的麦克风输出数据为零,直到我添加了这条线才能让它工作
Status = AUGraphConnectNodeInput(graph, ioNode, 1, ioNode, 0);
由于您没有使用图表,因此您需要使用 kAudioUnitProperty_MakeConnectio
n 调用 AudioUnitSetProperty()
并传递完整的 AudioUnitConnection 结构
【讨论】:
我能否获得您正在使用的代码的副本?如果是这样,请告诉我,我会给你我的电子邮件地址。 是的,我的网站是link 转到联系我们页面。我会把创建函数发给你。以上是关于AudioUnit 输入示例的主要内容,如果未能解决你的问题,请参考以下文章
配置 Mac OS X AudioUnit 以提供 SignedInteger 示例