问题描述
我使用VoiceProcessingIO类型的音频单元来接收没有回声的声音。在RenderCallback中,我获取声音样本,然后将所有缓冲区值设置为零,以便不进行回放。
现在,我需要在收到声音后将其采样率从48000更改为16000,然后将生成的声音通过低通滤波器。
我不知道如何配置多个音频单元以相互连接并链接数据。
我知道我必须将kAudioUnitSubType_AUConverter用于转换器,将kAudioUnitSubType_LowPassFilter用于过滤器。
我已经迫切希望找到任何帮助。
P.S。我发现这个blog post,存在类似的问题,但是作者从未回答过他的问题。但是我不明白为什么作者使用两个转换器。我也担心他使用远程类型,而且我不明白为什么他以这些顺序连接这些总线。
public static class SoundSettings
{
public static readonly int SampleRate = 16000;
public static readonly int Channels = 1;
public static readonly int BytesPerSample = 2;
public static readonly int FramesPerPacket = 1;
}
private void SetupAudioSession()
{
AudioSession.Initialize();
AudioSession.Category = AudioSessionCategory.PlayAndRecord;
AudioSession.Mode = AudioSessionMode.GameChat;
AudioSession.PreferredHardwareIOBufferDuration = 0.08f;
}
private void PrepareAudioUnit()
{
_srcFormat = new AudioStreamBasicDescription
{
Format = AudioFormatType.LinearPCM,FormatFlags = AudioFormatFlags.LinearPCMIsSignedInteger |
AudioFormatFlags.LinearPCMIsPacked,SampleRate = AudioSession.CurrentHardwareSampleRate,FramesPerPacket = SoundSettings.FramesPerPacket,BytesPerFrame = SoundSettings.BytesPerSample * SoundSettings.Channels,BytesPerPacket = SoundSettings.FramesPerPacket *
SoundSettings.BytesPerSample *
SoundSettings.Channels,BitsPerChannel = SoundSettings.BytesPerSample * 8,ChannelsPerFrame = SoundSettings.Channels,Reserved = 0
};
var audioComponent = AudioComponent.FindComponent(AudioTypeOutput.VoiceProcessingIO);
_audioUnit = new AudioUnit.AudioUnit(audioComponent);
_audioUnit.SetEnableIO(true,AudioUnitScopeType.Input,1);
_audioUnit.SetEnableIO(true,AudioUnitScopeType.Output,0);
_audioUnit.SetFormat(_srcFormat,0);
_audioUnit.SetFormat(_srcFormat,1);
_audioUnit.SetRenderCallback(this.RenderCallback,0);
}
private AudioUnitStatus RenderCallback(
AudioUnitRenderActionFlags actionFlags,AudioTimeStamp timeStamp,uint busNumber,uint numberFrames,AudioBuffers data)
{
var status = _audioUnit.Render(ref actionFlags,timeStamp,1,numberFrames,data);
if (status != AudioUnitStatus.OK)
{
return status;
}
var msgArray = new byte[dataByteSize];
Marshal.copy(data[0].Data,msgArray,dataByteSize);
var msg = _msgFactory.CreateAudioMsg(msgArray,msgArray.Length,(++_lastIndex));
this.OnMsgReady(msg);
// disable playback IO
var array = new byte[dataByteSize];
Marshal.copy(array,data[0].Data,dataByteSize);
return AudioUnitStatus.NoError;
}
解决方法
以下是可用于连接两个音频单元的功能示例(请注意,在成功连接源和目标之前,源和目标必须具有相同的流格式):
OSStatus connectAudioUnits(AudioUnit source,AudioUnit destination,AudioUnitElement sourceOutput,AudioUnitElement destinationInput) {
AudioUnitConnection connection;
connection.sourceAudioUnit = source;
connection.sourceOutputNumber = sourceOutput;
connection.destInputNumber = destinationInput;
return AudioUnitSetProperty (
destination,kAudioUnitProperty_MakeConnection,kAudioUnitScope_Input,destinationInput,&connection,sizeof(connection)
);
}