ボタンを押したら、MIDIの音を鳴らすだけの単純なプログラムです。鍵盤の作り方とかマウスイベントとか、見る人が見ればちょっと面白いかもしれません。
最近のWindowsはC#のコンパイラを持っているので、誰でも手軽にプログラムができます。
コンパイル方法は、以下の通り。
(1)以下のソースコードをテキストファイルにコピー、ファイル名を適当に"piano.cs"として保存
(2)コマンドプロンプトで次のコマンドをを実行すると、"piano.exe"ができる
>cd [csc.exeがあるフォルダ]
>csc.exe /target:winexe "[piano.csがあるフォルダ]/piano.cs"
うまくいかないという方は、周りの詳しそうな人かGoogle先生に聞いてみてください。csc.exeで調べればすぐ分かると思います。
例によって、保証はありませんが、悪しからず。
ご自由に遊んでください。
2016/2/27 : キーボードで複数のキーが押せるようにフラグを微修正しました
2016/3/6 : いろいろ微修正
2016/7/24 : すべてキーボードが使えるように修正
2017/5/4 : APIの宣言が32bit OS用だったので、64bit OS用に変更 (気分でキーボードの処理は削除)
using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Windows.Forms;
class Program
{
[STAThread]
static void Main()
{
Application.Run( new FormPiano());
}
}
class FormPiano : Form
{
/*--------------------------------------------------*/
/* 使用するAPIの宣言 */
/*--------------------------------------------------*/
[DllImport( "Winmm.dll")]
extern static uint midiOutOpen( ref long lphmo, uint uDeviceID, uint dwCallback, uint dwCallbackInstance, uint dwFlags);
[DllImport( "Winmm.dll")]
extern static uint midiOutClose( long hmo);
[DllImport( "Winmm.dll")]
extern static uint midiOutShortMsg( long hmo, uint dwMsg);
private const uint MMSYSERR_NOERROR = 0;
private const uint MIDI_MAPPER = 0xffffffff;
/*--------------------------------------------------*/
private long hMidi;
private Label[] lbl;
private ComboBox[] cmb;
private Panel pnl;
private Button[] key;
public FormPiano()
{
this.ClientSize = new Size( 840, 240);
this.Text = "Piano";
this.Load += new EventHandler( this.FormPiano_Load);
this.Closed += new EventHandler( this.FormPiano_Closed);
/*--------------------------------------------------*/
/* コントロールの作成 */
/*--------------------------------------------------*/
this.lbl = new Label[2];
for( int i = 0; i < this.lbl.Length; i++)
{
this.lbl[i] = new Label();
this.lbl[i].SetBounds( 180 * i, 0, 60, 40, BoundsSpecified.All);
this.Controls.Add( this.lbl[i]);
}
this.lbl[0].Text = "channel";
this.lbl[1].Text = "program";
this.cmb = new ComboBox[2];
for( int i = 0; i < this.cmb.Length; i++)
{
this.cmb[i] = new ComboBox();
this.cmb[i].SetBounds( 180 * i + 60, 0, 60, 40, BoundsSpecified.All);
this.cmb[i].DropDownStyle = ComboBoxStyle.DropDownList;
this.Controls.Add( this.cmb[i]);
}
this.cmb[0].Items.Add( 0);
this.cmb[0].Items.Add( 9);
this.cmb[0].SelectedIndex = 0;
for( int i = 0; i < 127; i++)
{
this.cmb[1].Items.Add( i);
}
this.cmb[1].SelectedIndex = 0;
this.cmb[1].SelectedIndexChanged += new EventHandler( this.cmb_SelectedIndexChanged);
/*--------------------------------------------------*/
/* 鍵盤(ボタン)の作成 */
/*--------------------------------------------------*/
this.pnl = new Panel();
this.pnl.SetBounds( 0, 40, 840, 200, BoundsSpecified.All);
this.pnl.AutoScroll = true;
this.pnl.Anchor = ( AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom);
this.Controls.Add( this.pnl);
this.key = new Button[128];
int count = 0;
for( int i = 0; i < this.key.Length; i++)
{
this.key[i] = new Button();
this.key[i].Name = i.ToString();
this.key[i].Text = i.ToString();
this.key[i].TextAlign = ContentAlignment.BottomCenter;
this.pnl.Controls.Add( this.key[i]);
this.key[i].MouseDown += new MouseEventHandler( this.key_MouseDown);
this.key[i].MouseUp += new MouseEventHandler( this.key_MouseUp);
this.key[i].MouseEnter += new EventHandler( this.key_MouseEnter);
this.key[i].MouseLeave += new EventHandler( this.key_MouseLeave);
if( count % 2 == 0)
{
this.key[i].SetBounds( 20 * count, 0, 40, 160, BoundsSpecified.All);
this.key[i].ForeColor = Color.Black;
this.key[i].BackColor = Color.White; //白
}
else
{
this.key[i].SetBounds( 20 * count + 5, 0, 30, 80, BoundsSpecified.All);
this.key[i].ForeColor = Color.White;
this.key[i].BackColor = Color.Black; //黒
this.key[i].BringToFront();
}
count += ( i % 12 == 4 || i % 12 == 11) ? 2 : 1;
}
}
/*--------------------------------------------------*/
/* MIDIデバイスのOpenとClose
/*--------------------------------------------------*/
private void FormPiano_Load( object sender, EventArgs e)
{
Console.WriteLine( "FormPiano_Load");
if( midiOutOpen( ref this.hMidi, MIDI_MAPPER, 0, 0, 0) != MMSYSERR_NOERROR)
{
MessageBox.Show( "midiOutOpen error");
Application.Exit();
}
this.pnl.AutoScrollPosition = new Point( 1120, 0);
}
private void FormPiano_Closed( object sender, EventArgs e)
{
Console.WriteLine( "FormPiano_Closed");
midiOutClose( this.hMidi);
}
/*--------------------------------------------------*/
/* Note On/Off */
/*--------------------------------------------------*/
private void NoteOn( byte key)
{
byte ch = (byte) ( ( this.cmb[0].SelectedIndex == 0) ? 0 : 9);
byte velocity = 0x7f;
uint msg;
msg = (uint)( ( velocity << 16) + ( key << 8) + 0x90 + ch);
midiOutShortMsg( this.hMidi, msg);
}
private void NoteOff( byte key)
{
byte ch = (byte) ( ( this.cmb[0].SelectedIndex == 0) ? 0 : 9);
byte velocity = 0x7f;
uint msg;
msg = (uint)( ( velocity << 16) + ( key << 8) + 0x80 + ch);
midiOutShortMsg( this.hMidi, msg);
}
/*--------------------------------------------------*/
/* プログラム変更 */
/*--------------------------------------------------*/
private void ProgramChange( byte prg)
{
byte ch = (byte) 0;
uint msg;
msg = (uint)( ( prg << 8) + 0xc0 + ch);
midiOutShortMsg( this.hMidi, msg);
}
/*--------------------------------------------------*/
/* コンボボックスの処理 */
/*--------------------------------------------------*/
private void cmb_SelectedIndexChanged(object sender, System.EventArgs e)
{
byte prg = (byte) this.cmb[1].SelectedIndex;
Console.WriteLine( "cmb_SelectedIndexChanged " + prg.ToString());
this.ProgramChange( prg);
}
/*--------------------------------------------------*/
/* マウス処理 */
/*--------------------------------------------------*/
private void key_MouseDown( object sender, MouseEventArgs e)
{
( (Button)sender).Capture = false;
byte key = (byte) int.Parse( ( (Button)sender).Name);
Console.WriteLine( "key_MouseDown " + key.ToString());
this.NoteOn( key);
}
private void key_MouseUp( object sender, MouseEventArgs e)
{
byte key = (byte) int.Parse( ( (Button)sender).Name);
Console.WriteLine( "key_MouseUp " + key.ToString());
this.NoteOff( key);
}
private void key_MouseEnter( object sender, EventArgs e)
{
if ((Control.MouseButtons & MouseButtons.Left) == MouseButtons.Left)
{
this.key_MouseDown( sender, new MouseEventArgs( MouseButtons.Left, 1, 0, 0, 0));
}
}
private void key_MouseLeave( object sender, EventArgs e)
{
if ((Control.MouseButtons & MouseButtons.Left) == MouseButtons.Left)
{
this.key_MouseUp( sender, new MouseEventArgs( MouseButtons.Left, 1, 0, 0, 0));
}
}
/*--------------------------------------------------*/
}
0 件のコメント:
コメントを投稿