Comment detail

Tiny MML (Nested Flatten)
MIDIマッパーを使って再生。Windows専用。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <windows.h>
#include <mmsystem.h>

#include <iostream>
#include <stdexcept>
#include <string>

#define MIDIMSG(status, channel, data1, data2) ((DWORD)((status<<4) | channel | (data1<<8) | (data2<<16)))

void check(MMRESULT result)
{
    if (result != MMSYSERR_NOERROR)
    {
        throw std::runtime_error("mmsystem error");
    }
}

class midi
{
public:
    midi()
    {
        check(::midiOutOpen(&_h, MIDI_MAPPER, 0, 0, CALLBACK_NULL));
    }

    ~midi()
    {
        check(::midiOutClose(_h));
    }

    void play(DWORD note)
    {
        check(::midiOutShortMsg(_h, MIDIMSG(0x9, 0, note, 100)));
        wait();
        check(::midiOutReset(_h));
    }

    void wait()
    {
        ::Sleep(500);
    }

private:
    HMIDIOUT _h;
};

void play(const char* s)
{
    midi m;

    for (; *s; ++s)
    {
        switch (*s)
        {
            case 'c': m.play(60); break;
            case 'd': m.play(62); break;
            case 'e': m.play(64); break;
            case 'f': m.play(65); break;
            case 'g': m.play(67); break;
            case 'a': m.play(69); break;
            case 'b': m.play(71); break;
            case 'r': m.wait(); break;
            default:
                throw std::runtime_error("invalid note");
        }
    }
}

int main(int argc, char* argv[])
{
    try
    {
        if (argc != 2)
        {
            play("cdefedcrefgagfercrcrcrcrcdefedcr");
        }
        else
        {
            play(argv[1]);
        }
    }
    catch (std::exception& e)
    {
        std::cout << e.what() << std::endl;
    }
}
上のと同じコードをPython+ctypesを使って記述。音の長さは他の人のコードを参考にして0.25秒に変更しました。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import ctypes
import time
import sys

MIDI_MAPPER = -1
MMSYSERR_NOERROR = 0
CALLBACK_NULL = 0

class Midi:
    def __init__(self):
        self._dll = ctypes.windll.winmm
        self._h = ctypes.c_void_p()
        self._call("midiOutOpen", ctypes.byref(self._h), MIDI_MAPPER, 0, 0, CALLBACK_NULL)

    def __del__(self):
        self._call("midiOutClose", self._h)

    def play(self, note):
        self._call("midiOutShortMsg", self._h, self._msg(0x9, 0, note, 100))
        self.wait()
        self._call("midiOutReset", self._h)

    def wait(self):
        time.sleep(0.25)

    def _call(self, name, *args):
        ret = getattr(self._dll, name)(*args)
        if ret != MMSYSERR_NOERROR:
            raise RuntimeError("mmsystem error (%s)" % hex(ret))

    def _msg(self, status, channel, data1, data2):
        return (status<<4) | channel | (data1<<8) | (data2<<16)

def play(s):
    m = Midi()
    notes = {'c': 60, 'd': 62, 'e': 64, 'f': 65,
             'g': 67, 'a': 69, 'b': 71}
    for c in s:
        if c == 'r':
            m.wait()
        else:
            m.play(notes[c])

def main():
    if len(sys.argv) == 2:
        play(sys.argv[1])
    else:
        play("cdefedcrefgagfercrcrcrcrcdefedcr")

if __name__ == '__main__':
    main()

Index

Feed

Other

Link

Pathtraq

loading...