What is KVR Audio? | Submit News | Advertise | Developer Account

Options (Affects News & Product results only):

OS:
Format:
Include:
Quick Search KVR

"Quick Search" KVR Audio's Product Database, News Items, Developer Listings, Forum Topics and videos here. For advanced Product Database searching please use the full product search. For the forum you can use the phpBB forum search.

To utilize the power of Google you can use the integrated Google Site Search.

Products 0

Developers 0

News 0

Forum 0

Videos 0

Search  

Wusik 4000 Module SDK Docs Ready

DSP, Plug-in and Host development discussion.

Moderator: Moderators (Main)

User avatar
KVRAF
 
18249 posts since 11 Jun, 2001, from Wusik Dot Com
 

Postby WilliamK; Fri Jan 10, 2014 5:21 am Re: Wusik 4000 Module SDK Docs Ready

Just a bump to check out if anyone wants to check this out. :D
User avatar
KVRAF
 
8830 posts since 7 Dec, 2004, from Vancouver, Canada
 

Postby aciddose; Wed Jan 15, 2014 12:26 am Re: Wusik 4000 Module SDK Docs Ready

The line "You cannot use any of this code for any other products", shouldn't this simply be:

Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3

?

Also what is the point of using Affero with the ASP loophole solution when you also license under GPL v2?

Also how is it possible to provide such a license when the two licenses are incompatible?

Edit: I see now it is located in "Wusik 4000 Module SDK.pdf", so most of the quote below doesn't make sense. I would recommend adding a line about that to the root README.md or "documentation.txt" or something.

A direct link from the info page on github and the post here might be good too, although I see you did link to the documentation directory.

Do you have a step-by-step guide with instructions on compiling a module? Apparently I need to link in the JUCE lib, but I have never used JUCE and have no desire to do so. This makes it a matter of "whenever I get around to researching how to use JUCE to build a module" which is probably never.

By distributing a VS2010 / 2012 project/solution files and a step-by-step guide with instructions on placing the JUCE lib directory in a certain location: (Wusik_4000_SDK/JUCE/ ?) where you can simply hit compile and output the basic gain example (or others) this will probably motivate people to write modules a lot more.

As it stands now you're making different statements at different points which makes it seem a bit ambiguous what the license terms are, and compiling a module is a lot more difficult than simply creating a project file and hitting compile since there is no documentation about how to include JUCE or even what is required to actually build a module.
User avatar
KVRAF
 
8830 posts since 7 Dec, 2004, from Vancouver, Canada
 

Postby aciddose; Wed Jan 15, 2014 1:00 am Re: Wusik 4000 Module SDK Docs Ready

Okay, an actually useful issue now:

Jules wrote:Ah, yes, that juce_gui_audio

Ah, yes, that juce_gui_audio thing was actually caused by a typo in the old introjucer, which would add it to the modules list when you create a new project, but in fact there's no such module! The old version's module list only displayed modules which existed, so it would never appear on screen, but the new version attempts to show everything that the project contains.

Just select it in the list and hit 'delete'!
User avatar
KVRAF
 
8830 posts since 7 Dec, 2004, from Vancouver, Canada
 

Postby aciddose; Wed Jan 15, 2014 1:15 am Re: Wusik 4000 Module SDK Docs Ready

wusik4000mod.h ln 441:

Using "float" instead of "fT" typedef.

patch:
Code: Select all
      fT vibratoBuffer;
      fT tremoloBuffer;
      fT filterEnvBuffer[128];
      fT pitchEnvBuffer[128];
User avatar
KVRAF
 
8830 posts since 7 Dec, 2004, from Vancouver, Canada
 

Postby aciddose; Wed Jan 15, 2014 2:04 am Re: Wusik 4000 Module SDK Docs Ready

I'll refactor the code and post it to github, you can decide if you want to use it or not.

I've split the code into separate files and used a namespace "w4k" instead, replacing w4kMod with w4k::module and so on.

I'll probably finish this up and clean up some of the modules and upload that before making further changes.
User avatar
KVRAF
 
8830 posts since 7 Dec, 2004, from Vancouver, Canada
 

Postby aciddose; Wed Jan 15, 2014 2:18 am Re: Wusik 4000 Module SDK Docs Ready

