diamond 0.5.1
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.
- checksums.yaml +7 -0
- data/LICENSE +13 -0
- data/README.md +126 -0
- data/lib/diamond.rb +35 -0
- data/lib/diamond/api.rb +102 -0
- data/lib/diamond/arpeggiator.rb +81 -0
- data/lib/diamond/clock.rb +88 -0
- data/lib/diamond/midi.rb +165 -0
- data/lib/diamond/osc.rb +102 -0
- data/lib/diamond/pattern.rb +95 -0
- data/lib/diamond/sequence.rb +178 -0
- data/lib/diamond/sequence_parameters.rb +164 -0
- data/test/api_test.rb +152 -0
- data/test/arpeggiator_test.rb +34 -0
- data/test/helper.rb +23 -0
- data/test/osc_test.rb +37 -0
- data/test/pattern_test.rb +63 -0
- data/test/sequence_parameters_test.rb +96 -0
- data/test/sequence_test.rb +36 -0
- metadata +222 -0
| @@ -0,0 +1,164 @@ | |
| 1 | 
            +
            module Diamond
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              # User-controller parameters that are used to formulate the note event sequence
         | 
| 4 | 
            +
              class SequenceParameters
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                RANGE = {
         | 
| 7 | 
            +
                  :gate => 1..500,
         | 
| 8 | 
            +
                  :interval => -48..48,
         | 
| 9 | 
            +
                  :pattern_offset => -16..16,
         | 
| 10 | 
            +
                  :range => 0..10,
         | 
| 11 | 
            +
                  :rate => 0..64,
         | 
| 12 | 
            +
                  :transpose => -64..64
         | 
| 13 | 
            +
                }
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                attr_reader :gate,
         | 
| 16 | 
            +
                  :interval,
         | 
| 17 | 
            +
                  :pattern,
         | 
| 18 | 
            +
                  :pattern_offset,
         | 
| 19 | 
            +
                  :range,
         | 
| 20 | 
            +
                  :rate,
         | 
| 21 | 
            +
                  :resolution
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                # @param [Sequence] sequence
         | 
| 24 | 
            +
                # @param [Fixnum] resolution
         | 
| 25 | 
            +
                # @param [Hash] options
         | 
| 26 | 
            +
                # @option options [Fixnum] :gate Duration of the arpeggiated notes. The value is a percentage based on the rate.  If the rate is 4, then a gate of 100 is equal to a quarter note. (default: 75). must be 1..500
         | 
| 27 | 
            +
                # @option options [Fixnum] :interval Increment (pattern) over (interval) scale degrees (range) times.  May be positive or negative. (default: 12)
         | 
| 28 | 
            +
                # @option options [Fixnum] :pattern_offset Begin on the nth note of the sequence (but not omit any notes). (default: 0)
         | 
| 29 | 
            +
                # @option options [String, Pattern] :pattern Computes the contour of the arpeggiated melody.  Can be the name of a pattern or a pattern object.
         | 
| 30 | 
            +
                # @option options [Fixnum] :range Increment the (pattern) over (interval) scale degrees (range) times. Must be positive (abs will be used). (default: 3)
         | 
| 31 | 
            +
                # @option options [Fixnum] :rate How fast the arpeggios will be played. Must be positive (abs will be used). (default: 8, eighth note.) must be 0..resolution
         | 
| 32 | 
            +
                # @param [Proc] callback
         | 
| 33 | 
            +
                def initialize(sequence, resolution, options = {}, &callback)
         | 
| 34 | 
            +
                  @transpose = 0
         | 
| 35 | 
            +
                  @resolution = resolution
         | 
| 36 | 
            +
                  @callback = callback
         | 
| 37 | 
            +
                  apply_options(options)
         | 
| 38 | 
            +
                  sequence.send(:use_parameters, self)
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                # Set the gate property
         | 
| 42 | 
            +
                # @param [Fixnum] num
         | 
| 43 | 
            +
                # @return [Fixnum]
         | 
| 44 | 
            +
                def gate=(num)
         | 
