音频单元输入样本

4

我在iOS上使用AudioUnit从麦克风/线路输入获取数据时遇到了一些问题。我已经对所有设置进行了调整,并且调用了我的录音回调函数,但是从缓冲区中获取的数据不正确。它总是返回完全相同的东西,大多数是零和随机的大数字。有人知道可能是什么原因吗?我的代码如下。

设置音频单元

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。请在其他地方分配缓冲区(或者懒惰地分配一次)。 - Joris Weimar
2个回答

2

如果我没记错的话,在回调函数中获取的音频缓冲区样本不是浮点数,而是SInt16。尝试像这样进行强制转换:

SInt16 *sn16AudioData= (SInt16 *)(bufferList.mBuffers[0].mData);

以下应该是最大值和最小值:

#define sn16_MAX_SAMPLE_VALUE 32767
#define sn16_MIN_SAMPLE_VALUE -32768

我也这样做,只是在这个例子中我忘记改回SInt16。它似乎一直返回一些无用的数据,我根本无法使用。 - MZimmerman6

0

我基本上是在尝试使用非常相似的代码,但是使用AudioGraph()来完成同样的事情。我遇到了同样的问题,从麦克风输出数据中得到了零,并且直到我添加了这行代码才使其正常工作。

Status = AUGraphConnectNodeInput(graph, ioNode, 1, ioNode, 0);

由于您未使用图形,您将需要使用完整的AudioUnitConnection结构调用AudioUnitSetProperty()并传递kAudioUnitProperty_MakeConnection

我能否得到你正在使用的代码副本?如果可以,请告诉我,我会给你我的电子邮件地址。 - MZimmerman6
是的,我的网站是链接,请前往联系我们页面。我会发送给您创建函数。 - Dan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接