AHK演奏——Music库

调用的是Winapi的midi模块

; Author: Mono
; Time: 2022.08.17
; Class Music

File2KeyArr(Filename, Flags := "r", Encoding := "utf-8")
{
    Res := []
    FileObj := FileOpen(Filename, Flags, Encoding)
    Flag := (FileObj.ReadLine() == "Key::") ? 1 : 0
    
    if Flag
    {
        While !FileObj.AtEOF
        {
            NewLine := StrSplit(FileObj.ReadLine())
            Lst_Flag := 0
            Tmp := []
            
            For i in NewLine
            {
                if i == " "
                    Res.Push(_)
                
                else if i == "+"
                    Res.Push("*0.5")
                
                else if i == "-"
                    Res.Push("*2")
                
                else if i == "("
                {
                    Lst_Flag := 1
                    Continue
                }
                
                else if i == ")"
                {
                    Lst_Flag := 0
                    Res.Push(Tmp.Clone())
                    Tmp := []
                    Continue
                }
                
                else if Lst_Flag
                    Tmp.Push(i)
                
                else if i == "|"
                    Continue
                
                else
                    Res.Push(i)
            }
        }
    }
        
    Return Res
}

LoadMidi()
{
    hModule := DllCall("LoadLibrary", "Str", "winmm.dll")
    Return hModule
}

MidiOutClose(handle)
{
    result := DllCall("winmm.dll\midiOutClose", "UInt", handle)
    
    if result
    {
        Msgbox "There was an error closing the midi output port.  There may still be midi events being processed through it."
        Return -1
    }
    
    Return
}

MidiOutOpen(DeviceID := 0)
{
    dwFlags := 0

    result := DllCall("winmm.dll\midiOutOpen"
                    , "UInt*", &handle := 0
                    , "UInt", DeviceID
                    , "UInt", 0
                    , "UInt", 0
                    , "UInt", dwFlags)

    if result
    {
        Msgbox "There was an error opening the midi port.  The port may be in use.  Try closing and reopening all midi-enabled applications."
        Return -1
    }
    
    Return handle
}

MidiOutShortMsg(handle, voice)
{
    result := DllCall("winmm.dll\midiOutShortMsg"
                    , "UInt", handle
                    , "UInt", voice)
  
    if result
    {
        Msgbox "There was an error sending the midi event."
        Return -1
    }
    
    Return
}