| 45 | 
            +
                  @gate = constrain(num, :range => RANGE[:gate])
         | 
| 46 | 
            +
                  mark_changed
         | 
| 47 | 
            +
                  @gate
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                # Set the interval property
         | 
| 51 | 
            +
                # @param [Fixnum] num
         | 
| 52 | 
            +
                # @param [Fixnum]
         | 
| 53 | 
            +
                def interval=(num)
         | 
| 54 | 
            +
                  @interval = num
         | 
| 55 | 
            +
                  mark_changed
         | 
| 56 | 
            +
                  @interval
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                # Set the pattern offset property
         | 
| 60 | 
            +
                # @param [Fixnum] num
         | 
| 61 | 
            +
                # @return [Fixnum]
         | 
| 62 | 
            +
                def pattern_offset=(num)
         | 
| 63 | 
            +
                  @pattern_offset = num
         | 
| 64 | 
            +
                  mark_changed
         | 
| 65 | 
            +
                  @pattern_offset
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                # Set the range property
         | 
| 69 | 
            +
                # @param [Fixnum] range
         | 
| 70 | 
            +
                # @return [Fixnum]
         | 
| 71 | 
            +
                def range=(num)
         | 
| 72 | 
            +
                  @range = constrain(num, :range => RANGE[:range])
         | 
| 73 | 
            +
                  mark_changed
         | 
| 74 | 
            +
                  @range
         | 
| 75 | 
            +
                end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                # Set the rate property
         | 
| 78 | 
            +
                # @param [Fixnum] num
         | 
| 79 | 
            +
                # @return [Fixnum]
         | 
| 80 | 
            +
                def rate=(num)
         | 
| 81 | 
            +
                  @rate = constrain(num, :range => RANGE[:rate].begin..@resolution)
         | 
| 82 | 
            +
                  mark_changed
         | 
| 83 | 
            +
                  @rate
         | 
| 84 | 
            +
                end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                # Set the pattern property
         | 
| 87 | 
            +
                # @param [Pattern] pattern
         | 
| 88 | 
            +
                # @return [Pattern]
         | 
| 89 | 
            +
                def pattern=(pattern)
         | 
| 90 | 
            +
                  @pattern = pattern
         | 
| 91 | 
            +
                  mark_changed
         | 
| 92 | 
            +
                  @pattern
         | 
| 93 | 
            +
                end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                # Transpose everything by the given number of scale degrees. Can be used as a getter
         | 
| 96 | 
            +
                # @param [Fixnum, nil] num
         | 
| 97 | 
            +
                # @return [Fixnum, nil]
         | 
| 98 | 
            +
                def transpose(num = nil)
         | 
| 99 | 
            +
                  @transpose = num unless num.nil?
         | 
| 100 | 
            +
                  mark_changed
         | 
| 101 | 
            +
                  @transpose      
         | 
| 102 | 
            +
                end
         | 
| 103 | 
            +
                alias_method :transpose=, :transpose
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                # The computed pattern given the sequence options
         | 
| 106 | 
            +
                # @return [Array<Fixnum>]
         | 
| 107 | 
            +
                def computed_pattern
         | 
| 108 | 
            +
                  @pattern.compute(@range, @interval)
         | 
| 109 | 
            +
                end
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                # The note duration given the sequence options
         | 
| 112 | 
            +
                # @return [Numeric]
         | 
| 113 | 
            +
                def duration
         | 
| 114 | 
            +
                  @resolution / @rate
         | 
| 115 | 
            +
                end
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                private
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                # Mark that there's been a change in the sequence
         | 
| 120 | 
            +
                def mark_changed
         | 
| 121 | 
            +
                  @callback.call
         | 
| 122 | 
            +
                end
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                # @param [Hash] options
         | 
| 125 | 
            +
                # @return [ArpeggiatorSequence::Parameters]
         | 
| 126 | 
            +
                def apply_options(options)
         | 
| 127 | 
            +
                  @interval = constrain((options[:interval] || 12), :range => RANGE[:interval])
         | 
