/* attempt to deal with prototype, bootstrap, jquery conflicts */ /* for dropdown menus */

\$4

### Image of the Day Submit

IOTD | Top Screenshots

## Sound pops and clicks - XAudio2

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

9 replies to this topic

Posted 16 September 2011 - 09:55 PM

I have to play different quadrangular waves of 12.5%, 25%, 50% and 75% duty cycle to create melodies. So far I have been able to get melodies right but one problem exist and that is when I try to start and stop the sound, it gives me nasty pops and clicks sound. The program has to start and stop the sound quite a lot so there is lot of pops and clicks. One way I have found to get rids of these pops and clicks is by instead of starting and stopping the sound, I just start it once and then change the volume, if I am starting the sound I change the volume to 1 and if I am stopping the sound I change the volume to 0. This method works but I am not sure if this is a good or the right method to stop sound. So, can anyone tell me how I can get rid of pops and clicks when I am starting and stopping sound?

Thanks!!!

### #2Geiger  Members

Posted 17 September 2011 - 03:41 AM

I'm no expert on XAudio2 but one option you could possibly try is to call IXAudio2SourceVoice::FlushSourceBuffers() before you ultimately stop playing your sound. What this does is it discards all of the queued audio buffers for that source voice and only maintains the currently playing buffer, which (depending on your implementation) could only be a second or so of audio.

One way I have found to get rids of these pops and clicks is by instead of starting and stopping the sound, I just start it once and then change the volume, if I am starting the sound I change the volume to 1 and if I am stopping the sound I change the volume to 0.

If this works for you, you can still Start() and Stop() your source voice's normally, but just add a call to SetVolume(1.0f) and SetVolume(0.0f) before you actually call Start() and Stop() respectively. I don't believe there is that much overhead with SetVolume() that it would cause much of a problem, but again I'm no expert.

However I think it would be best if you posted some of your code for everyone to look at. The most important things would be your start, stop, initialization and update functions

Posted 17 September 2011 - 06:18 AM

Thank you for your reply. Flushing off the buffer is not a bad idea but it wouldn't work for me because the source voice only has one buffer that is looped again and again. Also setting the volume to zero and starting and stopping didn't work.

Here are some codes, first this is how I have setup my WAVEFORMATEX:

	WAVEFORMATEX wFormat;

wFormat.wFormatTag = WAVE_FORMAT_PCM;
wFormat.wBitsPerSample = 8;
wFormat.nBlockAlign = 1;
wFormat.nAvgBytesPerSec = 8000;
wFormat.nSamplesPerSec = 8000;
wFormat.nChannels = 1;
wFormat.cbSize = 0;

ZeroMemory(&xABufferInfo, sizeof(xABufferInfo));
xABufferInfo.AudioBytes = 8;
xABufferInfo.pAudioData = xABuffer;
xABufferInfo.LoopCount = XAUDIO2_LOOP_INFINITE;

if (xASourceChTwo->SubmitSourceBuffer(&xABufferInfo) != S_OK) return false;


So the sample depth is 8 bits and sample rate is 8 kHz.

Now I have 5 buffers, 1st buffer that source voice reads and loops again and again and 4 others are wave patterns of different duty cycle. All of them are 8 bytes long:

	unsigned char xABuffer[8], wDTwelve[8], wDTwenty[8], wDFifty[8], wDSeventyFive[8];

//12.5% duty cycle
wDTwelve[0] = 0;	wDTwelve[1] = 64;	wDTwelve[2] = 64;	wDTwelve[3] = 64;
wDTwelve[4] = 64;	wDTwelve[5] = 64;	wDTwelve[6] = 64;	wDTwelve[7] = 64;

//25% duty cycle
wDTwentyFive[0] = 0;	wDTwentyFive[1] = 0;	wDTwentyFive[2] = 64;	wDTwentyFive[3] = 64;
wDTwentyFive[4] = 64;	wDTwentyFive[5] = 64;	wDTwentyFive[6] = 64;	wDTwentyFive[7] = 64;

//50% duty cycle
wDFifty[0] = 0;		wDFifty[1] = 0;		wDFifty[2] = 0;		wDFifty[3] = 0;
wDFifty[4] = 64;	wDFifty[5] = 64;	wDFifty[6] = 64;	wDFifty[7] = 64;