Class Music
{
    Static KeyPlay(Arr, DeviceID := 0, QuitKey := "Esc", Speed := 300, Wait := 0.5)
    {
        handle := MidiOutOpen(DeviceID)
        volume := 0x7f
        voice := 0x0
        SleepTime := Speed
        Lst_Voice := []
        v := Map('Z',C3,'X',D3,'C',E3,'V',F3,'B',G3,'N',A3,'M',B3,
            'A',C4,'S',D4,'D',E4,'F',F4,'G',G4,'H',A4,'J',B4,
            'Q',C5,'W',D5,'E',E5,'R',F5,'T',G5,'Y',A5,'U',B5)
        Print("请按"  QuitKey "键退出演奏")
        
        For i in Arr
        {
            tmp := []
            Lst_i := Type(i) == "Array" ? i : [i]
            
            if GetKeyState(QuitKey)
            {
                MidiOutClose(handle)
                WinClose("Sinet Print")
                Return
            }
            
            For j in Lst_i
            {
                
                if (j == LOW_SPEED || j == HIGH_SPEED || j == MIDDLE_SPEED)
                {
                    SleepTime := j
                    Continue 2
                }
                
                if InStr(j, "*")
                {
                    SleepTime *= StrReplace(j, "*")
                    Continue 2
                }
                
                if (j == _)
                {
                    Sleep(SleepTime * Wait)
                    Continue 2
                }
                
                voice := (volume << 16) + (v[j] << 8) + 0x94
                tmp.Push(voice)
            }
            
            For j in tmp
                MidiOutShortMsg(handle, j)
            
            Lst_Voice.Push(tmp)
            Sleep(SleepTime)
        }
        
        MidiOutClose(handle)
        WinClose("Sinet Print")
        Return Lst_Voice
    }
    
    Static Piano(DeviceID := 0, QuitKey := "Esc")
    {
        handle := MidiOutOpen(DeviceID)
        v := Map('Z',C3,'X',D3,'C',E3,'V',F3,'B',G3,'N',A3,'M',B3,
            'A',C4,'S',D4,'D',E4,'F',F4,'G',G4,'H',A4,'J',B4,
            'Q',C5,'W',D5,'E',E5,'R',F5,'T',G5,'Y',A5,'U',B5)
            
        Print("钢琴已开启,敲击键盘Q-U,A-J,Z-M")
        Print("请按"  QuitKey "键退出`n")
        
        While True
        {
            if GetKeyState(QuitKey)
            {
                MidiOutClose(handle)
                WinClose("Sinet Print")
                Return
            }
            
            For i in Range(Ord('A'), Ord('Z') + 1)
            {
                if GetKeyState(Chr(i))
                {
                    MidiOutShortMsg(handle, (0x007f << 16) + (v[Chr(i)] << 8) + 0x90)
                    Print("已按下" Chr(i) "键")
                    
                    While GetKeyState(Chr(i))
                        Sleep(100)
                }
            }
        }
    }
    
    Static Play(Arr, DeviceID := 0, QuitKey := "Esc", Speed := 300)
    {
        handle := MidiOutOpen(DeviceID)
        volume := 0x7f
        voice := 0x0
        SleepTime := Speed
        Lst_Voice := []
        Print("请按"  QuitKey "键退出演奏")
        
        For i in Arr
        {
            tmp := []
            Lst_i := Type(i) == "Array" ? i : [i]
            
            For j in Lst_i
            {
                if GetKeyState(QuitKey)
                {
                    MidiOutClose(handle)
                    WinClose("Sinet Print")
                    Return
                }
                
                if (j == LOW_SPEED || j == HIGH_SPEED || j == MIDDLE_SPEED)
                {
                    SleepTime := j
                    Continue 2
                }
                
                if InStr(j, "*")
                {
                    SleepTime *= StrReplace(j, "*")
                    Continue 2
                }
                
                if (j == _)
                {
                    Sleep(SleepTime / 2)
                    Continue 2
                }
            
                voice := (volume << 16) + (j << 8) + 0x94
                tmp.Push(voice)
            }
            
            For j in tmp
                MidiOutShortMsg(handle, j)
            
            Lst_Voice.Push(tmp)
            Sleep(SleepTime)
        }
        
        MidiOutClose(handle)
        WinClose("Sinet Print")
        Return Lst_Voice
    }
}

Print(Text*)
{
    Global Print_Gui
    Global Print_Edit
    Print_Text := ""

    Loop Text.Length
    {
        String_Text := ToStringPrint(Text[A_Index])
        
        if SubStr(String_Text, -1) == "," && (Type(Text[A_Index]) == "Array" || Type(Text[A_Index]) == "ComObjArray" || Type(Text[A_Index]) == "Map" || Type(Text[A_Index]) == "Object")
            String_Text := SubStr(String_Text, 1, StrLen(String_Text) - 1)
        
        Print_Text .= String_Text "`n"
    }
    
    Print_Text := SubStr(Print_Text, 1, StrLen(Print_Text) - 1)
    
    if WinExist("Sinet Print")
    {
        WinActivate("Sinet Print")
        Print_Edit.Value .= "`n" Print_Text
        Return
    }
    
    Print_Gui := Gui()
    Print_Gui.Title := "Sinet Print"
    Print_Gui.BackColor := "87CEFA"
    Print_Edit := Print_Gui.Add("Edit", "R30 W800 ReadOnly")
    Print_Edit.SetFont("S12", "Arial")
    Print_Edit.Value := Print_Text
    Print_Gui.Show()
}