| 128 | 
            +
                  @range = constrain((options[:range] || 3), :range => RANGE[:range])
         | 
| 129 | 
            +
                  @pattern_offset = constrain((options[:pattern_offset] || 0),:range => RANGE[:pattern_offset])
         | 
| 130 | 
            +
                  @rate = constrain((options[:rate] || 8), :range => 0..@resolution)
         | 
| 131 | 
            +
                  @gate = constrain((options[:gate] || 75), :range => RANGE[:gate])
         | 
| 132 | 
            +
                  @pattern = get_pattern(options[:pattern])
         | 
| 133 | 
            +
                  self
         | 
| 134 | 
            +
                end
         | 
| 135 | 
            +
             | 
| 136 | 
            +
                # Derive a pattern from the options or using the default
         | 
| 137 | 
            +
                # @param [Pattern, String, nil] option
         | 
| 138 | 
            +
                # @return [Pattern, nil]
         | 
| 139 | 
            +
                def get_pattern(option)
         | 
| 140 | 
            +
                  @pattern = case option
         | 
| 141 | 
            +
                             when Pattern then option
         | 
| 142 | 
            +
                             when String then Pattern.find(option)
         | 
| 143 | 
            +
                             end
         | 
| 144 | 
            +
                  @pattern ||= Pattern.first
         | 
| 145 | 
            +
                end
         | 
| 146 | 
            +
             | 
| 147 | 
            +
                # Constrain the given value based on the sequence options
         | 
| 148 | 
            +
                # @param [Numeric] value
         | 
| 149 | 
            +
                # @param [Hash] options
         | 
| 150 | 
            +
                # @option options [Numeric] :min
         | 
| 151 | 
            +
                # @option options [Numeric] :max
         | 
| 152 | 
            +
                # @option options [Range] :range
         | 
| 153 | 
            +
                # @return [Numeric]
         | 
| 154 | 
            +
                def constrain(value, options = {})
         | 
| 155 | 
            +
                  min = options[:range].nil? ? options[:min] : options[:range].begin
         | 
| 156 | 
            +
                  max = options[:range].nil? ? options[:max] : options[:range].end
         | 
| 157 | 
            +
                  new_value = value
         | 
| 158 | 
            +
                  new_value = min.nil? ? new_value : [new_value, min].max
         | 
| 159 | 
            +
                  new_value = max.nil? ? new_value : [new_value, max].min
         | 
| 160 | 
            +
                  new_value
         | 
| 161 | 
            +
                end
         | 
| 162 | 
            +
             | 
| 163 | 
            +
              end
         | 
| 164 | 
            +
            end
         | 
    
        data/test/api_test.rb
    ADDED
    
    | @@ -0,0 +1,152 @@ | |
| 1 | 
            +
            require "helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class Diamond::APITest < Test::Unit::TestCase
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              context "API" do
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                context "MIDI" do
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  context "#omni_on" do
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    setup do
         | 
| 12 | 
            +
                      @messages = [
         | 
| 13 | 
            +
                        MIDIMessage::NoteOn["C4"].new(10, 100),
         | 
| 14 | 
            +
                        MIDIMessage::NoteOn["C4"].new(3, 100),
         | 
| 15 | 
            +
                        MIDIMessage::NoteOn["C4"].new(2, 100)
         | 
| 16 | 
            +
                      ]
         | 
| 17 | 
            +
                      @arpeggiator = Diamond::Arpeggiator.new(:rx_channel => 3)
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    should "not acknowledge message with wrong rx channel" do
         | 
| 21 | 
            +
                      @arpeggiator.add(@messages[0])
         | 
| 22 | 
            +
                      assert_empty @arpeggiator.sequence.instance_variable_get("@input_queue")
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                    should "acknowledge message with rx channel" do
         | 
| 26 | 
            +
                      @arpeggiator.add(@messages[1])
         | 
| 27 | 
            +
                      @arpeggiator.sequence.instance_variable_get("@input_queue").expects(:concat).once.with([@messages[1]])
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    should "with omni on, acknowledge any rx channel" do
         | 
