在SoundEffectInstance上设置音量时出错

时间:2011-07-30 18:53:57

标签: silverlight windows-phone-7 xna windows-phone

我发现在我的应用程序中经常报告错误。我知道它发生在哪里,我只是不知道为什么。该应用程序播放声音效果(不是背景音乐),我正在使用Xna.Audio,我有一个计时器定期调用FrameworkDispatcher.Update()。我正在使用SoundEffect.CreateInstance,所以我可以使用声音效果循环。看起来更改音量时会发生错误。我不知道为什么。是否存在可能失败的已知情况?

功能 :::偏移


xxx_RaiseException ::: 32
WatsonUnhandledManagedException ::: 300
Dbg_NotifyManagedException ::: 136
FirstPassException ::: 1044
TransitionStub ::: 0
Microsoft.Xna.Framework.Helpers.ThrowExceptionFromErrorCode ::: 76
Microsoft.Xna.Framework.Audio.SoundEffectInstance.set_Volume ::: 232
Microsoft.Xna.Framework.Audio.SoundEffectInstance..ctor ::: 232
Microsoft.Xna.Framework.Audio.SoundEffect.CreateInstance ::: 192
AgiliTrain.PhoneyTools.Media.SoundEffectPlayer..ctor ::: 96 WildSafari.ClassicModeGame.animalVisibleTimer_Tick ::: 344
...剪断....

对于那些要求,这里有更多的代码。 SoundEffectPlayer获取SoundEffect,创建一个实例,然后启动XNA FrameworkDispatcher(通过GameTimer)。此代码取自PhoneyTools,如果您需要更多上下文,请查看codeplex项目。当我想播放效果时,我只是新建一个SoundEffectPlayer,并传递我想要的内容。

public class SoundEffectPlayer
{
    GameTimer _xnaTimer = new GameTimer();
    SoundEffectInstance _effect = null;
    public float _duration;

    public SoundEffectPlayer(SoundEffect effect, bool loop)
    {
        _effect = effect.CreateInstance();
        _effect.IsLooped = loop;
        _duration = (float)effect.Duration.TotalSeconds;
    }

    public void Play(float volume)
    {
        _xnaTimer.Start();
        _effect.Play();
        _effect.Volume = volume;
    }

    public void Stop()
    {

        _effect.Stop(true);
        _xnaTimer.Stop();
    }
}

public class GameTimer
{
    DispatcherTimer _timer = new DispatcherTimer()
    {
        Interval = TimeSpan.FromMilliseconds(50),
    };

    public GameTimer()
    {
        _timer.Tick += new EventHandler(_timer_Tick);
    }

    void _timer_Tick(object sender, EventArgs e)
    {
        FrameworkDispatcher.Update();
    }

    public void Start()
    {
        if (!_timer.IsEnabled) _timer.Start();
    }

    public void Stop()
    {
        if (_timer.IsEnabled) _timer.Stop();
    }
}

2 个答案:

答案 0 :(得分:1)

虽然我没有有效的解决方案,但仍尝试提供帮助......

SoundEffectInstance的setter属性并不像人们想象的那么简单:

  set
        {
            lock (this.voiceHandleLock)
            {
                if (this.IsDisposed)
                {
                    throw new ObjectDisposedException(base.GetType().Name, FrameworkResources.ObjectDisposedException);
                }
                if ((value < 0f) || (value > 1f))
                {
                    throw new ArgumentOutOfRangeException("value");
                }
                Helpers.ThrowExceptionFromErrorCode(SoundEffectUnsafeNativeMethods.SetVolume(this.voiceHandle, value));
                this.currentVolume = value;
            }
        }

基本上我们所追求的部分是在最后一行之前。

如果来自 SoundEffectUnsafeNativeMethods.SetVolume 的调用返回任何小于0的代码,则会触发您获得的异常。

以下是不安全方法中发生的事情:

public static unsafe int modopt(IsLong) SetVolume(uint soundEffectInstanceHandle, float volume)
{
    lock (SoundEffectSubsystemSyncObject)
    {
        if ((soundEffectInstanceHandle != 0) && (soundEffectInstanceHandle != uint.MaxValue))
        {
            CHandleTable* tablePtr = ?g_pTable@CHandleTable@@0PAV1@A;
            KernelSoundEffectInstance* instancePtr = CHandleTable.LookUp<class Microsoft::Xna::Framework::Audio::KernelSoundEffectInstance>((CHandleTable modopt(IsConst)* modopt(IsConst) modopt(IsConst)) ?g_pTable@CHandleTable@@0PAV1@A, soundEffectInstanceHandle, 0);
            if (instancePtr == null)
            {
                return -2147024809;
            }
            return **(((int*) instancePtr))[0x34](instancePtr, volume);
        }
        return -2147024809;
    }
}

您可以尝试使用try ... catch包围_effect.CreateInstance的创建并重新抛出一个更全面且有用的异常,其中包含有关您正在尝试创建的SoundEffect对象的信息(基本上您可以记下所有字段的值以供检查。(不确定从MS获得的只是堆栈跟踪或实际的异常消息)。

似乎在WP7上,设置音量的调用会转到某些操作系统指针表,这些表在幕后做了一些魔术,并在此表中查找声音效果句柄。

如果由于某种原因找不到它或类似的东西(不知道为什么,也许我们可以把它与XNA开发人员一起使用),它会抛出你得到的这个例外。

我知道这不是一个解决方案,但也许这是朝着正确方向迈出的一步。

答案 1 :(得分:0)

通常,不应该针对您描述的情况抛出异常,只要您按原样构建XNA兼容性层(详细信息here)。

但是,我注意到您正在使用PhoneyTools.Media.SoundEffectPlayer - 为什么?这可能是您遇到问题的原因。

此外,您似乎有不明确的引用 - effect_effect - 在播放内容时您正在使用哪一个?