Re: Using C++ enums like C# enums

I found out that only the Microsoft allows you to forward declare enums, but standard compliant compilers do not allow it since its size is not yet known.

I could use an int rather than the enum variable to get around the problem, but I prefer to be able to see what the enum is set to, so here is the macro to make the code work in non-Microsoft compilers.

#define ATHENA_START_CSHARP_ENUM( x )	 \
struct x	 			 \
{	 			 \
public:				 \
	enum EnumType
 
#define ATHENA_END_CSHARP_ENUM( x )	 \
	;			 \
				 \
 	inline x()		 \
	{			 \
	}			 \
					 \
	template<typename T>	 \
	inline x( const T & inValue )	 \
		:	 \
		value( (EnumType)inValue )	 \
	{	 \
	}	 \
		\
	inline x( const EnumType inValue )	 \
		:	 \
		value( inValue )	 \
	{	 \
	}	 \
		\
	inline void operator = ( const EnumType inValue )	 \
	{	 \
		value = inValue;	 \
	}	 \
\
	inline EnumType operator ~ () const	 \
	{	 \
		return (EnumType)~value;	 \
	}	 \
\
	inline EnumType operator & ( const EnumType inValue ) const	\
	{	 \
		return (EnumType)( value & inValue );	 \
	}	 \
\
	inline operator EnumType () const	 \
	{	 \
		return value;	 \
	}	 \
\
private:	 \
	EnumType value;	 \
}

 

Using C++ enums like C# enums

There is an update to this post: Re: Using C++ enums like C# enums

I’ve been playing around with idea for a while in my head, a way to have enums work similar to how they work in C#, where they are part of an object.

Usually I would do this.

enum BufferFlags
{
	kBufferFlags_Read = 1 << 0,
	kBufferFlags_Write = 1 << 1
};

 

Since I prefix all my enums with kBufferFlags_, so to access the read enum I’d write kBufferFlags_Read. I can reduce out this bit of code in C# to be an enum object called BufferFlags, and have enums Read and Write. Accessing them with BufferFlags.Read.

So how do I do it in C++? By putting the enum within a struct, I can access them with BufferFlags::Read. Not quite the same, but better. However the structure needs to operate like an enum, so I overloaded the cast operator to return the enum, and the assignment and copy constructors to take the enum too.

I choose to keep the internal value hidden, but it can all be public.

#define ATHENA_START_CSHARP_ENUM( x ) struct x \
{ \
public: \
	enum xEnum; \
\
	inline x() \
	{ \
	} \
\
	inline x( const xEnum inValue ) \
		: \
		value( inValue ) \
	{ \
	} \
\
	inline void operator = ( const xEnum inValue ) \
	{ \
		value = inValue; \
	} \
\
	inline operator xEnum () const \
	{ \
		return value; \
	} \
\
private: \
	xEnum value; \
\
public: \
	enum xEnum
 
#define ATHENA_END_CSHARP_ENUM() ; \
};

 

Originally, the end macro use to take in the name of the enum as well. The reason for this was that the variable value used its type so when viewed in the debugger I could see its value as an enum name instead of a number.

So I changed the enum to be forward declared. To use this macro you now declare an enum like this.

ATHENA_START_CSHARP_ENUM( BufferFlags )
{
	Read = 1 << 0,
	Write = 1 << 1
}
ATHENA_END_CSHARP_ENUM()

 

And an example of it in use.

int main()
{
	BufferFlags flags = BufferFlags::Read;
 
	//
	switch( flags )
	{
	case BufferFlags::Read:
		break;
 
	case BufferFlags::Write:
		break;
 
	default:
		break;
	}
 
	//
	return 0;
}

 

Its a bit more hassle to use it, but it does look nicer to look at when used.

C# – Endian Swap

In 1726, there were tensions between Lilliput and Blefuscu, the problem being soft-boiled eggs. The inhabitants of Lilliput crack open their eggs at the small end, while the inhabitants of Blefuscu crack open theirs at the big end.

In 2010, while writing a Midi file parser in C#, I needed the ability to swap the endian of the data, since Midi files are stored as Big Endian, converting them into Little Endian.

I would have thought there would be some function within the BitConverter class to be able to swap, but there didn’t appear to be, so I wrote my own.

Since swapping endian is just reversing the byte order, the simplest method would be to get the bytes of a number, and reverse the array, then reconstruct the number using the reversed bytes.

//
//
using System;
 
//
//
namespace Midi
{
class Endian
{
	//
	public static UInt16 SwapUInt16( UInt16 inValue )
	{
		byte[] byteArray = BitConverter.GetBytes(inValue);
		Array.Reverse(byteArray);
		return BitConverter.ToUInt16(byteArray,0);
	}
 
	//
	public static UInt32 SwapUInt32( UInt32 inValue )
	{
		byte[] byteArray = BitConverter.GetBytes(inValue);
		Array.Reverse(byteArray);
		return BitConverter.ToUInt32(byteArray,0);
	}
}
}

 

But this method is slower than just using a bitshift.

//
//
using System;
 