| 31 | 
            +
                      @arpeggiator.omni_on
         | 
| 32 | 
            +
                      @arpeggiator.add(@messages[2])
         | 
| 33 | 
            +
                      @arpeggiator.sequence.instance_variable_get("@input_queue").expects(:concat).once.with([@messages[2]]) 
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  context "#add_midi_source" do
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                    setup do
         | 
| 41 | 
            +
                      @input = $test_device[:input]
         | 
| 42 | 
            +
                      @arpeggiator = Diamond::Arpeggiator.new
         | 
| 43 | 
            +
                      refute @arpeggiator.midi_sources.include?(@input)
         | 
| 44 | 
            +
                    end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                    should "add a midi source" do
         | 
| 47 | 
            +
                      @arpeggiator.add_midi_source(@input)
         | 
| 48 | 
            +
                      assert_not_empty @arpeggiator.midi_sources
         | 
| 49 | 
            +
                      assert @arpeggiator.midi_sources.include?(@input)
         | 
| 50 | 
            +
                    end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                  context "#remove_midi_source" do
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                    setup do
         | 
| 57 | 
            +
                      @input = $test_device[:input]
         | 
| 58 | 
            +
                      @arpeggiator = Diamond::Arpeggiator.new
         | 
| 59 | 
            +
                      @arpeggiator.add_midi_source(@input)
         | 
| 60 | 
            +
                      assert_not_empty @arpeggiator.midi_sources
         | 
| 61 | 
            +
                      assert @arpeggiator.midi_sources.include?(@input)
         | 
| 62 | 
            +
                    end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                    should "remove a midi source" do
         | 
| 65 | 
            +
                      @arpeggiator.remove_midi_source(@input)
         | 
| 66 | 
            +
                      refute @arpeggiator.midi_sources.include?(@input)
         | 
| 67 | 
            +
                    end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                  end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                  context "#mute" do
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                    setup do
         | 
| 74 | 
            +
                      @arpeggiator = Diamond::Arpeggiator.new
         | 
| 75 | 
            +
                    end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                    should "mute the arpeggiator" do
         | 
| 78 | 
            +
                      refute @arpeggiator.muted?     
         | 
| 79 | 
            +
                      @arpeggiator.mute = true
         | 
| 80 | 
            +
                      assert @arpeggiator.muted?
         | 
| 81 | 
            +
                      @arpeggiator.mute = false
         | 
| 82 | 
            +
                      refute @arpeggiator.muted?
         | 
| 83 | 
            +
                      @arpeggiator.toggle_mute
         | 
| 84 | 
            +
                      assert @arpeggiator.muted?
         | 
| 85 | 
            +
                    end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                  end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                context "SequenceParameters" do
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                  setup do
         | 
| 94 | 
            +
                    @arpeggiator = Diamond::Arpeggiator.new
         | 
| 95 | 
            +
                  end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                  context "#rate=" do
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                    should "set the rate" do
         | 
| 100 | 
            +
                      assert_not_equal 16, @arpeggiator.rate
         | 
| 101 | 
            +
                      @arpeggiator.rate = 16
         | 
| 102 | 
            +
                      assert_equal 16, @arpeggiator.rate
         | 
| 103 | 
            +
                    end
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                  end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                  context "#range=" do
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                    should "set the range" do
         | 
| 110 | 
            +
                      @arpeggiator.range = 4
         | 
| 111 | 
            +
                      assert_equal 4, @arpeggiator.range
         | 
| 112 | 
            +
                      @arpeggiator.range += 1
         | 
| 113 | 
            +
                      assert_equal 5, @arpeggiator.range 
         | 
| 114 | 
            +
                    end
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                  end
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                  context "#interval=" do
         | 
| 119 | 
            +
             | 
| 120 | 
            +
                    should "set the interval" do
         | 
| 121 | 
            +
                      assert_not_equal 7, @arpeggiator.interval
         | 
| 122 | 
            +
                      @arpeggiator.interval = 7
         | 
