jsound 0.1.0-java
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +3 -0
- data/LICENSE.txt +27 -0
- data/README.md +96 -0
- data/Rakefile +19 -0
- data/examples/harmonizer.rb +25 -0
- data/examples/launchpad/launchpad.rb +65 -0
- data/examples/launchpad/launchpad_generator.rb +111 -0
- data/examples/list_devices.rb +6 -0
- data/examples/monitor.rb +15 -0
- data/examples/notes.rb +90 -0
- data/examples/transposer.rb +20 -0
- data/lib/jsound.rb +4 -0
- data/lib/jsound/convert.rb +30 -0
- data/lib/jsound/midi.rb +77 -0
- data/lib/jsound/midi/device.rb +72 -0
- data/lib/jsound/midi/device_list.rb +157 -0
- data/lib/jsound/midi/devices/generator.rb +22 -0
- data/lib/jsound/midi/devices/input_device.rb +51 -0
- data/lib/jsound/midi/devices/jdevice.rb +100 -0
- data/lib/jsound/midi/devices/monitor.rb +18 -0
- data/lib/jsound/midi/devices/output_device.rb +36 -0
- data/lib/jsound/midi/devices/recorder.rb +56 -0
- data/lib/jsound/midi/devices/repeater.rb +28 -0
- data/lib/jsound/midi/devices/transformer.rb +30 -0
- data/lib/jsound/midi/message.rb +165 -0
- data/lib/jsound/midi/message_builder.rb +52 -0
- data/lib/jsound/midi/messages/channel_pressure.rb +26 -0
- data/lib/jsound/midi/messages/control_change.rb +29 -0
- data/lib/jsound/midi/messages/note_off.rb +10 -0
- data/lib/jsound/midi/messages/note_on.rb +29 -0
- data/lib/jsound/midi/messages/pitch_bend.rb +43 -0
- data/lib/jsound/midi/messages/poly_pressure.rb +29 -0
- data/lib/jsound/midi/messages/program_change.rb +27 -0
- data/lib/jsound/type_from_class_name.rb +23 -0
- data/spec/jsound/convert_spec.rb +68 -0
- data/spec/jsound/midi/device_spec.rb +75 -0
- data/spec/jsound/midi/devices/generator_spec.rb +21 -0
- data/spec/jsound/midi/devices/output_device_spec.rb +22 -0
- data/spec/jsound/midi/devices/recorder_spec.rb +88 -0
- data/spec/jsound/midi/devices/repeater_device_spec.rb +19 -0
- data/spec/jsound/midi/devices/transformer_spec.rb +20 -0
- data/spec/jsound/midi/devlice_list_spec.rb +60 -0
- data/spec/jsound/midi/message_builder_spec.rb +22 -0
- data/spec/jsound/midi/message_spec.rb +30 -0
- data/spec/jsound/midi/messages/note_off_spec.rb +62 -0
- data/spec/jsound/midi/messages/note_on_spec.rb +109 -0
- data/spec/jsound/midi/messages/pitch_bend_spec.rb +88 -0
- data/spec/jsound/midi_spec.rb +33 -0
- data/spec/jsound/type_from_class_name_spec.rb +26 -0
- data/spec/spec_helper.rb +23 -0
- 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
|