Range(start, stop)
{
    tmp := []
    
    Loop stop - start
        tmp.Push(start + A_Index - 1)
    
    Return tmp
}

ToStringPrint(Text)
{
    if Type(Text) == "Array"
    {
        if Text.Length < 1
            Text.InsertAt(1, "")
        
        String_Plus := ""
        String_Text := "[" . ToStringPrint(Text[1])
        
        Loop Text.Length - 1
            String_Plus .= "," . ToStringPrint(Text[A_Index + 1])
        
        String_Text .= String_Plus
        String_Text .= "]"
        
        Return String_Text
    }
    
    else if Type(Text) == "ComObjArray"
    {
        if Text.MaxIndex() < 0
        {
            Text := ComObjArray(VT_VARIANT:=12, 1)
            Text[0] := ""
        }
        
        String_Plus := ""
        String_Text := "[" . ToStringPrint(Text[0])
        
        Loop Text.MaxIndex()
            String_Plus .= "," . ToStringPrint(Text[A_Index])
        
        String_Text .= String_Plus
        String_Text .= "]"
        
        Return String_Text
    }
    
    else if Type(Text) == "Map"
    {
        String_Text := "{"
        
        For i, Value in Text
            String_Text .= ToStringPrint(i) . ":" . ToStringPrint(Value) . ","
        
        if SubStr(String_Text, -1) !== "{"
            String_Text := SubStr(String_Text, 1, StrLen(String_Text) - 1)
        
        String_Text .= "}"
        
        Return String_Text
    }
    
    else if Type(Text) == "Integer" || Type(Text) == "Float" || Type(Text) == "String"
        Return Text
    
    else if Type(Text) == "Object"
    {
        String_Text := "{"
        
        For i, Value in Text.OwnProps()
            String_Text .= ToStringPrint(i) . ":" . ToStringPrint(Value) . ","
        
        if SubStr(String_Text, -1) !== "{"
            String_Text := SubStr(String_Text, 1, StrLen(String_Text) - 1)
        
        String_Text .= "},"
        
        Return String_Text
    }
    
    else
        Return "#Type: " Type(Text) "#"
}

; Scale音阶参数
Rest := 0, C8 := 108, B7 := 107, A7s := 106, A7 := 105, G7s := 104, G7 := 103, F7s := 102, F7 := 101, E7 := 100,
D7s := 99, D7 := 98, C7s := 97, C7 := 96, B6 := 95, A6s := 94, A6 := 93, G6s := 92, G6 := 91, F6s := 90, F6 := 89,
E6 := 88, D6s := 87, D6 := 86, C6s := 85, C6 := 84, B5 := 83, A5s := 82, A5 := 81, G5s := 80, G5 := 79, F5s := 78,
F5 := 77, E5 := 76, D5s := 75, D5 := 74, C5s := 73, C5 := 72, B4 := 71, A4s := 70, A4 := 69, G4s := 68, G4 := 67,
F4s := 66, F4 := 65, E4 := 64, D4s := 63, D4 := 62, C4s := 61, C4 := 60, B3 := 59, A3s := 58, A3 := 57, G3s := 56,
G3 := 55, F3s := 54, F3 := 53, E3 := 52, D3s := 51, D3 := 50, C3s := 49, C3 := 48, B2 := 47, A2s := 46, A2 := 45,
G2s := 44, G2 := 43, F2s := 42, F2 := 41, E2 := 40, D2s := 39, D2 := 38, C2s := 37, C2 := 36, B1 := 35, A1s := 34,
A1 := 33, G1s := 32, G1 := 31, F1s := 30, F1 := 29, E1 := 28, D1s := 27, D1 := 26, C1s := 25, C1 := 24, B0 := 23,
A0s := 22, A0 := 21