| 123 | 
            +
                      assert_equal 7, @arpeggiator.interval 
         | 
| 124 | 
            +
                    end
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                  end
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                  context "#gate=" do
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                    should "set the gate" do
         | 
| 131 | 
            +
                      assert_not_equal 125, @arpeggiator.gate
         | 
| 132 | 
            +
                      @arpeggiator.gate = 125
         | 
| 133 | 
            +
                      assert_equal 125, @arpeggiator.gate 
         | 
| 134 | 
            +
                    end
         | 
| 135 | 
            +
             | 
| 136 | 
            +
                  end
         | 
| 137 | 
            +
             | 
| 138 | 
            +
                  context "#pattern_offset=" do
         | 
| 139 | 
            +
             | 
| 140 | 
            +
                    should "set the offset" do
         | 
| 141 | 
            +
                      assert_not_equal 5, @arpeggiator.pattern_offset
         | 
| 142 | 
            +
                      @arpeggiator.pattern_offset = 5
         | 
| 143 | 
            +
                      assert_equal 5, @arpeggiator.pattern_offset
         | 
| 144 | 
            +
                    end
         | 
| 145 | 
            +
             | 
| 146 | 
            +
                  end
         | 
| 147 | 
            +
             | 
| 148 | 
            +
                end
         | 
| 149 | 
            +
             | 
| 150 | 
            +
              end
         | 
| 151 | 
            +
             | 
| 152 | 
            +
            end
         | 
| @@ -0,0 +1,34 @@ | |
| 1 | 
            +
            require "helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class Diamond::ApeggiatorTest < Test::Unit::TestCase
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              context "Arpeggiator" do
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                context "#initialize" do
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  should "have defaults" do
         | 
| 10 | 
            +
                    @arpeggiator = Diamond::Arpeggiator.new
         | 
| 11 | 
            +
                    assert_equal 8, @arpeggiator.rate
         | 
| 12 | 
            +
                    assert_equal 3, @arpeggiator.range    
         | 
| 13 | 
            +
                    assert_equal 12, @arpeggiator.interval  
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  should "allow setting params" do
         | 
| 17 | 
            +
                    @arpeggiator = Diamond::Arpeggiator.new(:interval => 7, :range => 4, :rate => 16)
         | 
| 18 | 
            +
                    assert_equal 16, @arpeggiator.rate
         | 
| 19 | 
            +
                    assert_equal 4, @arpeggiator.range    
         | 
| 20 | 
            +
                    assert_equal 7, @arpeggiator.interval  
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  should "allow passing in input" do
         | 
| 24 | 
            +
                    @input = $test_device[:input]
         | 
| 25 | 
            +
                    @arpeggiator = Diamond::Arpeggiator.new(:midi => @input)
         | 
| 26 | 
            +
                    assert_not_empty @arpeggiator.midi_sources
         | 
| 27 | 
            +
                    assert @arpeggiator.midi_sources.include?(@input) 
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            end
         | 
    
        data/test/helper.rb
    ADDED
    
    | @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            dir = File.dirname(File.expand_path(__FILE__))
         | 
| 2 | 
            +
            $LOAD_PATH.unshift dir + "/../lib"
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            require "test/unit"
         | 
| 5 | 
            +
            require "mocha/test_unit"
         | 
| 6 | 
            +
            require "shoulda-context"
         | 
| 7 | 
            +
            require "diamond"
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            module TestHelper
         | 
| 10 | 
            +
              
         | 
| 11 | 
            +
              def self.select_devices
         | 
| 12 | 
            +
                $test_device ||= {}
         | 
| 13 | 
            +
                { :input => UniMIDI::Input, :output => UniMIDI::Output }.each do |type, klass|
         | 
| 14 | 
            +
                  $test_device[type] = klass.gets
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
                 
         | 
| 18 | 
            +
            end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            TestHelper.select_devices
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            # Stub out OSC networking
         | 
