beats 2.1.0 → 2.1.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.
Files changed (57) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE +2 -2
  3. data/README.markdown +17 -80
  4. data/bin/beats +2 -7
  5. data/lib/beats.rb +12 -6
  6. data/lib/beats/{audioengine.rb → audio_engine.rb} +7 -8
  7. data/lib/beats/{audioutils.rb → audio_utils.rb} +35 -17
  8. data/lib/beats/{beatsrunner.rb → beats_runner.rb} +2 -2
  9. data/lib/beats/kit.rb +6 -5
  10. data/lib/beats/kit_builder.rb +12 -8
  11. data/lib/beats/pattern.rb +7 -16
  12. data/lib/beats/song.rb +7 -8
  13. data/lib/beats/{songoptimizer.rb → song_optimizer.rb} +11 -8
  14. data/lib/beats/{songparser.rb → song_parser.rb} +46 -48
  15. data/lib/beats/track.rb +14 -17
  16. data/lib/beats/transforms/song_swinger.rb +7 -5
  17. data/lib/wavefile/{cachingwriter.rb → caching_writer.rb} +2 -2
  18. data/test/{audioengine_test.rb → audio_engine_test.rb} +49 -46
  19. data/test/audio_utils_test.rb +86 -0
  20. data/test/{cachingwriter_test.rb → caching_writer_test.rb} +0 -0
  21. data/test/fixtures/invalid/sound_in_kit_wrong_format.txt +1 -1
  22. data/test/fixtures/invalid/sound_in_track_wrong_format.txt +1 -1
  23. data/test/fixtures/valid/empty_kit.txt +14 -0
  24. data/test/fixtures/valid/example_song_header_different_capitalization.txt +21 -0
  25. data/test/fixtures/valid/multiple_patterns_same_name.txt +31 -0
  26. data/test/fixtures/valid/multiple_song_header_sections.txt +29 -0
  27. data/test/includes.rb +0 -9
  28. data/test/kit_builder_test.rb +20 -0
  29. data/test/kit_test.rb +7 -0
  30. data/test/pattern_test.rb +86 -74
  31. data/test/{songoptimizer_test.rb → song_optimizer_test.rb} +5 -8
  32. data/test/{songparser_test.rb → song_parser_test.rb} +109 -13
  33. data/test/song_swinger_test.rb +6 -4
  34. data/test/song_test.rb +32 -14
  35. data/test/sounds/agogo_high_stereo_16.wav +0 -0
  36. data/test/sounds/agogo_low_stereo_16.wav +0 -0
  37. data/test/sounds/bass2_stereo_16.wav +0 -0
  38. data/test/sounds/bass_stereo_16.wav +0 -0
  39. data/test/sounds/clave_high_stereo_16.wav +0 -0
  40. data/test/sounds/clave_low_stereo_16.wav +0 -0
  41. data/test/sounds/conga_high_stereo_16.wav +0 -0
  42. data/test/sounds/conga_low_stereo_16.wav +0 -0
  43. data/test/sounds/cowbell_high_stereo_16.wav +0 -0
  44. data/test/sounds/cowbell_low_stereo_16.wav +0 -0
  45. data/test/sounds/hh_closed_stereo_16.wav +0 -0
  46. data/test/sounds/hh_open_stereo_16.wav +0 -0
  47. data/test/sounds/ride_stereo_16.wav +0 -0
  48. data/test/sounds/rim_stereo_16.wav +0 -0
  49. data/test/sounds/snare2_stereo_16.wav +0 -0
  50. data/test/sounds/snare_stereo_16.wav +0 -0
  51. data/test/sounds/tom1_stereo_16.wav +0 -0
  52. data/test/sounds/tom2_stereo_16.wav +0 -0
  53. data/test/sounds/tom3_stereo_16.wav +0 -0
  54. data/test/sounds/tom4_stereo_16.wav +0 -0
  55. data/test/track_test.rb +51 -5
  56. metadata +184 -176
  57. 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
@@ -4,7 +4,7 @@ Song:
4
4
  Flow:
5
5
  - Verse: x1
6
6
  Kit:
7
- - bad: test/songparser_test.rb
7
+ - bad: test/song_test.rb
8
8
 
