jsound 0.1.0-java

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.
Files changed (51) hide show
  1. data/.yardopts +3 -0
  2. data/LICENSE.txt +27 -0
  3. data/README.md +96 -0
  4. data/Rakefile +19 -0
  5. data/examples/harmonizer.rb +25 -0
  6. data/examples/launchpad/launchpad.rb +65 -0
  7. data/examples/launchpad/launchpad_generator.rb +111 -0
  8. data/examples/list_devices.rb +6 -0
  9. data/examples/monitor.rb +15 -0
  10. data/examples/notes.rb +90 -0
  11. data/examples/transposer.rb +20 -0
  12. data/lib/jsound.rb +4 -0
  13. data/lib/jsound/convert.rb +30 -0
  14. data/lib/jsound/midi.rb +77 -0
  15. data/lib/jsound/midi/device.rb +72 -0
  16. data/lib/jsound/midi/device_list.rb +157 -0
  17. data/lib/jsound/midi/devices/generator.rb +22 -0
  18. data/lib/jsound/midi/devices/input_device.rb +51 -0
  19. data/lib/jsound/midi/devices/jdevice.rb +100 -0
  20. data/lib/jsound/midi/devices/monitor.rb +18 -0
  21. data/lib/jsound/midi/devices/output_device.rb +36 -0
  22. data/lib/jsound/midi/devices/recorder.rb +56 -0
  23. data/lib/jsound/midi/devices/repeater.rb +28 -0
  24. data/lib/jsound/midi/devices/transformer.rb +30 -0
  25. data/lib/jsound/midi/message.rb +165 -0
  26. data/lib/jsound/midi/message_builder.rb +52 -0
  27. data/lib/jsound/midi/messages/channel_pressure.rb +26 -0
  28. data/lib/jsound/midi/messages/control_change.rb +29 -0
  29. data/lib/jsound/midi/messages/note_off.rb +10 -0
  30. data/lib/jsound/midi/messages/note_on.rb +29 -0
  31. data/lib/jsound/midi/messages/pitch_bend.rb +43 -0
  32. data/lib/jsound/midi/messages/poly_pressure.rb +29 -0
  33. data/lib/jsound/midi/messages/program_change.rb +27 -0
  34. data/lib/jsound/type_from_class_name.rb +23 -0
  35. data/spec/jsound/convert_spec.rb +68 -0
  36. data/spec/jsound/midi/device_spec.rb +75 -0
  37. data/spec/jsound/midi/devices/generator_spec.rb +21 -0
  38. data/spec/jsound/midi/devices/output_device_spec.rb +22 -0
  39. data/spec/jsound/midi/devices/recorder_spec.rb +88 -0
  40. data/spec/jsound/midi/devices/repeater_device_spec.rb +19 -0
  41. data/spec/jsound/midi/devices/transformer_spec.rb +20 -0
  42. data/spec/jsound/midi/devlice_list_spec.rb +60 -0
  43. data/spec/jsound/midi/message_builder_spec.rb +22 -0
  44. data/spec/jsound/midi/message_spec.rb +30 -0
  45. data/spec/jsound/midi/messages/note_off_spec.rb +62 -0
  46. data/spec/jsound/midi/messages/note_on_spec.rb +109 -0
  47. data/spec/jsound/midi/messages/pitch_bend_spec.rb +88 -0
  48. data/spec/jsound/midi_spec.rb +33 -0
  49. data/spec/jsound/type_from_class_name_spec.rb +26 -0
  50. data/spec/spec_helper.rb +23 -0
  51. metadata +103 -0
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ module JSound::Midi::Devices
4
+ describe Repeater do
5
+
6
+ let(:repeater) { Repeater.new }
7
+ let(:output1) { mock 'device1' }
8
+ let(:output2) { mock 'device1' }
9
+
10
+ before { repeater >> [output1, output2] }
11
+
12
+ it "should pass all messages to its outputs" do
13
+ output1.should_receive(:message).once.with :the_message
14
+ output2.should_receive(:message).once.with :the_message
15
+ repeater.message :the_message
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+ module JSound::Midi
3
+ module Devices
4
+
5
+ describe Transformer do
6
+
7
+ describe "#message" do
8
+ it "transform the messages using the block passed to .new" do
9
+ transformer = Transformer.new{|message| message.pitch += 12; message }
10
+ output = mock 'device'
11
+ transformer >> output
12
+ output.should_receive(:message).once.with MessageBuilder.note_on(72,100)
13
+ transformer.message MessageBuilder.note_on(60,100)
14
+ end
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ module JSound::Midi
4
+
5
+ describe DeviceList do
6
+
7
+ let(:device1) { mock('device1', :description => 'Mock Device #1') }
8
+ let(:device2) { mock('device2', :description => 'Mock Device #2') }
9
+ let(:device3) { mock('device3', :description => 'Mock Device #3') }
10
+ let(:devices) { [device1,device2,device3] }
11
+ let(:device_list) { DeviceList.new devices }
12
+
13
+ describe '.new' do
14
+ it "constructs an empty device list with no arguments" do
15
+ DeviceList.new.should be_empty
16
+ end
17
+
18
+ it "constructs a list with the given arguments" do
19
+ DeviceList.new(devices).devices.should == devices
20
+ end
21
+ end
22
+
23
+ describe "#open" do
24
+ it "acts like #find and also opens the device" do
25
+ device2.should_receive :open
26
+ device_list.open(/Mock.*2/).should == device2
27
+ end
28
+
29
+ it "raises an error when no device is not found" do
30
+ lambda{ device_list.open(:nothing) }.should raise_error
31
+ end
32
+ end
33
+
34
+ describe "#/" do
35
+ it "finds and opens the first device matching a regexp constructed from the argument" do
36
+ device1.should_receive(:open)
37
+ (device_list/'Mock').should == device1
38
+ end
39
+
40
+ it "is case insensitive" do
41
+ device1.should_receive(:open)
42
+ (device_list/'mock').should == device1
43
+ end
44
+ end
45
+
46
+ describe "#method_missing" do
47
+ it "acts like #/ for unimplemented methods" do
48
+ device1.should_receive(:open)
49
+ device_list.mock.should == device1
50
+ end
51
+
52
+ it "treats '_' like a wildard" do
53
+ device2.should_receive(:open)
54
+ device_list.mock_2.should == device2
55
+ end
56
+
57
+ end
58
+
59
+ end
60
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ module JSound::Midi
4
+ describe MessageBuilder do
5
+
6
+ it 'should expose its methods as module functions' do
7
+ msg = MessageBuilder.note_on(60)
8
+ msg.type.should == :note_on
9
+ end
10
+
11
+ context 'with MessageBuilder included' do
12
+ include MessageBuilder
13
+
14
+ it 'should provide a set of methods for building midi messages' do
15
+ msg = note_on(60)
16
+ msg.type.should == :note_on
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ module JSound::Midi
4
+
5
+ describe Message do
6
+
7
+ let(:data) { [50,100]}
8
+ let(:channel) { 5 }
9
+ let(:message) { Message.new(data, channel) }
10
+
11
+ describe "#clone" do
12
+ it "constructs a new Message" do
13
+ message.clone.should_not be_equal message
14
+ end
15
+
16
+ it "constructs an equivalent Message" do
17
+ message.clone.should == message
18
+ end
19
+
20
+ it "constructs a new Message with the same data" do
21
+ message.clone.data.should == data
22
+ end
23
+
24
+ it "constructs a new Message with the same channel" do
25
+ message.clone.channel.should == channel
26
+ end
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+ module JSound::Midi::Messages
3
+
4
+ describe NoteOff do
5
+
6
+ let(:pitch) { 60 }
7
+ let(:velocity) { 100 }
8
+ let(:channel) { 3 }
9
+ let(:note_off) { NoteOff.new(pitch,velocity,channel) }
10
+
11
+ describe ".from_java" do
12
+ before do
13
+ @java_message = javax.sound.midi.ShortMessage.new
14
+ @java_message.setMessage(javax.sound.midi.ShortMessage::NOTE_OFF, channel, pitch, velocity)
15
+ end
16
+
17
+ it "constructs a new instance from a javax.sound.midi.ShortMessage" do
18
+ NoteOff.from_java(@java_message).should be_a NoteOff
19
+ end
20
+
21
+ it "extracts the pitch from the data1 byte" do
22
+ NoteOff.from_java(@java_message).pitch.should == pitch
23
+ end
24
+
25
+ it "extracts the velocity from the data2 byte" do
26
+ NoteOff.from_java(@java_message).velocity.should == velocity
27
+ end
28
+
29
+ it "extracts the channel" do
30
+ NoteOff.from_java(@java_message).channel.should == channel
31
+ end
32
+
33
+ it "creates an equal object when called with itself's #to_java" do
34
+ NoteOff.from_java(note_off.to_java).should == note_off
35
+ end
36
+ end
37
+
38
+ describe "#to_java" do
39
+ it "creates a javax.sound.midi.ShortMessage" do
40
+ note_off.to_java.should be_a javax.sound.midi.ShortMessage
41
+ end
42
+
43
+ it "creates a message with a note_off command" do
44
+ note_off.to_java.command.should == javax.sound.midi.ShortMessage::NOTE_OFF
45
+ end
46
+
47
+ it "creates a message with pitch in the data1 byte" do
48
+ note_off.to_java.data1.should == pitch
49
+ end
50
+
51
+ it "creates a message with velocity in the data2 byte" do
52
+ note_off.to_java.data2.should == velocity
53
+ end
54
+
55
+ it "creates a message with the given channel" do
56
+ note_off.to_java.channel.should == channel
57
+ end
58
+ end
59
+
60
+
61
+ end
62
+ end
@@ -0,0 +1,109 @@
1
+ require 'spec_helper'
2
+ module JSound::Midi::Messages
3
+
4
+ describe NoteOn do
5
+
6
+ let(:pitch) { 60 }
7
+ let(:velocity) { 100 }
8
+ let(:channel) { 3 }
9
+ let(:note_on) { NoteOn.new(pitch,velocity,channel) }
10
+
11
+ describe ".from_java" do
12
+ before do
13
+ @java_message = javax.sound.midi.ShortMessage.new
14
+ @java_message.setMessage(javax.sound.midi.ShortMessage::NOTE_ON, channel, pitch, velocity)
15
+ end
16
+
17
+ it "constructs a new instance from a javax.sound.midi.ShortMessage" do
18
+ NoteOn.from_java(@java_message).should be_a NoteOn
19
+ end
20
+
21
+ it "extracts the pitch from the data1 byte" do
22
+ NoteOn.from_java(@java_message).pitch.should == pitch
23
+ end
24
+
25
+ it "extracts the velocity from the data2 byte" do
26
+ NoteOn.from_java(@java_message).velocity.should == velocity
27
+ end
28
+
29
+ it "extracts the channel" do
30
+ NoteOn.from_java(@java_message).channel.should == channel
31
+ end
32
+
33
+ it "creates an equal object when called with itself's #to_java" do
34
+ NoteOn.from_java(note_on.to_java).should == note_on
35
+ end
36
+ end
37
+
38
+ describe "#to_java" do
39
+ it "creates a javax.sound.midi.ShortMessage" do
40
+ note_on.to_java.should be_a javax.sound.midi.ShortMessage
41
+ end
42
+
43
+ it "creates a message with a NOTE_ON command" do
44
+ note_on.to_java.command.should == javax.sound.midi.ShortMessage::NOTE_ON
45
+ end
46
+
47
+ it "creates a message with pitch in the data1 byte" do
48
+ note_on.to_java.data1.should == pitch
49
+ end
50
+
51
+ it "creates a message with velocity in the data2 byte" do
52
+ note_on.to_java.data2.should == velocity
53
+ end
54
+
55
+ it "creates a message with the given channel" do
56
+ note_on.to_java.channel.should == channel
57
+ end
58
+ end
59
+
60
+ describe "#pitch" do
61
+ it "is the pitch of the message" do
62
+ note_on.pitch.should == pitch
63
+ end
64
+
65
+ it "is the first data byte" do
66
+ note_on.pitch.should == note_on.data[0]
67
+ end
68
+ end
69
+
70
+ describe "#pitch=" do
71
+ it "sets the pitch of the message" do
72
+ pitch2 = pitch+1
73
+ note_on.pitch = pitch2
74
+ note_on.pitch.should == pitch2
75
+ end
76
+
77
+ it "causes the java_message (returned from #to_java) to be regenereated" do
78
+ pitch2 = pitch+1
79
+ note_on.pitch = pitch2
80
+ note_on.to_java.data1.should == pitch2
81
+ end
82
+ end
83
+
84
+ describe "#velocity" do
85
+ it "is the velocity of the message" do
86
+ note_on.velocity.should == velocity
87
+ end
88
+
89
+ it "is the second data byte" do
90
+ note_on.velocity.should == note_on.data[1]
91
+ end
92
+ end
93
+
94
+ describe "#velocity=" do
95
+ it "sets the velocity of the message" do
96
+ velocity2 = velocity+1
97
+ note_on.velocity = velocity2
98
+ note_on.velocity.should == velocity2
99
+ end
100
+
101
+ it "causes the java_message (returned from #to_java) to be regenereated" do
102
+ velocity2 = velocity+1
103
+ note_on.velocity = velocity2
104
+ note_on.to_java.data2.should == velocity2
105
+ end
106
+ end
107
+
108
+ end
109
+ end
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+ module JSound::Midi::Messages
3
+
4
+ describe PitchBend do
5
+
6
+ let(:value) { 1000 }
7
+ let(:lsb) { value & 127 }
8
+ let(:msb) { (value >> 7) & 127 }
9
+ let(:channel) { 4 }
10
+ let(:pitch_bend) { PitchBend.new(value,channel) }
11
+
12
+ describe ".from_java" do
13
+ before do
14
+ @java_message = javax.sound.midi.ShortMessage.new
15
+ @java_message.setMessage(javax.sound.midi.ShortMessage::PITCH_BEND, channel, lsb, msb)
16
+ end
17
+
18
+ it "constructs a new instance from a javax.sound.midi.ShortMessage" do
19
+ PitchBend.from_java(@java_message).should be_a PitchBend
20
+ end
21
+
22
+ it "extracts the 14-bit value from the 2 7-bit data bytes" do
23
+ pitch_bend = PitchBend.from_java(@java_message)
24
+ pitch_bend.value.should == value
25
+ end
26
+
27
+ it "extracts the channel" do
28
+ PitchBend.from_java(@java_message).channel.should == channel
29
+ end
30
+
31
+ it "creates an equal object when called with itself's #to_java" do
32
+ PitchBend.from_java(pitch_bend.to_java).should == pitch_bend
33
+ end
34
+
35
+ it "creates an object that returns the java message in response to #to_java" do
36
+ PitchBend.from_java(@java_message).to_java.should be_equal @java_message
37
+ end
38
+ end
39
+
40
+ describe "#to_java" do
41
+ it "creates a javax.sound.midi.ShortMessage" do
42
+ pitch_bend.to_java.should be_a javax.sound.midi.ShortMessage
43
+ end
44
+
45
+ it "creates a message with a PITCH_BEND command" do
46
+ pitch_bend.to_java.command.should == javax.sound.midi.ShortMessage::PITCH_BEND
47
+ end
48
+
49
+ it "creates a message with the least significant 7-bits in the data1 byte" do
50
+ pitch_bend.to_java.data1.should == lsb
51
+ end
52
+
53
+ it "creates a message with the most significant 7-bits in the data2 byte" do
54
+ pitch_bend.to_java.data2.should == msb
55
+ end
56
+
57
+ it "creates a message with the given channel" do
58
+ pitch_bend.to_java.channel.should == channel
59
+ end
60
+ end
61
+
62
+ describe "#value" do
63
+ it "is the value of the message" do
64
+ pitch_bend.value.should == value
65
+ end
66
+
67
+ it "is the 14-bit value of the message" do
68
+ pitch_bend.value.should == lsb + (msb << 7)
69
+ end
70
+ end
71
+
72
+ describe "#value=" do
73
+ it "sets the value" do
74
+ pitch_bend.value = 2000
75
+ pitch_bend.value.should == 2000
76
+ end
77
+
78
+ it "affects the java message" do
79
+ pitch_bend.value = 2000
80
+ java_message = pitch_bend.to_java
81
+ java_message.data1.should == 2000 & 127
82
+ java_message.data2.should == (2000 >> 7) & 127
83
+ end
84
+
85
+ end
86
+
87
+ end
88
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ module JSound
4
+ describe Midi do
5
+
6
+ # The spec doesn't care what MIDI devices are found,
7
+ # but it better find something or this library is not useful.
8
+
9
+ it 'should have DEVICES' do
10
+ Midi::DEVICES.should_not be_empty
11
+ end
12
+
13
+ it 'should have some INPUTS or OUTPUTS' do
14
+ (Midi::INPUTS.length + Midi::OUTPUTS.length).should > 1
15
+ end
16
+
17
+ context 'with Midi included' do
18
+ include Midi
19
+ describe '#refresh_devices' do
20
+ it 'should refresh the list of midi devices' do
21
+ Midi::DEVICES.clear
22
+ refresh_devices
23
+ Midi::DEVICES.should_not be_empty
24
+ end
25
+ end
26
+ end
27
+
28
+ it 'should expose #refresh_devices as a module function' do
29
+ Midi.refresh_devices
30
+ end
31
+
32
+ end
33
+ end