Wusik 4000 Module SDK Docs Ready

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS
Wusik 8008

Post

WilliamK wrote:Now, please, help me out here. I was wondering on the FLAG system. Right now I use a single int32 variable for the flag. And the bitOperation to check, set, clear flags. BUT, I'm wondering on using a structure for this instead, but I wonder if this is safe. Here's an example:

Code: Select all

struct Flag
	{
		Flag() { flag = 0; };
		inline void set(const int32 flagEnum) { flag |= bitToMask(flagEnum); };
		static inline uint32 bitToMask(const int32 flagEnum) { return (uint32) 1 << (flagEnum & 31); };
		int32 flag;
	};
So, if I declare the Flag flag instead of int32 flag, is this safe to go from the Dynamic Library to the Host and back? I have no clue on this. I will test, it should be safe, since the structure is carefully declared, so I guess it is safe. I will run some tests tomorrow...

Thanks again! :hug:
Ideally you should just be using bool types rather than "bit packing" into a single int.

Alternatively it is possible to pack bits using a template like stl::bitset, although the real question is what is the point? Is it a memory issue? Why not leave the flags "unpacked" in a structure and pass a const reference to that structure?

http://cplus.about.com/od/learningc/ss/lowlevel_10.htm

Code: Select all

struct flag
{
 bool flag1;
 bool flag2;
 bool flag2;
};

function(const flag &f);
For example what I use for button flags:

Code: Select all

		struct keystate
		{
			keystate() { clear(); }
			void clear() { control = shift = alternate = left = middle = right = dbl = false; }
			bool control;
			bool shift;
			bool alternate;
			bool left;
			bool middle;
			bool right;
			bool dbl;
		};
Most platforms implement bool using a single byte.

If that still causes problems you can use a template:

Code: Select all

	template <class T>
	struct bool_t
	{
		bool operator =(const bool &b) {
			return (data = b ? 1 : 0) != 0;
		}

		bool operator ==(const bool &b) const {
			return (data != 0) == b;
		}

		bool operator !=(const bool &b) const {
			return (data != 0) != b;
		}

		operator bool() const {
			return data != 0;
		}

		T data;
	};

	typedef bool_t<int8_t> i8bool;
This will protect you by ensuring structs are padded with width = 1.

Keep in mind that if you use a struct for thus purpose (POD type) you must not mix types of different size or the padding of the struct will no longer be 1.

I don't find it is a problem in my own code even between platforms although if I were writing a filetype or interface I would use the template to ensure I know the size of the type.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

The idea behind a Flag system using bitPacking is that in the near future I can just add more options without breaking all modules. ;-)

Since Wusik 4000 is a work-in-progress, and a lot has to be done yet, I can't just close the format now. With a bitPacking Flag system I can add more stuff as required.

Post

In that case I guess all you can do is use the accessors as you already have.

It should be safe to pass a pointer to the type but you are better off passing the data and wrapping it in a whole new Flags struct to avoid the typecasting.

You could actually pack/unpack when in operator uint_32 and Flags(uint32) and get the ease of access by using native bool types.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

Ok, you lost me now, sorry, did not understand what that means in practical terms. :dog: I'm very slow when it comes to understanding new stuff, sorry... :oops:

Post

Ahhh, I think I understand what you are saying....

Keeping

int32 flags

and using

Flags(flags).set(kEnum)

Like that?

But the structure I created, isn't it easier to read?

Post

No, what I mean is:

- Use a structure with accessor functions and a uint32_t member

- Use a constructor to assign
- Use a operator-type to get the value out
- Plus accessors get(kFlag1), set(kFlag1, true), ...

Code: Select all

struct Flags
{
 Flags() { v = 0; }
 Flags(uint32_t v) : v(v) {}
 operator uint32_t() { return v; }
 uint32_t v;
};
You also could do this:

Code: Select all

struct Flags
{
 Flags() { flag1 = flag2 = flag3 = false; }
 Flags(uint32_t v) 
 {
  flag1 = v & kFlag1 ? true : false;
  flag2 = v & kFlag2 ? true : false;
  flag3 = v & kFlag3 ? true : false;
 }
 operator uint32_t() 
{ 
 uint32_t v = 0;
 v |= flag1 ? kFlag1 : 0;
 v |= flag2 ? kFlag2 : 0;
 v |= flag3 ? kFlag3 : 0;
 return v;
 }
 bool flag1;
 bool flag2;
 bool flag3;
};
This would allow you to access the flags like Flag.flag1 = true; while when you pass it to a function (to dll, or to host) you pass function(uint32_t(Flag));

