Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

moucard

c++ vectors and a directx audio class

This topic is 5223 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi to everyone! I need your help with this because my knowledge of vectors seems to get smaller and smaller everyday (the more I learn the less I know). I have a class that initializes directx sound objects like this:
//header
#ifndef _CSOUND_H
#define _CSOUND_H

#include "CAudio.h"

class CSound {
private:
	IDirectMusicPerformance8*	m_pPerformance;
	IDirectMusicLoader8*		m_pLoader;
	IDirectMusicSegment8*		m_pSegment;
public:
	CSound(char* szFilename_, IDirectMusicPerformance8 *pPerformance,
		IDirectMusicLoader8 *pLoader);
	~CSound();

	void Play();
	void Stop();

	void SetRepeats(DWORD);
	bool IsPlaying();
};

#endif

//.cpp
#include "CSound.h"

CSound::CSound(char *szFilename_, IDirectMusicPerformance8 *pPerformance,
		IDirectMusicLoader8 *pLoader)
{
	WCHAR wszFile[MAX_PATH];

	m_pSegment = NULL;
	m_pPerformance = pPerformance;
	m_pLoader = pLoader;

	//Create segment
	CoCreateInstance(CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC, IID_IDirectMusicSegment8, 
		(void**)&m_pSegment);

	//Load segment from file
	MultiByteToWideChar(CP_ACP, 0, szFilename_, -1, wszFile, MAX_PATH);

	if (FAILED(m_pLoader->LoadObjectFromFile(CLSID_DirectMusicSegment, IID_IDirectMusicSegment8, wszFile,
		(void**)&m_pSegment))) {
		MessageBox(NULL, "Failed to load sound", "CSound", MB_OK | MB_ICONEXCLAMATION);
	}

	//Download band
	m_pSegment->Download(m_pPerformance);
}

CSound::~CSound()
{
	if (m_pSegment) {
		m_pSegment->Unload(m_pPerformance);
		m_pSegment->Release();
		m_pSegment = NULL;
	}
}

void CSound:lay()
{
	m_pPerformance->PlaySegmentEx(m_pSegment, 0, NULL, 
		DMUS_SEGF_SECONDARY, 0, 0, NULL, NULL);
}

void CSound::Stop()
{
	m_pPerformance->StopEx(m_pSegment,0,0);
}

void CSound::SetRepeats(DWORD dwRepeats)
{
	//A value of DMUS_SEG_REPEAT_INFINITE means infinite
	m_pSegment->SetRepeats(dwRepeats);
}

bool CSound::IsPlaying()
{
	return (m_pPerformance->IsPlaying(m_pSegment, NULL) == S_OK);
}
 
The code is based from this [url]http://www.riaz.de/tutorials/dxaudio02/dxaudio02.html[/url] site. I''ve tested the code creating a normal istance of my class and it all works fine. (Using Win2K and VC++ 6.0) But what I would like to do is push the sound object instances in a vector container. Currently I "do" it like this:
m_cAudio = new CAudio(GetHWND());
m_cAudio->SetMasterVolume(500);

m_cSounds.push_back(CSound("perdu.wav",
  m_cAudio->GetPerformance(), 
  m_cAudio->GetLoader()));

m_cSounds.push_back(CSound("gagne.wav",
  m_cAudio->GetPerformance(), 
  m_cAudio->GetLoader()));
 
The problem is that it doesn''t work. (using the same method to fill a vector using another class I''ve created works just fine). If I''ve understood correctly the object is created and then destroyed. (Using a breakpoint, I see that the destructor is called at the "push_back".) So it actually closes down the channel before I get to use it (leading to exceptions and such). What do you propose I should do? Move the destructor stuff to another function? Is there another way to do it properly? Thank you for your time!

Share this post


Link to post
Share on other sites
Advertisement
Hello, STL on VC6 is messed up, you can get service packs that will fix alot of bugs, download SP6.

You haven't shown us how you've declared your variable m_cSounds, i assume its of type:
std::vector<CSound>


if you want a vector of "T" then the type "T" has the requirement of being assignable "=", at the moment you haven't defined an assignment operator your self so a default one is provideded that just assigns all the old memebers to the new members of the object created when you call push_back, so its basically copying all thous directx member pointers not sure thats what you wont.

You could either define an appropriate assignement operator or store pointers to CSound objects but then you have to manage the memory yourself if you create the objects on the heap.

[edited by - snk_kid on June 2, 2004 12:32:56 PM]

Share this post


Link to post
Share on other sites
you need to write an assignment operator, a copy constructor and a destructor for your class. You''ve probably got one of these already (a destructor) but the rule is that if you''ve got one you probably need all three (Rule of Three).

You''ll be making copies of the object by inserting it into the vector, the pointer to the resource will be copied (rather than creating a new resource), but the temporary object will call the destructor and delete the resource. Bang.

2 options are:
1) Use smart pointers for the resources
2) Store pointers to objects in the vector rather than the objects themselves.

Share this post


Link to post
Share on other sites
Thanks for the answers guys, they were really illuminating.
I've bypassed the problem with using another method for the desrtuction of the directx objects. So when I'm finished with it I use:

for (int i = 0; i < m_cSounds.size(); i++) {
m_cSounds.CloseDown();
}
m_cSounds.clear();

Do you think that I'm having a memory leak with the above method?
I guess that since the m_cSounds contained in the vector point to the same memory and since I'm closing them down, I don't. But I'm not a 100% sure.
Since my educcation for the containers is still poor I had no idea I had to provide a = operator and a copy constructor.
Also for the creation of the vector, yes I use
vector CSound m_cSounds; <--- I had trouble with the >< characters
Thank you again for your answers.


[edited by - moucard on June 2, 2004 12:56:45 PM]

[edited by - moucard on June 2, 2004 12:57:48 PM]

Share this post


Link to post
Share on other sites
if closeDown is the same as the deconstructor and you only need to release resources when your finished with the object then i would leave out the closeDown unless you wont to release resources at any time but still use the same oject.

If you wont to have container of objects then you''ll have to define those three methods we mentioned like so:

#include "CAudio.h"
#include <string>
class Sound {
IDirectMusicPerformance8* m_pPerformance; IDirectMusicLoader8* m_pLoader; IDirectMusicSegment8* m_pSegment;
public:
Sound(const Sound&); //copy constructor

Sound& operator=(const Sound&); //assignement operator

~Sound();

Sound(const std::string& filename,
IDirectMusicPerformance8 *pPerformance, IDirectMusicLoader8 *pLoader);

void play() const;
void stop() const;
void set_repeats(int);
const bool is_playing() const;
};


But i don''t think there is an appropriate way to copy and assign unless you don''t mind copying & assigning directx pointers around. I think you will be better of with a container of pointers to Sound, then everytime you call push_back it will just create a new pointer to Sound and assign the pointer passed to push_back to it, when your finished with it just remember to delete the objects on the heap so you don''t get memory leaks.

Share this post


Link to post
Share on other sites
Just to illustrate what i mean't:


#include "CSound.h"
#include <algorithm>
#include <functional>
#include <vector>

template<class T>
struct deleter : public std::unary_function< T&, void > {
public:
void operator()(T& obj) const {
if(obj != 0) {
delete obj;
obj = 0;
}
}
};

int main() {

std::vector<CSound*> my_sounds();

//... do some stuff


my_sounds.push_back(new CSound());
my_sounds.push_back(new Csound());

//... do some more stuff


std::for_each(my_sounds.begin(),
my_sounds.end(),
deleter<CSound*>());

my_sounds.clear();
return 0;
}


[edited by - snk_kid on June 2, 2004 1:58:11 PM]

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!