You don't need to call the destructor of the inherited class, if it is virtual that happens automatically.

That is the point of virtual:

If the class is deleted via a pointer typecast to its base class, its destructor would normally not be called.

By declaring the baseclass destructor as virtual it automatically takes that into account and calls the derived destructor first, which then automatically calls down through base classes.

In fact you should never call the baseclass destructor yourself because doing so can lead to it being called twice, which can cause serious havoc.
User avatar
KVRAF
 
18249 posts since 11 Jun, 2001, from Wusik Dot Com
 

Postby WilliamK; Wed Jan 15, 2014 4:11 am Re: Wusik 4000 Module SDK Docs Ready

You got my attention, but to be honest I don't understand everything yet, sorry, but I will try. In any even, thank you for the help. :hug:
User avatar
KVRAF
 
18249 posts since 11 Jun, 2001, from Wusik Dot Com
 

Postby WilliamK; Wed Jan 15, 2014 4:17 am Re: Wusik 4000 Module SDK Docs Ready

aciddose wrote:You don't need to call the destructor of the inherited class, if it is virtual that happens automatically.


Please please please, could you tell me more about this? I am getting a very random bug with the whole thing. The first time I run the program it will crash upon loading up, after that, it will work the whole day without problems. Also, the first time I load up modules, it crashes randomly, but once all modules were loaded at least once, it will start working for the whole day without problems. I couldn't figure this one out yet and it is frustrating me a LOT. :cry: Any help would be much appreciated... :hug:
User avatar
KVRAF
 
8830 posts since 7 Dec, 2004, from Vancouver, Canada
 

Postby aciddose; Wed Jan 15, 2014 5:09 am Re: Wusik 4000 Module SDK Docs Ready

WilliamK wrote:
aciddose wrote:You don't need to call the destructor of the inherited class, if it is virtual that happens automatically.


Please please please, could you tell me more about this? I am getting a very random bug with the whole thing. The first time I run the program it will crash upon loading up, after that, it will work the whole day without problems. Also, the first time I load up modules, it crashes randomly, but once all modules were loaded at least once, it will start working for the whole day without problems. I couldn't figure this one out yet and it is frustrating me a LOT. :cry: Any help would be much appreciated... :hug:


Sounds like an issue with heap corruption.

This means when some memory is written which is not allocated correctly.

For example the most common case is a buffer-overrun, writing to an array past the end of the array.

The same thing can happen when attempting to delete the same object twice, depending on the implementation of new/delete.

Normally when you do:

Code: Select all
char *myarray = new char[999];
delete [] myarray;


This will work fine, but:

Code: Select all
char *myarray = new char[999];
delete [] myarray;
delete [] myarray;
delete [] myarray;
delete [] myarray;
delete [] myarray;


This will (I hope) crash. The "myarray" is never set to zero, so delete[]() has no way to know it was already deleted. Some implementations will create a header in a block of memory which will be used in debug to mark if a block has been deleted. Sometimes no header is used, but memory is filled with 0xFEFEFEFE when deleted.

You can constantly read through memory to look for 0xBAADF00D (uninitialized heap from new) 0xFEFEFEFE (freed) and 0xCDCDCDCD (uninitialized too).

In some modules I see you have called the baseclass destructor, for example:

Wusik_4000_SDK / Modules / Envelopes / ADSR Envelope / Source / ADSR Envelope.cpp, ln 78
Code: Select all
ADSRenvelope::~ADSRenvelope()
{
        W4kMod::~W4kMod(); // ad: this should never be done!
        if (envVoices != nullptr) deleteAndZero(envVoices);
}


What will happen is you do this:

Code: Select all
w4kMod *module = new ADSRenvelope(...);
delete module;


When you ask the module to be deleted, this happens:

w4kMod::vtable[destructor] = ADSRenvelope::~ADSRenvelope()

so, calling delete module calls:

ADSRenvelope::~ADSRenvelope()
{
W4kMod::~W4kMod()
...
} // then automatically ~ADSRenvelope() will call w4kMod once it has finished.
... W4kMod::~W4kMod()

