#pragma comment(lib, "winmm")
#include <stdio.h>
#include <Windows.h>
#include <WindowsX.h>
#include <CommCtrl.h>
#include "resource.h"
// 定義
#define MAKESMSG(st,ch,d1,d2) st<<4|(ch)|(d1)<<8|(d2)<<16
struct NumName {
int num;
LPCTSTR name;
};
// タブ
int tab0[] = {
IDC_FAMILY_NAME,
IDC_FAMILY,
IDC_INSTRUMENT_NAME,
IDC_INSTRUMENT,
0
};
int tab1[] = {
IDC_PERCUSSION1,
IDC_PERCUSSION2,
IDC_PERCUSSION3,
0
};
int *tab[] = {tab0, tab1};
// 楽器ファミリー
LPCTSTR family[] = {
L"Piano",
L"Chromatic Percussion",
L"Organ",
L"Guitar",
L"Bass",
L"Strings",
L"Ensemble",
L"Brass",
L"Reed",
L"Pipe",
L"Synth Lead",
L"Synth Pad",
L"Synth Effects",
L"Ethnic",
L"Percussive",
L"Sound Effects",
};
// 楽器
NumName instrument[][8] = {
{ // Piano
{1, L"Acoustic Grand Piano"},
{2, L"Bright Acoustic Piano"},
{3, L"Electric Grand Piano"},
{4, L"Honky-tonk Piano"},
{5, L"Electric Piano 1"},
{6, L"Electric Piano 2"},
{7, L"Harpsichord"},
{8, L"Clavi"},
},
{ // Chromatic Percussion
{9, L"Celesta"},
{10, L"Glockenspiel"},
{11, L"Music Box"},
{12, L"Vibraphone"},
{13, L"Marimba"},
{14, L"Xylophone"},
{15, L"Tubular Bells"},
{16, L"Dulcimer"},
},
{ // Organ
{17, L"Drawbar Organ"},
{18, L"Percussive Organ"},
{19, L"Rock Organ"},
{20, L"Church Organ"},
{21, L"Reed Organ"},
{22, L"Accordion"},
{23, L"Harmonica"},
{24, L"Tango Accordion"},
},
{ // Guitar
{25, L"Acoustic Guitar (nylon)"},
{26, L"Acoustic Guitar (steel)"},
{27, L"Electric Guitar (jazz)"},
{28, L"Electric Guitar (clean)"},
{29, L"Electric Guitar (muted)"},
{30, L"Overdriven Guitar"},
{31, L"Distortion Guitar"},
{32, L"Guitar harmonics"},
},
{ // Bass
{33, L"Acoustic Bass"},
{34, L"Electric Bass (finger)"},
{35, L"Electric Bass (pick)"},
{36, L"Fretless Bass"},
{37, L"Slap Bass 1"},
{38, L"Slap Bass 2"},
{39, L"Synth Bass 1"},
{40, L"Synth Bass 2"},
},
{ // Strings
{41, L"Violin"},
{42, L"Viola"},
{43, L"Cello"},
{44, L"Contrabass"},
{45, L"Tremolo Strings"},
{46, L"Pizzicato Strings"},
{47, L"Orchestral Harp"},
{48, L"Timpani"},
},
{ // Ensemble
{49, L"String Ensemble 1"},
{50, L"String Ensemble 2"},
{51, L"SynthStrings 1"},
{52, L"SynthStrings 2"},
{53, L"Choir Aahs"},
{54, L"Voice Oohs"},
{55, L"Synth Voice"},
{56, L"Orchestra Hit"},
},
{ // Brass
{57, L"Trumpet"},
{58, L"Trombone"},
{59, L"Tuba"},
{60, L"Muted Trumpet"},
{61, L"French Horn"},
{62, L"Brass Section"},
{63, L"SynthBrass 1"},
{64, L"SynthBrass 2"},
},
{ // Reed
{65, L"Soprano Sax"},
{66, L"Alto Sax"},
{67, L"Tenor Sax"},
{68, L"Baritone Sax"},
{69, L"Oboe"},
{70, L"English Horn"},
{71, L"Bassoon"},
{72, L"Clarinet"},
},
{ // Pipe
{73, L"Piccolo"},
{74, L"Flute"},
{75, L"Recorder"},
{76, L"Pan Flute"},
{77, L"Blown Bottle"},
{78, L"Shakuhachi"},
{79, L"Whistle"},
{80, L"Ocarina"},
},
{ // Synth Lead
{81, L"Lead 1 (square)"},
{82, L"Lead 2 (sawtooth)"},
{83, L"Lead 3 (calliope)"},
{84, L"Lead 4 (chiff)"},
{85, L"Lead 5 (charang)"},
{86, L"Lead 6 (voice)"},
{87, L"Lead 7 (fifths)"},
{88, L"Lead 8 (bass + lead)"},
},
{ // Synth Pad
{89, L"Pad 1 (new age)"},
{90, L"Pad 2 (warm)"},
{91, L"Pad 3 (polysynth)"},
{92, L"Pad 4 (choir)"},
{93, L"Pad 5 (bowed)"},
{94, L"Pad 6 (metallic)"},
{95, L"Pad 7 (halo)"},
{96, L"Pad 8 (sweep)"},
},
{ // Synth Effects
{97, L"FX 1 (rain)"},
{98, L"FX 2 (soundtrack)"},
{99, L"FX 3 (crystal)"},
{100, L"FX 4 (atmosphere)"},
{101, L"FX 5 (brightness)"},
{102, L"FX 6 (goblins)"},
{103, L"FX 7 (echoes)"},
{104, L"FX 8 (sci-fi)"},
},
{ // Ethnic
{105, L"Sitar"},
{106, L"Banjo"},
{107, L"Shamisen"},
{108, L"Koto"},
{109, L"Kalimba"},
{110, L"Bag pipe"},
{111, L"Fiddle"},
{112, L"Shanai"},
},
{ // Percussive
{113, L"Tinkle Bell"},
{114, L"Agogo"},
{115, L"Steel Drums"},
{116, L"Woodblock"},
{117, L"Taiko Drum"},
{118, L"Melodic Tom"},
{119, L"Synth Drum"},
{120, L"Reverse Cymbal"},
},
{ // Sound Effects
{121, L"Guitar Fret Noise"},
{122, L"Breath Noise"},
{123, L"Seashore"},
{124, L"Bird Tweet"},
{125, L"Telephone Ring"},
{126, L"Helicopter"},
{127, L"Applause"},
{128, L"Gunshot"},
},
};
// 打楽器
NumName percussion[] = {
{35, L"Acoustic Bass Drum"},
{36, L"Bass Drum 1"},
{37, L"Side Stick"},
{38, L"Acoustic Snare"},
{39, L"Hand Clap"},
{40, L"Electric Snare"},
{41, L"Low Floor Tom"},
{42, L"Closed Hi Hat"},
{43, L"High Floor Tom"},
{44, L"Pedal Hi-Hat"},
{45, L"Low Tom"},
{46, L"Open Hi-Hat"},
{47, L"Low-Mid Tom"},
{48, L"Hi-Mid Tom"},
{49, L"Crash Cymbal 1"},
{50, L"High Tom"},
{51, L"Ride Cymbal 1"},
{52, L"Chinese Cymbal"},
{53, L"Ride Bell"},
{54, L"Tambourine"},
{55, L"Splash Cymbal"},
{56, L"Cowbell"},
{57, L"Crash Cymbal 2"},
{58, L"Vibraslap"},
{59, L"Ride Cymbal 2"},
{60, L"Hi Bongo"},
{61, L"Low Bongo"},
{62, L"Mute Hi Conga"},
{63, L"Open Hi Conga"},
{64, L"Low Conga"},
{65, L"High Timbale"},
{66, L"Low Timbale"},
{67, L"High Agogo"},
{68, L"Low Agogo"},
{69, L"Cabasa"},
{70, L"Maracas"},
{71, L"Short Whistle"},
{72, L"Long Whistle"},
{73, L"Short Guiro"},
{74, L"Long Guiro"},
{75, L"Claves"},
{76, L"Hi Wood Block"},
{77, L"Low Wood Block"},
{78, L"Mute Cuica"},
{79, L"Open Cuica"},
{80, L"Mute Triangle"},
{81, L"Open Triangle"},
};
// 外部変数
HMIDIOUT hmo;
UINT autoNote;
int chanNO = 0;
int noteNO;
int progNO = 0;
int tabSel = 0;
// 関数プロトタイプ宣言
INT_PTR CALLBACK DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
void OnInitDialog(HWND hDlg);
void OnTabSelChange(HWND hDlg);
void OnFamily(HWND hDlg);
void OnInstrument(HWND hDlg);
void OnPercussion(HWND hDlg, WORD wID);
void Play(HWND hDlg);
//==============================================================================
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
{
midiOutOpen(&hmo, MIDI_MAPPER, NULL, 0, CALLBACK_NULL);
DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG), NULL, DlgProc);
midiOutReset(hmo);
midiOutClose(hmo);
return 0;
}
INT_PTR CALLBACK DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
INT_PTR res = TRUE; // メッセージを処理した
switch (uMsg) {
case WM_COMMAND:
WORD wNotifyCode;
wNotifyCode = HIWORD(wParam);
switch (LOWORD(wParam)) {
case IDC_FAMILY:
if (wNotifyCode == LBN_SELCHANGE) {
OnFamily(hDlg);
}
break;
case IDC_INSTRUMENT:
if (wNotifyCode == LBN_SELCHANGE) {
OnInstrument(hDlg);
Play(hDlg);
}
break;
case IDC_PERCUSSION1:
case IDC_PERCUSSION2:
case IDC_PERCUSSION3:
if (wNotifyCode == LBN_SELCHANGE) {
OnPercussion(hDlg, LOWORD(wParam));
Play(hDlg);
}
break;
case IDC_AUTO_NOTE:
autoNote = IsDlgButtonChecked(hDlg, IDC_AUTO_NOTE);
break;
}
break;
case WM_NOTIFY:
switch (wParam) {
case IDC_TAB:
switch (((LPNMHDR)lParam)->code) {
case TCN_SELCHANGE:
OnTabSelChange(hDlg);
break;
}
break;
}
break;
case WM_INITDIALOG:
OnInitDialog(hDlg);
//res = FALSE; // SetFocusでフォーカスを設定した場合はFALSE
break;
case WM_CLOSE:
EndDialog(hDlg, 0);
break;
default:
res = FALSE; // メッセージを処理しなかった
}
return res;
}
void OnInitDialog(HWND hDlg)
{
HWND hTab = GetDlgItem(hDlg, IDC_TAB);
HWND hFamily = GetDlgItem(hDlg, IDC_FAMILY);
// タブ
TCITEM tci;
tci.mask = TCIF_TEXT;
tci.pszText = L"Instrument";
TabCtrl_InsertItem(hTab, 0, &tci);
tci.pszText = L"Percussion";
TabCtrl_InsertItem(hTab, 1, &tci);
// Family
for (int n = 0; n < _countof(family); n++) {
ListBox_InsertString(hFamily, n, family[n]);
}
// Percussion
for (int n = 0; n < _countof(percussion); n++) {
TCHAR buf[32];
swprintf_s(buf, L"%03d %s", percussion[n].num, percussion[n].name);
ListBox_InsertString(GetDlgItem(hDlg, IDC_PERCUSSION1 + n / 16), n % 16, buf);
}
OnTabSelChange(hDlg);
}
void OnTabSelChange(HWND hDlg)
{
tabSel = TabCtrl_GetCurSel(GetDlgItem(hDlg, IDC_TAB));
// タブ切り替え
for (int i = 0; i < _countof(tab); i++) {
int nCmdShow = (i == tabSel) ? SW_SHOWNA : SW_HIDE;
for (int n = 0; tab[i][n]; n++) {
ShowWindow(GetDlgItem(hDlg, tab[i][n]), nCmdShow);
}
}
}
void OnFamily(HWND hDlg)
{
int i = ListBox_GetCurSel(GetDlgItem(hDlg, IDC_FAMILY));
// Instrument
HWND hInstrument = GetDlgItem(hDlg, IDC_INSTRUMENT);
ListBox_ResetContent(hInstrument);
for (int n = 0; n < 8; n++) {
TCHAR buf[32];
swprintf_s(buf, L"%03d %s", instrument[i][n].num, instrument[i][n].name);
ListBox_InsertString(hInstrument, n, buf);
}
}
void OnInstrument(HWND hDlg)
{
int f = ListBox_GetCurSel(GetDlgItem(hDlg, IDC_FAMILY));
int i = ListBox_GetCurSel(GetDlgItem(hDlg, IDC_INSTRUMENT));
progNO = instrument[f][i].num;
}
void OnPercussion(HWND hDlg, WORD wID)
{
for (int n = IDC_PERCUSSION1; n <= IDC_PERCUSSION3; n++) {
if (n != wID) {
ListBox_SetCurSel(GetDlgItem(hDlg, n), -1);
}
}
}
void Play(HWND hDlg)
{
if (chanNO) {
midiOutShortMsg(hmo, MAKESMSG(0x8, chanNO - 1, noteNO, 0)); // Note Off
chanNO = 0;
}
if (autoNote != BST_CHECKED) return;
switch (tabSel) {
case 0: // Instrument
chanNO = 1;
noteNO = 69;
break;
case 1: // Percussion
chanNO = 10;
noteNO = -1;
for (int n = 0; n < 3; n++) {
int i = ListBox_GetCurSel(GetDlgItem(hDlg, IDC_PERCUSSION1 + n));
if (i != LB_ERR) {
noteNO = percussion[16 * n + i].num;
break;
}
}
break;
}
if (noteNO < 0) return;
if (chanNO != 10) {
if (progNO <= 0) return;
midiOutShortMsg(hmo, MAKESMSG(0xc, chanNO - 1, progNO - 1, 0)); // Program Change
}
midiOutShortMsg(hmo, MAKESMSG(0x9, chanNO - 1, noteNO, 127)); // Note On
}