Inside the function:

Code: Select all

function(uint32_t v)
{
 Flags flags(v);
 if (flags.flag1) {
  ...
 }
}
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

Aciddose, thank you so much for taking the time to help me out. I get what you mean, so far I only managed to get this done:

Code: Select all

	struct Flag
	{
		Flag() { value = 0; };
		Flag(uint32 _value) : value(_value) { };
		operator uint32() { return value; };
		inline bool get(int32 flagEnum)
		{
			return ((value & bitToMask(flagEnum)) > 0);
		};
		inline void set(const int32 flagEnum, bool setvalue)
		{
			if (setvalue) value |= bitToMask(flagEnum);
				else value &= ~bitToMask(flagEnum);
		};
		static inline uint32 bitToMask(const int32 flagEnum)
		{
			return (uint32) 1 << (flagEnum & 31);
		};
		uint32 value;
	};
I know you wanted the other format, but I can't get my head into implementing the other option, but maybe tomorrow I change my mind. :hihi:

Post

Stupid question, if I have this:

Flag flags;
uint32 _flags = 0;

Do I have to do this?
flags.value = _flags;

Or can I do?
flags = _flags;

Post

...
Last edited by WilliamK on Mon Nov 25, 2013 9:50 am, edited 1 time in total.

Post

Biggest paste ever! :hihi:

Well the get/set isn't that much more difficult than using bools, especially if you put the flags enum inside the class.

The main advantage we're looking for is that in your IDE it can pop-up a parameter list when you type flag.[ list pops up ]

With bools you get the list directly and can see which flags you want, with get/set you see the kFlag1, kFlag2 enum values and just need to memorize that and manually type it after "get(...". Not so much of a problem really, although when I turn 85 and it hurts my poor old arthritic fingers you'll get a through trouncing via a strongly worded letter!

So you have only a little more than 50 years left to switch to bools! :x
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

:hihi: ok ok... I will think about it. ;-)

Post

Ok, hope I got this right, a lot of work to be done, but you are right, it will be much easier to handle once it's done. :oops:

Code: Select all

	//=========================================================================
	/** Flags internal basic class

		This is used by each flag system on the classes below, no need to bother
		with this right now, just see the other flags.
	*/
	class WFlags
	{
	public:
		WFlags() {};
		WFlags(uint32 value) {};
		operator uint32() { return 0; };
	};

	//==============================================================================
	/** Bit Operators (internal use only)

		This is used by the Flags system, internally.
	*/
	class BitOp
	{
	public:
		static uint32 bitToMask(const int32 bit) { return (uint32) 1 << (bit & 31); }
		static void set(const int32 bit, uint32 &value) { value |= bitToMask(bit); }
		static bool isSet(const int32 bit, uint32 &value) { return ((value & bitToMask(bit)) > 0); }
	};

Code: Select all

	//=========================================================================
	/** Audio Buffer used for modulation inputs and outputs

		By default, the buffer will be Monophonic, to set as a Polyphonic
		buffer, you need to use: flags.set(kIsPolyphonic)
	*/
	class ModBuffer
	{
	public:
		ModBuffer() { zeromem(out, sizeof(out)); };
		fT out[128];
		//
		class Flags : public WFlags
		{
		public:
			Flags() : isPolyphonic(false) {};
			Flags(uint32 value) 
			{
				isPolyphonic = BitOp::isSet(0, value);
			};
			operator uint32() 
			{ 
				uint32 v = 0;
				if (isPolyphonic) BitOp::set(0, v);
				return v;
			};
			/** When set this buffer has multiple voices information */
			bool isPolyphonic;
		};
		//
		Flags flags;
	};

Post

I will also see how I could fix better the SpecialData Type to avoid using Enum there too. :cool:

Post

Quick question, from the code I posted before, what happens when I do the following, will it work, or I'm missing something extra in the code? (a bit tired here, can't think straight)

Flags flag;
uint32 newflag = something;
flag = newflag;

Post

Hummm, BAD news, I forgot a lot of those flags are read in real-time, so I can't use that system. :cry: The bitPacking on flags is just much faster. Let me check things out again...

Post Reply

Return to “DSP and Plugin Development”