//75% duty cycle
wDSeventyFive[0] = 0;	wDSeventyFive[1] = 0;	wDSeventyFive[2] = 0;	wDSeventyFive[3] = 0;
wDSeventyFive[4] = 0;	wDSeventyFive[5] = 0;	wDSeventyFive[6] = 64;	wDSeventyFive[7] = 64;

//Default wave duty cycle is 50%
memcpy(xABuffer, wDFifty, 8);


Now before playing and updating the sound, program checks duty cycle flag and just copies the data to xABuffer like this:

	switch (dutyFlag) {
case DUTY_TWELVE:
memcpy(xABuffer, wDTwelve, 8;
break;
case DUTY_TWENTYFIVE:
memcpy(xABuffer, wDTwentyFive, 8);
break;
case DUTY_FIFTY:
memcpy(xABuffer, wDFifty, 8);
break;
case DUTY_SEVENTYFIVE:
memcpy(xABuffer, wDSeventyFive, 8);
}


Then some flags are checked, frequency is set and the sound is played like this:

	if (!channelTwo) {
channelTwo = true;
xASourceChTwo->Start()
}


And at last when sound is suppose to stop, it stops like this:

	if (channelTwo) {
channelTwo = false;
xASourceChTwo->Stop();
}


Posted 17 September 2011 - 06:53 AM

When starting and stopping the sound, you should fade it in and out over a few milliseconds. Clicks and pops are caused by very sudden changes in amplitude.

### #5aregee  Members

Posted 17 September 2011 - 07:22 AM

When starting and stopping the sound, you should fade it in and out over a few milliseconds. Clicks and pops are caused by very sudden changes in amplitude.

This. And you can do a simple test:

Play a 0% duty cycle with full volume. Now you should not hear any clicks and pops at all when you start and stop the audio. If you do, the problem lies elsewhere.

Posted 17 September 2011 - 07:45 AM

Yeah sudden change of amplitude seems to be the cause. I want to ask something else, performance wise, if sound has to stop and start many times (once a second an average) is it better to leave the sound open with volume down when not playing or is it better to completely stop the sound and restart the sound.

EDIT:
@aregee: Uh oh, I just did that test with 0% duty cycle and I still got clicks and pops.

### #7aregee  Members

Posted 17 September 2011 - 02:57 PM

@aregee: Uh oh, I just did that test with 0% duty cycle and I still got clicks and pops.

I have read about XAudio2 and its capabilities. Unless XAudio2 is broken, I can not see that it should behave this way and I don't think XAudio2 is broken like that.

I have one suggestion to what may be the fault. You are probably feeding signed data where unsigned is expected or the oposite. This would create cracks and pops where there should be silence when you start and stop the sample.

So if you are feeding all zeroes when each sample is 16 bit, you may actually be feeding DC at max amplitude instead of DC at 0 amplitude. Try the 0% duty cycle again, but this time use the value in the middle of an unsigned word or an unsigned byte depending on 8 bits or 16 bits sample size. 32768 dec (8000 hex) for 16 bits and 128 dec (80 hex) for 8 bits.

Posted 17 September 2011 - 09:14 PM

Thank you very much. You were right, 0 amplitude is 128 for 8 bits. Cracks are far less frequent now in my program. But can you please answer my this question:

performance wise, if sound has to stop and start many times (once a second an average) is it better to leave the sound open with volume down when not playing or is it better to completely stop the sound and restart the sound.

Thank you...

### #9aregee  Members

Posted 18 September 2011 - 12:33 PM

Thank you very much. You were right, 0 amplitude is 128 for 8 bits. Cracks are far less frequent now in my program. But can you please answer my this question:

performance wise, if sound has to stop and start many times (once a second an average) is it better to leave the sound open with volume down when not playing or is it better to completely stop the sound and restart the sound.

Thank you...

Regarding your question, I am not sure really. It depends on a lot of factors. My initial thought is that this is what XAudio2 is made to do. Starting, stopping and mixing sounds through a convenient interface. I believe there is very little overhead in starting and stopping sounds since you are not deallocating or reallocating resources for each time you do. That would probably be a bit of a overhead and not a good idea anyway.

I suggest you just postpone any premature optimizations till you actually stumble upon a problem regarding performance since any optimization I can think of is a lot of work that is better spent on the progress of your work.