; Voice
L1 := C3, L2 := D3, L3 := E3, L4 := F3, L5 := G3, L6 := A3, L7 := B3,
M1 := C4, M2 := D4, M3 := E4, M4 := F4, M5 := G4, M6 := A4, M7 := B4,
H1 := C5, H2 := D5, H3 := E5, H4 := F5, H5 := G5, H6 := A5, H7 := B5,
LOW_SPEED := 600, MIDDLE_SPEED := 300, HIGH_SPEED := 150,
_ := 0XFF
; 8.15新使用方法——键盘演奏
; 初始化winmm.dll
LoadMidi()
; 转换演奏曲谱为库支持类型
Arr := File2KeyArr("Ultramarine.txt")
; 开始演奏
; 最后一个参数表示演奏速率(默认为中速300,数值越小速率越快)
Music.KeyPlay(Arr, , , 150)

来一首群青

Ultramarine.txt

提取码:mono复制
解压码:无

来一首卡农

Cannon.txt

提取码:mono复制
解压码:无
; 使用方法——键盘钢琴
; 初始化winmm.dll
LoadMidi()
; 打开钢琴
Music.Piano()
; 使用方法——演奏曲谱
; 初始化winmm.dll
LoadMidi()
; 编写曲谱(需要一定乐理基础)
; 列表里嵌套的列表表示多音符
Musical := 
[[H1,M5,M1],_,M5,M1,[H1,M5,M1],H2,M3,_,H5,_,[H1,M5,M1],H2,_,H3,_,[H1,M5,M1],H2,_,H3,_,
[H1,M5,M1],_,M5,M1,[H1,M5,M1],H2,M3,_,H5,_,H2,H2,_,H3,_,H2,H3,_,H3,_,
H3,H2,[H1,M5,M1],_,[H1,M5,M1],M5,M6,M3,M5,_,H3,H2,[H1,M5,M1],_,[H1,M5,M1],M5,M6,M3,M5,_,
H3,H2,H2,_,H2,[H1,M5,M1],M7,_,M6,M7,M5,M6,_,_,
M6,M5,M6,_,
M5,[H1,M5,M1],H2,H5,M5,[H1,M5,M1],H2,M5,H5,_,
M5,[H1,M5,M1],H2,M5,H5,M5,[H1,M5,M1],M5,H2,M5,H5,_,
M5,[H1,M5,M1],H2,H5,M5,[H1,M5,M1],H2,M5,H5,_,
M5,[H1,M5,M1],H2,H5,M5,[H1,M5,M1],M5,H2,M5,H5,_,
[H1,M5,M1],_,M5,M1,[H1,M5,M1],H2,M5,H3,_,H5,M5,H2,H2,_,H3,_,[H1,M5,M1],H2,_,H3,_,
[H1,M5,M1],_,M5,M1,[H1,M5,M1],H2,M5,H3,_,H5,_,H2,H2,_,H3,_,H2,M3,_,H3,_,
H3,H2,M3,[H1,M5,M1],_,[H1,M5,M1],M5,M6,M3,M5,_,H3,H2,M3,[H1,M5,M1],_,[H1,M5,M1],M5,M6,M3,M5,_,
H3,H2,H2,_,H2,[H1,M5,M1],M7,_,M6,M7,M5,M6,_,_,_]
Music.Play(Musical)

给TA捐赠
共{{data.count}}人
人已捐赠
AHKV2函数办公

调用在线微软数学计算(正在完善)

2022-8-10 14:25:15

AHKV2函数案例

Matplotlib尝试

2022-8-15 20:02:42

