NO

Author Topic: [RESOLVED] Memory leak while unpreparing waveout header... (Windows bug?)  (Read 4333 times)

leandrojardim

  • Guest
This is a test program that outputs to the loudspeaker a sine wave in real time using the WaveOut API. All the calculations are done in real time and the result is output to the sound card. It tries to manage the sample data into different "banks" of equal lengths, required by the WaveOut API to synchronize the data to the sound card.

Executing this code, the memory grows constantly, near the "for" loop. I see this with the task manager. Interesting is that the for loop only frees a used waveout header; it doesnt allocates nothing. What is hapenning with it, you could find the problem?

Sorry, I really could not find the problem by myself. Because the Waveout API is a bit old and is not being updated with new features except that related to sample rates and pitchs, my preliminary guess is that the problem is with the Windows API, but I am not sure. :(

Thanks to have heard me! :)

Code: [Select]
#include <stdlib.h>
#include <math.h>
#include <stdio.h>

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <mmsystem.h>
#include <mmreg.h>

#pragma lib "winmm.lib"

#define DEFAULT_CHANNEL_COUNT 1
#define DEFAULT_RATE 44100
#define DEFAULT_DEPTH 16

#define DEFAULT_BANK_COUNT 3
#define DEFAULT_BUFFER_LENGTH DEFAULT_RATE

#define PI 3.14159265

#define DEFAULT_FREQUENCY 440
#define DEFAULT_VOLUME 100

struct AudioSample {
WAVEHDR Header;
short Sample[DEFAULT_BUFFER_LENGTH];
};

WAVEFORMATEX Format;
HWAVEOUT WaveOut;

struct AudioSample Buffer[DEFAULT_BANK_COUNT];

size_t Phase = 0;
float Amplitude = 0;
float Period = 0;

void ShowWaveOutMessage (MMRESULT Result) {
static char String[256];

waveOutGetErrorText(Result, String, sizeof(String));
MessageBox(NULL, String, "Error Message", MB_ICONERROR | MB_OK);
};

int WINAPI WinMain(HINSTANCE Instance, HINSTANCE Previous, LPSTR Command, int Show)
{
MMRESULT Result = 0;
size_t Bank = 0;

WAVEHDR *Header = NULL;
short *Wave = NULL;

short *Next = NULL;
short *Last = NULL;

float Sample = 0;

ZeroMemory (&Format, sizeof(Format));

Format.wFormatTag = WAVE_FORMAT_PCM;
Format.nChannels = DEFAULT_CHANNEL_COUNT;

Format.nSamplesPerSec = DEFAULT_RATE;
Format.wBitsPerSample = DEFAULT_DEPTH;

Format.nBlockAlign = Format.nChannels * Format.wBitsPerSample / 8;
Format.nAvgBytesPerSec = Format.nSamplesPerSec * Format.nBlockAlign;

Format.cbSize = 0;

Result = waveOutOpen(&WaveOut, WAVE_MAPPER, &Format, 0, 0, CALLBACK_FUNCTION);
if (Result != MMSYSERR_NOERROR) {
ShowWaveOutMessage (Result);
return 1;
};

while (1) {
for (Bank = 0; Bank < DEFAULT_BANK_COUNT; Bank = Bank + 1) {
Header = &Buffer[Bank].Header;
Wave = Buffer[Bank].Sample;

if ((Header->dwFlags & WHDR_PREPARED) == 0)
break;

if ((Header->dwFlags & WHDR_DONE) == WHDR_DONE) {
Result = waveOutUnprepareHeader(WaveOut, Header, sizeof(*Header));

if (Result != MMSYSERR_NOERROR) {
ShowWaveOutMessage (Result);
return 2;
};

break;
};
};

Next = Wave;
Last = &Wave[DEFAULT_BUFFER_LENGTH];

while (Next < Last) {
Amplitude = DEFAULT_VOLUME / 100;
Amplitude = DEFAULT_FREQUENCY * Amplitude;

Period = (PI * 2.0f * DEFAULT_FREQUENCY) / DEFAULT_RATE;
Sample = Amplitude * sin(Period * (float) Phase);

*Next = Sample;

Phase = Phase + 1;
Next = Next + 1;
};

ZeroMemory (Header, sizeof(*Header));

Header->lpData = (char *)Wave;
Header->dwBufferLength = DEFAULT_BUFFER_LENGTH;

Header->dwFlags = 0;

Result = waveOutPrepareHeader(WaveOut, Header, sizeof(*Header));
if (Result != MMSYSERR_NOERROR) {
ShowWaveOutMessage (Result);
return 3;
};

Result = waveOutWrite(WaveOut, Header, sizeof(*Header));
if (Result != MMSYSERR_NOERROR) {
ShowWaveOutMessage (Result);
return 4;
};
};

return 0;
};
« Last Edit: June 12, 2011, 12:27:36 AM by leandrojardim »

