Wednesday, July 29, 2015

.Net and C# Alternative to Matlab

Note: For this post I was paid by the ILNumerics GmbH, but I was allowed and supposed to choose the content freely and express my personal opinion.

In today's post I want to present the class library ILNumerics and share my experiences with it.
ILNumerics is a class library for .Net with the aim of allowing faster and easier implementations of numerical calculations, plots etc. Of course one could do this in theory with .Net means alone, but this could turn out to be very tedious (just think of the representation of vectors, multiplying matrices etc.). With ILNumerics now a language extension very similar to Matlab is available, with which complex algorithms can be implemented efficiently. In the following I  will now, as stated, give an introduction to this topic and test the product which is subject to a charge but which I rate in total as very good.

Let us start with the installation: The library can be downloaded via the homepage. Available is only a trial version, this fact and the price is the only negative point in my opinion. The program is relatively costly, starting from 89 Euros per month, so probably not suited for the hobby user. But for universities, companies etc., here I can think of ILNumerics as a real alternative to Matlab, especially since I personally like C# and .Net a lot. A free version for students would be highly appreciated.
After the installation the trial version can be tested respectively the version activated. More information you find on the support page. On this you also find a tutorial and a more precise documentation, which also served me as a reference.

The library contains basically two components: The computation engine and the visualization engine. First I will explain the usage of the computation engine, then that of the visualization engine.

To include the computation engine easily we create a new Windows-Forms project and then click on Project - Add New Item in the menu. In the new window we select "Computing Module" and with that add a new .cs file in the form of a computing module to the project. In this already some example methods are implemented which demonstrate the usage of ILNumerics, but which can of course be deleted. We do this but leave the Main method since we want to use the computing module as entry point for the program. We have to set this in the project since also the created Form class contains a main method. We do this by selecting in the project properties the computing module as Application - Startup Object.
The code of the file Computing Module1.cs should look as follows:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ILNumerics;
using System.IO;

namespace IlNumericsTest
{

    public class Computing_Module1 : ILMath
    {
        public static void Main(params string[] parameter)
        {
        }
    }

}

Let us start with some easy operations for acclimatization.
Matrices are managed by the ILNumerics class ILArray. With this via +, -, *, / the expected calculation operations can be executed, which are matrix addition / subtraction and element wise multiplication / division. The following code creates 3 matrices of the size 10 x 10, the first is filled with ones, the second with zeros and the third with random values between 0 and 1. Then A + C and A * (-1) is outputted in the console.

ILArray<double> A = ones(10, 10);
ILArray<double> B = zeros(10, 10);
ILArray<double> C = rand(10, 10);
Console.WriteLine(A + C);
Console.WriteLine(-A);

Now some more complex examples, I want to show some operators on graphs and networks. Who does not know graphs is referred to Wikipedia, they are an often used data structure in computer science and mathematics. The research area Web Science especially deals with the investigation and analysis of networks (like the internet), for this graphs are used to represent the data, which can
take on huge sizes. Because of the thematic relevance (for example often Matlab is used) I decided to show some examples from this area as for examle the PageRank algorithm of Google.
But first a function for reading in data:

            var file = File.ReadAllText("Graph.txt");
            ILArray AdjMatrix = csvread(file);

In the first line the file is read to a string, which is then read to a matrix via the ILNumerics function csvread(). csvread() splits the read values (for example) by commas. The input file should contain the comma separatued adjacency matrix of a graph, which contains a 1 on position i, j if the nodes i and j are connected by an edge, otherwise 0. For a graph with 4 nodes the file could look as follows:

0, 1, 0, 0
1, 0, 1, 1
0, 1, 0, 1
0, 1, 1, 0

Now we want to determine the Laplacian Matrix out of the adjacency matrix, which contains the degree of node i in the i-th diagonal entry and -1 on position i, j if the nodes i, j, are connected. For this we create a new function. Since ILNumerics puts special emphasis on performance / memory management (or has to put if it wants to handle big data), we here have to watch some things. On the one hand there is not only the presented type ILArray, but also ILInArray, ILOutArray and ILRetArray (and in general also other types than Array). For more information I point to the documentation, here, just briefly, ILInArray is for example used for input parameters, is immutable and is immediately deleted after leaving the corresponding scope (because of memory / performance reasons). Because of this we have to enclose every function in a new scope, which contains the input parameters.
The function for calculating the Laplacian looks as follows:

public static ILRetArray<double> CalcLaplacian(ILInArray<double> AdjMatrix)
{
    using (ILScope.Enter(AdjMatrix))
    {
        ILArray<double> Degrees = sum(AdjMatrix);
        ILArray<double> LaplacianMatrix = Degrees * eye(AdjMatrix.Length, AdjMatrix.Length);
        LaplacianMatrix = LaplacianMatrix - AdjMatrix;
        return LaplacianMatrix;
    }
}

Input parameter is the adjacency matrix. In the first line in the scope the degree of the nodes is calculated, which is done via the function sum(). This sums over all columns of the matrix and then outputs a vector with the result, which equals exactly the sequence of degrees. eye() creates a matrix with ones in the diagonal, multiplying the degree vector and substracting it from the adjacency matrix gives us the desired matrix.

As a next example we calculate the density of a network. This is an important measure in networks, it is calcualted by dividing the number of present edges by the number of possible edges and thus points out how dense and centralized a network is. With a double summation over the matrix dimensions the density can simply be calculated:

public static ILRetArray<double> CalcDensity(ILInArray<double> AdjMatrix)
{
    using (ILScope.Enter(AdjMatrix))
    {
        ILArray<double> NrLinks = sum(sum(AdjMatrix));
        return (double)NrLinks / (AdjMatrix.Length * (AdjMatrix.Length - 1));
    }
}

