ios - 带 AuGraph 的变速单元 [iOS Swift]
问题描述
我们正在尝试使用 AUGraph 将变速单元与输出单元连接起来。这是我们当前的代码:
var graph: AUGraph?
var varispeedNode: AUNode = 0
var varispeedUnit: AudioUnit?
var outputNode: AUNode = 0
var outputUnit: AudioUnit?
init(_ client: UDPClient, _ tcpClient: TCPClient, _ opusHelper: OpusHelper, _ tvTemp: UILabel) {
super.init()
let success = initCircularBuffer(&circularBuffer, 4096)
if success {
print("Circular buffer init was successful")
} else {
print("Circular buffer init not successful")
}
self.tvTemp = tvTemp
self.opusHelper = opusHelper
monotonicTimer = MonotonicTimer()
udpClient = client
self.tcpClient = tcpClient
status = NewAUGraph(&graph)
if status != noErr {
print("NEW AUGrpah ERROR: \(status!)")
}
var varispeedDesc = AudioComponentDescription(
componentType: OSType(kAudioUnitType_FormatConverter),
componentSubType: OSType(kAudioUnitSubType_Varispeed),
componentManufacturer: OSType(kAudioUnitManufacturer_Apple),
componentFlags: 0,
componentFlagsMask: 0
)
status = AUGraphAddNode(self.graph!, &varispeedDesc, &varispeedNode)
if status != noErr {
print("Varispeed desc ERRROR: \(status!)")
}
var outputDesc = AudioComponentDescription(
componentType: OSType(kAudioUnitType_Output),
componentSubType: OSType(kAudioUnitSubType_VoiceProcessingIO),
componentManufacturer: OSType(kAudioUnitManufacturer_Apple),
componentFlags: 0,
componentFlagsMask: 0
)
status = AUGraphAddNode(self.graph!, &outputDesc, &outputNode)
if status != noErr {
print("Output Desc ERROR \(status!)")
}
status = AUGraphOpen(graph!)
if status != noErr {
print("AUGraph open ERROR: \(status!)")
}
status = AUGraphNodeInfo(self.graph!, self.varispeedNode, nil, &varispeedUnit)
if status != noErr {
print("Varispeed Unit Unable to get INFO: \(status!)")
}
status = AUGraphNodeInfo(self.graph!, self.outputNode, nil, &outputUnit)
if status != noErr {
print("Output Unit Unable to get INFO: \(status!)")
}
let inputComponent = AudioComponentFindNext(nil, &outputDesc)
status = AudioComponentInstanceNew(inputComponent!, &outputUnit)
if status != noErr {
print("Audio component instance new error \(status!)")
}
var flag: UInt32 = 1
var ioFormat = CAStreamBasicDescription(
sampleRate: 48000.0,
numChannels: 1,
pcmf: .int16,
isInterleaved: false
)
status = AudioUnitSetProperty(
outputUnit!,
AudioUnitPropertyID(kAudioUnitProperty_StreamFormat),
AudioUnitScope(kAudioUnitScope_Input),
0,
&ioFormat!,
MemoryLayoutStride.SizeOf32(ioFormat)
)
if status != noErr {
print("Unable to set stream format input to output \(status!)")
}
// Set the MaximumFramesPerSlice property. This property is used to describe to an audio unit the maximum number
// of samples it will be asked to produce on any single given call to AudioUnitRender
var maxFramesPerSlice: UInt32 = 4096
status = AudioUnitSetProperty(
varispeedUnit!,
AudioUnitPropertyID(kAudioUnitProperty_MaximumFramesPerSlice),
AudioUnitScope(kAudioUnitScope_Global),
0,
&maxFramesPerSlice,
MemoryLayoutStride.SizeOf32(UInt32.self)
)
if status != noErr {
print("Unable to set max frames per slice 1 \(status!)")
}
var playbackCallback = AURenderCallbackStruct(
inputProc: AudioController_PlaybackCallback,
inputProcRefCon: UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())
)
status = AudioUnitSetProperty(
outputUnit!,
AudioUnitPropertyID(kAudioUnitProperty_SetRenderCallback),
AudioUnitScope(kAudioUnitScope_Global),
kOutputBus,
&playbackCallback,
MemoryLayout<AURenderCallbackStruct>.size.ui
)
if status != noErr {
print("Failed to set recording render callback \(status!)")
}
status = AUGraphConnectNodeInput(
graph!,
varispeedNode,
AudioUnitElement(0),
outputNode,
AudioUnitElement(0)
)
if status != noErr {
print("Failed to connect varispeed node to output node \(status!)")
}
status = AudioUnitSetParameter(
varispeedUnit!,
AudioUnitParameterID(kVarispeedParam_PlaybackRate),
AudioUnitScope(kAudioUnitScope_Global),
0,
AudioUnitParameterValue(0.2000000082426955),
0
)
if status != noErr {
print("Varispeed rate failed to set \(status!)")
}
status = AudioOutputUnitStart(outputUnit!)
if status != noErr {
print("Failed to initialize output unit \(status!)")
}
if graph != nil {
var outIsInitialized = DarwinBoolean(false)
status = AUGraphIsInitialized(graph!, &outIsInitialized)
if status != noErr {
print("AUGraph is initialized 1 ERROR \(status!)")
}
if !outIsInitialized.boolValue {
status = AUGraphInitialize(graph!)
if status != noErr {
print("AUGraph is initialized 2 ERROR \(status!)")
}
} else {
print("AUGraph is already init")
}
var isRunning = DarwinBoolean(false)
status = AUGraphIsRunning(graph!, &isRunning)
if status != noErr {
print("AUGraph is running \(status!)")
}
if !isRunning.boolValue {
status = AUGraphStart(graph!)
if status != noErr {
print("AUGraph was not started \(status!)")
}
} else {
print("AUGraph is running")
}
} else {
print("Error processing graph NULL")
}
}
当我们设置速率时,我们可以听到声音,但输出不受 varispeed 属性的影响。我们正在通过 UDP 获取实时音频,并且我们正在尝试更改 iOS 上的播放速度。
谁能指导我们正确连接变速单元和输出单元。
解决方案
您可能希望输入回调位于图表的输入上,而不是中间。
您可能想尝试使用 kAudioUnitSubType_NewTimePitch 效果,而不是 Varispeed 效果音频单元。
您可能需要设置效果节点的输入和输出格式,并确保效果节点的输出格式与图表中下一个节点的输入格式相匹配。
您可能还想检查您的效果节点的旁路属性是否启用,并适当地设置它。
推荐阅读
- sql-server - 如何在 SQL Server 上查看 SSIS 包
- powershell - 在构建过程中重启 Docker 容器
- lua - 如何在lua中的同一个“for”上添加一个以上的数组
- sql-server - 将具有多个选项卡的 Excel 工作表中的数据插入 SQL Server 到多个表中
- python - 运算符不存在:jsonb ~~* 未知错误
- python-3.x - 为什么使用multiprocessing.Pool(N)时进程数会影响输出格式
- mqtt - 使用 MQTT 同时发布/订阅
- python - 如果段长度高于特定值,如何递归离散段
- python - 将接收到的输出转换为python中的数据框
- mysql - SQL 检索两个日期之间的所有行以及按日期排序的日期之前的特定行数