Monogame: Buffer boundary stutter using DynamicSoundEffectInstance

Created on 23 Jul 2016  路  16Comments  路  Source: MonoGame/MonoGame

See this forum post for a repro.

This was a known issue in the DynamicSoundEffectInstance PR (#4715) which I was not able to pin down. It seems to occur both on XAudio and OpenAL, but I don't know if the issue is in the common code or platform implementations. Any ideas from someone more knowledgeable about audio?

Help Wanted

Most helpful comment

I found it :) The problem is this. AL.SourcePlay is being called even when the soundeffect is not stopped. I fixed this by changing

if (_state == SoundState.Playing)

to

int sourceState;
AL.GetSource(SourceId, ALGetSourcei.SourceState, out sourceState);
ALHelper.CheckError();

if (_state == SoundState.Playing && sourceState == (int) ALSourceState.Stopped)

So AL.SourcePlay is only called when the soundeffect actually ran out of data and stopped. Maybe the problem is less or more the same with XAudio, I didn't check this out yet?

All 16 comments

I'm going to ask around a bit :)

Thanks @polsys !

Everything works as expected when I drop in FNA instead of MG. The audio glitch is tied directly to the size of the sample rate, if I bump up the sample rate to 300,000 it seems to play fine for about 7 seconds before making the clicking noise. seeing as 300/44 is roughly 7 that makes sense, just stepping thru the code I'm not really sure what I'm looking for but I'll keep digging a bit.

Hmm well I spent a few hours trying to debug to find the issue, but I don't really know what I'm looking for. All I know is that it seems to glitch out once it hits the sample rate, so the higher you set the sample rate the longer it will play as expected before glitching out. Obviously for audio processing stuff the lower the sample rate the better since it creates a lot of lag.

Here is the sine wave code all set up ready to step thru/debug : http://hathor.link/metawater.zip

Just breakpoint line 47 on WaterSynth.cs and you can step thru the code. Works fine in FNA, which is also included if you want to step thru that just delete the monogame.framework.windowsgl reference and add a solution reference to FNA.

Also have SimpleSynth project included if you want to play around with that, which also works fine in FNA and glitches in MG.

Hopefully we can get to the bottom of this. It seems like some minor bug but I'm just kind of stuck with it.

I found it :) The problem is this. AL.SourcePlay is being called even when the soundeffect is not stopped. I fixed this by changing

if (_state == SoundState.Playing)

to

int sourceState;
AL.GetSource(SourceId, ALGetSourcei.SourceState, out sourceState);
ALHelper.CheckError();

if (_state == SoundState.Playing && sourceState == (int) ALSourceState.Stopped)

So AL.SourcePlay is only called when the soundeffect actually ran out of data and stopped. Maybe the problem is less or more the same with XAudio, I didn't check this out yet?

I'm gonna try figure out the XAudio issue and then do a PR for both.

This might be related to https://github.com/mono/MonoGame/pull/5006#issuecomment-236380478

Awesome, @Jjagg thanks so much for digging into this :)

This works as expected if you submit the buffer on your game's Update event but the old issue still persists if you submit the buffer via handling the BufferNeeded event.

I did this with the WaterSynth sample you provided, so that worked for me

Okay, so I fixed this in my branch and it did not work. Looks like something else changed on develop that broke this.

hm weird on my end it works fine if i comment out line 41 and uncomment line 94 but with line 94 commented out and line 41 uncommented it stutters.

Well it's possible that when I was mucking around with the code I changed something and forgot about it. I'll have to do a diff between my mg-develop branch and the current mg-develop branch. But it does seem like we're really close to having everything working properly so I'm happy about that.

oh yeah I added this to OpenAL.cs at line #149.

    public static void BufferData(int bid, ALFormat format, float[] data, int size, int freq) {
        var handle = GCHandle.Alloc(data, GCHandleType.Pinned);
        BufferData((uint)bid, (int)format, handle.AddrOfPinnedObject(), size, freq);
        handle.Free();
    }

I did that because I noticed that FNA was handling float[] but MG wasn't.

Fixed in #5056 :)

Was this page helpful?
0 / 5 - 0 ratings