Now to an algorithm, which made its inventors rich and world famous, but is in principal so easy that we implement it now here (in principal - of course there is much more to it than just these lines of code). I am talking about Google's Pagerank algorithm, which was for a long time the basis of the ranking of websites in the Google search. The algorithm assigns to every page a pagerank (a populariy), which is made up of the pageranks of the pages linking to this page. The formula for calculating it is explained in the linked Wikipedia article, in practise though the pagerank is approximated iteratively: Start with an arbitrary pagerank vector P, then the new pagerank is calculated by P = (1 - d) * e * A'T*P. Here d is a damping factor (e.g. 0.5), e is the unity vector and A' the matrix which results of the adjacency matrix A by substituting all rows with only zeros by rows with the entries 1/n (n = number of nodes). We repeat this until old and new pagerank are sufficiently close, that means the procedure does not change much any more with the next iterations. In ILNumerics this looks as follows:

        public static ILRetArray<double> CalcPageRank(ILArray<double> AdjMatrix)
        {
            using (ILScope.Enter(AdjMatrix))
            {
                ILArray<double> Degrees = sum(AdjMatrix.T);
                double epsilon = 0.00001;
                double d = 0.5;
                for (int i = 0; i < AdjMatrix.Length; i++)
                {
                    for (int j = 0; j < AdjMatrix.Length; j++)
                    {
                        if (Degrees[i] != 0)
                            AdjMatrix[i, j] /= Degrees[i];
                    }
                    if (AdjMatrix["0", ":"].Equals(zeros(1, AdjMatrix.Length)))
                        AdjMatrix["0", ":"] = ones(AdjMatrix.Length) / AdjMatrix.Length;
                }
                ILArray<double> POld = zeros(AdjMatrix.Length);
                ILArray<double> PNew = ones(AdjMatrix.Length);

                do
                {
                    POld = PNew;
                    PNew = (1 - d) * ones(AdjMatrix.Length) + d * multiply(AdjMatrix.T, POld);
                }
                while (norm(POld - PNew, 1) > epsilon);

                return PNew;
            }
        }

So with the previously described method first the adjacency matrix of an arbitrary graph has to be read, the function then calculates for every node in the graph the Pagerank and returns the vector of Pageranks. As one can see, also the selection of submatrices is possible like in Matlab. Matrix["a:b", "c:d"] chooses the submatrix which consists of the rows a - b and the columns c - d of Matrix.

But, like this the Pagerank should not be implemented in ILNumerics. I simply wrote the code in this style first to give an intuitive introduction, and then show how to better use the possibilites of ILNumerics.
In general the usage of custom ILNumerics functions is recommended over the usage of self made ones, like looping with for - loops over big matrices etc. Thus we use the type ILLogical instead of looping over the matrix and testing the rows for 0. This gives us a vector which describes which elements from some given vector fulfill a certain condition. We choose as a condition Degrees = 0, then select the submatrix with the corresponding rows and replace them by 1/n. We do the same to divide entries of nodes with degree unequal to zero by n. Further we pull unneccessary calculation operations out of the loop, like generating a vector of ones and transposing the matrix. The resulting code is much more simpler and quicker and looks as follows:

        public static ILRetArray<double> CalcPageRank(ILArray<double> AdjMatrix)
        {
            using (ILScope.Enter(AdjMatrix))
            {
                ILArray<double> Degrees = sum(AdjMatrix, 1);
                double epsilon = 0.00001;
                double d = 0.5;

                ILLogical dummy = Degrees == 0;

                AdjMatrix[dummy, full] = 1.0 / AdjMatrix.Length;
                dummy = Degrees != 0;

                AdjMatrix[dummy, full] = AdjMatrix[dummy, full] / Degrees[dummy];
                AdjMatrix = AdjMatrix.T;

                ILArray<double> POld = zeros(AdjMatrix.Length);
                ILArray<double> PNew = ones(AdjMatrix.Length);
                ILArray<double> ILOnes = (1.0 - d) * ones(AdjMatrix.Length);

                do
                {
                    POld = PNew;
                    PNew = ILOnes + d * multiply(AdjMatrix, POld);
                }
                while (norm(POld - PNew, 1) > epsilon);

                return PNew;
            }
        }

This algorithm implemented in Matlab takes about 5s for a graph of size 20 MB (about 3000 nodes), in ILNumerics as well. Such short running times of course do not give a reliable performance measure, but I think the two tools prove to be comparable. According to the producers ILNumerics has a somewhat bigger overhead, but is supposed to be faster for longer running times.

To conclude the topic about the computation engine here an example of how to solve a linear equation system:

            ILArray<double> A = ILMath.zeros(3, 3);
            A["0;:"] = new double[] { 1, 2, 1 };
            A["1;:"] = new double[] { 3, 4, 0 };
            A["2;:"] = new double[] { -1, 0, 1 };

            ILArray<double> B = new double[] { 5, 4, 7};

            ILArray<double> x = ILMath.linsolve(A, B);

Let us come to the visualization engine. For this there are of course many many possibilities and settings to create the desired plots, therefore I will here just give a brief introduction and point out to the online documentation for the rest.
As also for the computation engine we here follow the quick start guide and create a new Windows-Form project. Then we add via Project - Add New Item a new Plotting form. In the file Program.cs we change the line Application.Run(new Form1()); to Application.Run(new Plotting_Form1()); to tell the program to start with the plotting form.
This already contains example plots, but we first delete the code to create a new plot from scratch. The plotting form provides a control named ilPanel1, in its Load() function we create a simple line plot with 6 points when starting the form:

        private void ilPanel1_Load(object sender, EventArgs e)
        {
            var scene = new ILScene();
            // create some data

            ILArray<float> A = new float[] { 1, 2, 3, 4, -1, -2 };
            // add a plot cube
            scene.Add(new ILPlotCube {
  new ILLinePlot(A)
});
            ilPanel1.Scene = scene;
        }

Basic components are so called scenes. We here create a new one and add to this then a new lineplot with the given data. The result looks as follows:


By default the plotting area can be moved, rescaled etc. For this it has to be redrawn.









This shall already be enough, here some interesting plots of the homepage which also can be implemented quickly:



