1

我正在尝试在 Windows Phone 7 上的 XNA 应用程序中同时演奏大约 30 个钢琴音符。我已经导入并加载了波形文件,如下所示

    protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(GraphicsDevice);

        sound3 = Content.Load<SoundEffect>("1");
        sound5 = Content.Load<SoundEffect>("3");
        sound6 = Content.Load<SoundEffect>("4");
        sound7 = Content.Load<SoundEffect>("5");
        sound8 = Content.Load<SoundEffect>("6");

    }

每个音效文件都不到一秒,所以我试图同时播放所有的音效文件。我使用每秒运行的 for 循环播放它们。(因此,在每个循环中,将播放 30 个声音,然后它继续播放并每秒播放相同的 30 个声音)它可以正常工作几秒钟,但突然停止播放任何声音(循环仍在工作)然后再次开始工作一次或两次,然后再次停止工作。有时它还会发出一些不好的声音,好像音频系统无法支持一次播放太多声音。

我不确定如何解决问题,如果它是缓冲区问题或线程。

4

1 回答 1

0

尼科·舍特勒是对的!我遇到了同样的问题并通过管理实例来解决它。通常,当您播放音效时,您总是会得到实例!默认情况下,您必须希望 XNA/Monogame 会关心它,但事实并非如此。当您有许多实时实例时(甚至停止,您会得到休息、噪音,甚至是沉默。

我为我的所有音效保留了矩形阵列,每个音效最多有 4 个实例,如果我有想要播放而不是创建声音的实例,我会停止最旧的(按时间戳),播放它并记住当前时间戳。

请参阅以下代码:

private const int MAX_INST_OF_ONE_SOUND = 4;
private SoundEffectInstance[][] sndInstArray = null;
private float[][] sndInstTimes = null;

public init()
{
    sndArray = new SoundEffect[SoundsSchema.sounds.Length];
    sndInstArray = new SoundEffectInstance[SoundsSchema.sounds.Length][];
    sndInstTimes = new float[SoundsSchema.sounds.Length][];

    for (int i = 0; i < SoundsSchema.sounds.Length; i++)
    {
        try
        {
            sndArray[i] = content.Load<SoundEffect>(SoundsSchema.sounds[i]);//SoundsSchema is string list holder class
        }
        catch (System.Exception)
        {
        }

        sndInstArray[i] = new SoundEffectInstance[MAX_INST_OF_ONE_SOUND];
        sndInstTimes[i] = new float[MAX_INST_OF_ONE_SOUND];
    }

}

private SoundEffectInstance getValidInstance(int sound)
{
    if (sound < 0 || sound > sndInstArray.Length)
        return null;

    SoundEffectInstance inst = null;
    for (int i = 0; i < MAX_INST_OF_ONE_SOUND; i++)
    {
        if (sndInstArray[sound][i] == null || (sndInstArray[sound][i] != null && sndInstArray[sound][i].IsDisposed))
        {
            sndInstArray[sound][i] = sndArray[sound].CreateInstance();
            sndInstTimes[sound][i] = MyEngine.CurTime;
            inst = sndInstArray[sound][i];
            break;
        }
    }

    if (inst == null)
    {
        float min_time = float.MaxValue;
        int ind = -1;
        for (int i = 0; i < MAX_INST_OF_ONE_SOUND; i++)
        {
            if (sndInstArray[sound][i] != null && sndInstTimes[sound][i] < min_time)
            {
                min_time = sndInstTimes[sound][i];
                ind = i;
            }
        }
        if (ind == -1)
            ind = 0;

        if (sndInstArray[sound][ind].IsDisposed)
            sndInstArray[sound][ind] = sndArray[sound].CreateInstance();
        else
        {
            try
            {
                sndInstArray[sound][ind].Stop();
            }
            catch
            {}
        }
        sndInstTimes[sound][ind] = MyEngine.CurTime;
        inst = sndInstArray[sound][ind];
    }

    return inst;
}



public virtual void playSound(int sound, float volume, float panoram, bool loop)
{
    if (sound < 0 || sound > sndArray.Length)
        return null;

    if (!mMuted && mVolume > 0)
    {
        SoundEffectInstance sndinst = getValidInstance(sound);
        if (sndinst == null)
            return null;

        try
        {
            sndinst.IsLooped = loop;
            sndinst.Pan = panoram;
            sndinst.Volume = mVolume * vol;
            sndinst.Play();
        }
        catch 
        {
        }
    }
}
于 2014-04-16T19:09:02.993 回答