So it has been called twice, and the object containing ADSRenvelope() is deleted while you're still inside the destructor of ADSRenvelope! That is unacceptable because w4kMod must maintain its state until destruction of ADSRenvelope has completed because during that it may attempt to access functions from w4kMod.

Also, any member of w4kMod will be deleted twice, and so if anywhere there is a case like:

Code: Select all
class myclass
{
 myclass()
 {
  myarray = new char[999];
 }

 ~myclass()
 {
  delete [] myarray;
 }
}


This will cause myarray to be deleted twice, which will cause the heap to be trashed.
User avatar
KVRAF
 
8830 posts since 7 Dec, 2004, from Vancouver, Canada
 

Postby aciddose; Wed Jan 15, 2014 5:19 am Re: Wusik 4000 Module SDK Docs Ready

The solution to this is to first, start using debug builds with the debug CRT. For example in visual studio project settings:

config properties -> c++ -> code generation -> runtime library

Set to "multithreaded debug".

If you were not using this setting before, it should now make it crash 100% of the time while you are using debug mode.

With the normal release runtime the memory is not initialized for you with 0xBAADF00D, so the first time in new memory it will crash. After that, the "good" values were already written in memory and the application will be loaded into the same space in memory, which will run fine.

These types of bugs are horrible to try to track down, there are "heap monitoring tools" you can run which constantly check memory for these values and alert you when there is an issue with the heap. I don't use these regularly but they can be useful when a bug does appear.

One example is valgrind on linux. There are many other free tools you might want to try.

First though, make sure you are using the debugging runtime and eliminate these obvious bugs calling destructors where you shouldn't... see if that solves the problem. If you are lucky it should work fine.

Otherwise it will be time to add 100s of assertions and use my refactor of the module to alert when something is accessed "out of bounds".
User avatar
KVRAF
 
8830 posts since 7 Dec, 2004, from Vancouver, Canada
 

Postby aciddose; Wed Jan 15, 2014 5:48 am Re: Wusik 4000 Module SDK Docs Ready

Ah, also I didn't mention uninitialized variables although I was thinking that in the back of my mind - using the debug runtime will help with that also.

Here is the code I use to help with that:

Code: Select all
#if _DEBUG
#include <stdint.h>

template <class T>
void check_init_func(T *p)
{
   // a struct or class may contain aligned members.
   // in the case of a 64-bit int packed with 32-bit ints,
   // it's possible to see 0xreal_valBAADF00D, for example.
   // therefore on x64 this check must be with qwords.
   if (sizeof(void *) == 4)
   {
      int size = (sizeof(T) + (sizeof(void *) - 1)) / sizeof(void *);
      int32_t *intptr = (int32_t *)p;
      for (int i = 0; i < size; i++)
      {
         ASSERT(intptr[i] != 0xBAADF00D);
         ASSERT(intptr[i] != 0xCDCDCDCD);
         ASSERT(intptr[i] != 0xFEFEFEFE);
      }
   } else if (sizeof(void *) == 8) {
      int size = (sizeof(T) + (sizeof(void *) - 1)) / sizeof(void *);
      int64_t *intptr = (int64_t *)p;
      for (int i = 0; i < size; i++)
      {
         ASSERT(intptr[i] != 0xBAADF00DBAADF00D);
         ASSERT(intptr[i] != 0xCDCDCDCDCDCDCDCD);
         ASSERT(intptr[i] != 0xFEFEFEFEFEFEFEFE);
      }
   } else {
      ASSERT(false);
   }
}

#define check_init(p) { check_init_func(p); }
// warning, check_init_once is dangerous in any situation where
// parameters passed to the constructor may ever influence program flow
// only use this if overhead is unbearable!
#define check_init_once(p) { static bool checked = false; if (!checked) { check_init_func(p); checked = true; } }
#endif

#else // !_DEBUG
   #define check_init(p)
   #define check_init_once(p)
#endif


If you put this in check_init.h or somewhere, include it in every .cpp file with a constructor. Initialize the object, then at the end call check_init(this)

Code: Select all
myclass.cpp

myclass::myclass()
{
 myvar = 0;
 mypointer = 0;
 mystruct.init();
 check_init(this);
}


Start following that rule: everything must be initialized in the constructor.

I would also recommend this rule: never initialize to valid defaults.