As a conclusion I can once again say that I see as a negative point the price, but that I otherwise liked the product a lot. It provides a fast and easy to use calculation and visualization toolkit and I am also convinced of the performance of the code. In ILNumerics see a real alternative to Matlab and would be happy to see it being used more often.

Saturday, July 18, 2015

Play Guitar Tabs with C#

In this post I want to show how one can read in guitar tabs and thus can automatically play songs with C# and the MIDI format. So called tabs are a popular and easy variant to notate songs. In the textformat simply the 6 guitar strings are represented by ---, on positions, where the strings have to be played a number is displayed which describes in which fret the string should be touched. This way a song can be represented pretty well, the tones definitely all can be described, only the tone duration cannot be represented, but often "-" between the numbers denote pauses. Since nearly all songs are (freely) available in this format I wrote a little program which reads in the tabs and then plays the interpreted song with the techniques from the previous posts.
First the function ReadTab() is called with an URL, its sourcecode is then downloaded with a Webclient. If 6 successive lines contain at least 3 "-", we interpret these lines as tabs and save then, eventually to a file (one line per guitar string).
Then the function ReadSong() is called. In this the file is read, the 6 lines are read simultaneously. For every point in time a pause is added if on no string a note is played, or a list with all played notes. For this we calculate the number of the to the tone corresponding piano key. We do this by starting from the enumeration Tone, which saves the to the 6 strings belonging keys, and add to this the number of half tones (keys), by which the string tone has to be incremented.
Finally we pass this list of lists of key numbers to the function Play(). It runs through all points in time and either plays the list of tones simultaneously or a break, as described in the previous post.

The code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.IO;
using Midi;
using System.Threading;

namespace TabReader
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            ReadTab("http://tabs.ultimate-guitar.com/m/metallica/master_of_puppets_tab.htm");    
        }

        int NoteDuration = 70;

        protected enum Tone
        {
            E2 = 20,
            A = 25,
            D = 30,
            G = 35,
            B = 39,
            E4 = 44,
        }

        public void ReadTab(string url)
        {
            System.Net.WebClient wc = new System.Net.WebClient();
            string HTML = wc.DownloadString(url);
            string[] Lines = HTML.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
            string[] Tabs = new string[6];

            for (int i = 0; i < Lines.Length - 6; i++)
            {
                bool Found = true;
                for (int j = 0; j < 6; j++)
                {
                    if (Lines[i + j].Count(f => f == '-') <= 3)
                    {
                        Found = false;
                        break;
                    }
                }
                if (Found)
                {
                    for (int j = 0; j < 6; j++)
                    {
                        Tabs[j] += Lines[i + j];
                    }
                    i += 6;
                }
            }

            string FileName = url.Replace("/", "").Replace("http", "").Replace(":", "");
            StreamWriter sw = new StreamWriter(FileName);
            for (int i = 0; i < 6; i++)
            {
                sw.WriteLine(Tabs[i]);
            }
            sw.Close();

            List<List<int>> Result = ReadSong(FileName);
            Play(Result);
        }

        public List<List<int>> ReadSong(string path)
        {
            System.IO.StreamReader sr = new System.IO.StreamReader(path);
            string[] Strings = new string[6];
            for (int i = 0; i < 6; i++)
            {
                Strings[i] = "";
            }

            string Temp = "";
            while ((Temp = sr.ReadLine()) != null)
            {
                Strings[5] += Temp;
                for (int i = 4; i >= 0; i--)
                {
                    Strings[i] += sr.ReadLine();
                }
            }
            sr.Close();

            List<List<int>> Song = new List<List<int>>();

            for (int i = 0; i < Strings[0].Length; i++)
            {

                bool ToneFound = false;

                List<int> Current = new List<int>();

                for (int j = 0; j < 6; j++)
                {
                    if (Strings[j][i] != '-' && Strings[j][i] != '/' && Strings[j][i] != '|')
                    {
                        int Dummy;

                        if (int.TryParse(Strings[j][i].ToString(), out Dummy))
                        {
                            Current.Add(((int)((Tone[])(Enum.GetValues(typeof(Tone))))[j] + int.Parse(Strings[j][i].ToString())));
                            ToneFound = true;
                        }
                    }

                }

                if (!ToneFound && Strings[0][i] == '-')
                    Song.Add(null);
                else
                    Song.Add(Current);
            }

            Play(Song);
            return Song;
        }

        public void Play(List<List<int>> keys)
        {
            OutputDevice outputDevice = OutputDevice.InstalledDevices[0];
            outputDevice.Open();

            foreach (List<int> t in keys)
            {
                if (t == null)
                    Thread.Sleep(NoteDuration);
                else
                {
                    foreach (int s in t)
                    {
                        outputDevice.SendNoteOn(Channel.Channel1, GetFreq(s), 80);
                    }
                    Thread.Sleep(NoteDuration);
                }
            }
        }

        public Pitch GetFreq(int key)
        {
            return ((Pitch[])Enum.GetValues(typeof(Pitch)))[key + 21];
        }
    }
}

As an example I here recorded the song Master of Puppets by Metallica. As already mentioned, of course the rhytm often is not correct and the melody sometimes seems off. But still I find it fascinating how good for example the intro riff is hit and how easy we can create such music outputs.
Also I recorded Yesterday and Wonderwall.

Friday, July 17, 2015

Create MIDI Tones with C#

After I explained in the previous posts the creation of basic musical tones via Beep, I today want to enhance the sound drastically, which we do with the MIDI format. MIDI is a standard for the exchange of musical control information. It was mainly designed for the communication between synthesizers and consists of messages which describe the playing of tones. With an external library we can play MIDI tones very easily with C#, which also sound pretty well. This kind of surprised and fascinated me - with only some lines of code one can play actual songs.

