我正在尝试在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));
但似乎没什么区别。