From following various discussions in the public forums, it seems that having the callbacks as cdecl causes a problem for VB, hence the requirement for a custom DLL to implement callbacks in VB. If these were stdcall, would this allow VB to implement callbacks directly without the need for a custom DLL? Adion, could you confirm this?
As far as I know and from what I heard I think that should do it.
I’ll have a further look into it.
It seems that that is all that needs to be done.
For full vb compatibility I’d also have to see if I can make some VB object similar to the c++ wrapper so that multiple sound cards can be used in VB too.
VB can use double pointers with a little work. Once I see how you’re using them I can write a little example of how it’d be done.
Vb’s addressof is for functions, you use varptr/strptr/objptr for variable addresses. You can sort of dereference a pointer in vb – either pass the pointer to CopyMemory using the ByVal flag, or to whatever function expects a pointer using byval and varptr. I do lots of pointer mangling in vb, myself.
- Janus answered 15 years ago
It seems that the CreateSystem function returns a pointer to a C++ class in the System parameter. This will not be usable directly by Delphi or VB since these languages cannot use C++ classes directly. I am assuming this is the case for VB. Adion, can you confirm if VB can or cannot use C++ classes directly? In these cases, Delphi (and VB) will need to declare classes that wrap the C functions. For example…[code:222h1f48]interface
FMOD_SYSTEM = Pointer;
TFMODSystem = class
constructor Create(ASystem: FMOD_SYSTEM);
function Init(MixRate: Integer; Flags: Cardinal): Integer;
constructor TFMODSystem.Create(ASystem: FMOD_SYSTEM);
FSystem := ASystem;
function TFMODSystem.Init(MixRate: Integer; Flags: Cardinal): Integer;
Result := FMOD_System_Init(FSystem, Mixrate, Flags);
end;[/code:222h1f48]The constructor would be called to initialise the FSystem member. The Init method would call the C function passing the FSystem member as the first parameter.
Am I right in assuming that the C functions are just a wrapper around the class methods? For example…[code:222h1f48]FMOD_RESULT FMOD_System_Init(FMOD_SYSTEM *system, int mixrate, unsigned int flags)
return ((System *)system)->init(mixrate, flags);
}[/code:222h1f48]If this is so, then Delphi and VB classes will be quite inefficient due to the several layers of function calls for every call to FMOD.
Delphi application code -> Delphi FMOD class method -> FMOD C function -> FMOD C++ class method
Or, are the classes a wrapper around the C function calls? In this case, the indirection is reduced by one layer.
Delphi application code -> Delphi FMOD class method -> FMOD C function
If they were COM objects, then none of this would be required, but that would break cross-platform compatibility.
That wouldn’t hardly change a thing for most of the VB code.
If it is the same as it is now (the pointers are only to indicate what sound you are refering to, and you cannot directly get parts of a FMOD_SOUND structure) then it would work as follows :
Any pointer to a sound is just stored in a 32-bit integer as is now.
Dim sound As Long
The only difference is that in the declaration of the function, the sound should not be passed ByVal, but ByRef.
ByRef will pass the pointer to the Long variable, but the Long variable actually is a memory address, which makes it a double pointer.
When the function declaration is changed, you can just use it the same way as it is now :
Edit: As Janus says, it is also possible to use CopyMemory and VarPtr and such, but if it is possible, I like to try not to use these as much as possible, because that would make it quite hard to use, especially for people that aren’t very experienced with vb and it will also make the code some slower because you always have to copy your pointer before calling any function.
Of course copymemory and such is a solution for some functions that can easily be wrapped in the fmod module, such as is currently the case with the function for getting fft data.
- Adion answered 15 years ago
Since it are all just handles I don’t think there will be any problem for VB support.
I could just write the module with the function definitions, that you could simply use and handle all of the pointer stuff on your own.
This method would look like the c header and would be quite fast and direct.
Then I could also make a class that is a wrapper of the functions and can be used if you want an object-oriented way.
In VB6, the performance drop from using objects will probably be a lot greater than the performance drop from the wrapper functions.
VB.NET and C# support will also be very important I think, but I don’t know yet what’s possible in these languages concerning objects and such.
One more question about the c++ header:
How is the FMOD_SYSTEM handle passed to all these functions? Is it just C++ that passes the handle as first argument of each function automatically?
I would use the approach of having a private member containing the handle. Then just pass this handle to all the C functions. The handle can be passed to the class as a constructor parameter. An example of this is in my earlier message (in Object Pascal but the same principle applies to C++).
I don’t really care about the API naming scheme, as long as you don’t get them mixed up like you have with FMOD 3.x, hehe. The FMOD 3.x naming convention has always been a little confusing because it was mixed up in places, but other than that I love how it worked like a C api… no annoying ‘objects’ to keep track of like DirectSound. The main reason I’ve been using FMod so much is that when I tried DirectSound, I could not stand having to keep track of a COM object for every sound effect. ^_^
- Janus answered 16 years ago
[quote:1bmq2oo5]’Channel’ API. Pass NULL to let FMOD pick a channel for you?[/quote:1bmq2oo5]
how would that be possible ? neither of the functions provide the functionality of a PlaySound, at least 2 calls need to be made to play a sound. (SetSound and Start).
And, if there are multiple FMOD_SYSTEMs, it is not clear which one should be invoked.
I’m not too happy with channel ‘objects’ at the moment interface wise as it seems harder to use. The alternative is to do something like
I don’t see an alternative to channel objects. You can of course call it “channel handle” if you prefer that, but how would I keep track of channels if I don’t have anything to identify them?
hard coded channel numbers suck, because one sound might kick another sound off a channel, and you now what happens. (The FMOD 3 channel handles solve this problem very well…)
i dont like this much either tho, so at the moment it is the given method.
I agree, this would kinda rule out the possibility of FMOD chosing which channel to play on.
its possible i might change setsound/start to
FMOD_RESULT F_API FMOD_Channel_Start (FMOD_CHANNEL *cptr, FMOD_SOUND *sptr, int paused);
like fmod3’s playsoundex, which will make things a bit less verbose, though i’ll have to see what happens in practice with regards to this[/quote:1spsdz3l]
I somewhat like the separation of setsound and play, but if you want to make it less verbose, how about a good old
FMOD_Sound_Play(FMOD_Sound*, FMOD_Channel **)
which does a getchannel and a setsound/play and returns the chosen channel ?
Please login first to submit.