beats 2.1.0 → 2.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/LICENSE +2 -2
- data/README.markdown +17 -80
- data/bin/beats +2 -7
- data/lib/beats.rb +12 -6
- data/lib/beats/{audioengine.rb → audio_engine.rb} +7 -8
- data/lib/beats/{audioutils.rb → audio_utils.rb} +35 -17
- data/lib/beats/{beatsrunner.rb → beats_runner.rb} +2 -2
- data/lib/beats/kit.rb +6 -5
- data/lib/beats/kit_builder.rb +12 -8
- data/lib/beats/pattern.rb +7 -16
- data/lib/beats/song.rb +7 -8
- data/lib/beats/{songoptimizer.rb → song_optimizer.rb} +11 -8
- data/lib/beats/{songparser.rb → song_parser.rb} +46 -48
- data/lib/beats/track.rb +14 -17
- data/lib/beats/transforms/song_swinger.rb +7 -5
- data/lib/wavefile/{cachingwriter.rb → caching_writer.rb} +2 -2
- data/test/{audioengine_test.rb → audio_engine_test.rb} +49 -46
- data/test/audio_utils_test.rb +86 -0
- data/test/{cachingwriter_test.rb → caching_writer_test.rb} +0 -0
- data/test/fixtures/invalid/sound_in_kit_wrong_format.txt +1 -1
- data/test/fixtures/invalid/sound_in_track_wrong_format.txt +1 -1
- data/test/fixtures/valid/empty_kit.txt +14 -0
- data/test/fixtures/valid/example_song_header_different_capitalization.txt +21 -0
- data/test/fixtures/valid/multiple_patterns_same_name.txt +31 -0
- data/test/fixtures/valid/multiple_song_header_sections.txt +29 -0
- data/test/includes.rb +0 -9
- data/test/kit_builder_test.rb +20 -0
- data/test/kit_test.rb +7 -0
- data/test/pattern_test.rb +86 -74
- data/test/{songoptimizer_test.rb → song_optimizer_test.rb} +5 -8
- data/test/{songparser_test.rb → song_parser_test.rb} +109 -13
- data/test/song_swinger_test.rb +6 -4
- data/test/song_test.rb +32 -14
- data/test/sounds/agogo_high_stereo_16.wav +0 -0
- data/test/sounds/agogo_low_stereo_16.wav +0 -0
- data/test/sounds/bass2_stereo_16.wav +0 -0
- data/test/sounds/bass_stereo_16.wav +0 -0
- data/test/sounds/clave_high_stereo_16.wav +0 -0
- data/test/sounds/clave_low_stereo_16.wav +0 -0
- data/test/sounds/conga_high_stereo_16.wav +0 -0
- data/test/sounds/conga_low_stereo_16.wav +0 -0
- data/test/sounds/cowbell_high_stereo_16.wav +0 -0
- data/test/sounds/cowbell_low_stereo_16.wav +0 -0
- data/test/sounds/hh_closed_stereo_16.wav +0 -0
- data/test/sounds/hh_open_stereo_16.wav +0 -0
- data/test/sounds/ride_stereo_16.wav +0 -0
- data/test/sounds/rim_stereo_16.wav +0 -0
- data/test/sounds/snare2_stereo_16.wav +0 -0
- data/test/sounds/snare_stereo_16.wav +0 -0
- data/test/sounds/tom1_stereo_16.wav +0 -0
- data/test/sounds/tom2_stereo_16.wav +0 -0
- data/test/sounds/tom3_stereo_16.wav +0 -0
- data/test/sounds/tom4_stereo_16.wav +0 -0
- data/test/track_test.rb +51 -5
- metadata +184 -176
- data/test/audioutils_test.rb +0 -46
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'includes'
|
2
|
+
|
3
|
+
class AudioUtilsTest < Minitest::Test
|
4
|
+
def test_composite
|
5
|
+
assert_raises(ArgumentError) { AudioUtils.composite([[100, 200], [300, 400], [500, 600]], 0, 5) }
|
6
|
+
assert_raises(ArgumentError) { AudioUtils.composite([[100, 200], [300, 400], [500, 600]], -1, 5) }
|
7
|
+
|
8
|
+
# Mono empty arrays
|
9
|
+
assert_equal([], AudioUtils.composite([], 1))
|
10
|
+
assert_equal([], AudioUtils.composite([[]], 1))
|
11
|
+
assert_equal([], AudioUtils.composite([[], [], [], []], 1))
|
12
|
+
|
13
|
+
# Stereo empty arrays
|
14
|
+
assert_equal([], AudioUtils.composite([], 2))
|
15
|
+
assert_equal([], AudioUtils.composite([[]], 2))
|
16
|
+
assert_equal([], AudioUtils.composite([[], [], [], []], 2))
|
17
|
+
|
18
|
+
# Mono
|
19
|
+
assert_equal([10, 20, 30, 40], AudioUtils.composite([[10, 20, 30, 40]], 1))
|
20
|
+
assert_equal([10, 20, 30, 40], AudioUtils.composite([[10, 20, 30, 40], []], 1))
|
21
|
+
assert_equal([10, 20, 30, 40], AudioUtils.composite([[], [10, 20, 30, 40]], 1))
|
22
|
+
assert_equal([30, 50, 70, -10], AudioUtils.composite([[10, 20, 30, 40], [20, 30, 40, -50]], 1))
|
23
|
+
assert_equal([30, 50, 70, -10], AudioUtils.composite([[20, 30, 40, -50], [10, 20, 30, 40]], 1))
|
24
|
+
assert_equal([70, 80, 60], AudioUtils.composite([[20, 30], [10], [40, 50, 60]], 1))
|
25
|
+
assert_equal([70, 80, 60], AudioUtils.composite([[40, 50, 60], [20, 30], [10]], 1))
|
26
|
+
|
27
|
+
# Stereo
|
28
|
+
assert_equal([[10, 20], [30, 40]], AudioUtils.composite([[[10, 20], [30, 40]]], 2))
|
29
|
+
assert_equal([[10, 20], [30, 40]], AudioUtils.composite([[[10, 20], [30, 40]], []], 2))
|
30
|
+
assert_equal([[10, 20], [30, 40]], AudioUtils.composite([[], [[10, 20], [30, 40]]], 2))
|
31
|
+
assert_equal([[30, 50], [70, -10]], AudioUtils.composite([[[10, 20], [30, 40]], [[20, 30], [40, -50]]], 2))
|
32
|
+
assert_equal([[30, 50], [70, -10]], AudioUtils.composite([[[20, 30], [40, -50]], [[10, 20], [30, 40]]], 2))
|
33
|
+
assert_equal([[90, 120], [120, 140], [100, 110]], AudioUtils.composite([[[20, 30], [40, 50]], [[10, 20]], [[60, 70], [80, 90], [100, 110]]], 2))
|
34
|
+
assert_equal([[90, 120], [120, 140], [100, 110]], AudioUtils.composite([[[60, 70], [80, 90], [100, 110]], [[10, 20]], [[20, 30], [40, 50]]], 2))
|
35
|
+
|
36
|
+
# 3 Channel
|
37
|
+
assert_equal([[10, 20, 30], [30, 40, 50]], AudioUtils.composite([[[10, 20, 30], [30, 40, 50]]], 3))
|
38
|
+
assert_equal([[10, 20, 30], [30, 40, 50]], AudioUtils.composite([[[10, 20, 30], [30, 40, 50]], []], 3))
|
39
|
+
assert_equal([[10, 20, 30], [30, 40, 50]], AudioUtils.composite([[], [[10, 20, 30], [30, 40, 50]]], 3))
|
40
|
+
assert_equal([[30, 50, 70], [70, -10, -30]], AudioUtils.composite([[[10, 20, 30], [30, 40, 50]], [[20, 30, 40], [40, -50, -80]]], 3))
|
41
|
+
assert_equal([[30, 50, 70], [70, -10, -30]], AudioUtils.composite([[[20, 30, 40], [40, -50, -80]], [[10, 20, 30], [30, 40, 50]]], 3))
|
42
|
+
assert_equal([[90, 120, 150], [120, 140, 160], [100, 110, 120]], AudioUtils.composite([[[20, 30, 40], [40, 50, 60]],
|
43
|
+
[[10, 20, 30]],
|
44
|
+
[[60, 70, 80], [80, 90, 100], [100, 110, 120]]], 3))
|
45
|
+
assert_equal([[90, 120, 150], [120, 140, 160], [100, 110, 120]], AudioUtils.composite([[[60, 70, 80], [80, 90, 100], [100, 110, 120]],
|
46
|
+
[[10, 20, 30]],
|
47
|
+
[[20, 30, 40], [40, 50, 60]]], 3))
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_scale
|
51
|
+
assert_equal([], AudioUtils.scale([], 1, 5))
|
52
|
+
assert_equal([], AudioUtils.scale([], 2, 5))
|
53
|
+
assert_equal([100, 200, 300, 400, 500], AudioUtils.scale([100, 200, 300, 400, 500], 1, 1))
|
54
|
+
assert_equal([20, 40, 60, 80, 100], AudioUtils.scale([100, 200, 300, 400, 500], 1, 5))
|
55
|
+
|
56
|
+
assert_equal([[100, 200], [300, 400], [500, 600]], AudioUtils.scale([[100, 200], [300, 400], [500, 600]], 2, 1))
|
57
|
+
assert_equal([[20, 40], [60, 80], [100, 120]], AudioUtils.scale([[100, 200], [300, 400], [500, 600]], 2, 5))
|
58
|
+
|
59
|
+
assert_equal([[10, 20, 30], [100, 200, 300], [1000, 2000, 3000]], AudioUtils.scale([[10, 20, 30], [100, 200, 300], [1000, 2000, 3000]], 3, 1))
|
60
|
+
assert_equal([[5, 10, 15], [50, 100, 150], [500, 1000, 1500]], AudioUtils.scale([[10, 20, 30], [100, 200, 300], [1000, 2000, 3000]], 3, 2))
|
61
|
+
|
62
|
+
assert_raises(ArgumentError) { AudioUtils.scale([[100, 200], [300, 400], [500, 600]], 0, 5) }
|
63
|
+
assert_raises(ArgumentError) { AudioUtils.scale([[100, 200], [300, 400], [500, 600]], -1, 5) }
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_step_sample_length
|
67
|
+
assert_equal(6615.0, AudioUtils.step_sample_length(44100, 100))
|
68
|
+
assert_equal(3307.5, AudioUtils.step_sample_length(44100, 200))
|
69
|
+
assert_equal(3307.5, AudioUtils.step_sample_length(22050, 100))
|
70
|
+
|
71
|
+
assert_equal(6874.612880831729, AudioUtils.step_sample_length(44100, 96.2236))
|
72
|
+
assert_equal(3437.3064404158645, AudioUtils.step_sample_length(22050, 96.2236))
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_step_start_sample
|
76
|
+
assert_equal(0, AudioUtils.step_start_sample(0, 100))
|
77
|
+
assert_equal(100, AudioUtils.step_start_sample(1, 100))
|
78
|
+
assert_equal(200, AudioUtils.step_start_sample(2, 100))
|
79
|
+
assert_equal(1500, AudioUtils.step_start_sample(15, 100))
|
80
|
+
|
81
|
+
assert_equal(0, AudioUtils.step_start_sample(0, 64.8))
|
82
|
+
assert_equal(64, AudioUtils.step_start_sample(1, 64.8))
|
83
|
+
assert_equal(129, AudioUtils.step_start_sample(2, 64.8))
|
84
|
+
assert_equal(972, AudioUtils.step_start_sample(15, 64.8))
|
85
|
+
end
|
86
|
+
end
|
File without changes
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Song:
|
2
|
+
Tempo: 100
|
3
|
+
# Kit is defined, but has no sounds. This is valid.
|
4
|
+
Kit:
|
5
|
+
Flow:
|
6
|
+
- Verse: x2
|
7
|
+
- Chorus: x2
|
8
|
+
|
9
|
+
Verse:
|
10
|
+
- test/sounds/bass_mono_8.wav: X...X...
|
11
|
+
- test/sounds/snare_mono_8.wav: ..X...X.
|
12
|
+
Chorus:
|
13
|
+
- test/sounds/bass_mono_8.wav: XXXXXXXX
|
14
|
+
- test/sounds/snare_mono_8.wav: .X.X.X.X
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# The elements in the "Song" header have different capitalization from the normal examples
|
2
|
+
# The element keys should be case-insensitive, so this should be valid.
|
3
|
+
|
4
|
+
SONg:
|
5
|
+
TeMpO: 100
|
6
|
+
fLoW:
|
7
|
+
- Verse: x1
|
8
|
+
- Chorus: x2
|
9
|
+
- Verse: x1
|
10
|
+
- Chorus: x2
|
11
|
+
kIT:
|
12
|
+
- bass: test/sounds/bass_mono_8.wav
|
13
|
+
- snare: test/sounds/snare_mono_8.wav
|
14
|
+
|
15
|
+
Verse:
|
16
|
+
- bass: X...X...X...X...
|
17
|
+
- snare: ..............X.
|
18
|
+
|
19
|
+
Chorus:
|
20
|
+
- bass: X...X...XX..X...
|
21
|
+
- snare: ....X.......X...
|
@@ -0,0 +1,31 @@
|
|
1
|
+
Song:
|
2
|
+
Tempo: 120
|
3
|
+
Flow:
|
4
|
+
- Verse: x2
|
5
|
+
- Chorus: x2
|
6
|
+
- Verse: x2
|
7
|
+
- Chorus: x2
|
8
|
+
Kit:
|
9
|
+
- bass: test/sounds/bass_mono_8.wav
|
10
|
+
- snare: test/sounds/snare_mono_8.wav
|
11
|
+
- hh_closed: test/sounds/hh_closed_mono_8.wav
|
12
|
+
- agogo: test/sounds/agogo_high_mono_8.wav
|
13
|
+
|
14
|
+
# This pattern will be ignored because it is overridden by a different
|
15
|
+
# 'Verse' pattern later in the file.
|
16
|
+
Verse:
|
17
|
+
- bass: X...X...X...X...
|
18
|
+
- snare: ..............X.
|
19
|
+
- hh_closed: X.XXX.XX........
|
20
|
+
- hh_closed: ........X.X.X.X.
|
21
|
+
- agogo: ..............XX
|
22
|
+
|
23
|
+
Chorus:
|
24
|
+
- bass: X...X...XX..X...
|
25
|
+
- snare: ....X.......X...
|
26
|
+
|
27
|
+
# This is the winner, and should override the earlier 'Verse' definition
|
28
|
+
Verse:
|
29
|
+
- bass: X.X.X.X.
|
30
|
+
- snare: .X.X.X.X
|
31
|
+
- test/sounds/tom4_mono_8.wav: XXXXXX..
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# This song header is ignored, because it is overridden by a subsequent song
|
2
|
+
# header at the end of the file
|
3
|
+
Song:
|
4
|
+
Tempo: 100
|
5
|
+
Flow:
|
6
|
+
- Verse: x1
|
7
|
+
- Chorus: x2
|
8
|
+
- Verse: x1
|
9
|
+
- Chorus: x2
|
10
|
+
Kit:
|
11
|
+
- bass: test/sounds/bass_mono_8.wav
|
12
|
+
- snare: test/sounds/snare_mono_8.wav
|
13
|
+
|
14
|
+
Verse:
|
15
|
+
- bass: X...X...X...X...
|
16
|
+
- snare: ..............X.
|
17
|
+
|
18
|
+
Chorus:
|
19
|
+
- bass: X...X...XX..X...
|
20
|
+
- snare: ....X.......X...
|
21
|
+
|
22
|
+
# This is the actual song header that should be used
|
23
|
+
Song:
|
24
|
+
Tempo: 200
|
25
|
+
Flow:
|
26
|
+
- Chorus: x4
|
27
|
+
Kit:
|
28
|
+
- bass: test/sounds/ride_mono_8.wav
|
29
|
+
- snare: test/sounds/snare2_mono_8.wav
|
data/test/includes.rb
CHANGED
data/test/kit_builder_test.rb
CHANGED
@@ -12,6 +12,26 @@ class KitBuilderTest < Minitest::Test
|
|
12
12
|
assert_equal(false, kit_builder.has_label?("label2"))
|
13
13
|
end
|
14
14
|
|
15
|
+
def test_add_item
|
16
|
+
kit_builder = KitBuilder.new("test/sounds")
|
17
|
+
|
18
|
+
kit_builder.add_item("bass", "bass_mono_8.wav")
|
19
|
+
assert_equal({}, kit_builder.composite_replacements)
|
20
|
+
|
21
|
+
kit_builder.add_item("snare", ["snare_mono_8.wav", "rim_mono_8.wav"])
|
22
|
+
assert_equal({"snare" => ["snare-snare_mono_8", "snare-rim_mono_8"]}, kit_builder.composite_replacements)
|
23
|
+
|
24
|
+
# Re-adding the same label with different sounds replaces the value in `composite_replacments`
|
25
|
+
kit_builder.add_item("snare", ["hhclosed_mono_8.wav", "ride_mono_8.wav"])
|
26
|
+
assert_equal({"snare" => ["snare-hhclosed_mono_8", "snare-ride_mono_8"]}, kit_builder.composite_replacements)
|
27
|
+
|
28
|
+
# Re-adding the same label with a non-composite sounds removes the value from `composite_replacments`
|
29
|
+
kit_builder.add_item("snare", "snare_mono_8.wav")
|
30
|
+
assert_equal({}, kit_builder.composite_replacements)
|
31
|
+
|
32
|
+
assert_raises(KitBuilder::SoundFileNotFoundError) { kit_builder.add_item("bass", []) }
|
33
|
+
end
|
34
|
+
|
15
35
|
def test_build_kit_happy_path
|
16
36
|
kit_builder = KitBuilder.new("test/sounds")
|
17
37
|
|
data/test/kit_test.rb
CHANGED
@@ -4,6 +4,7 @@ class KitTest < Minitest::Test
|
|
4
4
|
def test_kit_with_items
|
5
5
|
kit = Kit.new({'label1' => [1,2,3], 'label2' => [4,5,6], 'label3' => [7,8,9]}, 1, 16)
|
6
6
|
|
7
|
+
assert_equal(["label1", "label2", "label3"], kit.labels)
|
7
8
|
assert_equal([1,2,3], kit.get_sample_data('label1'))
|
8
9
|
assert_equal([4,5,6], kit.get_sample_data('label2'))
|
9
10
|
assert_raises(Kit::LabelNotFoundError) { kit.get_sample_data('nope') }
|
@@ -12,16 +13,22 @@ class KitTest < Minitest::Test
|
|
12
13
|
|
13
14
|
def test_kit_with_no_items
|
14
15
|
kit = Kit.new({}, 1, 16)
|
16
|
+
|
17
|
+
assert_equal([], kit.labels)
|
15
18
|
assert_raises(Kit::LabelNotFoundError) { kit.get_sample_data('foo') }
|
16
19
|
end
|
17
20
|
|
18
21
|
def test_num_channels
|
19
22
|
kit = Kit.new({}, 2, 16)
|
23
|
+
|
24
|
+
assert_equal([], kit.labels)
|
20
25
|
assert_equal(2, kit.num_channels)
|
21
26
|
end
|
22
27
|
|
23
28
|
def test_bits_per_sample
|
24
29
|
kit = Kit.new({}, 2, 16)
|
30
|
+
|
31
|
+
assert_equal([], kit.labels)
|
25
32
|
assert_equal(16, kit.bits_per_sample)
|
26
33
|
end
|
27
34
|
end
|
data/test/pattern_test.rb
CHANGED
@@ -10,17 +10,21 @@ class PatternTest < Minitest::Test
|
|
10
10
|
pattern = Pattern.new :blank
|
11
11
|
test_patterns[:blank] = pattern
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
verse_tracks = [
|
14
|
+
Track.new("bass.wav", "X...X...X...XX..X...X...XX..X..."),
|
15
|
+
Track.new("snare.wav", "..X...X...X...X.X...X...X...X..."),
|
16
|
+
Track.new("hh_closed.wav", "X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X."),
|
17
|
+
Track.new("hh_open.wav", "X...............X..............X"),
|
18
|
+
]
|
19
|
+
pattern = Pattern.new(:verse, verse_tracks)
|
18
20
|
test_patterns[:verse] = pattern
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
staircase_tracks = [
|
23
|
+
Track.new("bass.wav", "X..."),
|
24
|
+
Track.new("snare.wav", "X.."),
|
25
|
+
Track.new("hh_closed.wav", "X."),
|
26
|
+
]
|
27
|
+
pattern = Pattern.new(:staircase, staircase_tracks)
|
24
28
|
test_patterns[:staircase] = pattern
|
25
29
|
|
26
30
|
test_patterns
|
@@ -40,36 +44,26 @@ class PatternTest < Minitest::Test
|
|
40
44
|
pattern = test_patterns[:staircase]
|
41
45
|
assert_equal(pattern.name, :staircase)
|
42
46
|
assert_equal(pattern.tracks.length, 3)
|
43
|
-
end
|
44
|
-
|
45
|
-
def test_track
|
46
|
-
pattern = Pattern.new("whatevs")
|
47
|
-
|
48
|
-
assert_equal({}, pattern.tracks)
|
49
|
-
|
50
|
-
pattern.track("my_sound", "X...X...")
|
51
|
-
assert_pattern_tracks(pattern, {"my_sound" => {name: "my_sound", rhythm: "X...X..."}})
|
52
|
-
|
53
|
-
# Rhythm is shorter than length of current longer rhythm, so should be made same length
|
54
|
-
pattern.track("my_other_sound", "X...")
|
55
|
-
assert_pattern_tracks(pattern, {"my_sound" => {name: "my_sound", rhythm: "X...X..."},
|
56
|
-
"my_other_sound" => {name: "my_other_sound", rhythm: "X......."}})
|
57
|
-
|
58
|
-
# Track has same name as previous track, and longer rhythm than previous tracks.
|
59
|
-
# Track should have expected name, but pattern key be unique.
|
60
|
-
# The rhythm of other existing tracks should be lengthened.
|
61
|
-
pattern.track("my_sound", ".X..........")
|
62
|
-
assert_pattern_tracks(pattern, {"my_sound" => {name: "my_sound", rhythm: "X...X......."},
|
63
|
-
"my_other_sound" => {name: "my_other_sound", rhythm: "X..........."},
|
64
|
-
"my_sound2" => {name: "my_sound", rhythm: ".X.........."}})
|
65
47
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
48
|
+
tracks = [
|
49
|
+
Track.new("track1", "X...X..."),
|
50
|
+
Track.new("track2", "X..."),
|
51
|
+
]
|
52
|
+
pattern = Pattern.new(:tracks_provided_in_constructor, tracks)
|
53
|
+
assert_equal(pattern.name, :tracks_provided_in_constructor)
|
54
|
+
assert_equal(pattern.tracks.length, 2)
|
55
|
+
assert_pattern_tracks(pattern, {"track1" => {name: "track1", rhythm: "X...X..."},
|
56
|
+
"track2" => {name: "track2", rhythm: "X......."}})
|
57
|
+
|
58
|
+
tracks = [
|
59
|
+
Track.new("my_sound", "X...X..."),
|
60
|
+
Track.new("my_other_sound", "X..."),
|
61
|
+
Track.new("my_sound", ".X.........."),
|
62
|
+
Track.new("my_sound2", "..X........."),
|
63
|
+
Track.new("my_sound", ".."),
|
64
|
+
]
|
65
|
+
pattern = Pattern.new("whatevs", tracks)
|
71
66
|
|
72
|
-
pattern.track("my_sound", "..")
|
73
67
|
assert_pattern_tracks(pattern, {"my_sound" => {name: "my_sound", rhythm: "X...X......."},
|
74
68
|
"my_other_sound" => {name: "my_other_sound", rhythm: "X..........."},
|
75
69
|
"my_sound2" => {name: "my_sound", rhythm: ".X.........."},
|
@@ -77,22 +71,28 @@ class PatternTest < Minitest::Test
|
|
77
71
|
"my_sound3" => {name: "my_sound", rhythm: "............"},})
|
78
72
|
end
|
79
73
|
|
80
|
-
def
|
81
|
-
|
82
|
-
|
83
|
-
|
74
|
+
def test_track_array_is_frozen
|
75
|
+
tracks = [
|
76
|
+
Track.new("my_sound1", "X...X..."),
|
77
|
+
Track.new("my_sound2", "X.X.X.X."),
|
78
|
+
Track.new("my_sound3", "XXXXXXXX"),
|
79
|
+
]
|
80
|
+
pattern = Pattern.new("whatevs", tracks)
|
84
81
|
|
85
|
-
pattern.
|
86
|
-
|
82
|
+
assert_raises(RuntimeError) { pattern.tracks["my_sound4"] = Track.new("my_sound4", "X...X...") }
|
83
|
+
end
|
87
84
|
|
88
|
-
|
89
|
-
|
90
|
-
|
85
|
+
def test_track_unique_name_already_taken
|
86
|
+
tracks = [
|
87
|
+
Track.new("my_sound2", "X...X..."),
|
88
|
+
Track.new("my_sound", "X.X.X.X."),
|
89
|
+
Track.new("my_sound", "XXXXXXXX"),
|
90
|
+
]
|
91
|
+
pattern = Pattern.new("whatevs", tracks)
|
91
92
|
|
92
|
-
# The first attempt at a unique name would be "my_sound2", but that is already taken
|
93
|
-
pattern.track("my_sound", "XXXXXXXX")
|
94
93
|
assert_pattern_tracks(pattern, {"my_sound2" => {name: "my_sound2", rhythm: "X...X..."},
|
95
94
|
"my_sound" => {name: "my_sound", rhythm: "X.X.X.X."},
|
95
|
+
# The first attempt at a unique name would be "my_sound2", but that is already taken
|
96
96
|
"my_sound3" => {name: "my_sound", rhythm: "XXXXXXXX"}})
|
97
97
|
end
|
98
98
|
|
@@ -105,48 +105,60 @@ class PatternTest < Minitest::Test
|
|
105
105
|
end
|
106
106
|
|
107
107
|
def test_same_tracks_as?
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
108
|
+
left_tracks = [
|
109
|
+
Track.new("bass", "X...X..."),
|
110
|
+
Track.new("snare", "..X...X."),
|
111
|
+
Track.new("hh_closed", "X.X.X.X."),
|
112
|
+
]
|
113
|
+
left_pattern = Pattern.new("left", left_tracks)
|
114
|
+
|
115
|
+
right_tracks = [
|
116
|
+
Track.new("bass", "X...X..."),
|
117
|
+
Track.new("snare", "..X...X."),
|
118
|
+
Track.new("hh_closed", "X.X.X.X."),
|
119
|
+
]
|
120
|
+
right_pattern = Pattern.new("right", right_tracks)
|
117
121
|
assert(left_pattern.same_tracks_as?(right_pattern))
|
118
122
|
assert(right_pattern.same_tracks_as?(left_pattern))
|
119
123
|
|
120
124
|
# Now switch up the order. Left and right should still be equal.
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
+
right_tracks = [
|
126
|
+
Track.new("snare", "..X...X."),
|
127
|
+
Track.new("hh_closed", "X.X.X.X."),
|
128
|
+
Track.new("bass", "X...X..."),
|
129
|
+
]
|
130
|
+
right_pattern = Pattern.new("right", right_tracks)
|
125
131
|
assert(left_pattern.same_tracks_as?(right_pattern))
|
126
132
|
assert(right_pattern.same_tracks_as?(left_pattern))
|
127
133
|
|
128
134
|
# Now compare the pattern with same rhythms but different track names. Should not be equal.
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
135
|
+
different_names_tracks = [
|
136
|
+
Track.new("tom", "X...X..."),
|
137
|
+
Track.new("cymbal", "..X...X."),
|
138
|
+
Track.new("hh_open", "X.X.X.X."),
|
139
|
+
]
|
140
|
+
different_names_pattern = Pattern.new("different_names", different_names_tracks)
|
133
141
|
assert_equal(false, left_pattern.same_tracks_as?(different_names_pattern))
|
134
142
|
assert_equal(false, different_names_pattern.same_tracks_as?(left_pattern))
|
135
143
|
|
136
144
|
# Now compare the pattern with same track names but different rhythms. Should not be equal.
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
145
|
+
different_beats_tracks = [
|
146
|
+
Track.new("bass", "X...X..."),
|
147
|
+
Track.new("snare", "..X...X."),
|
148
|
+
Track.new("hh_closed", "X.XXX.X."),
|
149
|
+
]
|
150
|
+
different_beats_pattern = Pattern.new("different_beats", different_beats_tracks)
|
141
151
|
assert_equal(false, left_pattern.same_tracks_as?(different_beats_pattern))
|
142
152
|
assert_equal(false, different_beats_pattern.same_tracks_as?(left_pattern))
|
143
153
|
|
144
154
|
# Now compare a pattern with the same tracks, but with one extra one as well. Should not be equal.
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
155
|
+
something_extra_tracks = [
|
156
|
+
Track.new("bass", "X...X..."),
|
157
|
+
Track.new("snare", "..X...X."),
|
158
|
+
Track.new("hh_closed", "X.X.X.X."),
|
159
|
+
Track.new("extra", "X..X..X."),
|
160
|
+
]
|
161
|
+
something_extra = Pattern.new("something_extra", something_extra_tracks)
|
150
162
|
assert_equal(false, left_pattern.same_tracks_as?(something_extra))
|
151
163
|
assert_equal(false, something_extra.same_tracks_as?(left_pattern))
|
152
164
|
end
|