Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Open source C# code to present wave form?

Tags:

c#

audio

Is there any open source C# code or library to present a graphical waveform given a byte array?

like image 992
vondip Avatar asked Jul 31 '09 23:07

vondip


People also ask

Is C an open-source?

The C language is not a piece of software but a defined standard, so one wouldn't say that it's open-source, but rather that it's an open standard. There are a gazillion different compilers for C however, and many of those are indeed open-source.

Is Linux a C language?

Linux. Linux is also written mostly in C, with some parts in assembly. About 97 percent of the world's 500 most powerful supercomputers run the Linux kernel. It is also used in many personal computers.

Do you need Linux to code C?

There's a good reason the Linux kernel is written in C. Finally, C is easy to get started with, especially if you're running Linux. You can already run C code because Linux systems include the GNU C library ( glibc ). To write and build it, all you need to do is install a compiler, open a text editor, and start coding.

What is Linux C programming?

Along with the C programming language comes Linux, an essential operating system used by most computer scientists and developers. Linux powers almost all supercomputers and most of the servers worldwide as well as all android devices and most internet of things devices.


2 Answers

This is as open source as it gets:

public static void DrawNormalizedAudio(ref float[] data, PictureBox pb,     Color color) {     Bitmap bmp;     if (pb.Image == null)     {         bmp = new Bitmap(pb.Width, pb.Height);     }     else     {         bmp = (Bitmap)pb.Image;     }      int BORDER_WIDTH = 5;     int width = bmp.Width - (2 * BORDER_WIDTH);     int height = bmp.Height - (2 * BORDER_WIDTH);      using (Graphics g = Graphics.FromImage(bmp))     {         g.Clear(Color.Black);         Pen pen = new Pen(color);         int size = data.Length;         for (int iPixel = 0; iPixel < width; iPixel++)         {             // determine start and end points within WAV             int start = (int)((float)iPixel * ((float)size / (float)width));             int end = (int)((float)(iPixel + 1) * ((float)size / (float)width));             float min = float.MaxValue;             float max = float.MinValue;             for (int i = start; i < end; i++)             {                 float val = data[i];                 min = val < min ? val : min;                 max = val > max ? val : max;             }             int yMax = BORDER_WIDTH + height - (int)((max + 1) * .5 * height);             int yMin = BORDER_WIDTH + height - (int)((min + 1) * .5 * height);             g.DrawLine(pen, iPixel + BORDER_WIDTH, yMax,                  iPixel + BORDER_WIDTH, yMin);         }     }     pb.Image = bmp; } 

This function will produce something like this:

enter image description here

This takes an array of samples in floating-point format (where all sample values range from -1 to +1). If your original data is actually in the form of a byte[] array, you'll have to do a little bit of work to convert it to float[]. Let me know if you need that, too.

Update: since the question technically asked for something to render a byte array, here are a couple of helper methods:

public float[] FloatArrayFromStream(System.IO.MemoryStream stream) {     return FloatArrayFromByteArray(stream.GetBuffer()); }  public float[] FloatArrayFromByteArray(byte[] input) {     float[] output = new float[input.Length / 4];     for (int i = 0; i < output.Length; i++)     {         output[i] = BitConverter.ToSingle(input, i * 4);     }     return output; } 

Update 2: I forgot there's a better way to do this:

public float[] FloatArrayFromByteArray(byte[] input) {     float[] output = new float[input.Length / 4];     Buffer.BlockCopy(input, 0, output, 0, input.Length);     return output; } 

I'm just so in love with for loops, I guess.

like image 164
MusiGenesis Avatar answered Sep 20 '22 08:09

MusiGenesis


I modified MusiGenesis's solution a little bit. This gave me a much better result, especially with house music :)

public static Bitmap DrawNormalizedAudio(List<float> data, Color foreColor, Color backColor, Size imageSize) {     Bitmap bmp = new Bitmap(imageSize.Width, imageSize.Height);      int BORDER_WIDTH = 0;     float width = bmp.Width - (2 * BORDER_WIDTH);     float height = bmp.Height - (2 * BORDER_WIDTH);      using (Graphics g = Graphics.FromImage(bmp))     {         g.Clear(backColor);         Pen pen = new Pen(foreColor);         float size = data.Count;         for (float iPixel = 0; iPixel < width; iPixel += 1)         {             // determine start and end points within WAV             int start = (int)(iPixel * (size / width));             int end = (int)((iPixel + 1) * (size / width));             if (end > data.Count)                 end = data.Count;              float posAvg, negAvg;             averages(data, start, end, out posAvg, out negAvg);              float yMax = BORDER_WIDTH + height - ((posAvg + 1) * .5f * height);             float yMin = BORDER_WIDTH + height - ((negAvg + 1) * .5f * height);              g.DrawLine(pen, iPixel + BORDER_WIDTH, yMax, iPixel + BORDER_WIDTH, yMin);         }     }      return bmp; }   private static void averages(List<float> data, int startIndex, int endIndex, out float posAvg, out float negAvg) {     posAvg = 0.0f;     negAvg = 0.0f;      int posCount = 0, negCount = 0;      for (int i = startIndex; i < endIndex; i++)     {         if (data[i] > 0)         {             posCount++;             posAvg += data[i];         }         else         {             negCount++;             negAvg += data[i];         }     }      posAvg /= posCount;     negAvg /= negCount; } 
like image 21
robyy Avatar answered Sep 22 '22 08:09

robyy