For this we use the MIDI library midi-dot-net. This has to be downloaded, and then the file "midi.dll" has to be included in the project (Project - Add Reference). After using Midi; then an OutputDevice can be created, which we set via InstalledDevices[0] to our standard speaker. Via SendNoteOn() we then can play a note. For this we have to pass over the desired channel as the first parameter, as a second one the tone and finally the velocity as an int value (it measures, how forcefully the virtual key is pressed).  The note is specified as an object of the enumeration Pitch, which contains a broad spectrum of tones.
I liked the approach from the previous though, to use the keyboard keys, therefore we use this here: We convert the enumeration into an array of the type Pitch and then choose the tone belonging to the pressed key (the desired tone of key n is the entry n + 21).
The tone is played until another command is send, for example we can send SendNoteOff() to turn off the tone. We here simply wait via Sleep() the corresponding tone duration and then play the next one.
The following program plays the anthems from the previous post with MIDI tones:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using Midi;
using System.Threading;

namespace Beep
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            PlayAmericanAnthem();
            PlayGermanAnthem();
        }

        OutputDevice outputDevice;

        public void PlayNote(int key, double duration)
        {
            Pitch Note = ((Pitch[])Enum.GetValues(typeof(Pitch)))[key + 21];
            outputDevice.SendNoteOn(Channel.Channel1, Note, 80);
            Thread.Sleep((int)duration);
        }

        public void PlayGermanAnthem()
        {
            outputDevice = OutputDevice.InstalledDevices[0];
            outputDevice.Open();

            PlayNote(31, 700);
            PlayNote(33, 300);

            PlayNote(35, 500);
            PlayNote(33, 500);
            PlayNote(36, 500);
            PlayNote(35, 500);

            PlayNote(33, 250);
            PlayNote(30, 250);
            PlayNote(31, 500);
            PlayNote(40, 500);
            PlayNote(38, 500);

            PlayNote(36, 500);
            PlayNote(35, 500);
            PlayNote(33, 500);
            PlayNote(35, 250);
            PlayNote(31, 250);

            PlayNote(38, 800);
            outputDevice.Close();
        }

        public void PlayAmericanAnthem()
        {
            outputDevice = OutputDevice.InstalledDevices[0];
            outputDevice.Open();

            PlayNote(20, 300 * 1.3);
            PlayNote(17, 170 * 1.3);

            PlayNote(13, 333 * 1.3);
            PlayNote(17, 333 * 1.3);
            PlayNote(20, 333 * 1.3);

            PlayNote(25, 666 * 1.3);
            PlayNote(29, 200 * 1.3);
            PlayNote(27, 130 * 1.3);

            PlayNote(25, 333 * 1.3);
            PlayNote(17, 333 * 1.3);
            PlayNote(19, 333 * 1.3);

            PlayNote(20, 666 * 1.3);
            PlayNote(20, 170 * 1.3);
            PlayNote(20, 170 * 1.3);

            PlayNote(29, 450 * 1.3);
            PlayNote(27, 220 * 1.3);
            PlayNote(25, 333 * 1.3);

            PlayNote(24, 666 * 1.3);
            PlayNote(22, 200 * 1.3);
            PlayNote(24, 100 * 1.3);

            PlayNote(25, 333 * 1.3);
            PlayNote(25, 333 * 1.3);
            PlayNote(20, 333 * 1.3);

            PlayNote(17, 333 * 1.3);
            PlayNote(13, 333 * 1.3);
            outputDevice.Close();
        }
    }
}

Thursday, July 16, 2015

Piano Keyboard

After I explained in a previous post how to create musical tones via Beep(), I today want to simply show a little program which simulates a basic playable piano keyboard. The tones are calculated by the formula out of the previous post, the surface of the program looks as follows:











Here is the code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace KeyboardTone
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void PlayKey(int key)
        {
            Console.Beep((int)(Math.Pow(Math.Pow(2, 1 / (double)12), key - 49) * 440), 500);
        }

        private void button_Click(object sender, EventArgs e)
        {
            PlayKey(int.Parse(((Button)sender).Name.Substring(6)));
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            button13.Click += button_Click;
            button14.Click += button_Click;
            button15.Click += button_Click;
            button16.Click += button_Click;
            button17.Click += button_Click;
            button18.Click += button_Click;
            button19.Click += button_Click;
            button20.Click += button_Click;
            button21.Click += button_Click;
            button22.Click += button_Click;
            button23.Click += button_Click;
            button24.Click += button_Click;
            button25.Click += button_Click;
            button26.Click += button_Click;
            button27.Click += button_Click;
            button28.Click += button_Click;
            button29.Click += button_Click;
            button30.Click += button_Click;
            button31.Click += button_Click;
            button32.Click += button_Click;
            button33.Click += button_Click;
            button34.Click += button_Click;
            button35.Click += button_Click;
            button36.Click += button_Click;
            button37.Click += button_Click;
            button38.Click += button_Click;
            button39.Click += button_Click;
            button40.Click += button_Click;
            button41.Click += button_Click;
            button42.Click += button_Click;
            button43.Click += button_Click;
            button44.Click += button_Click;
            button45.Click += button_Click;
            button46.Click += button_Click;
            button47.Click += button_Click;
            button48.Click += button_Click;
            button49.Click += button_Click;
            button50.Click += button_Click;
            button51.Click += button_Click;
            button52.Click += button_Click;
            button53.Click += button_Click;
            button54.Click += button_Click;
            button55.Click += button_Click;
            button56.Click += button_Click;
            button57.Click += button_Click;
            button58.Click += button_Click;
            button59.Click += button_Click;
            button60.Click += button_Click;
        }

    }
}
And here the content of the file Form1.Designer.cs:
namespace KeyboardTone
{
    partial class Form1
    {
        /// <summary>
       /// Erforderliche Designervariable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
       /// Verwendete Ressourcen bereinigen.
        /// </summary>
        /// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Vom Windows Form-Designer generierter Code

