超簡易 MIDI キーボード for cygwin Perl ― 2006年12月07日 02時03分16秒
概要
PC のキーボードを MIDI キーボードにしてしまうという、激しくありがちなプログラムです。MIDI マッパーが正しく設定されていればふつーに音が鳴ります。
操作方法
画面の表示に合わせてキーを押すと音が鳴り、放せば止まります。
また、カーソルキーの上下でオクターブを移動することができます。
動作環境
- 本プログラムは cygwin 上の Perl にて動作確認していますが、Win32API::MIDI をビルドして動かすことができるようであれば、ActivePerl 上でも動かせるかもしれません。
- Windows 以外の OS では動作しません。
- Win32API::MIDI モジュールを追加インストールする必要があります。
- Win32::Console のバージョンが古いと、定義済み変数であるはずの変数が定義されていない為に例外が発生するかもしれません。その場合は、最新のモジュールに差し替えてください。
制限事項
音色の差し替えやベロシティの変更など、その他のいろんなことは一切できません。
また、キーリピートが発生するぐらい押しっぱなしにしていると、何故か和音が 3 つぐらいまでしか鳴らせなくなっちゃったりします。
免責事項
Artistic License (参考: 日本語訳) に準じます。ご自由にどうぞ。また、一切の保証はありません。ご利用は自己責任で。
ソースコード
#!/usr/bin/perl
package Keybord;
use strict;
use Win32::Console;
# 鍵盤のキー割り当て
use constant KEYBORD_MAP_WHITE_LOW => [qw(z x c v b n m , . / \\)];
use constant KEYBORD_MAP_BLACK_LOW => [qw(s d), '', qw(g h j), '', qw(l ;)];
use constant KEYBORD_MAP_WHITE_HIGH => [qw(q w e r t y u i o p @ [)];
use constant KEYBORD_MAP_BLACK_HIGH => [qw(2 3 4), '', qw(6 7), '', qw(9 0 -)];
# 鍵盤の垂直表示位置
use constant KEYBORD_POS_Y_WHITE_LOW => [ 12, 20 ];
use constant KEYBORD_POS_Y_BLACK_LOW => [ 12, 16 ];
use constant KEYBORD_POS_Y_WHITE_HIGH => [ 2, 10 ];
use constant KEYBORD_POS_Y_BLACK_HIGH => [ 2, 6 ];
# 鍵盤の水平表示位置
use constant KEYBORD_POS_X_LOW => 10;
use constant KEYBORD_POS_X_HIGH => 8;
# 鍵盤の幅
use constant KEY_WIDTH_WHITE => 4;
use constant KEY_WIDTH_BLACK => 2;
# 鍵盤の色
use constant KEY_COLOR_WHITE => $FG_BLACK | $BG_LIGHTGRAY;
use constant KEY_COLOR_BLACK => $FG_LIGHTGRAY | $BG_BLACK;
use constant KEY_COLOR_HIGHLIGHT => $FG_BLACK | $BG_YELLOW;
# 鍵盤の最初のキーに割り当てられるノート値 (デフォルト値)
use constant FIRST_NOTE_LOW => 48;
use constant FIRST_NOTE_HIGH => 65;
# オクターブシフトで変化するノート値
use constant OCTAVE => 12;
# オクターブシフトの閾値
use constant NOTE_UNDER_LIMIT => 0;
use constant NOTE_UPPER_LIMIT => 127 - scalar(@{&KEYBORD_MAP_WHITE_HIGH}) * 2;
# 鍵盤のキーに対する各種情報 (ノート値差分、インデクス、白鍵 or 黒鍵、押下中か否か)
my %keybord_info_low;
my %keybord_info_high;
{
my $setNoteDiff = sub {
my ($note_diff, $white, $black) = @_;
for (my $i = 0, my $note = 0; $i < @$white; $i++){
$note_diff->{$white->[$i]} = {
'note' => $note++,
'index' => $i,
'type' => 'white',
'is down' => 0,
};
$note_diff->{$black->[$i]} = {
'note' => $note++,
'index' => $i,
'type' => 'black',
'is down' => 0
} if $black->[$i] ne '';
}
};
$setNoteDiff->(\%keybord_info_low, KEYBORD_MAP_WHITE_LOW, KEYBORD_MAP_BLACK_LOW);
$setNoteDiff->(\%keybord_info_high, KEYBORD_MAP_WHITE_HIGH, KEYBORD_MAP_BLACK_HIGH);
}
# コンソール出力オブジェクト
our $console_out = new Win32::Console(STD_OUTPUT_HANDLE);
# パッケージローカル関数
my ($displayKeybord);
# オブジェクト生成 - 画面作り
sub new {
my $invocant = shift;
my $class = ref $invocant || $invocant;
$console_out->Cls($FG_BLACK | $BG_BLUE);
$displayKeybord->(KEYBORD_MAP_WHITE_LOW, KEYBORD_POS_X_LOW, 'white', KEYBORD_POS_Y_WHITE_LOW);
$displayKeybord->(KEYBORD_MAP_WHITE_HIGH, KEYBORD_POS_X_HIGH, 'white', KEYBORD_POS_Y_WHITE_HIGH);
$displayKeybord->(KEYBORD_MAP_BLACK_LOW, KEYBORD_POS_X_LOW, 'black', KEYBORD_POS_Y_BLACK_LOW);
$displayKeybord->(KEYBORD_MAP_BLACK_HIGH, KEYBORD_POS_X_HIGH, 'black', KEYBORD_POS_Y_BLACK_HIGH);
my $self = {
'first note low' => FIRST_NOTE_LOW, # 下鍵盤の最初のキーのノート値
'first note high' => FIRST_NOTE_HIGH, # 上鍵盤の (以下略)
};
bless $self, $class
}
# デストラクタ - 画面消去
sub DESTROY {
$console_out->Cls($ATTR_NORMAL);
}
# キー on/off 切り替え - 対応するノート値を返す
sub keyTurn {
my ($self, $key, $is_down) = @_;
my $high_or_low = $keybord_info_low{$key} ? 'low'
: $keybord_info_high{$key} ? 'high'
: undef;
return unless $high_or_low;
my $keybord = $high_or_low eq 'low' ? \%keybord_info_low : \%keybord_info_high;
# リピート防止の為、押し続けている間はノート値を返さない
return if $keybord->{$key}{'is down'} && $is_down;
$keybord->{$key}{'is down'} = $is_down;
my ($note, $index, $type) = @{$keybord->{$key}}{qw(note index type)};
my $y = $high_or_low eq 'low' ? ($type eq 'white' ? KEYBORD_POS_Y_WHITE_LOW->[1]
: KEYBORD_POS_Y_BLACK_LOW->[1])
: ($type eq 'white' ? KEYBORD_POS_Y_WHITE_HIGH->[1]
: KEYBORD_POS_Y_BLACK_HIGH->[1]);
# ハイライトの切り替え
$console_out->FillAttr(
$is_down ? KEY_COLOR_HIGHLIGHT
: $type eq 'white' ? KEY_COLOR_WHITE : KEY_COLOR_BLACK,
$type eq 'white' ? KEY_WIDTH_WHITE : KEY_WIDTH_BLACK,
($high_or_low eq 'low' ? KEYBORD_POS_X_LOW : KEYBORD_POS_X_HIGH) +
($type eq 'white' ? 0 : KEY_WIDTH_WHITE - int(KEY_WIDTH_BLACK / 2)) +
KEY_WIDTH_WHITE * $index,
$y);
$note + $self->{"first note $high_or_low"}
}
# オクターブを上げる / 下げる
sub moveOctave {
my ($self, $updown) = @_;
return if $updown eq 'down' && $self->{'first note low'} - OCTAVE < NOTE_UNDER_LIMIT;
return if $updown eq 'up' && $self->{'first note high'} + OCTAVE > NOTE_UPPER_LIMIT;
$self->{'first note low'} += $updown eq 'up' ? OCTAVE : - OCTAVE;
$self->{'first note high'} += $updown eq 'up' ? OCTAVE : - OCTAVE;
}
# 画面作り - キーボード描画
$displayKeybord = sub {
my ($keymap, $x, $type) = (shift, shift, shift);
my ($y1, $y2) = @{shift()};
$x += $type eq 'white' ? 0 : KEY_WIDTH_WHITE - int(KEY_WIDTH_BLACK / 2);
local $_;
for my $key (@$keymap){
next if $key eq '';
$console_out->FillAttr(
$type eq 'white' ? (KEY_COLOR_WHITE, KEY_WIDTH_WHITE, $x, $_)
: (KEY_COLOR_BLACK, KEY_WIDTH_BLACK, $x, $_)
) for ($y1 .. $y2);
$console_out->WriteChar($key, $x, $y2);
}
continue {
$x += KEY_WIDTH_WHITE;
}
};
package main;
use strict;
use Win32::Console;
use Win32API::MIDI;
# 仮想キー
use constant VKEY_END => 27; # 終了キー : [ESC]
use constant VKEY_OCTAVE_UP => 38; # オクターブを上げる : カーソルキー [↑]
use constant VKEY_OCTAVE_DOWN => 40; # オクターブを下げる : カーソルキー [↓]
# MIDI イベント
use constant MIDI_STATUS_NOTE_ON => 0x90; # ステータスコード: note on
use constant MIDI_VELOCITY => 100; # ベロシティ
my $console_in = new Win32::Console(STD_INPUT_HANDLE);
my $midi = new Win32API::MIDI;
my $midi_out = new Win32API::MIDI::Out or die $midi->OutGetErrorText;
my $keybord = new Keybord;
while (1){
my ($type, $is_down, undef, $vkey, undef, $char) = $console_in->Input;
next if $type != 1; # キー入力以外のイベントの場合
last if $vkey == VKEY_END; # 終了キーが押された場合
# オクターブ移動
$keybord->moveOctave('up'), next if $vkey == VKEY_OCTAVE_UP && $is_down;
$keybord->moveOctave('down'), next if $vkey == VKEY_OCTAVE_DOWN && $is_down;
my $key = $keybord->keyTurn(chr $char, $is_down);
next unless defined $key;
$midi_out->ShortMsg(
(($is_down ? 100 : 0) << 16) |
($key << 8) |
MIDI_STATUS_NOTE_ON)
or die $midi_out->GetErrorText;
}
$midi_out->Close;
__END__
Yahoo! ブログの転載機能 ― 2006年12月07日 03時04分37秒
TB どもです。やっと話が見えてきました。
なるほど。Yahoo! ブログには、Yahoo! ブログシステムローカルで機能する「転載」機能が存在し、転載したい記事の「転載」ボタンを押すだけで、自分の Yahoo! ブログに記事を転載できるようになっている。この機能を中心とした話題だったわけですね。
昔、試しに使っていてそのままにしていた Yahoo! ブログがあったので、自分のブログだけで転載機能を試してみました。
自分で試して見て解った点を以下に列挙します。
- 転載機能を用いてコピーした記事は、編集できない。転載時の内容がそのまま保たれる。
- 上記で転載元と転載先の内容が異なるのは、転載を行ってから転載元を編集しなおした為。この場合、現時点では、転載元と転載先の記事は同期しない模様 (つまり、ハードリンクのようなものではなく、あくまでコピーであるということ)。
- オリジナルの記事を作成もしくは編集時に、転載機能を許可するか拒否するかを設定可能。
- 転載機能によってコピーした記事は編集できないため、転載を拒否する設定に変更することはできないっぽい。転載元の記事がコメント・トラックバックを受け付ける設定の場合は、これらも拒否する設定には変更できないっぽい。
この機能を実装した Yahoo! は、サーバーのキャパシティによほどの自身があるのでしょう。。。
個人的な見解を申し上げます。
Yahoo! ブログが機能として提供している以上、Yahoo! ブログシステム内の仲間同士で、この機能を用いて記事の転載を行いあうこと自体は、多くの場合、それほど問題は無いように思います。
ただ、「転載」という用語自体はごく一般的なものですので、「ご自由に転載してください」のような記述をした場合、Yahoo! ブログ以外のブログ等をもつ人が、手動で記事をコピーし、転載する行為も認めることになるという点には、注意する必要があるかもしれません (Yahoo! ブログが SNS だったならば、問題にはならないのですが)。
あとは、まぁ、各自の良識の範囲内で使われればよろしいのではないかと思います。
経営情報 ― 2006年12月07日 11時00分42秒
- オープンシステム移行による弊害を断罪する (@IT)
経営情報学についてはあんまり興味のないおいらなのですが、上記記事が結構面白かったので、著者の方のサイトを覗いてみました。
経営と情報に関する私の主張の中で、ERPパッケージ批判という記事があり、まだこれぐらいしか目を通していないのですが、これがまた面白い。要チェックです。
何この妄想。 ― 2006年12月07日 11時44分22秒
小飼氏による記事経由。
- 5分で人を育てる技術 (5)言うことを聞かない“自信過剰な部下” (ITpro Watcher)
この記事を読む前に言っておくッ!
おれは今この記事を流し読みだが読んできた
い…いや…読んだというよりはまったく理解を超えていたのだが……
,. -‐'''''""¨¨¨ヽ
(.___,,,... -ァァフ| あ…ありのまま 今 起こった事を話すぜ!
|i i| }! }} //|
|l、{ j} /,,ィ//| 『部下を教育する話だと思ったら
i|:!ヾ、_ノ/ u {:}//ヘ 実は馴れ合いごっこによる部下いびりの話だった』
|リ u' } ,ノ _,!V,ハ |
/´fト、_{ル{,ィ'eラ , タ人 な… 何を言ってるのか わからねーと思うが
/' ヾ|宀| {´,)⌒`/ |<ヽトiゝ おれも何が「ひとつ上」なのかわからなかった…
,゙ / )ヽ iLレ u' | | ヾlトハ〉
|/_/ ハ !ニ⊇ '/:} V:::::ヽ 頭がどうにかなりそうだった…
// 二二二7'T'' /u' __ /:::::::/`ヽ
/'´r -―一ァ‐゙T´ '"´ /::::/-‐ \ 勘違いだとか作り話だとか
/ // 广¨´ /' /:::::/´ ̄`ヽ ⌒ヽ そんなチャチなもんじゃあ 断じてねえ
ノ ' / ノ:::::`ー-、___/:::::// ヽ }
_/`丶 /:::::::::::::::::::::::::: ̄`ー-{:::... イ もっと恐ろしいものの片鱗を味わったぜ…
つか、こういうことが本当に行われて、上司を疑えないようじゃ、単なる馬鹿だと思うわけだが。おいらがこの「坂本君」だったら、この時点でもう辞めることを前提に出力 10% ぐらいでしか仕事しなくなっちゃうけどね。
ただまぁ、こういう形で、上司と結託して部下をいびるどーしよーも無い人間は結構いるよーというケーススタディとしてはそれなりに参考になった。現場の上司がこういうことになっちゃっているような会社はまず間違いなく古き悪しき序列社会を強いる会社であり、あなたの実力がまともに評価されて反映されることは有り得ないので、心の距離を物凄く長めにとることにするか、若しくはさっさと辞めることを考えた方がよろしいかと思われ。
BlueScreen Screen Saver ― 2006年12月07日 14時06分56秒
- 「触っちゃいけない」オーラが出るスクリーンセーバー (IT media)
- BlueScreen Screen Saver v3.2 (Microsoft TechNet)
この発想はなかったわ。。。しかも MS 純正だし \(^O^)/ 。
蛇足。
例えば、ブルースクリーンが出ていたら、そんなPCは誰しも触りたくないだろう。離席のたびに人だかりができて、むしろ防犯対策になるかもしれない。
「先輩の PC、ブルースクリーンになっちゃってたから、再起動しておきましたよ♪」とか言い出すおせっかいな後輩による被害が続出する悪寒。。。w





最近のコメント