For example it is common to see people init sample_rate = 44100.0f;

That is insane, because it won't catch uninitialized bugs. It should be expected to be init in the constructor, but "set" to a valid value elsewhere in the code. Instead, it should be: sample_rate = 0;

Every time it is used, it should be: ASSERT(sample_rate > 0.0f);

This is not error handling code. This is an assertion, the purpose is to ensure that things you do with the code are valid during runtime. It will only be used in debug, for example:

Code: Select all
#if _DEBUG
   // break to debugger immediately if failed
   #if defined(_WIN32)
      #define ASSERT(N) if (!(N)) { __debugbreak(); }
   #elif defined(__GNUC__)
      #define ASSERT(N) if (!(N)) { asm("int %3" : "" : "" : ""); }
   #else // will usually trigger an annoying message box, but oh well
      #include <assert.h>
      #define ASSERT(N) assert(N)
   #endif

   // print the code asserted if failed
   #define ASSERTX(N) if (!(N)) { printf("assertx(%s)\n", #N); }
   
   // print a nice error message if failed
   #define ASSERTMSG(N, MSG) if (!(N)) { printf("assertmsg(%s) failed: %s\n", #N, MSG); }

   // break, but only once after loaded
   // for potentially frequent errors you want to know about the first time, but not 100s of times
   #define ASSERT_ONCE(N) { static bool asserted = false; if (!asserted) { ASSERT(N); asserted = true; } }
#else
   // don't do anything if not in debug
   #define ASSERT(N)
   #define ASSERTX(N)
   #define ASSERTMSG(N, MSG)
   #define ASSERT_ONCE(N)
#endif


If you put that in assert.h and make it a part of the w4k sdk as well, that will allow you to use it in many different cases which should help to eliminate any of these types of programmer error.

You may want to use W4K_ prefix on all these to avoid name collisions.
KVRAF
 
3927 posts since 11 Feb, 2006, from Helsinki, Finland
 

Postby mystran; Wed Jan 15, 2014 7:08 am Re: Wusik 4000 Module SDK Docs Ready

WilliamK wrote:
aciddose wrote:You don't need to call the destructor of the inherited class, if it is virtual that happens automatically.


Please please please, could you tell me more about this?


The short version: if you have a pointer, then the type of the pointer decides which class will get it's destructor called. That destructor (as chosen for the type of the pointer) can be virtual, in which case the usual dynamic dispatch logic will apply. Otherwise (not virtual) it will be whatever the pointer claimed the type to be, which will usually result in garbage.

This applies to automatically generated destructors as well: if a base-class has a virtual destructor, the automatically generated destructors will override it correctly.

In other words: the first type in an inheritance hierarchy (typically, but not necessarily that would be the actual "root" base-class) that defines a virtual destructor is the most general type that you can use (a pointer to) to delete the objects safely, because that's the most general type where you have a destructor-entry in the virtual method dispatch tables [and this is why it's not a default: it forces the type to have a vtable pointer].
Image <- plugins | forum
KVRian
 
1070 posts since 28 Mar, 2005
 

Postby otristan; Wed Jan 15, 2014 9:26 am Re: Wusik 4000 Module SDK Docs Ready

Olivier Tristan
Developer - UVI Team
http://www.uvi.net
http://blog.uvi.net
KVRAF
 
3927 posts since 11 Feb, 2006, from Helsinki, Finland
 

Postby mystran; Wed Jan 15, 2014 10:25 am Re: Wusik 4000 Module SDK Docs Ready



I like http://aszt.inf.elte.hu/~gsd/halado_cpp/ (I think it's that one anyway) :P
Image <- plugins | forum
User avatar
KVRAF
 
18249 posts since 11 Jun, 2001, from Wusik Dot Com
 

Postby WilliamK; Thu Jan 16, 2014 9:07 am Re: Wusik 4000 Module SDK Docs Ready

I haven't read the whole thing yet, but I will, just give me time. But one thing, in most places I'm using the OwnedArray class from JUCE. I will check the code for places where I use new and delete and maybe just replace with a JUCE alternative and see how it goes.
PreviousNext

Moderator: Moderators (Main)

Return to DSP and Plug-in Development