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.
@@ -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.