0
0

As the subject suggests, I have two questions.
1. Imagine you have a 3D-world with around 100 soundobjects in it (most of them not moving). Most sounds have a rather limited range, so you mostly can hear far less objects at once. Is it ok for FMOD to create all these 100 3D sound-objects, setting a limited range for them and trust FMOD to “cull” away the sounds that cannot be heard? Or should I implement some sort of spatial partition management and enable/disable hearable sounds by hand ?
2. I have the problem that I want to be able to give away my executable without including fmod.dll. Is there a way to dynamically load FMOD in Windows? Is there some code available that will do this for me? (I don´t want to write all that getProcessAdress() stuff myself )

  • You must to post comments
0
0

wrong Forum :-(
please move my thread to General Discussion, thanks.

  • You must to post comments
0
0

Well… the name “DLL” stands for “dynamic-link library”. Windows already manages the loading of a .DLL, [b:1p88atrv]if[/b:1p88atrv] the executable is [i:1p88atrv]early-bound[/i:1p88atrv] to it. All your end-user will need is a copy of “fmod.dll” somewhere in the search path.

It is advisable to ship a .DLL to avoid the issue of which [b:1p88atrv]version[/b:1p88atrv] of the .DLL they might have available. The only way to ensure that the end-user is using the correct version with your program is to include the right .DLL with your program and ensure it is in the same directory as the executable (which places it first on the search path).

A [i:1p88atrv]late-bound[/i:1p88atrv] dynamic link would be where, in your own code, you did the LoadLibrary(), GetProcAddress(), etc yourself. This is best done with virtual function pointer tables. (1) Define an interface class (abstract, pure virtual, fully public). (2) Define a class to inherit from the interface class, where all methods do nothing but assert. (3) In the constructor of the class, write the code to load the .DLL, optionally checking for the desired version, get all of the function addresses and overwrite the [i:1p88atrv]vtable[/i:1p88atrv] for the class. For any invalid addresses, do not overwrite the entry in the table, so that the original assert-only functionality is there. This will let you know which functions are not loading during your debugging phase. (4) In the destructor of the class, do your standard clean up of the loaded module. [i:1p88atrv]Sample source code for this design can be provided, once I test it.[/i:1p88atrv] 😉

Another approach is to wrap the .DLL in a COM object. Much of the same steps would be needed. You still define an interface (only this time a true COM interface). The advantage to COM is the actual implementation class can be hidden or even not exist at all. (You allocate a chunk of memory to act as the [i:1p88atrv]vtable[/i:1p88atrv] and cast the pointer. Pretty messy work though. 😕 )

There are no easy generic solutions. You are best using the built-in dynamic-linking support with Windows, or doing the object-oriented approach above.

  • You must to post comments
0
0

Thanks for your answer. I don´t need an object oriented approach at this level – besides the fact that manipulating an vtable by hand sounds rather odd to me. Have you ever worked with OpenGL? Most modern games do not statically link to opengl32.dll anymore (at least unreal and quake3 don´t do it). Instead they use LoadLibrary() (as you mentioned) and then do a GetProcessAdress() for each glXXX() function. What I want is the possibility to have the sam with FMOD, like:

[code:2niuk30e]

include <fmod_dyn.h> // declares all FMOD-functions as function pointers

if (FMOD_LoadLibrary())
{
g_SoundSystem=new FMODSoundSystem(); // provide "working" Sound
}
else
{
g_SoundSystem= new DummySoundSystem() // provide empty API
}
[/code:2niuk30e]

This way the rest of my program gets no problems, because it speaks only to g_SoundSystem which is always a valid object. FMODSoundSystem will wrap all FMOD-stuff invisibly to the application.

My problem still is to do all these GetProcessAdress() calls. Call me lazy, but I don´t want to do this myself – its too hairy and error prone.

  • You must to post comments
0
0

I’ve looked through the Win32 API and cannot find any methods that will do anything better than GetProcAddress().

You’re right about the static linking. I doubt any programs still statically link anymore, but most do not use LoadLibrary() and the like either. It’s usually sufficient to use the import library (.LIB) when compiling, so that you get “load-time dynamic linking”. This option only fails when the end-user does not have the library requested. Using “run-time dynamic linking” (as you are wanting) allows the program to continue to run even if the library is missing. Of course, your code needs to be smart enough not to try using a bad function pointer.

Might I ask why using the import library and “load-time dynamic linking” is not an option for you?

Back to the issue of GetProcAddress()… If your concern is error prone code, then I would suggest you write an inline function to reduce the amount of redundant typing. (Macros are okay, only if you are coding in C.) This is sorta what it would look like:
[code:35abux7f]/*** Untested Code ***/

include <windows.h>

include <crtdbg.h>

/* Our function pointer types. */
// typedef int (FAR WINAPI *FARPROC)(); // from <windef.h>
typedef void (FAR WINAPI *SIMPLEPROC)(void);
typedef int (FAR WINAPI *MATHPROC)(int, int);

/* This method updates the output parameter
if and only if the address is valid. */
inline void SafeGetProcAddress(HMODULE hModule, LPCSTR lpProcName, FARPROC *fpFunc)
{
_ASSERTE(NULL != fpFunc);

FARPROC fpTemp = NULL;
if ((NULL != hModule) &amp;&amp; (NULL != lpProcName) &amp;&amp;
    (NULL != (fpTemp = GetProcAddress(hModule, lpProcName)))
{
    (*fpFunc) = fpTemp;
}

}

/* Our safe functions, to eliminate NULL pointers. */
void SafeSimpleProc(void) { _ASSERT(0); }
int SafeMathProc(int, int) { _ASSERT(0); return 0; }

/* The actual function pointers. */
SIMPLEPROC simpleFunc = SafeSimpleProc;
MATHPROC mathFunc = SafeMathProc;

/* This method updates the global function pointers. */
void GetFunctions(void)
{
HMODULE hModule = LoadLibrary("foo.dll");

SafeGetProcAddress(hModule, &quot;simpleFunc&quot;, (FARPROC *)&amp;simpleFunc);
SafeGetProcAddress(hModule, &quot;mathFunc&quot;, (FARPROC *)&amp;mathFunc);

if (NULL != hModule)
    FreeLibrary(hModule);

}[/code:35abux7f]
By the way, there may even be a way to use C++ templates so that you can even further reduce typing. In fact, just like they have “smart pointers”, I would believe you could create the “smart function pointer”.

The only other way I could imagine you loading the function pointers is by loading the DLL into memory and examining the image yourself. Included with the Visual Studio tools is “DUMPBIN.EXE”, which can, among other things, list the exports of a .DLL. My guess is that they are looking at the PE (Portable Executable) format directly. The [b:35abux7f]ImageHlp[/b:35abux7f] API has routines to let you get down and dirty with a Win32 executable.

  • You must to post comments
0
0

[quote:2r36ww3n]
Might I ask why using the import library and “load-time dynamic linking” is not an option for you? [/quote:2r36ww3n]

This is the method I´m currently using. Its very convenient, I admit. But my program currently focuses mainly on the graphics engine (Yet Another Quake3 Viewer – [url:2r36ww3n]http://www.tu-ilmenau.de/~amigo[/url:2r36ww3n] ). I don´t have any in-world-sounds yet and use FMOD to play some background music. I currently just include fmod.dll into the downloadable zip file. That makes the filesize bigger and I probably run into legal issues (do I?). It would be neat to be able to give the exe away without FMOD. I would the just give a warning “FMOD.dll not found, you can get it here: …..” and continue starting the application.

Besides that, have you any experiences/advises related to my other question?[/url][/quote]

  • You must to post comments
0
0

What other question? 😉

About 3D sound culling… we’d need Brett to answer the specifics on FMOD. The key factors I see are memory and timing. If you allocate 100 sounds, that may use up a lot of audio memory depending on the length of each effect. (Good question may be: can you re-instance the same sound in a different 3D location without needing more sample memory, for any duplicated sounds?) Or if you manually limit yourself to, say, 20 sounds (how many overlapping sounds can a human reasonably distinguish?), would the overhead of culling 80 effects cause undesirable latency? And besides that, what is the natural overhead by letting FMOD deal with all 100 sounds in a 3D spectrum?

My experience with sounds is that they are generally tiny as far as memory footprints go. So I doubt having that many sounds in memory would be an issue, even duplicates. Manually dealing with the sounds would probably incur little noticable latency, as processors are pretty fast these days. But leaving it up to FMOD means less code for you.

If you have the time, try to implement more than one approach, giving yourself an option to switch methods on the fly. You should never be concerned with performance on the first go-around. Try to focus on coding it correctly in the beginning. There’s always later for making it speedy and slick.

On the topic of run-time dynamic linking… I see what you are going for. You want the application to run regardless of a valid FMOD install. If it’s there and it’s the right version, go nuts and play sounds. Otherwise, run silent, run deep.

More than likely, you do not need the entire API for what you are doing. I would say the best solution now is to do a bunch of manually coded GetProcAddress() calls. I am working on the “fmod_dyn.h” that you described right now. I’m trying various techniques for making it easy to read and use. If you would still rather not code it, let me know and I’ll ship you the code for you to use. (Here’s how it looks so far, doing something like you would want…)
[code:2ubrgexs]/* Headers and stuff */

int main(void)
{
HMODULE fmod = LoadLibrary("fmod.dll");
FSOUND fsound(fmod);
bool haveFmod = FMOD_VERSION <= (*fsound.GetVersion)();

FMUSIC fmusic(fmod);
FMUSIC_MODULE fmm = NULL;

if (haveFmod)
{
    (*fsound.Init)(44100,32,0);
    fmm = (*fmusic.LoadSong)(&quot;demosong.nst&quot;);
    (*fmusic.PlaySong)(fmm);
}
else
    printf(&quot;FMOD not available.  Please visit http://www.fmod.org/.\n&quot;);

printf(&quot;Press ESC to end the program.\n&quot;);
int key = 0; do { key = getch(); } while (27 != key);

if (haveFmod)
{
    (*fmusic.StopAllSongs)();
    (*fmusic.FreeSong)(fmm);
    (*fsound.Close)();
}

if (NULL != fmod) FreeLibrary(fmod);
return 0;

}[/code:2ubrgexs]

  • You must to post comments
0
0

[quote:261gh3ct]More than likely, you do not need the entire API for what you are doing. I would say the best solution now is to do a bunch of manually coded GetProcAddress() calls. I am working on the “fmod_dyn.h” that you described right now.[/quote:261gh3ct]

The entire API wouldn´t be too bad. Just define a functionpointer to every fmod-function in the API and name it equally to the original FMOD function. This is nice if you want to switch between load-at-startup and load-at-need. If you still want to do this task, then take a look into Unreal´s source code, available here: [url:261gh3ct]http://unreal.epicgames.com/[/url:261gh3ct] . They have some nice macros to load the whole OpenGL DLL at runtime.
The only additional functions I´d need are:

bool loadFMOD(version)
void unloadFMOD()

thanks in adavance

  • You must to post comments
0
0

No problem, I will work on it and post it tonight, since I doubt it will take long.

Thanks for the tip on Unreal. I like what they did with the OpenGL dynamic loading, by including the one header more than once. I will see how I can use that for our advantage.

  • You must to post comments
Showing 8 results
Your Answer

Please first to submit.