//
//
namespace Midi
{
class Endian
{
	//
	public static UInt16 SwapUInt16( UInt16 inValue )
	{
		return (UInt16)( ((inValue & 0xff00) >> 8) |
				 ((inValue & 0x00ff) << 8) );
	}
 
	//
	public static UInt32 SwapUInt32( UInt32 inValue )
	{
		return (UInt32)( ((inValue & 0xff000000) >> 24) |
				 ((inValue & 0x00ff0000) >> 8) |
				 ((inValue & 0x0000ff00) << 8) |
				 ((inValue & 0x000000ff) << 24) );
	}
}
}

 

Since any the there are only 16 bit and 32 bit numbers in the Midi file format, and anything larger is of Variable Length Quantity, these are the only two required.

Midi Delta Time Ticks to Seconds

One of the main problems with parsing midi files, is the amount of bad documentation people have put on their websites for converting delta time ticks into seconds or milliseconds.

Eventually I got ahold of the Midi Standard 1.0 which helped me solve this riddle for when calculating it myself, and will hopefully help others who have this problem.

When calculating delta time, “Set Tempo” and “Time Signature” meta events need to be handled. Also remember that the raw denominator for “Time Signature” meta events needs to be used as the exponent for raising two to a power:

const float kTimeSignatureDenominator = powf( 2, rawTimeSignatureDenominator );

 

This first page will cover correctly calculating “Beats Per Minute” (BPM) correctly. And although a lot of examples seem to think you require this to convert delta time ticks to seconds or milliseconds, you don’t.

What is a Beat?

In music, there is something called a Bar, which is a segment of time defined by a given number of beats of a given duration. The values which define a Bar, are called the Time Signature.

A Time Signature, is two numbers, one on top of the other. The numerator describes the number of Beats in a Bar, while the denominator describes of what note value a Beat is.

So 4/4 would be four quarter-notes per Bar, while 4/2 would be four half-notes per Bar, 4/8 would be four eighth-notes per Bar, and 2/4 would be two quarter-notes per Bar.

Calculating BPM

Now a lot of examples say to default the tempo to 120 BPM, and the time signature to 4/4, which is correct. But when handling the “Set Tempo” meta event, the same examples just use the value straight out to calculate the BPM, which is incorrect if the time signature has changed.

The “Set Tempo” meta event in midi only deals in quarter notes, so if the time signature is 4/8, a quarter-note is not a Beat since its described as an eighth-note, so using it to calculate BPM  on its own is incorrect.

const float kOneMinuteInMicroseconds = 60000000;
 
// This is wrong if the time signature is not 4/4
float BPM = kOneMinuteInMicroseconds / newMicrosecondsPerQuarterNote;

 

So how do we solve this? We use the new time signature to scale our BPM to the correct value.

const float kOneMinuteInMicroseconds = 60000000;
const float kTimeSignatureNumerator = 4.0f; // For show only, use the actual time signature numerator
const float kTimeSignatureDenominator = 4.0f; // For show only, use the actual time signature denominator
// This is correct
float BPM = ( kOneMinuteInMicroseconds / newMicrosecondsPerQuarterNote ) * ( kTimeSignatureDenominator / 4.0f );

 

In the code above, we divide the time signature denominator by four (The number four is the denominator value for quarter note), this gives us the number of notes per quarter note. Four divided by four is one, so the BPM remains the same.

If the value of kTimeSignatureDenominator was “8.0f”, then eight divided by four is two (there are two eighth-notes in a quarter note).

The next page will cover the actual conversion of delta time ticks to seconds (or milliseconds).

C# – Midi Variable Length Quantity

On the way home on the train for Christmas, I began porting my Midi parsing class over to C#.

The snippet below shows how to read to read a Variable Length Quantity (sometimes known as a Variable Length Value).

The way it works is very simple, it checks the first byte to see if the MSB is set, if it set it will keep iterating, moving along one byte and doing the same, shifting the previous value across 7 bits until the MSB isn’t set.

If it isn’t set on the initial test, the value from that byte will be used for the value of the VLQ.

//
//
using System;
 
//
//
namespace Midi
{
class VariableLengthQuantity
{
	//
	// Functions
	public VariableLengthQuantity( byte[] inVariableData, int inOffset )
	{
		int offset = inOffset;
 
		// At least one byte is always used
		m_value = inVariableData[offset];
		m_numBytes = 1;
		++offset;
 
		//
		if( ((m_value & 0x80) != 0) )
		{
			UInt32 c;
 
			//
			m_value &= 0x7F;
 
			//
			do
			{
				//
				c = inVariableData[offset];
 
				//
				m_value = (m_value << 7) + (c & 0x7F);
 
				//
				++m_numBytes;
				++offset;
			} while( (c & 0x80) != 0 );
		}
	}
 
	//
	public UInt32 Value
	{
		get
		{
			return m_value;
		}
	}
 
	//
	public UInt32 NumBytes
	{
		get
		{
			return m_numBytes;
		}
	}
 
	//
	// Attributes
	UInt32 m_value;
	UInt32 m_numBytes;
}
}