Short answer: I don't know. Long answer: Wave files are "recordings" of sounds using digital samples of the audio waveform amplitude. At the risk of oversimplifying, they're essentially a series of numbers, and if you draw a graph of those numbers you'll see a waveform that looks just like the sound would look on an oscilliscope. MIDI files consist of instructions for synthesized musical instruments, such as "press the C key on the piano softly, wait a quarter of a second, then release it". A wav to midi conversion program would need to be able to look at a waveform and determine not only what note is being played, but how loudly and by which type of instrument, and to distinguish the sounds of multiple instruments playing at the same time, potentially mixed with sound effects, vocals, etc., any of which may not be able to be represented in MIDI format. Despite those difficulties such programs do exist. Sort of. Search for "convert wav to midi" on Google to find some of them and to read more about this complicated subject. This doesn't answer your question, though, which is how to do it in C#. I don't know the answer to that.
Bret Mulvey
Posts
-
Wav To Midi -
Image Class ProblemYou should be able to do it by looking at the raw data bytes. This is more complicated than GetPixel(), but the System.Color structure definitely only supports 8bpp. The upside is that this method can be a lot faster than calling GetPixel thousands of times. To get at the raw data for a System.Drawing.Bitmap you first have to lock the bits (so the array doesn't move around in memory while you're doing unsafe pointer stuff), then you can get a pointer to the start of a particular scan line, which will be a pointer to the raw array of bytes for that scanline. All of this requires the "unsafe" keyword, which requires a special compiler flag. Inside the unsafe { ... } block, first call LockBits() on the Bitmap to get a BitmapData structure. Then you can use the Scan0 property of the BitmapData to get a pointer to the first scanline. In your case you would cast this to a (ushort*) type, since each 16bit value is a ushort. Incrementing the pointer will point to subsequent ushort's on the same scanline. To get to the next row (scan line) of the image, add the value of the Stride property of the BitmapData to the Scan0 value to get the pointer to the start of the second scan line. I don't have a 48bpp image to try this on, but here's some code for a 32bpp image which you can use as a starting point:
using (Bitmap bmp = new Bitmap("image.tif"))
{
int[,] raw = new int[bmp.Width, bmp.Height];
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
unsafe
{
BitmapData data = bmp.LockBits(rect,
ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
int max = int.MinValue;
byte *p = (byte *) data.Scan0;
for (int y = 0; y < bmp.Height; y++)
{
byte *q = p;
for (int x = 0; x < bmp.Width; x++)
{
byte red = *(q++);
byte grn = *(q++);
byte blu = *(q++);
raw[x, y] = blu + 256 * grn + 65536 * red;
}
p += data.Stride;
}
bmp.UnlockBits(data);
}
}In your case you'll want ushort instead of byte everywhere, and you wouldn't be saving the pixels as 32-bit ints of course, but the logic is the same. It's also possible that I have the red/blu values backwards here, but you can figure that out.
-
struct and pointer question in c#Instead of using the "unsafe" keyword in C# and using void* in the extern function signature, try this:
public static extern bool InitialButton(ref TESTA pInfo);
and in the call to the function you would just docallDLL.InitialButton(ref pInfo);
The marshaller should automatically treat this as a pointer. -
Arrays in c#In C# you would just do
int[] array = new int[64]; ... BitMangle(array, 8);
and the BitMangle method would be something likevoid BitMangle(int[] array, int offset) { for (int i=offset; i<array.Length; i++) { // do something with array[i] } }