Yamaha PM7 Trumpet Mute

Ok. So this is not about programming, but I know a lot of programmers who are musicians. For all you trumpet players out there (I know there’s gotta be at least one), I bought the Yamaha PM7 practice mute because of it’s ability to, first and foremost, mute the sound so that I don’t disturb, kids, neighbors, very small rocks, etc. and, secondly, because it provides a way for me to record trumpet playing on my multi-track recorder (DAW). Well, I bought it believing that the “Personal Studio” that you usually buy it with wasn’t necessary. Plus I got the thing brand new off of ebay for $30 (retails for $70). I had figured that the “Personal Studio” was just acting as a simple pre-amp. Apparently there is something else to it. I borrowed the “Personal Studio” from a friend who had one already and it worked fine, so I now need to get one of those.

Anyhow, I just figured that others who buy just the mute would want to know that the “Personal Studio” (Yamaha ST9) is required for it to work. This information isn’t presented anywhere on the web including the Yamaha web site and music instrument vendors such as Musician’s Friend, etc.

At some point, I woould like to crack open the ST9 and and see what they are doing in there to make it work that my recorder doesn’t seem to provide. If there are any audio engineers out there with an idea, please let me know.

C# Memory Pinning: Convert a byte array to a data structure

C# Memory Pinning: Convert a byte array to a data structure. Have you ever wanted to simply typecast a byte array to a data structure and then use that data structure like you used to be able to do in C? Well, C# provides a facility to accomplish this.

This solution is several months old to me now, but I feel it is something very worthwhile for C# programmers to know.

Have you ever wanted to simply typecast a byte array to a data structure and then use that data structure like you used to be able to do in C? Well, C# provides a facility to accomplish this. Several months ago I needed to take a byte array 64 bytes long and extract different fields from it. At first it seemed that the only solution was to convert the byte array to a string and then use substrings to get what I needed. To add insult to injury, I then had to take each of the substrings and convert them into the data types that I wanted and then assign the members of my data structre to each of those. Something ain’t right about that!!

Now, being the stubborn programmer that I am, I was not satisfied with this solution as I used to have the ability to just typecast a byte array into whatever structure I wanted in C and dangit newer languages such as C# shouldn’t remove features. They should enhance existing ones along with introducing new ones.

Enter memory pinning. Now, I can’t take credit for finding this on my own. It was a tough find and I was only most of the way there when a co-worker of mine found the answer. Here is a code snippet to show how it’s done:

public static object RawDataToObject(ref byte[] rawData,
		Type overlayType) 
{ 
	object result = null;




	GCHandle pinnedRawData = GCHandle.Alloc(rawData,
		GCHandleType.Pinned);
	try
	{
	
		// Get the address of the data array
		IntPtr pinnedRawDataPtr = 
			pinnedRawData.AddrOfPinnedObject(); 

		// overlay the data type on top of the raw data
		result = Marshal.PtrToStructure(
			pinnedRawDataPtr ,
			overlayType);
	}
	finally
	{
		// must explicitly release
		pinnedRawData.Free(); 
	} 

	return result;
} 

Becaues the garbage collector will normally have the ability to change the location of where we have our object allocated in memory, we have to actually pin it by calling GCHandle.Alloc() passing it a handle type of GCHandleType.Pinned.

In the application I was working on I knew that the byte array would always be the same size. If, however, it had been a variable size, then we would have to ensure that the size of the overlay type is the same as the length of the byte array.

Now that we know how to actually do the conversion from byte array to data type, we should probably look at the data types themselves. The data types and their members have to be explicitly set to their correct sizes in the code. The following is an example structure:

[StructLayout(LayoutKind.Sequential, Size=64, Pack=1,
		CharSet=CharSet.Ansi)]
public class MyDataStructure
{
	[ MarshalAs( UnmanagedType.ByValArray, SizeConst=40 )]
	public byte[] name;
    
	public byte eyeColor;
	public byte hairColor;
	public Int16 age; // Two byte integer
	public Int16 height;
	public Int16 weight;
	public Int16 noOfPets;
	public byte sign;

	[ MarshalAs( UnmanagedType.ByValArray, SizeConst=3 )]
	public byte[] birthDate; //yymmdd

	[ MarshalAs( UnmanagedType.ByValArray, SizeConst=10 )]
	public byte[] unused;
	
}

There are several items that need to be explained here. First off, our structure is actually a class. Both classes and structs can be used. Classes just need to be treated as structs and include no methods. Next, notice our StructLayout attribute. Here are the meanings of each of the fields used in this attribute:

  • LayoutKind.Sequential: Tells the compiler that the fields in the structure should be allocated in the same order they are laid out in code
  • Size: This is the total size of the structure. When this is set, you must ensure that the fields all add up to this number.
  • Pack: This is the packing size that the compiler should use to allocate memory for the structure. The default is 8, so if you left this blank, Pack would would be set to 8. In this case, however, we have set the pack to 1, ensuring that memory for the structure is all allocated together. Pack is only used when the LayoutKind is set to Seqential.
  • CharSet: Indicates how the data fields should be marshaled.

Next, look at each of the fields in the data structure. We are representing three different data types in this particular code snippet. They include a single byte a two byte integer and byte arrays which are normally used for strings. To indicate that a field should be marshaled as an array, we have to use the MarshalAs attribute specifying the size the array should be in the attribute rather than in the delcaration code.

Now, when we put this all together, it looks something like this:

// We assume GetNextRecord retuns the 64 byte array
byte[] arrayOfBytes = GetNextRecord();
MyDataStructure mds = (MyDataStructure)RawDataToObject( 
		ref arrayOfBytes, typeof( MyDataStructure ) );

// Now we can reference the data structure
// however we would like
string name = ASCIIEncoding.ASCII.GetString( mds.name );
string age = mds.age.ToString();
...

This solution works great if you have to read in a fixed length data record from either a binary file or even some hardware device. It’s a very cool technique (if you ask me).

Welcome to Long Pointers

Welcome to Matt Long’s weblog. Here you’ll find blog entries relating mostly to programming and mostly using C# with the .NET framwork.

Welcome to Matt Long’s weblog. Here you’ll find blog entries relating mostly to programming and mostly using C# with the .NET framwork. From time to time I solve programming problems that have an elegant solution and there is often a methodology or at least a code snippet I want to share with others. This is the place where I intend to do that. If you are looking for Matt Long’s company, it is now called Skye Road Systems, Inc. You can view the website at http://www.skyeroadsystems.com.

If you’re wondering about the site name “Long Pointers”, well it has a bit of a double meaning. Those of you who are reading this who are programmers may already understand it, but for others, a long pointer is “a 64-bit pointer that may point to an object outside its current process space”. If you don’t know what that means, don’t worry about. Most programmers don’t worry about it anymore either, because it was something you only dealt with in the C programming language, which by most accounts is antiquated and these days primarily used for embedded devices and legacy computer systems (with some exceptions). The double meaning comes in because my last name is Long and I am providing programming tips (a.k.a. pointers) on this site. Call it cheezy. Call it what you will. It’s here to stay.