gpt4 book ai didi

swift - 将 AudioUnit 效果附加到 SceneKit 中的 SCNAudioSource 节点

转载 作者:搜寻专家 更新时间:2023-10-31 19:34:24 25 4
gpt4 key购买 nike

我已经成功创建了一些函数来获取 SNSpeechSynthesizer.startSpeakingString(string, url) 并通过闭包将生成的 .aiff 文件附加到 SCNAudioPlayer 并附加整个事情到 SCNNode

这将运行具有给定 SCNNode.position(x, y, z) 的音频片段。

一切都很好,但没有与 SCNAudioSource 相关的效果,除了音量、速率和混响本身什么都不做。

我想添加音频单元效果,如延迟回声法兰等,但我找不到相关信息,除了 AVAudioEngineAVAudioFile 类似乎是SCNAudioSource 的父类(super class),AVAudioEngine 包含 AudioUnitPitch 等类。但是,我无法弄清楚SCNAudioSourceSCNAudioPlayerAVAudioEngineAVAudioFile 之间有什么联系。没有在子类或父类(super class)中引用另一个,并且任何教程(例如下面)仅在 AVFoundation 中讲,而不是在 SceneKit 中讲。 http://www.jawadrashid.com/swift-tutorial-udacity-7/

非常感谢对我可以阅读更多相关内容的任何链接的任何帮助

编辑:我找到了另一个链接,该链接显示了使用 AVAudioNodeSCNAudioPlayer 构造函数。也许我可以通过以下方式扩展它:

class CustomAudioPlayer:SCNAudioPlayer{}

然后通过将 AudioUnit 附加到 AudioNode 来覆盖父类(super class) init?但是,这似乎不会出现在 AudioEngine 中。

这是 objective-c 中的以下链接:

http://developer.xamarin.com/api/constructor/SceneKit.SCNAudioPlayer.SCNAudioPlayer/p/AVFoundation.AVAudioNode/

编辑2:我找到了对音频单元的引用并执行了以下操作,但现在我遇到了段错误

命令因信号而失败:段错误:11

code:
let source = prepareSynth(welcome, url: URL)
source.volume = 500.0
source.reverbBlend = 30.0
source.rate = 0.8
let clip = SCNAudioPlayer(source: source)
let mixer = clip.audioNode as AVAudioNode!?
distortion.loadFactoryPreset(AVAudioUnitDistortionPreset.SpeechRadioTower)
mixer?.engine?.attachNode(distortion)
mixer?.engine?.connect(mixer!, to: distortion, format: nil)
return clip

最佳答案

因此,在进行了大量研究以将任何可用的 AVAudioUnitEffec* 效果放入 SceneKit 场景之后,我终于找到了一个解决方案,经过测试、尝试和尝试。

AVAudioEngine 的以下子类将1-实例化具有特定配置的AVAudioEngine2-添加了一些方法来封装错误处理和效果预设加载3-使用连线方法将每个播放器和效果器节点放入音频引擎图中4-创建 AVAudioPCMBuffer 实例,配置帧数,文件格式作为辅助方法,以简化从 SceneKit 调用这些函数

注意:多声道代码未包含在内,因为我没有环绕声 5.1 系统,并且我已经对从 AVAudioEnvironmentNode 类公开的 HRTF(头部相关传输函数)算法感到非常满意。请注意,尽管此算法是双耳格式,但它是计算 secret 集度最高的算法。

可能的补充:1-添加一个混响区域预设切换器,这需要断开音频引擎,将环境节点重新连接到新的混响预设(大厅、小房间等)2-从 SceneKit SCNNode 列表中创建一个基于 RayCast 的回声传输维度以添加更逼真的效果,即:你在 T 形路口的中央栏,一个敌人在路口顶部栏的左侧滑行,声音穿过 RayCast 离开敌人并反弹到面对你的墙上。 AVAudioUnitDelay 类具有内部函数来更改早期延迟以创建所需的回声效果,而无需在任何地方使用相同的效果清洗节点。

代码在这里:

import Foundation
import SceneKit
import AVFoundation

class AudioLayerEngine:AVAudioEngine{
var engine:AVAudioEngine!
var environment:AVAudioEnvironmentNode!
var outputBuffer:AVAudioPCMBuffer!
var voicePlayer:AVAudioPlayerNode!
var multiChannelEnabled:Bool!
//audio effects
let delay = AVAudioUnitDelay()
let distortion = AVAudioUnitDistortion()
let reverb = AVAudioUnitReverb()

override init(){
super.init()
engine = AVAudioEngine()
environment = AVAudioEnvironmentNode()

engine.attachNode(self.environment)
voicePlayer = AVAudioPlayerNode()
engine.attachNode(voicePlayer)
voicePlayer.volume = 1.0
outputBuffer = loadVoice()
wireEngine()
startEngine()
voicePlayer.scheduleBuffer(self.outputBuffer, completionHandler: nil)
voicePlayer.play()
}

func startEngine(){
do{
try engine.start()
}catch{
print("error loading engine")
}
}

func loadVoice()->AVAudioPCMBuffer{
let URL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("art.scnassets/sounds/interface/test", ofType: "aiff")!)
do{
let soundFile = try AVAudioFile(forReading: URL, commonFormat: AVAudioCommonFormat.PCMFormatFloat32, interleaved: false)
outputBuffer = AVAudioPCMBuffer(PCMFormat: soundFile.processingFormat, frameCapacity: AVAudioFrameCount(soundFile.length))
do{
try soundFile.readIntoBuffer(outputBuffer)
}catch{
print("somethign went wrong with loading the buffer into the sound fiel")
}
print("returning buffer")
return outputBuffer
}catch{
}
return outputBuffer
}

func wireEngine(){
loadDistortionPreset(AVAudioUnitDistortionPreset.MultiCellphoneConcert)
engine.attachNode(distortion)
engine.attachNode(delay)
engine.connect(voicePlayer, to: distortion, format: self.outputBuffer.format)
engine.connect(distortion, to: delay, format: self.outputBuffer.format)
engine.connect(delay, to: environment, format: self.outputBuffer.format)
engine.connect(environment, to: engine.outputNode, format: constructOutputFormatForEnvironment())

}

func constructOutputFormatForEnvironment()->AVAudioFormat{
let outputChannelCount = self.engine.outputNode.outputFormatForBus(1).channelCount
let hardwareSampleRate = self.engine.outputNode.outputFormatForBus(1).sampleRate
let environmentOutputConnectionFormat = AVAudioFormat(standardFormatWithSampleRate: hardwareSampleRate, channels: outputChannelCount)
multiChannelEnabled = false
return environmentOutputConnectionFormat
}

func loadDistortionPreset(preset: AVAudioUnitDistortionPreset){
distortion.loadFactoryPreset(preset)
}

func createPlayer(node: SCNNode){
let player = AVAudioPlayerNode()
distortion.loadFactoryPreset(AVAudioUnitDistortionPreset.SpeechCosmicInterference)
engine.attachNode(player)
engine.attachNode(distortion)
engine.connect(player, to: distortion, format: outputBuffer.format)
engine.connect(distortion, to: environment, format: constructOutputFormatForEnvironment())
let algo = AVAudio3DMixingRenderingAlgorithm.HRTF
player.renderingAlgorithm = algo
player.reverbBlend = 0.3
player.renderingAlgorithm = AVAudio3DMixingRenderingAlgorithm.HRTF
}

}

e

关于swift - 将 AudioUnit 效果附加到 SceneKit 中的 SCNAudioSource 节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33984205/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com