AVAudioEngine,使用3D音频

时间:2017-08-22 22:01:28

标签: swift audio core-audio avaudioengine

我想将AVAudioEngine用于3D音频效果,声源环绕用户头部。来源似乎从左向右移动,但我一直无法弄清楚如何让它围绕用户头。音频源必须是单声道或无法正常工作。

我不懂AVAudioMake3DVectorOrientation和AVAudioMake3DAngularOrientation。

我认为我的数学是正确的,但我怀疑如果是,我会得到我想要的结果。

这是骨干,所以没有多少错误检查。

有人会提供指导让我走上正轨吗?

谢谢,

W上。

import AVFoundation
class ThreeDAudio {

var _angleIndx   = 0.0
var _engine      : AVAudioEngine!
var _player      : AVAudioPlayerNode!
var _environment : AVAudioEnvironmentNode!
var _circleTimer : Timer!

func initTimer()
{
    _circleTimer = Timer.scheduledTimer(timeInterval: 0.10, target: self,
                                       selector: #selector(ThreeDAudio.updatePosition),userInfo: nil, repeats: true)
}


@objc func updatePosition()
{
    let centerX =  0.0
    let centerY =  0.0
    let radius  = 10.0

    let degToRads = Double.pi / 180.0
    let angle = _angleIndx * degToRads
    let x = centerX + sin(angle) * radius
    let y = centerY + cos(angle) * radius
    let z = 0.0

    let posInSpace = AVAudioMake3DPoint(Float(x), Float(y), Float(z))

    _angleIndx      += 1.0
    _player.position = posInSpace
    print("angle: \(_angleIndx) , \(posInSpace)")

    if(_angleIndx == 360.0) { _circleTimer.invalidate() }
}


func getBufferFromFileInBundle(fileName: String, fileType: String) -> AVAudioPCMBuffer?
{
    // audio MUST be a monoaural source or it cant work in 3D
    var file:AVAudioFile
    var audioBuffer : AVAudioPCMBuffer? = nil
    let path = Bundle.main.path(forResource: fileName, ofType: fileType)!

    do{
        file = try AVAudioFile(forReading: URL(fileURLWithPath:path))
        audioBuffer = AVAudioPCMBuffer(pcmFormat:(file.processingFormat), frameCapacity: AVAudioFrameCount(file.length))
        try file.read(into: audioBuffer!)
    } catch let error as NSError {
        print("Error AVAudioFile:\(error)")
    }

    return audioBuffer
}

func outputFormat() -> AVAudioFormat
{
    let outputFormat = _engine.outputNode.outputFormat(forBus: 0)
    let nChannels    = outputFormat.channelCount // testing, will always be 2 channels
    let sampleRate   = outputFormat.sampleRate
    return AVAudioFormat(standardFormatWithSampleRate: sampleRate, channels: nChannels)
}

func setupEngine(_ audioBuffer: AVAudioPCMBuffer )
{
    _engine      = AVAudioEngine()
    _player      = AVAudioPlayerNode()
    _environment = AVAudioEnvironmentNode()

    _player.renderingAlgorithm = .HRTF
    _engine.attach(_player)
    _engine.attach(_environment)

    _engine.connect(_player, to: _environment, format: audioBuffer.format)
    _engine.connect(_environment, to: _engine.outputNode, format: outputFormat())

    _environment.listenerPosition = AVAudioMake3DPoint(0.0, 0.0, 0.0);
    _environment.listenerVectorOrientation = AVAudioMake3DVectorOrientation(AVAudioMake3DVector(0, 0, -1), AVAudioMake3DVector(0, 0, 0))
    _environment.listenerAngularOrientation = AVAudioMake3DAngularOrientation(0.0,0.0, 0.0)


    do{
        try _engine.start()
    } catch let error as NSError {
        print("Error start:\(error)")
    }   
}

func startAudioTest()
{
    var thisFile = (name: "", fileType: "")
    thisFile = (name: "sound_voices", fileType: "wav")
    thisFile = (name: "Bouncing-Ball-MONO", fileType: "aiff")

    let audioBuffer = getBufferFromFileInBundle(fileName: thisFile.name, fileType: thisFile.fileType )
    if ( audioBuffer != nil )
    {
        setupEngine( audioBuffer! )
        initTimer()
        _player.scheduleBuffer(audioBuffer!, at: nil, options: .loops, completionHandler: nil)
        _player.play()
    }
}

}

0 个答案:

没有答案