使用kAudioUnitType_FormatConverter类型的AudioUnit从FFmpeg重新采样LinearPCM数据

时间:2016-06-20 10:28:42

标签: ios audio ffmpeg

我正在尝试在iOS上播放音频使用AudioUnit。因为默认采样率是44100而且我有几个不同采样率的音频流,例如32000,48000等,所以我试图设置AVAudioSession的preferredSampleRate和preferredIOBufferDuration根据音频流。

但是我发现根据preferredSampleRate很难得到一个合适的preferredIOBufferDuration,似乎必须根据preferredSampleRate设置preferredIOBufferDuration,否则可能会有噪音。

所以现在我正在尝试将各种音频流重新采样到默认的硬件采样率(44100Hz),使用kAudioUnitType_FormatConverter的AudioUnit。

我使用AUGraph和FormatConverter单元和remoteIO单元来做这个。现在看来我成功地为kAudioUnitScope_Output设置了kAudioUnitProperty_SampleRate(回读的kAudioUnitProperty_SampleRate属性确实是44100.但是当输入音频流不是44100时也会有噪音虽然当输入音频流最初为44100 Hz时听起来很正常。一切看起来都像我没有使用FormatConverter并直接将数据流传输到remoteIO单元(44100没问题,而其他没有)。

我想知道我的问题在哪里。它根本不进行重采样,还是输出数据错误?有没有人有FormatConverter AudioUnit的经验?任何帮助将不胜感激。

我的AUGraph:

AUGraphConnectNodeInput(_processingGraph, converterNode, 0, remoteIONode, 0);

转换器单元:(输入格式为FFMpeg的AV_SAMPLE_FMT_FLTP)

UInt32 bytesPerFrame = bitsPerChannel / 8;
UInt32 bytesPerPacket = bytesPerFrame * 1;

AudioStreamBasicDescription streamDescription = {
    .mSampleRate    = spec->sample_rate,
    .mFormatID      = kAudioFormatLinearPCM,
    .mFormatFlags   = formatFlags,
    .mChannelsPerFrame  = spec->channels,
    .mFramesPerPacket   = 1,
    .mBitsPerChannel    = bitsPerChannel,
    .mBytesPerFrame = bytesPerFrame,
    .mBytesPerPacket = bytesPerPacket
};

status = AudioUnitSetProperty(converterUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescription, sizeof(streamDescription));
if (status != noErr) {
    NSLog(@"AudioUnit: failed to set stream format (%d)", (int)status);
}

/* input callback */
AURenderCallbackStruct renderCallback;
renderCallback.inputProc = performRender;
renderCallback.inputProcRefCon = (__bridge void *)self;

AUGraphSetNodeInputCallback(_processingGraph, converterNode, 0, &renderCallback);

转换器单位输出采样率:

Float64 sampleRate = 44100.0;
AudioUnitSetProperty(converterUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Output, 0, &sampleRate, sizeof(sampleRate));

我也试过

AudioStreamBasicDescription outStreamDescription = {
    .mSampleRate    = 44100.0,
    .mFormatID      = kAudioFormatLinearPCM,
    .mFormatFlags   = formatFlags,
    .mChannelsPerFrame  = spec->channels,
    .mFramesPerPacket   = 1,
    .mBitsPerChannel    = bitsPerChannel,
    .mBytesPerFrame = bytesPerFrame,
    .mBytesPerPacket = bytesPerPacket
};
status = AudioUnitSetProperty(converterUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &outStreamDescription, sizeof(outStreamDescription));

但似乎没什么区别。

0 个答案:

没有答案