        /// <summary>
       /// Erforderliche Methode für die Designerunterstützung.
       /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
        /// </summary>
        private void InitializeComponent()
        {
            this.button13 = new System.Windows.Forms.Button();
            this.button15 = new System.Windows.Forms.Button();
            this.button14 = new System.Windows.Forms.Button();
            this.button16 = new System.Windows.Forms.Button();
            this.button17 = new System.Windows.Forms.Button();
            this.button18 = new System.Windows.Forms.Button();
            this.button19 = new System.Windows.Forms.Button();
            this.button20 = new System.Windows.Forms.Button();
            this.button21 = new System.Windows.Forms.Button();
            this.button22 = new System.Windows.Forms.Button();
            this.button23 = new System.Windows.Forms.Button();
            this.button24 = new System.Windows.Forms.Button();
            this.button35 = new System.Windows.Forms.Button();
            this.button36 = new System.Windows.Forms.Button();
            this.button33 = new System.Windows.Forms.Button();
            this.button34 = new System.Windows.Forms.Button();
            this.button31 = new System.Windows.Forms.Button();
            this.button32 = new System.Windows.Forms.Button();
            this.button30 = new System.Windows.Forms.Button();
            this.button28 = new System.Windows.Forms.Button();
            this.button29 = new System.Windows.Forms.Button();
            this.button26 = new System.Windows.Forms.Button();
            this.button27 = new System.Windows.Forms.Button();
            this.button25 = new System.Windows.Forms.Button();
            this.button47 = new System.Windows.Forms.Button();
            this.button48 = new System.Windows.Forms.Button();
            this.button45 = new System.Windows.Forms.Button();
            this.button46 = new System.Windows.Forms.Button();
            this.button43 = new System.Windows.Forms.Button();
            this.button44 = new System.Windows.Forms.Button();
            this.button42 = new System.Windows.Forms.Button();
            this.button40 = new System.Windows.Forms.Button();
            this.button41 = new System.Windows.Forms.Button();
            this.button38 = new System.Windows.Forms.Button();
            this.button39 = new System.Windows.Forms.Button();
            this.button37 = new System.Windows.Forms.Button();
            this.button59 = new System.Windows.Forms.Button();
            this.button60 = new System.Windows.Forms.Button();
            this.button57 = new System.Windows.Forms.Button();
            this.button58 = new System.Windows.Forms.Button();
            this.button55 = new System.Windows.Forms.Button();
            this.button56 = new System.Windows.Forms.Button();
            this.button54 = new System.Windows.Forms.Button();
            this.button52 = new System.Windows.Forms.Button();
            this.button53 = new System.Windows.Forms.Button();
            this.button50 = new System.Windows.Forms.Button();
            this.button51 = new System.Windows.Forms.Button();
            this.button49 = new System.Windows.Forms.Button();
            this.SuspendLayout();
            //
            // button13
            //
            this.button13.BackColor = System.Drawing.Color.White;
            this.button13.Location = new System.Drawing.Point(17, 42);
            this.button13.Name = "button13";
            this.button13.Size = new System.Drawing.Size(21, 113);
            this.button13.TabIndex = 0;
            this.button13.UseVisualStyleBackColor = false;
            //
            // button15
            //
            this.button15.BackColor = System.Drawing.Color.White;
            this.button15.Location = new System.Drawing.Point(38, 42);
            this.button15.Name = "button15";
            this.button15.Size = new System.Drawing.Size(21, 113);
            this.button15.TabIndex = 1;
            this.button15.UseVisualStyleBackColor = false;
            //
            // button14
            //
            this.button14.BackColor = System.Drawing.Color.Black;
            this.button14.Location = new System.Drawing.Point(29, 22);
            this.button14.Name = "button14";
            this.button14.Size = new System.Drawing.Size(17, 87);
            this.button14.TabIndex = 2;
            this.button14.UseVisualStyleBackColor = false;
            //
            // button16
            //
            this.button16.BackColor = System.Drawing.Color.Black;
            this.button16.Location = new System.Drawing.Point(50, 22);
            this.button16.Name = "button16";
            this.button16.Size = new System.Drawing.Size(17, 87);
            this.button16.TabIndex = 4;
            this.button16.UseVisualStyleBackColor = false;
            //
            // button17
            //
            this.button17.BackColor = System.Drawing.Color.White;
            this.button17.Location = new System.Drawing.Point(59, 42);
            this.button17.Name = "button17";
            this.button17.Size = new System.Drawing.Size(21, 113);
            this.button17.TabIndex = 3;
            this.button17.UseVisualStyleBackColor = false;
            //
            // button18
            //
            this.button18.BackColor = System.Drawing.Color.White;
            this.button18.Location = new System.Drawing.Point(80, 42);
            this.button18.Name = "button18";
            this.button18.Size = new System.Drawing.Size(21, 113);
            this.button18.TabIndex = 5;
            this.button18.UseVisualStyleBackColor = false;
            //
            // button19
            //
            this.button19.BackColor = System.Drawing.Color.Black;
            this.button19.Location = new System.Drawing.Point(92, 22);
            this.button19.Name = "button19";
            this.button19.Size = new System.Drawing.Size(17, 87);
            this.button19.TabIndex = 7;
            this.button19.UseVisualStyleBackColor = false;
            //
            // button20
            //
            this.button20.BackColor = System.Drawing.Color.White;
            this.button20.Location = new System.Drawing.Point(101, 42);
            this.button20.Name = "button20";
            this.button20.Size = new System.Drawing.Size(21, 113);
            this.button20.TabIndex = 6;
            this.button20.UseVisualStyleBackColor = false;
            //
            // button21
            //
            this.button21.BackColor = System.Drawing.Color.Black;
            this.button21.Location = new System.Drawing.Point(112, 22);
            this.button21.Name = "button21";
            this.button21.Size = new System.Drawing.Size(17, 87);
            this.button21.TabIndex = 9;
            this.button21.UseVisualStyleBackColor = false;
            //
            // button22
            //
            this.button22.BackColor = System.Drawing.Color.White;
            this.button22.Location = new System.Drawing.Point(121, 42);
            this.button22.Name = "button22";
            this.button22.Size = new System.Drawing.Size(21, 113);
            this.button22.TabIndex = 8;
            this.button22.UseVisualStyleBackColor = false;
            //
            // button23
            //
            this.button23.BackColor = System.Drawing.Color.Black;
            this.button23.Location = new System.Drawing.Point(133, 22);
            this.button23.Name = "button23";
            this.button23.Size = new System.Drawing.Size(17, 87);
            this.button23.TabIndex = 11;
            this.button23.UseVisualStyleBackColor = false;
            //
            // button24
            //
            this.button24.BackColor = System.Drawing.Color.White;
            this.button24.Location = new System.Drawing.Point(142, 42);
            this.button24.Name = "button24";
            this.button24.Size = new System.Drawing.Size(21, 113);
            this.button24.TabIndex = 10;
            this.button24.UseVisualStyleBackColor = false;
            //
            // button35
            //
            this.button35.BackColor = System.Drawing.Color.Black;
            this.button35.Location = new System.Drawing.Point(285, 22);
            this.button35.Name = "button35";
            this.button35.Size = new System.Drawing.Size(17, 87);
            this.button35.TabIndex = 23;
            this.button35.UseVisualStyleBackColor = false;
            //
            // button36
            //
            this.button36.BackColor = System.Drawing.Color.White;
            this.button36.Location = new System.Drawing.Point(294, 42);
            this.button36.Name = "button36";
            this.button36.Size = new System.Drawing.Size(21, 113);
            this.button36.TabIndex = 22;
            this.button36.UseVisualStyleBackColor = false;
            //
            // button33
            //
            this.button33.BackColor = System.Drawing.Color.Black;
            this.button33.Location = new System.Drawing.Point(264, 22);
            this.button33.Name = "button33";
            this.button33.Size = new System.Drawing.Size(17, 87);
            this.button33.TabIndex = 21;
            this.button33.UseVisualStyleBackColor = false;
            //
            // button34
            //
            this.button34.BackColor = System.Drawing.Color.White;
            this.button34.Location = new System.Drawing.Point(273, 42);
            this.button34.Name = "button34";
            this.button34.Size = new System.Drawing.Size(21, 113);
            this.button34.TabIndex = 20;
            this.button34.UseVisualStyleBackColor = false;
            //
            // button31
            //
            this.button31.BackColor = System.Drawing.Color.Black;
            this.button31.Location = new System.Drawing.Point(244, 22);
            this.button31.Name = "button31";
            this.button31.Size = new System.Drawing.Size(17, 87);
            this.button31.TabIndex = 19;
            this.button31.UseVisualStyleBackColor = false;
            //
            // button32
            //
            this.button32.BackColor = System.Drawing.Color.White;
            this.button32.Location = new System.Drawing.Point(253, 42);
            this.button32.Name = "button32";
            this.button32.Size = new System.Drawing.Size(21, 113);
            this.button32.TabIndex = 18;
            this.button32.UseVisualStyleBackColor = false;
            //
            // button30
            //
            this.button30.BackColor = System.Drawing.Color.White;
            this.button30.Location = new System.Drawing.Point(232, 42);
            this.button30.Name = "button30";
            this.button30.Size = new System.Drawing.Size(21, 113);
            this.button30.TabIndex = 17;
            this.button30.UseVisualStyleBackColor = false;
            //
            // button28
            //
            this.button28.BackColor = System.Drawing.Color.Black;
            this.button28.Location = new System.Drawing.Point(202, 22);
            this.button28.Name = "button28";
            this.button28.Size = new System.Drawing.Size(17, 87);
            this.button28.TabIndex = 16;
            this.button28.UseVisualStyleBackColor = false;
            //
            // button29
            //
            this.button29.BackColor = System.Drawing.Color.White;
            this.button29.Location = new System.Drawing.Point(211, 42);
            this.button29.Name = "button29";
            this.button29.Size = new System.Drawing.Size(21, 113);
            this.button29.TabIndex = 15;
            this.button29.UseVisualStyleBackColor = false;
            //
            // button26
            //
            this.button26.BackColor = System.Drawing.Color.Black;
            this.button26.Location = new System.Drawing.Point(181, 22);
            this.button26.Name = "button26";
            this.button26.Size = new System.Drawing.Size(17, 87);
            this.button26.TabIndex = 14;
            this.button26.UseVisualStyleBackColor = false;
            //
            // button27
            //
            this.button27.BackColor = System.Drawing.Color.White;
            this.button27.Location = new System.Drawing.Point(190, 42);
            this.button27.Name = "button27";
            this.button27.Size = new System.Drawing.Size(21, 113);
            this.button27.TabIndex = 13;
            this.button27.UseVisualStyleBackColor = false;
            //
            // button25
            //
            this.button25.BackColor = System.Drawing.Color.White;
            this.button25.Location = new System.Drawing.Point(169, 42);
            this.button25.Name = "button25";
            this.button25.Size = new System.Drawing.Size(21, 113);
            this.button25.TabIndex = 12;
            this.button25.UseVisualStyleBackColor = false;
            //
            // button47
            //
            this.button47.BackColor = System.Drawing.Color.Black;
            this.button47.Location = new System.Drawing.Point(439, 22);
            this.button47.Name = "button47";
            this.button47.Size = new System.Drawing.Size(17, 87);
            this.button47.TabIndex = 35;
            this.button47.UseVisualStyleBackColor = false;
            //
            // button48
            //
            this.button48.BackColor = System.Drawing.Color.White;
            this.button48.Location = new System.Drawing.Point(448, 42);
            this.button48.Name = "button48";
            this.button48.Size = new System.Drawing.Size(21, 113);
            this.button48.TabIndex = 34;
            this.button48.UseVisualStyleBackColor = false;
            //
            // button45
            //
            this.button45.BackColor = System.Drawing.Color.Black;
            this.button45.Location = new System.Drawing.Point(418, 22);
            this.button45.Name = "button45";
            this.button45.Size = new System.Drawing.Size(17, 87);
            this.button45.TabIndex = 33;
            this.button45.UseVisualStyleBackColor = false;
            //
            // button46
            //
            this.button46.BackColor = System.Drawing.Color.White;
            this.button46.Location = new System.Drawing.Point(427, 42);
            this.button46.Name = "button46";
            this.button46.Size = new System.Drawing.Size(21, 113);
            this.button46.TabIndex = 32;
            this.button46.UseVisualStyleBackColor = false;
            //
            // button43
            //
            this.button43.BackColor = System.Drawing.Color.Black;
            this.button43.Location = new System.Drawing.Point(398, 22);
            this.button43.Name = "button43";
            this.button43.Size = new System.Drawing.Size(17, 87);
            this.button43.TabIndex = 31;
            this.button43.UseVisualStyleBackColor = false;
            //
            // button44
            //
            this.button44.BackColor = System.Drawing.Color.White;
            this.button44.Location = new System.Drawing.Point(407, 42);
            this.button44.Name = "button44";
            this.button44.Size = new System.Drawing.Size(21, 113);
            this.button44.TabIndex = 30;
            this.button44.UseVisualStyleBackColor = false;
            //
            // button42
            //
            this.button42.BackColor = System.Drawing.Color.White;
            this.button42.Location = new System.Drawing.Point(386, 42);
            this.button42.Name = "button42";
            this.button42.Size = new System.Drawing.Size(21, 113);
            this.button42.TabIndex = 29;
            this.button42.UseVisualStyleBackColor = false;
            //
            // button40
            //
            this.button40.BackColor = System.Drawing.Color.Black;
            this.button40.Location = new System.Drawing.Point(356, 22);
            this.button40.Name = "button40";
            this.button40.Size = new System.Drawing.Size(17, 87);
            this.button40.TabIndex = 28;
            this.button40.UseVisualStyleBackColor = false;
            //
            // button41
            //
            this.button41.BackColor = System.Drawing.Color.White;
            this.button41.Location = new System.Drawing.Point(365, 42);
            this.button41.Name = "button41";
            this.button41.Size = new System.Drawing.Size(21, 113);
            this.button41.TabIndex = 27;
            this.button41.UseVisualStyleBackColor = false;
            //
            // button38
            //
            this.button38.BackColor = System.Drawing.Color.Black;
            this.button38.Location = new System.Drawing.Point(335, 22);
            this.button38.Name = "button38";
            this.button38.Size = new System.Drawing.Size(17, 87);
            this.button38.TabIndex = 26;
            this.button38.UseVisualStyleBackColor = false;
            //
            // button39
            //
            this.button39.BackColor = System.Drawing.Color.White;
            this.button39.Location = new System.Drawing.Point(344, 42);
            this.button39.Name = "button39";
            this.button39.Size = new System.Drawing.Size(21, 113);
            this.button39.TabIndex = 25;
            this.button39.UseVisualStyleBackColor = false;
            //
            // button37
            //
            this.button37.BackColor = System.Drawing.Color.White;
            this.button37.Location = new System.Drawing.Point(323, 42);
            this.button37.Name = "button37";
            this.button37.Size = new System.Drawing.Size(21, 113);
            this.button37.TabIndex = 24;
            this.button37.UseVisualStyleBackColor = false;
            //
            // button59
            //
            this.button59.BackColor = System.Drawing.Color.Black;
            this.button59.Location = new System.Drawing.Point(594, 22);
            this.button59.Name = "button59";
            this.button59.Size = new System.Drawing.Size(17, 87);
            this.button59.TabIndex = 47;
            this.button59.UseVisualStyleBackColor = false;
            //
            // button60
            //
            this.button60.BackColor = System.Drawing.Color.White;
            this.button60.Location = new System.Drawing.Point(603, 42);
            this.button60.Name = "button60";
            this.button60.Size = new System.Drawing.Size(21, 113);
            this.button60.TabIndex = 46;
            this.button60.UseVisualStyleBackColor = false;
            //
            // button57
            //
            this.button57.BackColor = System.Drawing.Color.Black;
            this.button57.Location = new System.Drawing.Point(573, 22);
            this.button57.Name = "button57";
            this.button57.Size = new System.Drawing.Size(17, 87);
            this.button57.TabIndex = 45;
            this.button57.UseVisualStyleBackColor = false;
            //
            // button58
            //
            this.button58.BackColor = System.Drawing.Color.White;
            this.button58.Location = new System.Drawing.Point(582, 42);
            this.button58.Name = "button58";
            this.button58.Size = new System.Drawing.Size(21, 113);
            this.button58.TabIndex = 44;
            this.button58.UseVisualStyleBackColor = false;
            //
            // button55
            //
            this.button55.BackColor = System.Drawing.Color.Black;
            this.button55.Location = new System.Drawing.Point(553, 22);
            this.button55.Name = "button55";
            this.button55.Size = new System.Drawing.Size(17, 87);
            this.button55.TabIndex = 43;
            this.button55.UseVisualStyleBackColor = false;
            //
            // button56
            //
            this.button56.BackColor = System.Drawing.Color.White;
            this.button56.Location = new System.Drawing.Point(562, 42);
            this.button56.Name = "button56";
            this.button56.Size = new System.Drawing.Size(21, 113);
            this.button56.TabIndex = 42;
            this.button56.UseVisualStyleBackColor = false;
            //
            // button54
            //
            this.button54.BackColor = System.Drawing.Color.White;
            this.button54.Location = new System.Drawing.Point(541, 42);
            this.button54.Name = "button54";
            this.button54.Size = new System.Drawing.Size(21, 113);
            this.button54.TabIndex = 41;
            this.button54.UseVisualStyleBackColor = false;
            //
            // button52
            //
            this.button52.BackColor = System.Drawing.Color.Black;
            this.button52.Location = new System.Drawing.Point(511, 22);
            this.button52.Name = "button52";
            this.button52.Size = new System.Drawing.Size(17, 87);
            this.button52.TabIndex = 40;
            this.button52.UseVisualStyleBackColor = false;
            //
            // button53
            //
            this.button53.BackColor = System.Drawing.Color.White;
            this.button53.Location = new System.Drawing.Point(520, 42);
            this.button53.Name = "button53";
            this.button53.Size = new System.Drawing.Size(21, 113);
            this.button53.TabIndex = 39;
            this.button53.UseVisualStyleBackColor = false;
            //
            // button50
            //
            this.button50.BackColor = System.Drawing.Color.Black;
            this.button50.Location = new System.Drawing.Point(490, 22);
            this.button50.Name = "button50";
            this.button50.Size = new System.Drawing.Size(17, 87);
            this.button50.TabIndex = 38;
            this.button50.UseVisualStyleBackColor = false;
            //
            // button51
            //
            this.button51.BackColor = System.Drawing.Color.White;
            this.button51.Location = new System.Drawing.Point(499, 42);
            this.button51.Name = "button51";
            this.button51.Size = new System.Drawing.Size(21, 113);
            this.button51.TabIndex = 37;
            this.button51.UseVisualStyleBackColor = false;
            //
            // button49
            //
            this.button49.BackColor = System.Drawing.Color.White;
            this.button49.Location = new System.Drawing.Point(478, 42);
            this.button49.Name = "button49";
            this.button49.Size = new System.Drawing.Size(21, 113);
            this.button49.TabIndex = 36;
            this.button49.UseVisualStyleBackColor = false;
            //
            // Form1
            //
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(652, 180);
            this.Controls.Add(this.button59);
            this.Controls.Add(this.button60);
            this.Controls.Add(this.button57);
            this.Controls.Add(this.button58);
            this.Controls.Add(this.button55);
            this.Controls.Add(this.button56);
            this.Controls.Add(this.button54);
            this.Controls.Add(this.button52);
            this.Controls.Add(this.button53);
            this.Controls.Add(this.button50);
            this.Controls.Add(this.button51);
            this.Controls.Add(this.button49);
            this.Controls.Add(this.button47);
            this.Controls.Add(this.button48);
            this.Controls.Add(this.button45);
            this.Controls.Add(this.button46);
            this.Controls.Add(this.button43);
            this.Controls.Add(this.button44);
            this.Controls.Add(this.button42);
            this.Controls.Add(this.button40);
            this.Controls.Add(this.button41);
            this.Controls.Add(this.button38);
            this.Controls.Add(this.button39);
            this.Controls.Add(this.button37);
            this.Controls.Add(this.button35);
            this.Controls.Add(this.button36);
            this.Controls.Add(this.button33);
            this.Controls.Add(this.button34);
            this.Controls.Add(this.button31);
            this.Controls.Add(this.button32);
            this.Controls.Add(this.button30);
            this.Controls.Add(this.button28);
            this.Controls.Add(this.button29);
            this.Controls.Add(this.button26);
            this.Controls.Add(this.button27);
            this.Controls.Add(this.button25);
            this.Controls.Add(this.button23);
            this.Controls.Add(this.button24);
            this.Controls.Add(this.button21);
            this.Controls.Add(this.button22);
            this.Controls.Add(this.button19);
            this.Controls.Add(this.button20);
            this.Controls.Add(this.button18);
            this.Controls.Add(this.button16);
            this.Controls.Add(this.button17);
            this.Controls.Add(this.button14);
            this.Controls.Add(this.button15);
            this.Controls.Add(this.button13);
            this.Name = "Form1";
            this.Text = "Piano";
            this.Load += new System.EventHandler(this.Form1_Load);
            this.ResumeLayout(false);

        }