| 23 | 
            +
            ::EM.stubs(:run).returns(:true)
         | 
    
        data/test/osc_test.rb
    ADDED
    
    | @@ -0,0 +1,37 @@ | |
| 1 | 
            +
            require "helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class Diamond::OSCTest < Test::Unit::TestCase
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              context "OSC" do
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                context "#enable_parameter_control" do
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  setup do
         | 
| 10 | 
            +
                    @map = [
         | 
| 11 | 
            +
                     { :property => :interval, :address => "/1/rotaryA", :value => (0..1.0) },
         | 
| 12 | 
            +
                     { :property => :transpose, :address => "/1/rotaryB" }
         | 
| 13 | 
            +
                    ]
         | 
| 14 | 
            +
                    @addresses = @map.map { |mapping| mapping[:address] }
         | 
| 15 | 
            +
                    @osc = Diamond::OSC.new(:server_port => 8000)
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  should "start server" do
         | 
| 19 | 
            +
                    ::OSC::EMServer.any_instance.expects(:run).once
         | 
| 20 | 
            +
                    @osc.enable_parameter_control(Object.new, @map)
         | 
| 21 | 
            +
                    ::OSC::EMServer.any_instance.unstub(:run)
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  should "assign map" do
         | 
| 25 | 
            +
                    ::OSC::EMServer.any_instance.expects(:add_method).times(@map.size).with do |arg| 
         | 
| 26 | 
            +
                      assert @addresses.include?(arg)
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
                    @osc.enable_parameter_control(Object.new, @map)
         | 
| 29 | 
            +
                    ::OSC::EMServer.any_instance.unstub(:add_method)
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            end
         | 
| 37 | 
            +
             | 
| @@ -0,0 +1,63 @@ | |
| 1 | 
            +
            require "helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class PatternTest < Test::Unit::TestCase
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              context "Pattern" do
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                setup do
         | 
| 8 | 
            +
                  ::OSC::EMServer.any_instance.stubs(:run).returns(:true)
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                context "#initialize" do
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  should "create usable pattern" do
         | 
| 14 | 
            +
                    pattern = Diamond::Pattern.new("test") do |range, interval|
         | 
| 15 | 
            +
                      0.upto(range).map { |num| num * interval }
         | 
| 16 | 
            +
                    end
         | 
| 17 | 
            +
                    result = pattern.compute(2, 12)
         | 
| 18 | 
            +
                    assert_equal [0, 12, 24], result
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                context "#compute" do
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  should "reflect range and interval" do
         | 
| 26 | 
            +
                    pattern = Diamond::Pattern.find("Up")
         | 
| 27 | 
            +
                    result = pattern.compute(3, 7)
         | 
| 28 | 
            +
                    assert_equal 4, result.length
         | 
| 29 | 
            +
                    assert_equal [0, 7, 14, 21], result        
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
                context "Presets" do
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  should "populate Up" do
         | 
| 36 | 
            +
                    pattern = Diamond::Pattern.find("Up")
         | 
| 37 | 
            +
                    result = pattern.compute(2, 12)
         | 
| 38 | 
            +
                    assert_equal [0, 12, 24], result    
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  should "populate Down" do
         | 
| 42 | 
            +
                    pattern = Diamond::Pattern.find("Down")
         | 
| 43 | 
            +
                    result = pattern.compute(2, 12)
         | 
| 44 | 
            +
                    assert_equal [24, 12, 0], result  
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  should "populate UpDown" do
         | 
| 48 | 
            +
                    pattern = Diamond::Pattern.find("UpDown")
         | 
| 49 | 
            +
                    result = pattern.compute(3, 12)
         | 
| 50 | 
            +
                    assert_equal [0, 12, 24, 36, 24, 12, 0], result   
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                  should "populate DownUp" do
         | 
| 54 | 
            +
                    pattern = Diamond::Pattern.find("DownUp")
         | 
| 55 | 
            +
                    result = pattern.compute(3, 12)
         | 
| 56 | 
            +
                    assert_equal [36, 24, 12, 0, 12, 24, 36], result   
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
              end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
            end
         |