stachel

  • Guest
Re: Memory leak while unpreparing waveout header?
« Reply #1 on: June 10, 2011, 08:31:22 PM »
Hi, i don't know what is the goal of your program. I played a little around and it seems to me that this line
Code: [Select]
Header->dwFlags = 0; in your while loop makes memory leaks.

I have changed some lines and it seems to be ok now.
Code: [Select]
#include <stdlib.h>
#include <math.h>
#include <stdio.h>

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <mmsystem.h>
#include <mmreg.h>

#pragma lib "winmm.lib"

#define DEFAULT_CHANNEL_COUNT 1
#define DEFAULT_RATE 44100
#define DEFAULT_DEPTH 16

#define DEFAULT_BANK_COUNT 3
#define DEFAULT_BUFFER_LENGTH DEFAULT_RATE

#define PI 3.14159265

#define DEFAULT_FREQUENCY 440
#define DEFAULT_VOLUME 100

struct AudioSample {
WAVEHDR Header;
short Sample[DEFAULT_BUFFER_LENGTH];
};

WAVEFORMATEX Format;
HWAVEOUT WaveOut;

struct AudioSample Buffer[DEFAULT_BANK_COUNT];

size_t Phase = 0;
float Amplitude = 0;
float Period = 0;

void ShowWaveOutMessage(MMRESULT Result)
{
static char String[256];

waveOutGetErrorText(Result, String, sizeof(String));
MessageBox(NULL, String, "Error Message", MB_ICONERROR | MB_OK);
};

int WINAPI WinMain(HINSTANCE Instance, HINSTANCE Previous, LPSTR Command, int Show)
{
MMRESULT Result = 0;
size_t Bank = 0;

WAVEHDR *Header = NULL;
short *Wave = NULL;

short *Next = NULL;
short *Last = NULL;

float Sample = 0;

ZeroMemory(&Format, sizeof(Format));

Format.wFormatTag = WAVE_FORMAT_PCM;
Format.nChannels = DEFAULT_CHANNEL_COUNT;

Format.nSamplesPerSec = DEFAULT_RATE;
Format.wBitsPerSample = DEFAULT_DEPTH;

Format.nBlockAlign = Format.nChannels * Format.wBitsPerSample / 8;
Format.nAvgBytesPerSec = Format.nSamplesPerSec * Format.nBlockAlign;

Format.cbSize = 0;

Result = waveOutOpen(&WaveOut, WAVE_MAPPER, &Format, 0, 0, CALLBACK_FUNCTION);
if (Result != MMSYSERR_NOERROR)
{
ShowWaveOutMessage(Result);
return 1;
};


for (Bank = 0; Bank < DEFAULT_BANK_COUNT; Bank = Bank + 1)
{
Header = &Buffer[Bank].Header;
Wave = Buffer[Bank].Sample;

if ((Header->dwFlags & WHDR_PREPARED) == 0)
break;

if ((Header->dwFlags & WHDR_DONE) == WHDR_DONE)
{
Result = waveOutUnprepareHeader(WaveOut, Header, sizeof(*Header));

if (Result != MMSYSERR_NOERROR)
{
ShowWaveOutMessage(Result);
return 2;
};

break;
};
};

Next = Wave;
Last = &Wave[DEFAULT_BUFFER_LENGTH];

while (Next < Last)
{
Amplitude = DEFAULT_VOLUME / 100;
Amplitude = DEFAULT_FREQUENCY * Amplitude;

Period = (PI * 2.0f * DEFAULT_FREQUENCY) / DEFAULT_RATE;
Sample = Amplitude * sin(Period * (float)Phase);

*Next = Sample;

Phase = Phase + 1;
Next = Next + 1;
};

ZeroMemory(Header, sizeof(*Header));

Header->lpData = (char *)Wave;
Header->dwBufferLength = DEFAULT_BUFFER_LENGTH;

Header->dwLoops = -1;
Header->dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;

Result = waveOutPrepareHeader(WaveOut, Header, sizeof(*Header));
if (Result != MMSYSERR_NOERROR)
{
ShowWaveOutMessage(Result);
return 3;
};
while (1)
{
Result = waveOutWrite(WaveOut, Header, sizeof(*Header));
//if (Result != MMSYSERR_NOERROR) {
//  ShowWaveOutMessage (Result);
//  return 4;
//};

//Sleep(100);
};

return 0;
};

leandrojardim

  • Guest
Re: Memory leak while unpreparing waveout header?
« Reply #2 on: June 12, 2011, 12:25:25 AM »
Yes, thats it! Thank you, stachel! :)

I want this code to envolve in some more complex program, a bit like an analog synthesizer, but for games.

For now I am doing some tests to see its prerequisites for me.

Thanks! :)