micromidi 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +13 -0
- data/README.rdoc +103 -0
- data/TODO +8 -0
- data/lib/micromidi/context.rb +57 -0
- data/lib/micromidi/instructions/composite.rb +35 -0
- data/lib/micromidi/instructions/input.rb +114 -0
- data/lib/micromidi/instructions/message.rb +100 -0
- data/lib/micromidi/instructions/output.rb +28 -0
- data/lib/micromidi/instructions/process.rb +57 -0
- data/lib/micromidi/instructions/shorthand.rb +79 -0
- data/lib/micromidi/instructions/sticky.rb +59 -0
- data/lib/micromidi/instructions/sysex.rb +43 -0
- data/lib/micromidi/state.rb +79 -0
- data/lib/micromidi.rb +67 -0
- data/lib/midi.rb +15 -0
- data/test/helper.rb +32 -0
- data/test/test_composite.rb +36 -0
- data/test/test_context.rb +33 -0
- data/test/test_effect.rb +135 -0
- data/test/test_input.rb +23 -0
- data/test/test_message.rb +123 -0
- data/test/test_output.rb +21 -0
- data/test/test_state.rb +32 -0
- data/test/test_sticky.rb +134 -0
- data/test/test_sysex.rb +60 -0
- metadata +103 -0
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright 2011 Ari Russo
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.rdoc
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
= micromidi
|
2
|
+
|
3
|
+
A Ruby DSL for MIDI
|
4
|
+
|
5
|
+
{pic}[http://images.treetrouble.net/images/midi.png]
|
6
|
+
|
7
|
+
== Features
|
8
|
+
|
9
|
+
* Cross-platform compatible using MRI or JRuby.
|
10
|
+
* Simplified MIDI and Sysex message output
|
11
|
+
* MIDI Thru, processing and custom input events
|
12
|
+
* Optional shorthand for {live coding}[http://en.wikipedia.org/wiki/Live_coding]
|
13
|
+
|
14
|
+
== Installation
|
15
|
+
|
16
|
+
gem install micromidi
|
17
|
+
|
18
|
+
== Requirements
|
19
|
+
|
20
|
+
Ruby 1.9.2+ or JRuby in 1.9 mode
|
21
|
+
|
22
|
+
Requires {midi-eye}[http://github.com/arirusso/midi-eye], {midi-message}[http://github.com/arirusso/midi-message] and {unimidi}[http://github.com/arirusso/unimidi]. These should install automatically with the gem.
|
23
|
+
|
24
|
+
== Usage
|
25
|
+
|
26
|
+
The following are basic examples that use {unimidi}[http://github.com/arirusso/unimidi] inputs and outputs. ({see an example here that explains selecting an output...}[http://github.com/arirusso/unimidi/blob/master/examples/select_a_device.rb])
|
27
|
+
|
28
|
+
require "midi"
|
29
|
+
|
30
|
+
@i = UniMIDI::Input.use(:first)
|
31
|
+
@o = UniMIDI::Output.use(:first)
|
32
|
+
|
33
|
+
This example plays some arpeggios
|
34
|
+
|
35
|
+
MIDI.using($o) do
|
36
|
+
|
37
|
+
5.times do |oct|
|
38
|
+
octave oct
|
39
|
+
%w{C E G B}.each { |n| play n 0.5 }
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
While running, this next example sends all input directly to the output except for notes; notes that are received are only sent to the output if their octave is between 1 and 3. Output is also printed to the console by passing in <em>$stdout</em>.
|
45
|
+
|
46
|
+
MIDI.using(@i, @o, $stdout) do
|
47
|
+
|
48
|
+
thru_except :note { |msg| only(msg, :octave, (1..3)) }
|
49
|
+
|
50
|
+
join
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
This is the same example redone using shorthand aliases
|
55
|
+
|
56
|
+
M(@i, @o) do
|
57
|
+
|
58
|
+
te :n { |m| only(m, :oct, (1..3)) }
|
59
|
+
|
60
|
+
j
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
Finally, here is an example that maps some MIDI Control Change messages to SysEx
|
65
|
+
|
66
|
+
MIDI.using(@i, @o) do
|
67
|
+
|
68
|
+
*@the_map =
|
69
|
+
[0x40, 0x7F, 0x00],
|
70
|
+
[0x41, 0x7F, 0x00],
|
71
|
+
[0x42, 0x7F, 0x00]
|
72
|
+
|
73
|
+
node :roland, :model_id => 0x42, :device_id => 0x10
|
74
|
+
|
75
|
+
receive :cc do |message|
|
76
|
+
|
77
|
+
command @the_map[message.index - 1], message.value
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
I've written up a few posts explaining each of the concepts used here in greater detail:
|
84
|
+
|
85
|
+
* {Output}[http://tx81z.blogspot.com/2011/08/micromidi-midi-messages-and-output.html]
|
86
|
+
* {MIDI Thru and Processing}[http://tx81z.blogspot.com/2011/08/micromidi-midi-thru-and-midi-processing.html]
|
87
|
+
* {Binding Custom Input Events}[http://tx81z.blogspot.com/2011/08/micromidi-custom-events.html]
|
88
|
+
* {Shorthand}[http://tx81z.blogspot.com/2011/08/micromidi-shorthand.html]
|
89
|
+
* {Sysex}[http://tx81z.blogspot.com/2011/09/generating-sysex-messages-with.html]
|
90
|
+
|
91
|
+
== Documentation
|
92
|
+
|
93
|
+
* {rdoc}[http://rubydoc.info/github/arirusso/micromidi]
|
94
|
+
|
95
|
+
== Author
|
96
|
+
|
97
|
+
* {Ari Russo}[http://github.com/arirusso] <ari.russo at gmail.com>
|
98
|
+
|
99
|
+
== License
|
100
|
+
|
101
|
+
Apache 2.0, See the file LICENSE
|
102
|
+
|
103
|
+
Copyright (c) 2011 Ari Russo
|
data/TODO
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
|
4
|
+
module MicroMIDI
|
5
|
+
|
6
|
+
class Context
|
7
|
+
|
8
|
+
include Instructions::Composite
|
9
|
+
|
10
|
+
attr_reader :state
|
11
|
+
|
12
|
+
def initialize(ins, outs, &block)
|
13
|
+
|
14
|
+
@state = State.new(ins, outs)
|
15
|
+
|
16
|
+
@instructions = {
|
17
|
+
:process => Instructions::Process.new(@state),
|
18
|
+
:input => Instructions::Input.new(@state),
|
19
|
+
:message => Instructions::Message.new(@state),
|
20
|
+
:output => Instructions::Output.new(@state),
|
21
|
+
:sticky => Instructions::Sticky.new(@state),
|
22
|
+
:sysex => Instructions::SysEx.new(@state)
|
23
|
+
}
|
24
|
+
|
25
|
+
instance_eval(&block) unless block.nil?
|
26
|
+
end
|
27
|
+
|
28
|
+
def repeat
|
29
|
+
self.send(@state.last_command[:method], *@state.last_command[:args]) unless @state.last_command.nil?
|
30
|
+
end
|
31
|
+
|
32
|
+
def method_missing(m, *a, &b)
|
33
|
+
delegated = false
|
34
|
+
outp = nil
|
35
|
+
options = a.last.kind_of?(Hash) ? a.last : {}
|
36
|
+
do_output = options[:output] || true
|
37
|
+
[@instructions[:sysex], @instructions[:message], @instructions[:process]].each do |dsl|
|
38
|
+
if dsl.respond_to?(m)
|
39
|
+
msg = dsl.send(m, *a, &b)
|
40
|
+
outp = @state.auto_output && do_output ? @instructions[:output].output(msg) : msg
|
41
|
+
delegated = true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
unless delegated
|
45
|
+
[@instructions[:input], @instructions[:output], @instructions[:sticky]].each do |dsl|
|
46
|
+
if dsl.respond_to?(m)
|
47
|
+
outp = dsl.send(m, *a, &b)
|
48
|
+
delegated = true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
@state.record(m, a, b, outp)
|
53
|
+
delegated ? outp : super
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
module MicroMIDI
|
4
|
+
|
5
|
+
module Instructions
|
6
|
+
|
7
|
+
module Composite
|
8
|
+
|
9
|
+
# play note n, wait <em>duration</em> seconds, then do note off for note n
|
10
|
+
def play(n, duration)
|
11
|
+
msg = case n
|
12
|
+
when Numeric, String then note(n)
|
13
|
+
when MIDIMessage then n
|
14
|
+
end
|
15
|
+
sleep(duration)
|
16
|
+
off
|
17
|
+
msg
|
18
|
+
end
|
19
|
+
|
20
|
+
# sends a note off message for every note on every channel
|
21
|
+
def all_off
|
22
|
+
(0..15).each do |channel|
|
23
|
+
(0..127).each do |note_num|
|
24
|
+
note_off(note_num, :channel => channel)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
true
|
28
|
+
end
|
29
|
+
alias_method :quiet!, :all_off
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
module MicroMIDI
|
4
|
+
|
5
|
+
module Instructions
|
6
|
+
|
7
|
+
class Input
|
8
|
+
|
9
|
+
include MIDIMessage
|
10
|
+
|
11
|
+
def initialize(state)
|
12
|
+
@state = state
|
13
|
+
end
|
14
|
+
|
15
|
+
# bind an event that will be called every time a message is received
|
16
|
+
def receive(*a, &block)
|
17
|
+
options = a.last.kind_of?(Hash) ? a.pop : {}
|
18
|
+
match = a.empty? ? nil : { :class => msg_classes(a) }
|
19
|
+
listener(match, options) { |event| yield(event[:message], event[:timestamp]) }
|
20
|
+
end
|
21
|
+
alias_method :gets, :receive
|
22
|
+
alias_method :handle, :receive
|
23
|
+
alias_method :listen, :receive
|
24
|
+
alias_method :listen_for, :receive
|
25
|
+
alias_method :when_receive, :receive
|
26
|
+
|
27
|
+
def receive_unless(*a, &block)
|
28
|
+
options = a.last.kind_of?(Hash) ? a.pop : {}
|
29
|
+
match = { :class => msg_classes(a) }
|
30
|
+
listener(nil, options) { |event| yield(event[:message], event[:timestamp]) unless match.include?(event[:message].class) }
|
31
|
+
end
|
32
|
+
alias_method :handle_unless, :receive_unless
|
33
|
+
alias_method :listen_unless, :receive_unless
|
34
|
+
alias_method :listen_for_unless, :receive_unless
|
35
|
+
alias_method :unless_receive, :receive_unless
|
36
|
+
|
37
|
+
# send input messages thru to the outputs
|
38
|
+
def thru
|
39
|
+
thru_if
|
40
|
+
end
|
41
|
+
|
42
|
+
# send input messages thru to the outputs if it has a specific class
|
43
|
+
def thru_if(*a)
|
44
|
+
a.last.kind_of?(Hash) ? a.last[:thru] = true : a.push({ :thru => true })
|
45
|
+
receive(*a) { |message, timestamp| output(message) }
|
46
|
+
end
|
47
|
+
|
48
|
+
# send input messages thru to the outputs unless of a specific class
|
49
|
+
def thru_unless(*a)
|
50
|
+
a.last.kind_of?(Hash) ? a.last[:thru] = true : a.push({ :thru => true })
|
51
|
+
receive_unless(*a) { |message, timestamp| output(message) }
|
52
|
+
end
|
53
|
+
|
54
|
+
# like <em>thru_unless</em> except a block can be passed that will be called when
|
55
|
+
# notes specified as the <em>unless</em> arrive
|
56
|
+
def thru_except(*a, &block)
|
57
|
+
thru_unless(*a)
|
58
|
+
receive(*a, &block)
|
59
|
+
end
|
60
|
+
|
61
|
+
# wait for input on the last input passed in
|
62
|
+
# can pass the option :from => [an input] to specify which one to wait on
|
63
|
+
def wait_for_input(options = {})
|
64
|
+
listener = options[:from] || @state.listeners.last || @state.thru_listeners.last
|
65
|
+
listener.join
|
66
|
+
end
|
67
|
+
|
68
|
+
def join
|
69
|
+
loop { wait_for_input }
|
70
|
+
end
|
71
|
+
|
72
|
+
protected
|
73
|
+
|
74
|
+
def listener(match = {}, options = {}, &block)
|
75
|
+
inputs = options[:from] || @state.inputs
|
76
|
+
thru = options[:thru] || false
|
77
|
+
match ||= {}
|
78
|
+
inputs.each do |input|
|
79
|
+
listener = MIDIEye::Listener.new(input)
|
80
|
+
listener.listen_for(match, &block)
|
81
|
+
if thru
|
82
|
+
@state.thru_listeners.each { |l| l.stop }
|
83
|
+
@state.thru_listeners.clear
|
84
|
+
@state.thru_listeners << listener
|
85
|
+
else
|
86
|
+
@state.listeners << listener
|
87
|
+
end
|
88
|
+
listener.start(:background => true) unless !options[:start].nil? && !options[:start]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def msg_classes(list)
|
95
|
+
list.map do |type|
|
96
|
+
case type
|
97
|
+
when :aftertouch, :pressure, :aft then [ChannelAftertouch, PolyphonicAftertouch]
|
98
|
+
when :channel_aftertouch, :channel_pressure, :ca, :cp then ChannelAftertouch
|
99
|
+
when :control_change, :cc, :c then ControlChange
|
100
|
+
when :note, :n then [NoteOn, NoteOff]
|
101
|
+
when :note_on, :nn then NoteOn
|
102
|
+
when :note_off, :no, :off then NoteOff
|
103
|
+
when :pitch_bend, :pb then PitchBend
|
104
|
+
when :polyphonic_aftertouch, :poly_aftertouch, :poly_pressure, :polyphonic_pressure, :pa, :pp then PolyphonicAftertouch
|
105
|
+
when :program_change, :pc, :p then ProgramChange
|
106
|
+
end
|
107
|
+
end.flatten.compact
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
module MicroMIDI
|
4
|
+
|
5
|
+
module Instructions
|
6
|
+
|
7
|
+
class Message
|
8
|
+
|
9
|
+
include MIDIMessage
|
10
|
+
|
11
|
+
def initialize(state)
|
12
|
+
@state = state
|
13
|
+
end
|
14
|
+
|
15
|
+
# create a control change message
|
16
|
+
def control_change(id, value, opts = {})
|
17
|
+
props = @state.message_properties(opts, :channel)
|
18
|
+
id.kind_of?(Numeric) ? ControlChange.new(props[:channel], id, value) : ControlChange[id].new(props[:channel], value)
|
19
|
+
end
|
20
|
+
|
21
|
+
# create a note message
|
22
|
+
def note(id, opts = {})
|
23
|
+
props = @state.message_properties(opts, :channel, :velocity)
|
24
|
+
note = if id.kind_of?(Numeric)
|
25
|
+
NoteOn.new(props[:channel], id, props[:velocity])
|
26
|
+
elsif id.kind_of?(String) || id.kind_of?(Symbol)
|
27
|
+
note_string = parse_note_name(id)
|
28
|
+
NoteOn[note_string].new(props[:channel], props[:velocity])
|
29
|
+
end
|
30
|
+
@state.last_note = note
|
31
|
+
note
|
32
|
+
end
|
33
|
+
|
34
|
+
# create a note off message
|
35
|
+
def note_off(id, opts = {})
|
36
|
+
props = @state.message_properties(opts, :channel, :velocity)
|
37
|
+
if id.kind_of?(Numeric)
|
38
|
+
NoteOff.new(props[:channel], id, props[:velocity])
|
39
|
+
elsif id.kind_of?(String) || id.kind_of?(Symbol)
|
40
|
+
note_string = parse_note_name(id)
|
41
|
+
NoteOff[parse_note_name(id)].new(props[:channel], props[:velocity])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# create a MIDI message from a byte string, array of bytes, or list of bytes
|
46
|
+
def parse(message)
|
47
|
+
MIDIMessage.parse(message)
|
48
|
+
end
|
49
|
+
|
50
|
+
# create a program change message
|
51
|
+
def program_change(program, opts = {})
|
52
|
+
props = @state.message_properties(opts, :channel)
|
53
|
+
MIDIMessage::ProgramChange.new(props[:channel], program)
|
54
|
+
end
|
55
|
+
|
56
|
+
# create a note-off message from the last note-on message
|
57
|
+
def off
|
58
|
+
o = @state.last_note.to_note_off unless @state.last_note.nil?
|
59
|
+
@state.last_note = nil
|
60
|
+
o
|
61
|
+
end
|
62
|
+
|
63
|
+
# create a channel pressure message
|
64
|
+
def channel_aftertouch(value, opts = {})
|
65
|
+
props = @state.message_properties(opts, :channel)
|
66
|
+
MIDIMessage::ChannelAftertouch.new(props[:channel], value)
|
67
|
+
end
|
68
|
+
alias_method :channel_pressure, :channel_aftertouch
|
69
|
+
|
70
|
+
# create a poly pressure message
|
71
|
+
def polyphonic_aftertouch(note, value, opts = {})
|
72
|
+
props = @state.message_properties(opts, :channel)
|
73
|
+
MIDIMessage::PolyphonicAftertouch.new(props[:channel], note, value)
|
74
|
+
end
|
75
|
+
alias_method :poly_aftertouch, :polyphonic_aftertouch
|
76
|
+
alias_method :polyphonic_pressure, :polyphonic_aftertouch
|
77
|
+
alias_method :poly_pressure, :polyphonic_aftertouch
|
78
|
+
|
79
|
+
def pitch_bend(low, high, opts = {})
|
80
|
+
props = @state.message_properties(opts, :channel)
|
81
|
+
MIDIMessage::PitchBend.new(props[:channel], low, high)
|
82
|
+
end
|
83
|
+
alias_method :bend, :pitch_bend
|
84
|
+
alias_method :pitchbend, :pitch_bend
|
85
|
+
|
86
|
+
protected
|
87
|
+
|
88
|
+
def parse_note_name(name)
|
89
|
+
name = name.to_s #ensure that name is a string
|
90
|
+
string_opts = { :octave => name.scan(/-?\d\z/).first }
|
91
|
+
note = name.split(/-?\d\z/).first
|
92
|
+
string_props = @state.message_properties(string_opts, :octave)
|
93
|
+
"#{note}#{string_props[:octave].to_s}"
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
module MicroMIDI
|
4
|
+
|
5
|
+
module Instructions
|
6
|
+
|
7
|
+
class Output
|
8
|
+
|
9
|
+
def initialize(state)
|
10
|
+
@state = state
|
11
|
+
end
|
12
|
+
|
13
|
+
def output(msg)
|
14
|
+
auto_output(msg) if msg === false || msg === true
|
15
|
+
@state.outputs.each { |o| o.puts(msg) } unless msg.nil?
|
16
|
+
msg
|
17
|
+
end
|
18
|
+
|
19
|
+
# toggle mode where messages are automatically outputted
|
20
|
+
def auto_output(mode = nil)
|
21
|
+
mode.nil? ? @state.toggle_auto_output : @state.auto_output = mode
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
module MicroMIDI
|
4
|
+
|
5
|
+
module Instructions
|
6
|
+
|
7
|
+
class Process
|
8
|
+
|
9
|
+
include MIDIMessage
|
10
|
+
include MIDIMessage::Process
|
11
|
+
|
12
|
+
def initialize(state)
|
13
|
+
@state = state
|
14
|
+
end
|
15
|
+
|
16
|
+
def transpose(message, property, factor, options = {})
|
17
|
+
Transpose.process(message, property, factor, options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def limit(message, property, range, options = {})
|
21
|
+
Limit.process(message, property, range, options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def filter(message, property, bandwidth, options = {})
|
25
|
+
Filter.process(message, property, bandwidth, options)
|
26
|
+
end
|
27
|
+
|
28
|
+
def high_pass_filter(message, property, min, options = {})
|
29
|
+
HighPassFilter.process(message, property, min, options)
|
30
|
+
end
|
31
|
+
alias_method :only_above, :high_pass_filter
|
32
|
+
alias_method :except_below, :high_pass_filter
|
33
|
+
|
34
|
+
def low_pass_filter(message, property, max, options = {})
|
35
|
+
LowPassFilter.process(message, property, max, options)
|
36
|
+
end
|
37
|
+
alias_method :only_below, :low_pass_filter
|
38
|
+
alias_method :except_above, :low_pass_filter
|
39
|
+
|
40
|
+
def band_pass_filter(message, property, bandwidth, options = {})
|
41
|
+
BandPassFilter.process(message, property, bandwidth, options)
|
42
|
+
end
|
43
|
+
alias_method :only_in, :band_pass_filter
|
44
|
+
alias_method :only, :band_pass_filter
|
45
|
+
|
46
|
+
def notch_filter(message, property, bandwidth, options = {})
|
47
|
+
NotchFilter.process(message, property, bandwidth, options)
|
48
|
+
end
|
49
|
+
alias_method :band_reject_filter, :notch_filter
|
50
|
+
alias_method :except_in, :notch_filter
|
51
|
+
alias_method :except, :notch_filter
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
|
4
|
+
module MicroMIDI
|
5
|
+
|
6
|
+
alias l loop
|
7
|
+
|
8
|
+
class << self
|
9
|
+
alias_method :m, :message
|
10
|
+
end
|
11
|
+
|
12
|
+
class Context
|
13
|
+
alias_method :r, :repeat
|
14
|
+
end
|
15
|
+
|
16
|
+
module Instructions
|
17
|
+
|
18
|
+
module Composite
|
19
|
+
alias_method :p, :play
|
20
|
+
alias_method :q!, :all_off
|
21
|
+
alias_method :x, :all_off
|
22
|
+
end
|
23
|
+
|
24
|
+
class Input
|
25
|
+
alias_method :j, :join
|
26
|
+
alias_method :rc, :receive
|
27
|
+
alias_method :rcu, :receive_unless
|
28
|
+
alias_method :t, :thru
|
29
|
+
alias_method :te, :thru_except
|
30
|
+
alias_method :tu, :thru_unless
|
31
|
+
alias_method :w, :wait_for_input
|
32
|
+
end
|
33
|
+
|
34
|
+
class Message
|
35
|
+
alias_method :c, :control_change
|
36
|
+
alias_method :cc, :control_change
|
37
|
+
alias_method :n, :note
|
38
|
+
alias_method :no, :note_off
|
39
|
+
alias_method :o, :off
|
40
|
+
alias_method :pc, :program_change
|
41
|
+
end
|
42
|
+
|
43
|
+
class Output
|
44
|
+
alias_method :out, :output
|
45
|
+
end
|
46
|
+
|
47
|
+
class Process
|
48
|
+
alias_method :bp, :band_pass_filter
|
49
|
+
alias_method :bpf, :band_pass_filter
|
50
|
+
alias_method :br, :notch_filter
|
51
|
+
alias_method :f, :filter
|
52
|
+
alias_method :hp, :high_pass_filter
|
53
|
+
alias_method :hpf, :high_pass_filter
|
54
|
+
alias_method :l, :limit
|
55
|
+
alias_method :lp, :low_pass_filter
|
56
|
+
alias_method :lpf, :low_pass_filter
|
57
|
+
alias_method :mbf, :filter
|
58
|
+
alias_method :nf, :notch_filter
|
59
|
+
alias_method :tp, :transpose
|
60
|
+
end
|
61
|
+
|
62
|
+
class Sticky
|
63
|
+
alias_method :ch, :channel
|
64
|
+
alias_method :ss, :super_sticky
|
65
|
+
alias_method :v, :velocity
|
66
|
+
end
|
67
|
+
|
68
|
+
class SysEx
|
69
|
+
alias_method :sc, :sysex_command
|
70
|
+
alias_method :sr, :sysex_request
|
71
|
+
alias_method :sx, :sysex_message
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def M(*a, &block)
|
78
|
+
MIDI.message(*a, &block)
|
79
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
module MicroMIDI
|
4
|
+
|
5
|
+
module Instructions
|
6
|
+
|
7
|
+
class Sticky
|
8
|
+
|
9
|
+
def initialize(state)
|
10
|
+
@state = state
|
11
|
+
end
|
12
|
+
|
13
|
+
# sets the sticky channel for the current block
|
14
|
+
def channel(val = nil)
|
15
|
+
val.nil? ? @state.channel : @state.channel = val
|
16
|
+
end
|
17
|
+
|
18
|
+
# sets the octave for the current block
|
19
|
+
def octave(val = nil)
|
20
|
+
val.nil? ? @state.octave : @state.octave = val
|
21
|
+
end
|
22
|
+
|
23
|
+
# sets the sysex node for the current block
|
24
|
+
def sysex_node(*args)
|
25
|
+
options = args.last.kind_of?(Hash) ? args.last : {}
|
26
|
+
args.empty? ? @state.sysex_node : @state.sysex_node = MIDIMessage::SystemExclusive::Node.new(args.first, options)
|
27
|
+
end
|
28
|
+
alias_method :node, :sysex_node
|
29
|
+
|
30
|
+
# sets the sticky velocity for the current block
|
31
|
+
def velocity(val = nil)
|
32
|
+
val.nil? ? @state.velocity : @state.velocity = val
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
# toggles super_sticky mode, a mode where any explicit values used to create MIDI messages
|
37
|
+
# automatically become sticky -- whereas normally the explicit value would only be used for
|
38
|
+
# the current message.
|
39
|
+
#
|
40
|
+
# e.g.
|
41
|
+
#
|
42
|
+
# note "C4", :channel => 5
|
43
|
+
#
|
44
|
+
# will have the exact same effect as
|
45
|
+
#
|
46
|
+
# channel 5
|
47
|
+
# note "C4"
|
48
|
+
#
|
49
|
+
# while in super sticky mode
|
50
|
+
#
|
51
|
+
def super_sticky
|
52
|
+
@state.toggle_super_sticky
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
module MicroMIDI
|
4
|
+
|
5
|
+
module Instructions
|
6
|
+
|
7
|
+
class SysEx
|
8
|
+
|
9
|
+
include MIDIMessage
|
10
|
+
|
11
|
+
def initialize(state)
|
12
|
+
@state = state
|
13
|
+
end
|
14
|
+
|
15
|
+
# create a sysex command
|
16
|
+
def sysex_command(address, data, options = {})
|
17
|
+
options[:sysex_node] ||= options[:node]
|
18
|
+
props = @state.message_properties(options, :sysex_node)
|
19
|
+
SystemExclusive::Command.new(address, data, :node => props[:sysex_node])
|
20
|
+
end
|
21
|
+
alias_method :command, :sysex_command
|
22
|
+
|
23
|
+
# create a sysex request
|
24
|
+
def sysex_request(address, size, options = {})
|
25
|
+
options[:sysex_node] ||= options[:node]
|
26
|
+
props = @state.message_properties(options, :sysex_node)
|
27
|
+
SystemExclusive::Request.new(address, size, :node => props[:sysex_node])
|
28
|
+
end
|
29
|
+
alias_method :request, :sysex_request
|
30
|
+
|
31
|
+
# create an indeterminate sysex message
|
32
|
+
def sysex_message(data, options = {})
|
33
|
+
options[:sysex_node] ||= options[:node]
|
34
|
+
props = @state.message_properties(options, :sysex_node)
|
35
|
+
SystemExclusive::Message.new(data, :node => props[:sysex_node])
|
36
|
+
end
|
37
|
+
alias_method :sysex, :sysex_message
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|