        #endregion

        private System.Windows.Forms.Button button13;
        private System.Windows.Forms.Button button15;
        private System.Windows.Forms.Button button14;
        private System.Windows.Forms.Button button16;
        private System.Windows.Forms.Button button17;
        private System.Windows.Forms.Button button18;
        private System.Windows.Forms.Button button19;
        private System.Windows.Forms.Button button20;
        private System.Windows.Forms.Button button21;
        private System.Windows.Forms.Button button22;
        private System.Windows.Forms.Button button23;
        private System.Windows.Forms.Button button24;
        private System.Windows.Forms.Button button35;
        private System.Windows.Forms.Button button36;
        private System.Windows.Forms.Button button33;
        private System.Windows.Forms.Button button34;
        private System.Windows.Forms.Button button31;
        private System.Windows.Forms.Button button32;
        private System.Windows.Forms.Button button30;
        private System.Windows.Forms.Button button28;
        private System.Windows.Forms.Button button29;
        private System.Windows.Forms.Button button26;
        private System.Windows.Forms.Button button27;
        private System.Windows.Forms.Button button25;
        private System.Windows.Forms.Button button47;
        private System.Windows.Forms.Button button48;
        private System.Windows.Forms.Button button45;
        private System.Windows.Forms.Button button46;
        private System.Windows.Forms.Button button43;
        private System.Windows.Forms.Button button44;
        private System.Windows.Forms.Button button42;
        private System.Windows.Forms.Button button40;
        private System.Windows.Forms.Button button41;
        private System.Windows.Forms.Button button38;
        private System.Windows.Forms.Button button39;
        private System.Windows.Forms.Button button37;
        private System.Windows.Forms.Button button59;
        private System.Windows.Forms.Button button60;
        private System.Windows.Forms.Button button57;
        private System.Windows.Forms.Button button58;
        private System.Windows.Forms.Button button55;
        private System.Windows.Forms.Button button56;
        private System.Windows.Forms.Button button54;
        private System.Windows.Forms.Button button52;
        private System.Windows.Forms.Button button53;
        private System.Windows.Forms.Button button50;
        private System.Windows.Forms.Button button51;
        private System.Windows.Forms.Button button49;
    }
}