• 在XNA 3.0 项目添加声音——根据相机位置从一个3D位置播放声音:3D声音


    问题

    要让你的3D游戏更真实,你想让每个声音都位于3D空间的某个位置。通过这种方式,在相机右侧发生的爆炸会主要通过右声道播放,这样用户就会感到爆炸是真的发生在他的右侧。即使爆炸不在相机的视野中,玩家也可以知道在他的右侧发生了什么事。

    注意:Zune不支持Xact和下面的Apply3D()方法,只支持Cue对象,3D音效只被PC和Xbox 360支持。

    解决方案

    XNA可以让这些事变得简单。对每个声音,你必须设置相机的3D位置和使用声音Cue对象的Apply3D方法设置声源的位置。注意当相机或声源移动时,你需要调用这个方法更新Cue。工作原理如果你想设置声源的3D位置,首先必须为这个音源设置一个AudioEmitter对象和为相机设置一个AudioListener对象。当将这两者传递到Cue的Apply3D方法中时,XNA会计算音响(或耳机)左右声道声音的分配。

    下面的方法创建了两个对象:

    private void UpdateSoundPosition(Cue cue, Vector3 sourcePos, Vector3 camPos, Vector3 camForward, Vector3 camUp)
    ...{
        AudioEmitter emitter = new AudioEmitter();
        emitter.Position = sourcePos;
    
        AudioListener listener = new AudioListener(); 
        listener.Position = camPos;
        listener.Forward = camForward;
        listener.Up = camUp;
    
        cue.Apply3D(listener, emitter); 
    }

    对emitter(音源)来说,你只需设置位置。对listener(相机)来说,你还要设置Forward和Up向量,因为当相机旋转了180度后,左右声道会互换。

    当创建了这两个变量后,你可以将它们传递到Cue的Apply3D方法中,当音源或相机发生移动时都要进行这个操作。

    你需要在第一次调用Play方法前调用Apply3D方法。所以,确保在Cue中还没有调用 Play方法:

    protected override void Initialize() 
    ...{
        fpsCam = new QuakeCamera(GraphicsDevice.Viewport, new Vector3(0,0,5) , 0, 0);
    
        audioEngine = new AudioEngine("Content/Audio/MyXACTproject.xgs"); 
        waveBank = new WaveBank(audioEngine, "Content/Audio/myWaveBank.xwb"); 
        soundBank = new SoundBank(audioEngine, "Content/Audio/mySoundBank.xsb");
    
        cue1 = soundBank.GetCue("audio1");
    
        base.Initialize(); 
    }

    在Update方法中,如果你移动了相机位置或音源位置,就需要调用UpdateSoundPosition方法:

    protected override void Update(GameTime gameTime)
    ...{
        GamePadState gamePadState = GamePad.GetState(PlayerIndex.One); 
        if (gamePadState.Buttons.Back == ButtonState.Pressed) 
            this.Exit();
    
        MouseState mouseState = Mouse.GetState(); 
        KeyboardState keyState = Keyboard.GetState();
    
        fpsCam.Update(mouseState, keyState, gamePadState);
    
        float time = (float)gameTime.TotalGameTime.TotalMilliseconds/1000.0f; 
        Vector3 startingPos = new Vector3(0, 0, -10);
        Matrix rotMatrix = Matrix.CreateRotationY(time);
        modelPos = Vector3.Transform(startingPos, rotMatrix);
    
        UpdateSoundPosition(cue1, modelPos, fpsCam.Position, fpsCam.Forward, fpsCam.UpVector);
    
        if (cue1.IsPrepared)
            cue1.Play();
        audioEngine.Update();
    
        base.Update(gameTime); 
    }

    这个方法的前半部分检查用户输入并将输入传递到相机,解释请见教程2-3。当中的代码块更新音源位置。当相机和音源更新后,你需要调用UpdateSoundPosition方法告知cue1对象最后的位置。如果cue1还没有播放,则开始播放。

    当心:因为3D effect是通过控制左右声道的音量实现的,所以声音中的任何立体声信息会丢失:首先将声音转换为单声道,然后对应物体的3D位置设置左右声道的音量。

    代码

    所有的Initialize,UpdateSoundPosition和Update方法前面已经写过了。

    扩展阅读

    Xact音频工具让你可以在cue中添加一些很棒的3D音效,诸如距离衰减和多普勒效应。因为是图形界面,在视频中介绍要比在书中好得多。在http://creators.xna.com 网站上有一些很好的视频介绍如何将3D音效添加到cue中。

    译者注:http://creators.xna.com/en-US/sample/3daudio网页上也有一个3D音效的例子,实现了距离衰减,多普勒效应。

  • 相关阅读:
    课程作业一
    关于代码中的抄袭(不针对任何人)
    第四次作业
    第三次寒假作业-随笔汇总
    第三次寒假作业-合作
    第三次寒假作业-个人
    第二次寒假作业汇总
    问题
    第二次寒假作业——自学安排
    第二次寒假作业
  • 原文地址:https://www.cnblogs.com/AlexCheng/p/2120087.html
Copyright © 2020-2023  润新知