midiator 0.2.0 → 0.3.0
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/examples/chromatic_scale.rb +1 -0
- data/examples/metronome.rb +1 -0
- data/examples/twinkle.rb +34 -0
- data/lib/midiator.rb +1 -1
- data/lib/midiator/driver.rb +49 -1
- data/lib/midiator/drivers/alsa.rb +11 -0
- data/lib/midiator/drivers/core_midi.rb +1 -1
- data/lib/midiator/drivers/dls_synth.rb +119 -0
- data/lib/midiator/interface.rb +4 -0
- data/spec/interface_spec.rb +10 -0
- metadata +5 -3
data/examples/chromatic_scale.rb
CHANGED
data/examples/metronome.rb
CHANGED
data/examples/twinkle.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# A simple example that plays Twinkle Twinkle Little Star. Also
|
4
|
+
# shows how to use the MIDIator::Notes mixin.
|
5
|
+
#
|
6
|
+
# == Authors
|
7
|
+
#
|
8
|
+
# * Ben Bleything <ben@bleything.net>
|
9
|
+
#
|
10
|
+
# == Copyright
|
11
|
+
#
|
12
|
+
# Copyright (c) 2008 Ben Bleything
|
13
|
+
#
|
14
|
+
# This code released under the terms of the MIT license.
|
15
|
+
#
|
16
|
+
|
17
|
+
require 'rubygems'
|
18
|
+
require 'midiator'
|
19
|
+
|
20
|
+
midi = MIDIator::Interface.new
|
21
|
+
midi.autodetect_driver
|
22
|
+
|
23
|
+
include MIDIator::Notes
|
24
|
+
|
25
|
+
scale = [ C4, Cs4, D4, Eb4, E4, F4, Fs4, G4, Gs4, A4, Bb4, B4,
|
26
|
+
C5, Cs5, D5, Eb5, E5, F5, Fs5, G5, Gs5, A5, Bb5, B5 ]
|
27
|
+
|
28
|
+
scale.each do |note|
|
29
|
+
midi.play note
|
30
|
+
end
|
31
|
+
|
32
|
+
scale.reverse.each do |note|
|
33
|
+
midi.play note
|
34
|
+
end
|
data/lib/midiator.rb
CHANGED
data/lib/midiator/driver.rb
CHANGED
@@ -6,6 +6,10 @@
|
|
6
6
|
#
|
7
7
|
# * Ben Bleything <ben@bleything.net>
|
8
8
|
#
|
9
|
+
# == Contributors
|
10
|
+
#
|
11
|
+
# * Jeremy Voorhis <jvoorhis@gmail.com>
|
12
|
+
#
|
9
13
|
# == Copyright
|
10
14
|
#
|
11
15
|
# Copyright (c) 2008 Ben Bleything
|
@@ -28,9 +32,21 @@ class MIDIator::Driver
|
|
28
32
|
# Note off
|
29
33
|
OFF = 0x80
|
30
34
|
|
35
|
+
# Polyphonic aftertouch
|
36
|
+
PA = 0xa0
|
37
|
+
|
38
|
+
# Control change
|
39
|
+
CC = 0xb0
|
40
|
+
|
31
41
|
# Program change
|
32
42
|
PC = 0xc0
|
33
43
|
|
44
|
+
# Channel aftertouch
|
45
|
+
CA = 0xd0
|
46
|
+
|
47
|
+
# Pitch bend
|
48
|
+
PB = 0xe0
|
49
|
+
|
34
50
|
##########################################################################
|
35
51
|
### M A G I C H O O K S
|
36
52
|
##########################################################################
|
@@ -62,16 +78,42 @@ class MIDIator::Driver
|
|
62
78
|
|
63
79
|
|
64
80
|
### Shortcut to send a note_off message.
|
65
|
-
def note_off( note, channel, velocity )
|
81
|
+
def note_off( note, channel, velocity = 0 )
|
66
82
|
message( OFF | channel, note, velocity )
|
67
83
|
end
|
68
84
|
|
69
85
|
|
86
|
+
### Shortcut to send a polyphonic aftertouch message for an individual note.
|
87
|
+
def aftertouch( note, channel, pressure )
|
88
|
+
message( PA | channel, note, pressure )
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
### Shortcut to send a control change.
|
93
|
+
def control_change( number, channel, value )
|
94
|
+
message( CC | channel, number, value )
|
95
|
+
end
|
96
|
+
|
97
|
+
|
70
98
|
### Shortcut to send a program_change message.
|
71
99
|
def program_change( channel, program )
|
72
100
|
message( PC | channel, program )
|
73
101
|
end
|
74
102
|
|
103
|
+
|
104
|
+
### Shortcut to send a channel aftertouch message.
|
105
|
+
def channel_aftertouch( channel, pressure )
|
106
|
+
message( CA | channel, pressure )
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
### Shortcut to send a pitch bend message.
|
111
|
+
def pitch_bend( channel, value )
|
112
|
+
message( PB | channel, value )
|
113
|
+
end
|
114
|
+
alias bend pitch_bend
|
115
|
+
|
116
|
+
|
75
117
|
##########################################################################
|
76
118
|
### D R I V E R A P I
|
77
119
|
##########################################################################
|
@@ -97,4 +139,10 @@ class MIDIator::Driver
|
|
97
139
|
raise NotImplementedError, "You must implement #message in your driver."
|
98
140
|
end
|
99
141
|
|
142
|
+
|
143
|
+
### The only non-required method. Override this to give the user instructions
|
144
|
+
### if necessary.
|
145
|
+
def instruct_user!
|
146
|
+
end
|
147
|
+
|
100
148
|
end
|
@@ -24,6 +24,17 @@ require 'midiator/driver'
|
|
24
24
|
require 'midiator/driver_registry'
|
25
25
|
|
26
26
|
class MIDIator::Driver::ALSA < MIDIator::Driver # :nodoc:
|
27
|
+
# tell the user they need to connect to their output
|
28
|
+
def instruct_user!
|
29
|
+
$stderr.puts "[MIDIator] Please connect the MIDIator output port to your input"
|
30
|
+
$stderr.puts "[MIDIator] of choice. You can use qjackctl or aconnect to do so."
|
31
|
+
$stderr.puts "[MIDIator]"
|
32
|
+
$stderr.puts "[MIDIator] Press enter when you're done."
|
33
|
+
|
34
|
+
gets # wait for the enter
|
35
|
+
end
|
36
|
+
|
37
|
+
|
27
38
|
module C # :nodoc:
|
28
39
|
extend DL::Importable
|
29
40
|
dlload 'libasound.so'
|
@@ -51,7 +51,7 @@ class MIDIator::Driver::CoreMIDI < MIDIator::Driver # :nodoc:
|
|
51
51
|
##########################################################################
|
52
52
|
|
53
53
|
def open
|
54
|
-
client_name = CF.cFStringCreateWithCString( nil, "
|
54
|
+
client_name = CF.cFStringCreateWithCString( nil, "MIDIator", 0 )
|
55
55
|
@client = DL::PtrData.new( nil )
|
56
56
|
C.mIDIClientCreate( client_name, nil, nil, @client.ref )
|
57
57
|
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# A MIDI driver to play MIDI using OSX's built in DLS synthesizer.
|
2
|
+
#
|
3
|
+
# == Authors
|
4
|
+
#
|
5
|
+
# * Adam Murray <adam@compusition.com>
|
6
|
+
#
|
7
|
+
# == Copyright
|
8
|
+
#
|
9
|
+
# Copyright (c) 2008 Adam Murray
|
10
|
+
#
|
11
|
+
# This code released under the terms of the MIT license.
|
12
|
+
#
|
13
|
+
|
14
|
+
require 'dl/import'
|
15
|
+
require 'dl/struct'
|
16
|
+
|
17
|
+
class String
|
18
|
+
def to_bytes
|
19
|
+
bytes = 0
|
20
|
+
self.each_byte do |byte|
|
21
|
+
bytes <<= 8
|
22
|
+
bytes += byte
|
23
|
+
end
|
24
|
+
return bytes
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class MIDIator::Driver::DLSSynth < MIDIator::Driver # :nodoc:
|
29
|
+
|
30
|
+
attr_accessor :synth
|
31
|
+
|
32
|
+
module AudioToolbox
|
33
|
+
extend DL::Importable
|
34
|
+
dlload '/System/Library/Frameworks/AudioToolbox.framework/Versions/Current/AudioToolbox'
|
35
|
+
|
36
|
+
ComponentDescription = struct [
|
37
|
+
"int componentType",
|
38
|
+
"int componentSubType",
|
39
|
+
"int componentManufacturer",
|
40
|
+
"int componentFlags",
|
41
|
+
"int componentFlagsMask"
|
42
|
+
]
|
43
|
+
|
44
|
+
# to_bytes may not be strictly necessary but these are supposed to be 4 byte numbers
|
45
|
+
AudioUnitManufacturer_Apple = 'appl'.to_bytes
|
46
|
+
AudioUnitType_MusicDevice = 'aumu'.to_bytes
|
47
|
+
AudioUnitSubType_DLSSynth = 'dls '.to_bytes
|
48
|
+
AudioUnitType_Output = 'auou'.to_bytes
|
49
|
+
AudioUnitSubType_DefaultOutput = 'def '.to_bytes
|
50
|
+
|
51
|
+
extern 'int NewAUGraph(void *)'
|
52
|
+
extern 'int AUGraphAddNode(void *, ComponentDescription *, void *)'
|
53
|
+
extern 'int AUGraphOpen(void *)'
|
54
|
+
extern 'int AUGraphConnectNodeInput(void *, void *, int, void *, int)'
|
55
|
+
extern 'int AUGraphNodeInfo(void *, void *, ComponentDescription *, void *)'
|
56
|
+
extern 'int AUGraphInitialize(void *)'
|
57
|
+
extern 'int AUGraphStart(void *)'
|
58
|
+
extern 'int AUGraphStop(void *)'
|
59
|
+
extern 'int DisposeAUGraph(void *)'
|
60
|
+
|
61
|
+
extern 'void * CAShow(void *)'
|
62
|
+
|
63
|
+
extern 'void * MusicDeviceMIDIEvent(void *, int, int, int, int)'
|
64
|
+
end
|
65
|
+
|
66
|
+
protected
|
67
|
+
|
68
|
+
def require_noerr(action_description, &block)
|
69
|
+
if block.call != 0
|
70
|
+
fail "Failed to #{action_description}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def open
|
75
|
+
@synth = DL::PtrData.new(nil)
|
76
|
+
@graph = DL::PtrData.new(nil)
|
77
|
+
synthNode = DL::PtrData.new(nil)
|
78
|
+
outNode = DL::PtrData.new(nil)
|
79
|
+
|
80
|
+
cd = AudioToolbox::ComponentDescription.malloc()
|
81
|
+
cd.componentManufacturer = AudioToolbox::AudioUnitManufacturer_Apple
|
82
|
+
cd.componentFlags = 0
|
83
|
+
cd.componentFlagsMask = 0
|
84
|
+
|
85
|
+
require_noerr('create AUGraph') { AudioToolbox.newAUGraph(@graph.ref) }
|
86
|
+
|
87
|
+
cd.componentType = AudioToolbox::AudioUnitType_MusicDevice
|
88
|
+
cd.componentSubType = AudioToolbox::AudioUnitSubType_DLSSynth
|
89
|
+
require_noerr('add synthNode') { AudioToolbox.aUGraphAddNode(@graph, cd, synthNode.ref) }
|
90
|
+
|
91
|
+
cd.componentType = AudioToolbox::AudioUnitType_Output
|
92
|
+
cd.componentSubType = AudioToolbox::AudioUnitSubType_DefaultOutput
|
93
|
+
require_noerr('add outNode') { AudioToolbox.aUGraphAddNode(@graph, cd, outNode.ref) }
|
94
|
+
|
95
|
+
require_noerr('open graph') { AudioToolbox.aUGraphOpen(@graph) }
|
96
|
+
|
97
|
+
require_noerr('connect synth to out') { AudioToolbox.aUGraphConnectNodeInput(@graph, synthNode, 0, outNode, 0) }
|
98
|
+
|
99
|
+
require_noerr('graph info') { AudioToolbox.aUGraphNodeInfo(@graph, synthNode, nil, @synth.ref) }
|
100
|
+
require_noerr('init graph') { AudioToolbox.aUGraphInitialize(@graph) }
|
101
|
+
require_noerr('start graph') { AudioToolbox.aUGraphStart(@graph) }
|
102
|
+
|
103
|
+
AudioToolbox.cAShow(@graph) if $DEBUG
|
104
|
+
end
|
105
|
+
|
106
|
+
def message(*args)
|
107
|
+
arg0 = args[0] || 0
|
108
|
+
arg1 = args[1] || 0
|
109
|
+
arg2 = args[2] || 0
|
110
|
+
AudioToolbox.musicDeviceMIDIEvent(@synth, arg0, arg1, arg2, 0)
|
111
|
+
end
|
112
|
+
|
113
|
+
def close
|
114
|
+
if @graph
|
115
|
+
AudioToolbox.aUGraphStop(@graph)
|
116
|
+
AudioToolbox.disposeAUGraph(@graph)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
data/lib/midiator/interface.rb
CHANGED
@@ -10,6 +10,7 @@
|
|
10
10
|
# == Contributors
|
11
11
|
#
|
12
12
|
# * Giles Bowkett
|
13
|
+
# * Jeremy Voorhis
|
13
14
|
#
|
14
15
|
# == Copyright
|
15
16
|
#
|
@@ -65,6 +66,9 @@ class MIDIator::Interface
|
|
65
66
|
# special case for the WinMM driver
|
66
67
|
driver_class.sub!( /Winmm/, 'WinMM' )
|
67
68
|
|
69
|
+
# special case for the DLSSynth driver
|
70
|
+
driver_class.sub!( /Dls/, 'DLS' )
|
71
|
+
|
68
72
|
# this little trick stolen from ActiveSupport. It looks for a top-
|
69
73
|
# level module with the given name.
|
70
74
|
@driver = Object.module_eval( "::#{driver_class}" ).new
|
data/spec/interface_spec.rb
CHANGED
@@ -126,5 +126,15 @@ describe MIDIator::Interface do
|
|
126
126
|
|
127
127
|
@interface.use( :winmm )
|
128
128
|
end
|
129
|
+
|
130
|
+
it "correctly spells DLSSynth when the DLSSynth driver is requested" do
|
131
|
+
@interface.stub!( :require )
|
132
|
+
|
133
|
+
Object.should_receive( :module_eval ).with(
|
134
|
+
"::MIDIator::Driver::DLSSynth"
|
135
|
+
).and_return( Class.new )
|
136
|
+
|
137
|
+
@interface.use( :dls_synth )
|
138
|
+
end
|
129
139
|
end
|
130
140
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: midiator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Bleything
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-11-23 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -39,6 +39,7 @@ files:
|
|
39
39
|
- lib/midiator/driver_registry.rb
|
40
40
|
- lib/midiator/drivers/alsa.rb
|
41
41
|
- lib/midiator/drivers/core_midi.rb
|
42
|
+
- lib/midiator/drivers/dls_synth.rb
|
42
43
|
- lib/midiator/drivers/winmm.rb
|
43
44
|
- lib/midiator/drums.rb
|
44
45
|
- lib/midiator/exceptions.rb
|
@@ -49,6 +50,7 @@ files:
|
|
49
50
|
- lib/string_extensions.rb
|
50
51
|
- examples/chromatic_scale.rb
|
51
52
|
- examples/metronome.rb
|
53
|
+
- examples/twinkle.rb
|
52
54
|
- misc/rake/packaging.rb
|
53
55
|
- misc/rake/rdoc.rb
|
54
56
|
- misc/rake/testing.rb
|
@@ -74,7 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
74
76
|
requirements: []
|
75
77
|
|
76
78
|
rubyforge_project: midiator
|
77
|
-
rubygems_version: 1.
|
79
|
+
rubygems_version: 1.3.1
|
78
80
|
signing_key:
|
79
81
|
specification_version: 2
|
80
82
|
summary: MIDIator - A a nice Ruby interface to your system's MIDI services.
|