midiator 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -19,6 +19,7 @@ require 'midiator'
19
19
 
20
20
  midi = MIDIator::Interface.new
21
21
  midi.autodetect_driver
22
+ midi.instruct_user!
22
23
 
23
24
  include MIDIator::Notes
24
25
 
@@ -50,6 +50,7 @@ include MIDIator::Notes
50
50
 
51
51
  @midi = MIDIator::Interface.new
52
52
  @midi.autodetect_driver
53
+ @midi.instruct_user!
53
54
  @midi.program_change 0, 115 # Wood block!
54
55
 
55
56
  # trap interrupts to properly kill the timer
@@ -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
@@ -14,7 +14,7 @@
14
14
  #
15
15
 
16
16
  module MIDIator
17
- VERSION = "0.2.0"
17
+ VERSION = "0.3.0"
18
18
  end
19
19
 
20
20
  #####################################################################
@@ -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, "RubyMIDI", 0 )
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
@@ -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
@@ -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.2.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-10-29 00:00:00 -07:00
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.2.0
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.