9
9
  Verse:
10
10
  - bad: X...X...
@@ -5,4 +5,4 @@ Song:
5
5
  - Verse: x1
6
6
 
7
7
  Verse:
8
- - test/songparser_test.rb: X...X...
8
+ - test/song_test.rb: X...X...
@@ -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
@@ -1,12 +1,3 @@
1
- # Standard Ruby libraries
2
1
  require 'minitest/autorun'
3
- require 'yaml'
4
- require 'rubygems'
5
-
6
- # External gems
7
- require 'wavefile'
8
-
9
- # BEATS classes
10
2
  require 'beats'
11
- require 'wavefile/cachingwriter'
12
3
  include Beats
@@ -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
 
@@ -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
@@ -10,17 +10,21 @@ class PatternTest < Minitest::Test
10
10
  pattern = Pattern.new :blank
11
11
  test_patterns[:blank] = pattern
12
12
 
13
- pattern = Pattern.new :verse
14
- pattern.track "bass.wav", "X...X...X...XX..X...X...XX..X..."
15
- pattern.track "snare.wav", "..X...X...X...X.X...X...X...X..."
16
- pattern.track "hh_closed.wav", "X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X."
17
- pattern.track "hh_open.wav", "X...............X..............X"
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
- pattern = Pattern.new :staircase
21
- pattern.track "bass.wav", "X..."
22
- pattern.track "snare.wav", "X.."
23
- pattern.track "hh_closed.wav", "X."
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
- pattern.track("my_sound2", "..X.........")
67
- assert_pattern_tracks(pattern, {"my_sound" => {name: "my_sound", rhythm: "X...X......."},
68
- "my_other_sound" => {name: "my_other_sound", rhythm: "X..........."},
69
- "my_sound2" => {name: "my_sound", rhythm: ".X.........."},
70
- "my_sound22" => {name: "my_sound2", rhythm: "..X........."}})
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 test_track_unique_name_already_taken
81
- pattern = Pattern.new("whatevs")
82
-
83
- assert_equal({}, pattern.tracks)
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.track("my_sound2", "X...X...")
86
- assert_pattern_tracks(pattern, {"my_sound2" => {name: "my_sound2", rhythm: "X...X..."}})
82
+ assert_raises(RuntimeError) { pattern.tracks["my_sound4"] = Track.new("my_sound4", "X...X...") }
83
+ end
87
84
 
88
- pattern.track("my_sound", "X.X.X.X.")
89
- assert_pattern_tracks(pattern, {"my_sound2" => {name: "my_sound2", rhythm: "X...X..."},
90
- "my_sound" => {name: "my_sound", rhythm: "X.X.X.X."}})
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
- left_pattern = Pattern.new("left")
109
- left_pattern.track("bass", "X...X...")
110
- left_pattern.track("snare", "..X...X.")
111
- left_pattern.track("hh_closed", "X.X.X.X.")
112
-
113
- right_pattern = Pattern.new("right")
114
- right_pattern.track("bass", "X...X...")
115
- right_pattern.track("snare", "..X...X.")
116
- right_pattern.track("hh_closed", "X.X.X.X.")
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
- right_pattern = Pattern.new("right")
122
- right_pattern.track("snare", "..X...X.")
123
- right_pattern.track("hh_closed", "X.X.X.X.")
124
- right_pattern.track("bass", "X...X...")
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
- different_names_pattern = Pattern.new("different_names")
130
- different_names_pattern.track("tom", "X...X...")
131
- different_names_pattern.track("cymbal", "..X...X.")
132
- different_names_pattern.track("hh_open", "X.X.X.X.")
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
- different_beats_pattern = Pattern.new("different_beats")
138
- different_beats_pattern.track("bass", "X...X...")
139
- different_beats_pattern.track("snare", "..X...X.")
140
- different_beats_pattern.track("hh_closed", "X.XXX.X.")
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
- something_extra = Pattern.new("something_extra")
146
- something_extra.track("bass", "X...X...")
147
- something_extra.track("snare", "..X...X.")
148
- something_extra.track("hh_closed", "X.X.X.X.")
149
- something_extra.track("extra", "X..X..X.")
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