4 条回复 A文章作者 M管理员
  1. 陌诺Mono

    小星星曲谱 [[C5,C4],G4,[C5,E4],G4, [G5,C4],F4,[G5,G4],F4, [A5,C4],A4,[A5,F4],A4, [G5,C4],G4,[C5,E5],_, [F5,C4],E4,[F5,A4],E4, [E5,B4],E4,[E5,G4],E4, [D5,B4],G4,[D5,D4],HIGH_SPEED,F4,G4,LOW_SPEED, [C5,E4,G4],HIGH_SPEED,C4,_,MIDDLE_SPEED, [G5,C4],D4,[G5,E4],G4, [F5,C5],A4,[F5,F4],D4, [E5,B4],E4,[E5,G4],E4, [D5,B4],G4,D4,HIGH_SPEED,F4,G4,MIDDLE_SPEED, [G5,C4],D4,[G5,E4],G4, [F5,C5],A4,[F5,F4],D4, [E5,B4],E4,[E5,G4],E4, [D5,B4],G4,D4,HIGH_SPEED,F4,G4,MIDDLE_SPEED, [C5,C4],[E4,G4],[C5,E4,G4],[E4,G4], [G5,C4],[F4,G4],[G5,F4,G4],[F4,G4], [A5,C4],[F4,A4],[A5,F4,A4],[F4,A4], [G5,C4],G4,HIGH_SPEED,[C5,E5],MIDDLE_SPEED,_, [F5,C4],[E4,A4],[F5,E4,A4],[E4,A4], [E5,B4],[E4,G4],[E5,E4,G4],[E4,G4], [D5,B4],[D4,F4,G4],[D5,B4],[D4,F4,G4], [C5,C4],HIGH_SPEED,C5,A4,G4,F4,E4,D4,LOW_SPEED,[C5,C4],_]

  2. 陌诺Mono

    卡农曲谱 Key:: (ZBD) |(XBM) |(CNA) |(CBM)| (ZVN) |(ZBA) |(ZVN) |(XBM) | (ZBQE) |(BSJW) |(NDHQ) |(CMGJ)| (VAFH) |(ZBDG) |(VAFH) |(BSGJ) | (ZBQE) |(BSJW) F|(NDHQ) |(CMGJ) S| (VAFH) |(ZBDG) D|(VAFH) |(BSGJ) F| (ZDQ) B A |(BGJ) X (MF)| (NDQ) C (AHE)|(CET) M (DWY)| (VHR) Z (NQ) |(ZGE) B (AD) | (VSF) Z (NHQ)|(BGQ) X (MFQ) J| (ZQ)(BJ)(AQ)(BD)|(BG) X (MGJ) X| (NDQ) C (AHE) C|(CT)(ME)(DT)(MY)| (VHR)(ZGE)(NFW)(ZHR)|(ZE)(BW)(AQ)(BJ)| (VFH)(ZSF)(NHQ) Z|(BGQ)(XF)(MDQ)(XSJ)| (ZQ)(BJ)(AQ)(BF)|(BG) X (MGJ) X| (NDQ) C (AHE) C|(CT)(ME)(DT)(MY)| (VHR)(ZGE)(NFW)(ZHR)|(ZE)(BW)(AQ)(BJ)| (VFH)(ZDG)(NSF)(ZHQ)|(BGQ) XS(MJ) (XW)G| (ZQE) BG(AE) (BQ)W|B XE(MR)E(XW)| (NW) CQA (CJ)Q|(CJ) (BG)DMG (BM)A| (VFH) Z(GJ) N (ZHQ)|(ZDG) B A (BA)A| (VH)AZA (NF)H(ZQ)W|(BQ) XJMQ(XW)G| (ZQE) BG(AE) (BQ)W|B XE(MR)E(XW)| (NW) CQA (CJ)Q|(CJ) (BG)DMG (BM)A| (VFH) Z(HQ)NH(ZR)|(ZE) (BW)QA (BA)A| (VH)AZA (NF)H(ZQ)W|(BJ) XQM (XW)Q| (ZT) (BE)R(AT) (BE)R|(BT)G(XH)J(MQ)W(XE)R| (NE) (CQ)W(AE) (CD)F|(CG)H(BG)F(MG)Q(BJ)Q| (VH) (ZQ)J(NH) (ZG)F|(ZG)F(BD)F(AG)H(BJ)Q| (VH) (ZQ)J(NQ) (ZJ)Q|(BJ)H(XJ)Q(MW)E(XR)T| (ZT) (BE)R(AT) (BE)R|(BT)G(XH)J(MQ)W(XE)R| (NE) (CQ)W(AE) (CD)F|(CG)H(BG)F(MG)Q(BJ)Q| (VH) (ZQ)J(NH) (ZG)F|(ZG)F(BD)F(AG)H(BJ)Q| (VH) (ZQ)J(NQ) (ZJ)Q|(BJ)H(XJ)Q(MW)E(XR)T| (ZT) (BE)R(AT) (BE)R|(BT)G(XH)J(MQ)W(XE)R| (NE) (CQ)W(AE) (CD)F|(CG)H(BG)F(MG)Q(BJ)Q| (VH) (ZQ)J(NH) (ZG)F|(ZG)F(BD)F(AG)H(BJ)Q| (VH) (ZQ)J(NQ) (ZJ)Q|(BJ)H(XJ)Q(MW)E(XR)T| (ZE) (BQ)W(AE) (BW)Q|(BW)J(XQ)W(ME)W(XQ)J| (NQ) (CH)J(AQ) (CA)S|(CD)F(BD)S(MD)Q(BJ)Q| (VH) (ZQ)J(NH) (ZG)F|(ZG)F(BD)F(AG)H(BJ)Q| (VH) (ZQ)J(NQ) (ZJ)Q|(BJ)H(XJ)Q(MW)Q(XH)J| (ZQ) B A D | B X M S| N C N A| C B M D| V Z N A | Z C B A | V Z N A | B X M S | (ZT) (BE)R(AT) (BE)R|(BT)G(XH)J(MQ)W(XE)R| (NE) (CQ)W(AE) (CD)F|(CG)H(BG)F(MG)Q(BJ)Q| (VH) (ZQ)J(NH) (ZG)F|(ZG)F(BD)F(AG)H(BJ)Q| (VH) (ZQ)J(NQ) (ZJ)Q|(BJ)H(XJ)Q(MW)E(XR)T| (ZT) (BE)R(AT) (BE)R|(BT)G(XH)J(MQ)W(XE)R| (NE) (CQ)W(AE) (CD)F|(CG)H(BG)F(MG)Q(BJ)Q| (VH) (ZQ)J(NH) (ZG)F|(ZG)F(BD)F(AG)H(BJ)Q| (VH) (ZQ)J(NQ) (ZJ)Q|(BJ)H(XJ)Q(MW)E(XR)T| (ZT) (BE)R(AT) (BE)R|(BT)G(XH)J(MQ)W(XE)R| (NE) (CQ)W(AE) (CD)F|(CG)H(BG)F(MG)Q(BJ)Q| (VH) (ZQ)J(NH) (ZG)F|(ZG)F(BD)F(AG)H(BJ)Q| (VH) (ZQ)J(NQ) (ZJ)Q|(BJ)H(XJ)Q(MW)E(XR)T| (ZE) (BQ)W(AE) (BW)Q|(BW)J(XQ)W(ME)W(XQ)J| (NQ) (CH)J(AQ) (CA)S|(CD)F(BD)S(MD)Q(BJ)Q| (VH) (ZQ)J(NH) (ZG)F|(ZG)F(BD)F(AG)H(BJ)Q| (VH) (ZQ)J(NQ) (ZJ)Q|(BJ)H(XJ)Q(MW)Q(XH)J| (ZQ) B A D | B X M S| N C N A| C B M D| V Z N A | Z C B A | V Z N A | B X M S |

  3. 11010010
    1河许人给您打赏了¥2
  4. 11010010

    多来点曲谱,很感兴趣

个人中心
有新私信 私信列表
搜索