2009年10月30日 星期五

簡易電子琴

 
按 zxcvbnmasdfghjqwertyu 發音,
按 0~7 變更樂器,樂器種類可在 prog[] 裡自行變更。
樂器編號有點忘了,印象中是 0~127,可自行改變。
有些樂器如法國號等,聲音很吵,拉的很長,這部分程式未做處理;
pitchs[] = {0,2,4,5,7,9,11} 用來跳過 {1,3,6,8,10}
等 5 筆黑鍵音,因為鍵盤的編排很難將黑鍵安插進來。
#pragma comment(lib, "winmm.lib")
#include <conio.h>  
#include <stdio.h>  
#include <windows.h>
#include <mmsystem.h>

#define DO(s) if (MMSYSERR_NOERROR != s) {\
            printf ("Error in %s: %d",__FILE__,__LINE__);\
            getch(); exit(1);\
        }

HMIDIOUT midi;   

void play (int state, int d1=0, int d2=0)
{
    UCHAR data[4] = {state, d1, d2, 0};
    DO (midiOutShortMsg (midi, *(DWORD*)data));            
}

UCHAR get_pitch (char ch)
{
    static char *p, key[] = "zxcvbnmasdfghjqwertyu";
    static UCHAR pitchs[] = {0,2,4,5,7,9,11};
    for (p=key; *p && ch^*p; ++p);
    return (60-12) + 12*((p-key)/7) + pitchs [(p-key)%7];
}
int main (/* daviddr 081223 */)
{
    int  ch, prog[] = {0,13,24,15,7,73,46,53}; //樂器編號
    DO (midiOutOpen (&midi, 0,0,0, CALLBACK_NULL));
    while (VK_ESCAPE != (ch = getch()))         
        if ('0'<=ch && ch<='7') 
            play (0xC0, prog[ch-'0']);
        else {
            play (0x80); 
            play (0x90, get_pitch(ch), 100);
        }         
    midiOutReset (midi);
    midiOutClose (midi);
    return 0;
}

沒有留言:

張貼留言