Clicks and Pops with WaveOut

Started by leandrojardim, May 29, 2011, 06:03:57 AM

Previous topic - Next topic

leandrojardim

Hi, the first time I use the waveout api to play a streamed sound (actually a real time generated sine wave) the speaker emits a big popping sound.

I guess the problem is with Windows, because the pop only happens at the beginning of the sound, at the first use of the api and I dont know if it only happens with my sound card.

How do I can remove the pops at the beginning of the use of the waveout api? Or, do not exists any way to do it?

Thanks!

CommonTater

It's probably the audio chip being initialized...

Does it do it if you play any other sound first?


leandrojardim


CommonTater

Hmmm... I'm not sure if this is a solution or not... but have you tried muting the volume while intializing then setting it back after?  You could try doing this manually first, using the windows mixer dialog and see what happens.




leandrojardim

#4
Nothing happened...

I think it should be a problem of my chipset. I have seen finished programs of other authors with very similar problems.

I hear some pops even while writting the wave to the sound card. I dont know if it is my bug or a bug of Windows. But WaveOut is not a good API for doing these things and the way it need to synchronize the writes to the sound card is error prone.

If I do not enconter a solution, I will need to use DirectSound, with its weak macro based C-API, but for now, it will suffice.

CommonTater

Ok... one last thought... when you begin generating the sound wave, are you starting with 0 and counting up or from max and counting down?   It may just be the initial value causing a very sharp jump in the output...

Beyond that, I'm as lost as you are. 

leandrojardim

Thanks CommonTater for the time spend to me. :)

My program had a tiny bug that doubled the volume of the sine wave at very high speeds... And this was the cause of the "pops". Unfortunately... well I "breaked" the source code in a way that I didnt know if I could fix it quickly, so I will do it, again... :(

Hopefully I did a backup of the "important" parts. ;)

CommonTater

Lets hope it's not too broken...

TimoVJL

Some code to test that
#define WIN32_DEFAULT_LIBS
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <mmsystem.h>
#define _USE_MATH_DEFINES
#include <math.h>

//#define CHANNEL 2
#define SAMPLE_RATE 44100

void writeAudioBlock(HWAVEOUT hWaveOut, LPSTR block, DWORD size);
VOID FillBufferLR(short *pBuffer, int nSize, int iFreq, int iSampleRate);

char *WinMMErrorString(MMRESULT res)
{
static char szError[MAXERRORLENGTH];
waveOutGetErrorText(res, szError, sizeof(szError));
return szError;
}

int WINAPI WinMain(HINSTANCE Instance, HINSTANCE Previous, LPSTR Command, int Show)
{
HWAVEOUT hWaveOut;
WAVEFORMATEX wfx;
WAVEHDR whdr;
MMRESULT rc;
short aSine[16385];

wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = 2;
wfx.nSamplesPerSec = SAMPLE_RATE;
wfx.wBitsPerSample = 16;
wfx.cbSize = 0;
wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels;
wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;

if ((rc = waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL)) != MMSYSERR_NOERROR)
{
MessageBox(0, WinMMErrorString(rc), 0, MB_ICONERROR | MB_OK);
return 1;
}

// Some tests
FillBufferLR(aSine, sizeof(aSine)/sizeof(aSine[0]), 440, SAMPLE_RATE);
whdr.lpData = (LPSTR)&aSine;
whdr.dwBufferLength = sizeof(aSine)/sizeof(aSine[0]);
whdr.dwUser = 0;
whdr.dwFlags = 0;
whdr.dwLoops = 0;
whdr.lpNext = NULL;
whdr.reserved = 0;
waveOutPrepareHeader(hWaveOut, &whdr, sizeof(WAVEHDR));
waveOutWrite(hWaveOut, &whdr, sizeof(WAVEHDR));
Sleep(100);
while (waveOutUnprepareHeader(hWaveOut, &whdr, sizeof(WAVEHDR)) == WAVERR_STILLPLAYING)
Sleep(100);
waveOutClose(hWaveOut);
return 0;
}

// Stereo L R 8-bit data is unsigned, but 16-bit data is signed
VOID FillBufferLR(short *pBuffer, int nSize, int iFreq, int iSampleRate)
{
double fAngle;
int i;

fAngle = 0;
for (i = 0; i < nSize; i+=2) {
pBuffer[i] = (short) (0x7FFF * sin(fAngle)*0.5);
pBuffer[i+1] = pBuffer[i];
fAngle += 2 * M_PI * iFreq / iSampleRate;
if (fAngle > 2 * M_PI)
fAngle -= 2 * M_PI;
}
}
May the source be with you

leandrojardim

Yes, I heard the pops. Gets confusing, as I cant percept the sound quality of the algorithm.

TimoVJL

It was only example to test that problem.
Test putting enought silence to end of buffer.
FillBufferLR(aSine, (sizeof(aSine)/sizeof(aSine[0]))/2, 440, SAMPLE_RATE);

This example starts end ends to silence:
// Stereo L R 16-bit data is signed
VOID FillBufferLR(short *pBuffer, int nSize, int iFreq, int iSampleRate)
{
double fAngle, fLevel, fLevel2;
int i;

fAngle = 0;
fLevel = 1; // 0 - 1.0
int iPInc, iPDec;
iPInc = nSize / 3;
iPDec = nSize - iPInc - 1;
for (i = 0; i < nSize; i+=2) {
if (i <= iPInc) fLevel2 = (float)i / iPInc;
if (i >= iPDec) fLevel2 = (float)1.0 - (float)(i-iPDec) / iPInc;
pBuffer[i] = (short) (0x7FFF * sin(fAngle)*fLevel*fLevel2);
pBuffer[i+1] = pBuffer[i];

fAngle += 2 * M_PI * iFreq / iSampleRate;

if (fAngle > 2 * M_PI)
fAngle -= 2 * M_PI;
}
}
May the source be with you

leandrojardim

#11
It not worked. :)