beats 1.2.0 → 1.2.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 (69) hide show
  1. data/LICENSE +1 -1
  2. data/README.markdown +28 -10
  3. data/bin/beats +9 -7
  4. data/lib/audioengine.rb +172 -0
  5. data/lib/audioutils.rb +73 -0
  6. data/lib/beats.rb +14 -15
  7. data/lib/beatswavefile.rb +17 -37
  8. data/lib/kit.rb +148 -71
  9. data/lib/pattern.rb +20 -117
  10. data/lib/patternexpander.rb +111 -0
  11. data/lib/song.rb +78 -132
  12. data/lib/songoptimizer.rb +29 -33
  13. data/lib/songparser.rb +70 -45
  14. data/lib/track.rb +11 -82
  15. data/test/audioengine_test.rb +261 -0
  16. data/test/audioutils_test.rb +45 -0
  17. data/test/fixtures/expected_output/example_split_mono_16-hh_closed.wav +0 -0
  18. data/test/{examples/split-agogo_high.wav → fixtures/expected_output/example_split_mono_16-hh_closed2.wav} +0 -0
  19. data/test/fixtures/expected_output/example_split_mono_8-hh_closed.wav +0 -0
  20. data/test/{examples/split-tom4.wav → fixtures/expected_output/example_split_mono_8-hh_closed2.wav} +0 -0
  21. data/test/fixtures/expected_output/example_split_stereo_16-hh_closed.wav +0 -0
  22. data/test/fixtures/expected_output/example_split_stereo_16-hh_closed2.wav +0 -0
  23. data/test/fixtures/expected_output/example_split_stereo_8-hh_closed.wav +0 -0
  24. data/test/fixtures/expected_output/example_split_stereo_8-hh_closed2.wav +0 -0
  25. data/test/fixtures/invalid/{bad_structure.txt → bad_flow.txt} +2 -2
  26. data/test/fixtures/invalid/bad_repeat_count.txt +1 -1
  27. data/test/fixtures/invalid/bad_rhythm.txt +1 -1
  28. data/test/fixtures/invalid/bad_tempo.txt +1 -1
  29. data/test/fixtures/invalid/{no_structure.txt → no_flow.txt} +1 -1
  30. data/test/fixtures/invalid/pattern_with_no_tracks.txt +1 -1
  31. data/test/fixtures/invalid/sound_in_kit_not_found.txt +1 -1
  32. data/test/fixtures/invalid/sound_in_kit_wrong_format.txt +10 -0
  33. data/test/fixtures/invalid/sound_in_track_not_found.txt +1 -1
  34. data/test/fixtures/invalid/sound_in_track_wrong_format.txt +8 -0
  35. data/test/fixtures/invalid/template.txt +1 -1
  36. data/test/fixtures/valid/example_mono_16.txt +5 -3
  37. data/test/fixtures/valid/example_mono_8.txt +5 -3
  38. data/test/fixtures/valid/example_no_kit.txt +1 -1
  39. data/test/fixtures/valid/example_stereo_16.txt +7 -4
  40. data/test/fixtures/valid/example_stereo_8.txt +5 -3
  41. data/test/fixtures/valid/example_with_empty_track.txt +1 -1
  42. data/test/fixtures/valid/example_with_kit.txt +1 -1
  43. data/test/fixtures/valid/multiple_tracks_same_sound.txt +33 -0
  44. data/test/fixtures/valid/no_tempo.txt +1 -1
  45. data/test/fixtures/valid/optimize_pattern_collision.txt +28 -0
  46. data/test/fixtures/valid/pattern_with_overflow.txt +1 -1
  47. data/test/fixtures/valid/repeats_not_specified.txt +2 -2
  48. data/test/fixtures/valid/with_structure.txt +10 -0
  49. data/test/fixtures/yaml/song_yaml.txt +5 -5
  50. data/test/includes.rb +4 -2
  51. data/test/integration.rb +3 -3
  52. data/test/kit_test.rb +136 -109
  53. data/test/pattern_test.rb +31 -131
  54. data/test/patternexpander_test.rb +142 -0
  55. data/test/song_test.rb +104 -102
  56. data/test/songoptimizer_test.rb +52 -38
  57. data/test/songparser_test.rb +79 -46
  58. data/test/sounds/composite_snare_mono_8_tom3_mono_16_mono_16.wav +0 -0
  59. data/test/sounds/composite_snare_mono_8_tom3_mono_8_mono_16.wav +0 -0
  60. data/test/sounds/composite_snare_stereo_16_tom3_mono_16_stereo_16.wav +0 -0
  61. data/test/sounds/composite_snare_stereo_8_tom3_mono_16_stereo_16.wav +0 -0
  62. data/test/track_test.rb +30 -185
  63. metadata +56 -24
  64. data/lib/songsplitter.rb +0 -38
  65. data/test/examples/combined.wav +0 -0
  66. data/test/examples/split-bass.wav +0 -0
  67. data/test/examples/split-hh_closed.wav +0 -0
  68. data/test/examples/split-snare.wav +0 -0
  69. data/test/examples/split-tom2.wav +0 -0
@@ -7,28 +7,22 @@ class PatternTest < Test::Unit::TestCase
7
7
  SECONDS_IN_MINUTE = 60.0
8
8
 
9
9
  def generate_test_data
10
- kit = Kit.new("test/sounds")
11
- kit.add("bass.wav", "bass_mono_8.wav")
12
- kit.add("snare.wav", "snare_mono_8.wav")
13
- kit.add("hh_closed.wav", "hh_closed_mono_8.wav")
14
- kit.add("hh_open.wav", "hh_open_mono_8.wav")
15
-
16
10
  test_patterns = {}
17
11
 
18
12
  pattern = Pattern.new :blank
19
13
  test_patterns[:blank] = pattern
20
14
 
21
15
  pattern = Pattern.new :verse
22
- pattern.track "bass.wav", kit.get_sample_data("bass.wav"), "X...X...X...XX..X...X...XX..X..."
23
- pattern.track "snare.wav", kit.get_sample_data("snare.wav"), "..X...X...X...X.X...X...X...X..."
24
- pattern.track "hh_closed.wav", kit.get_sample_data("hh_closed.wav"), "X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X."
25
- pattern.track "hh_open.wav", kit.get_sample_data("hh_open.wav"), "X...............X..............X"
16
+ pattern.track "bass.wav", "X...X...X...XX..X...X...XX..X..."
17
+ pattern.track "snare.wav", "..X...X...X...X.X...X...X...X..."
18
+ pattern.track "hh_closed.wav", "X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X."
19
+ pattern.track "hh_open.wav", "X...............X..............X"
26
20
  test_patterns[:verse] = pattern
27
21
 
28
22
  pattern = Pattern.new :staircase
29
- pattern.track "bass.wav", kit.get_sample_data("bass.wav"), "X..."
30
- pattern.track "snare.wav", kit.get_sample_data("snare.wav"), "X.."
31
- pattern.track "hh_closed.wav", kit.get_sample_data("hh_closed.wav"), "X."
23
+ pattern.track "bass.wav", "X..."
24
+ pattern.track "snare.wav", "X.."
25
+ pattern.track "hh_closed.wav", "X."
32
26
  test_patterns[:staircase] = pattern
33
27
 
34
28
  return test_patterns
@@ -50,152 +44,58 @@ class PatternTest < Test::Unit::TestCase
50
44
  assert_equal(pattern.tracks.length, 3)
51
45
  end
52
46
 
53
- def test_sample_length
54
- test_patterns = generate_test_data()
55
-
56
- tick_sample_length = 13860.0
57
- assert_equal(test_patterns[:blank].sample_length(tick_sample_length), 0)
58
- assert_equal(test_patterns[:verse].sample_length(tick_sample_length), tick_sample_length * 32)
59
- assert_equal(test_patterns[:staircase].sample_length(tick_sample_length), tick_sample_length * 4)
60
-
61
- tick_sample_length = 6681.81818181818
62
- assert_equal(test_patterns[:blank].sample_length(tick_sample_length), 0)
63
- assert_equal(test_patterns[:verse].sample_length(tick_sample_length), (tick_sample_length * 32).floor)
64
- assert_equal(test_patterns[:staircase].sample_length(tick_sample_length), (tick_sample_length * 4).floor)
65
-
66
- tick_sample_length = 16134.1463414634
67
- assert_equal(test_patterns[:blank].sample_length(tick_sample_length), 0)
68
- assert_equal(test_patterns[:verse].sample_length(tick_sample_length), (tick_sample_length * 32).floor)
69
- assert_equal(test_patterns[:staircase].sample_length(tick_sample_length), (tick_sample_length * 4).floor)
70
- end
71
-
72
- def test_tick_count
47
+ def test_step_count
73
48
  test_patterns = generate_test_data()
74
49
 
75
- assert_equal(0, test_patterns[:blank].tick_count())
76
- assert_equal(32, test_patterns[:verse].tick_count())
77
- assert_equal(4, test_patterns[:staircase].tick_count())
50
+ assert_equal(0, test_patterns[:blank].step_count())
51
+ assert_equal(32, test_patterns[:verse].step_count())
52
+ assert_equal(4, test_patterns[:staircase].step_count())
78
53
  end
79
54
 
80
55
  def test_same_tracks_as?
81
56
  left_pattern = Pattern.new("left")
82
- left_pattern.track("bass", nil, "X...X...")
83
- left_pattern.track("snare", nil, "..X...X.")
84
- left_pattern.track("hh_closed", nil, "X.X.X.X.")
57
+ left_pattern.track("bass", "X...X...")
58
+ left_pattern.track("snare", "..X...X.")
59
+ left_pattern.track("hh_closed", "X.X.X.X.")
85
60
 
86
61
  right_pattern = Pattern.new("right")
87
- right_pattern.track("bass", nil, "X...X...")
88
- right_pattern.track("snare", nil, "..X...X.")
89
- right_pattern.track("hh_closed", nil, "X.X.X.X.")
62
+ right_pattern.track("bass", "X...X...")
63
+ right_pattern.track("snare", "..X...X.")
64
+ right_pattern.track("hh_closed", "X.X.X.X.")
90
65
  assert(left_pattern.same_tracks_as?(right_pattern))
91
66
  assert(right_pattern.same_tracks_as?(left_pattern))
92
67
 
93
68
  # Now switch up the order. Left and right should still be equal.
94
69
  right_pattern = Pattern.new("right")
95
- right_pattern.track("snare", nil, "..X...X.")
96
- right_pattern.track("hh_closed", nil, "X.X.X.X.")
97
- right_pattern.track("bass", nil, "X...X...")
70
+ right_pattern.track("snare", "..X...X.")
71
+ right_pattern.track("hh_closed", "X.X.X.X.")
72
+ right_pattern.track("bass", "X...X...")
98
73
  assert(left_pattern.same_tracks_as?(right_pattern))
99
74
  assert(right_pattern.same_tracks_as?(left_pattern))
100
75
 
101
76
  # Now compare the pattern with same rhythms but different track names. Should not be equal.
102
77
  different_names_pattern = Pattern.new("different_names")
103
- different_names_pattern.track("tom", nil, "X...X...")
104
- different_names_pattern.track("cymbal", nil, "..X...X.")
105
- different_names_pattern.track("hh_open", nil, "X.X.X.X.")
78
+ different_names_pattern.track("tom", "X...X...")
79
+ different_names_pattern.track("cymbal", "..X...X.")
80
+ different_names_pattern.track("hh_open", "X.X.X.X.")
106
81
  assert_equal(false, left_pattern.same_tracks_as?(different_names_pattern))
107
82
  assert_equal(false, different_names_pattern.same_tracks_as?(left_pattern))
108
83
 
109
84
  # Now compare the pattern with same track names but different rhythms. Should not be equal.
110
85
  different_beats_pattern = Pattern.new("different_beats")
111
- different_beats_pattern.track("bass", nil, "X...X...")
112
- different_beats_pattern.track("snare", nil, "..X...X.")
113
- different_beats_pattern.track("hh_closed", nil, "X.XXX.X.")
86
+ different_beats_pattern.track("bass", "X...X...")
87
+ different_beats_pattern.track("snare", "..X...X.")
88
+ different_beats_pattern.track("hh_closed", "X.XXX.X.")
114
89
  assert_equal(false, left_pattern.same_tracks_as?(different_beats_pattern))
115
90
  assert_equal(false, different_beats_pattern.same_tracks_as?(left_pattern))
116
91
 
117
92
  # Now compare a pattern with the same tracks, but with one extra one as well. Should not be equal.
118
93
  something_extra = Pattern.new("something_extra")
119
- something_extra.track("bass", nil, "X...X...")
120
- something_extra.track("snare", nil, "..X...X.")
121
- something_extra.track("hh_closed", nil, "X.X.X.X.")
122
- something_extra.track("extra", nil, "X..X..X.")
94
+ something_extra.track("bass", "X...X...")
95
+ something_extra.track("snare", "..X...X.")
96
+ something_extra.track("hh_closed", "X.X.X.X.")
97
+ something_extra.track("extra", "X..X..X.")
123
98
  assert_equal(false, left_pattern.same_tracks_as?(something_extra))
124
99
  assert_equal(false, something_extra.same_tracks_as?(left_pattern))
125
100
  end
126
-
127
- def test_sample_data
128
- tick_sample_lengths = [
129
- 13860.0,
130
- (SAMPLE_RATE * SECONDS_IN_MINUTE) / 200 / 4, # 3307.50
131
- (SAMPLE_RATE * SECONDS_IN_MINUTE) / 99 / 4 # 6681.81818181818
132
- ]
133
-
134
- tick_sample_lengths.each{|tick_sample_length| helper_test_sample_data(tick_sample_length) }
135
- end
136
-
137
- def helper_test_sample_data(tick_sample_length)
138
-
139
- test_patterns = generate_test_data()
140
-
141
- # Combined
142
- test_patterns.each{|pattern_name, test_pattern|
143
- sample_data = test_pattern.sample_data(tick_sample_length, 1, test_pattern.tracks.length, {})
144
- assert_equal(sample_data.class, Hash)
145
- assert_equal(sample_data.keys.map{|key| key.to_s}.sort, ["overflow", "primary"])
146
-
147
- primary_sample_length = test_pattern.sample_length(tick_sample_length)
148
- full_sample_length = test_pattern.sample_length_with_overflow(tick_sample_length)
149
- assert_equal(sample_data[:primary].length, primary_sample_length)
150
- assert_equal(sample_data[:overflow].length, test_pattern.tracks.length)
151
- sample_data[:overflow].values.each do |track_overflow|
152
- assert_equal(track_overflow.class, Array)
153
- end
154
- # To do: add test to verify that longest overflow == full_sample_length - primary_sample_length
155
- }
156
- end
157
-
158
- def find_longest_overflow(overflow)
159
- longest_overflow = overflow.keys.first
160
- overflow.keys.each do |name|
161
- if(overflow[name].length > overflow[longest_overflow].length)
162
- longest_overflow = name
163
- end
164
- end
165
-
166
- return longest_overflow
167
- end
168
-
169
- # Test scenario where incoming overflow for a track not in the pattern is longer than the pattern itself.
170
- # In this situation, the the overflow should continue into the outgoing overflow so it is handled in the
171
- # next pattern.
172
- def test_sample_data_incoming_overflow_longer_than_pattern_length
173
- # bass.wav sample length: 6179
174
- # snare.wav sample length: 14700
175
- kit = Kit.new("test/sounds")
176
- kit.add("bass", "bass_mono_8.wav")
177
- kit.add("snare", "snare_mono_8.wav")
178
- bass_sample_data = kit.get_sample_data("bass")
179
- snare_sample_data = kit.get_sample_data("snare")
180
- tick_sample_length = bass_sample_data.length.to_f
181
-
182
- # Construct expected
183
- expected_primary_sample_data = Array.new(bass_sample_data.length)
184
- bass_sample_data.length.times do |i|
185
- expected_primary_sample_data[i] = ((bass_sample_data[i] + snare_sample_data[i]) / 2).round
186
- end
187
- expected_overflow_sample_data = snare_sample_data[bass_sample_data.length...snare_sample_data.length]
188
-
189
- # Get actual
190
- pattern = Pattern.new :verse
191
- pattern.track "bass", bass_sample_data, "X"
192
- actual_sample_data = pattern.sample_data(tick_sample_length, 1, 2, {"snare" => snare_sample_data})
193
-
194
- assert_equal(Hash, actual_sample_data.class)
195
- assert_equal(["overflow", "primary"], actual_sample_data.keys.map{|key| key.to_s}.sort)
196
- assert_equal(expected_primary_sample_data, actual_sample_data[:primary])
197
- assert_equal(["bass", "snare"], actual_sample_data[:overflow].keys.sort)
198
- assert_equal([], actual_sample_data[:overflow]["bass"])
199
- assert_equal(expected_overflow_sample_data, actual_sample_data[:overflow]["snare"])
200
- end
201
- end
101
+ end
@@ -0,0 +1,142 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
2
+
3
+ require 'test/includes'
4
+
5
+ class PatternExpanderTest < Test::Unit::TestCase
6
+ def test_expand_pattern_no_repeats
7
+ expected_pattern = Pattern.new :verse
8
+ expected_pattern.track "bass", "X...X.X."
9
+ expected_pattern.track "snare", "....X..."
10
+
11
+ # All of these should result in no expansion, since there are no repeats.
12
+ # In other words, the pattern shouldn't change.
13
+ # TODO: Add test for when flow is longer than longest track in pattern
14
+ ["", "|----|----|", "|----", "----:-:1"].each do |flow|
15
+ actual_pattern = Pattern.new :verse
16
+ actual_pattern.track "bass", "|X...|X.X.|"
17
+ actual_pattern.track "snare", "|....|X...|"
18
+ actual_pattern = PatternExpander.expand_pattern(flow, actual_pattern)
19
+ assert(expected_pattern.same_tracks_as?(actual_pattern))
20
+ end
21
+ end
22
+
23
+ def test_expand_pattern_single_repeats
24
+ expected_pattern = Pattern.new :verse
25
+ expected_pattern.track "bass", "X...X.X.X...X.X."
26
+ expected_pattern.track "snare", "....X.......X..."
27
+
28
+ ["|----|---:|", "|----|---:2|", ":------:"].each do |flow|
29
+ actual_pattern = Pattern.new :verse
30
+ actual_pattern.track "bass", "|X...|X.X.|"
31
+ actual_pattern.track "snare", "|....|X...|"
32
+ actual_pattern = PatternExpander.expand_pattern(flow, actual_pattern)
33
+ assert(expected_pattern.same_tracks_as?(actual_pattern))
34
+ end
35
+
36
+
37
+ expected_pattern = Pattern.new :verse
38
+ expected_pattern.track "bass", "X...X.X.X.X.X.X.X.X...X."
39
+ expected_pattern.track "snare", "....X...X...X...X...XXXX"
40
+
41
+ ["|----|:-:4|----|"].each do |flow|
42
+ actual_pattern = Pattern.new :verse
43
+ actual_pattern.track "bass", "|X...|X.X.|..X.|"
44
+ actual_pattern.track "snare", "|....|X...|XXXX|"
45
+ actual_pattern = PatternExpander.expand_pattern(flow, actual_pattern)
46
+ assert(expected_pattern.same_tracks_as?(actual_pattern))
47
+ end
48
+
49
+
50
+ # Zero repeats, so section gets removed from pattern
51
+ expected_pattern = Pattern.new :verse
52
+ expected_pattern.track "bass", "X.....X."
53
+ expected_pattern.track "snare", "....XXXX"
54
+
55
+ ["|----|:-:0|----|"].each do |flow|
56
+ actual_pattern = Pattern.new :verse
57
+ actual_pattern.track "bass", "|X...|X.X.|..X.|"
58
+ actual_pattern.track "snare", "|....|X...|XXXX|"
59
+ actual_pattern = PatternExpander.expand_pattern(flow, actual_pattern)
60
+ assert(expected_pattern.same_tracks_as?(actual_pattern))
61
+ end
62
+ end
63
+
64
+ def test_expand_pattern_multiple_repeats
65
+ expected_pattern = Pattern.new :verse
66
+ expected_pattern.track "bass", "X...X...X.X.X.X."
67
+ expected_pattern.track "snare", "........X...X..."
68
+
69
+ [":--::--:", ":-:2:--:", ":-:2:-:2"].each do |flow|
70
+ actual_pattern = Pattern.new :verse
71
+ actual_pattern.track "bass", "|X...|X.X.|"
72
+ actual_pattern.track "snare", "|....|X...|"
73
+ actual_pattern = PatternExpander.expand_pattern(flow, actual_pattern)
74
+ assert(expected_pattern.same_tracks_as?(actual_pattern))
75
+ end
76
+
77
+
78
+ expected_pattern = Pattern.new :verse
79
+ expected_pattern.track "bass", "X...X.X.X.X.X.X..XXX..XX.."
80
+ expected_pattern.track "snare", "....X...X...X...X...XX..XX"
81
+
82
+ ["----:-:3--:--:", "|----|:-:3|--|:-:2|"].each do |flow|
83
+ actual_pattern = Pattern.new :verse
84
+ actual_pattern.track "bass", "|X...|X.X.|.X|XX..|"
85
+ actual_pattern.track "snare", "|....|X...|X.|..XX|"
86
+ actual_pattern = PatternExpander.expand_pattern(flow, actual_pattern)
87
+ assert(expected_pattern.same_tracks_as?(actual_pattern))
88
+ end
89
+ end
90
+
91
+ def test_expand_pattern_invalid
92
+ pattern = Pattern.new :verse
93
+ pattern.track "bass", "|X...|X.X.|"
94
+ pattern.track "snare", "|....|X...|"
95
+
96
+ # Patterns with an invalid character
97
+ ["a", "|---!---|", "|....|....|"].each do |invalid_flow|
98
+ assert_raise(InvalidFlowError) do
99
+ PatternExpander.expand_pattern(invalid_flow, pattern)
100
+ end
101
+ end
102
+
103
+ ["----4:--", ":-:-:4-:", ":4-:-:-:"].each do |invalid_flow|
104
+ assert_raise(InvalidFlowError) do
105
+ PatternExpander.expand_pattern(invalid_flow, pattern)
106
+ end
107
+ end
108
+ end
109
+
110
+ def test_valid_flow?
111
+ # Contains nothing but :, always valid
112
+ assert_equal(true, PatternExpander.valid_flow?(""))
113
+ assert_equal(true, PatternExpander.valid_flow?(":"))
114
+ assert_equal(true, PatternExpander.valid_flow?("::"))
115
+ assert_equal(true, PatternExpander.valid_flow?(":::"))
116
+ assert_equal(true, PatternExpander.valid_flow?("::::"))
117
+ assert_equal(true, PatternExpander.valid_flow?("|:--:|----|:--:|"))
118
+
119
+ # Contains characters other than :|- and [0-9]
120
+ assert_equal(false, PatternExpander.valid_flow?("a"))
121
+ assert_equal(false, PatternExpander.valid_flow?("1"))
122
+ assert_equal(false, PatternExpander.valid_flow?(":--:z---"))
123
+ assert_equal(false, PatternExpander.valid_flow?(": :"))
124
+
125
+ assert_equal(true, PatternExpander.valid_flow?(":0"))
126
+ assert_equal(true, PatternExpander.valid_flow?(":1"))
127
+ assert_equal(true, PatternExpander.valid_flow?(":4"))
128
+ assert_equal(true, PatternExpander.valid_flow?(":4"))
129
+ assert_equal(true, PatternExpander.valid_flow?(":16"))
130
+ assert_equal(true, PatternExpander.valid_flow?("::4"))
131
+ assert_equal(true, PatternExpander.valid_flow?(":::4"))
132
+ assert_equal(true, PatternExpander.valid_flow?(":2::4"))
133
+ assert_equal(true, PatternExpander.valid_flow?("::2::4"))
134
+
135
+ assert_equal(false, PatternExpander.valid_flow?(":4:"))
136
+ assert_equal(false, PatternExpander.valid_flow?("::4:"))
137
+ assert_equal(false, PatternExpander.valid_flow?(":4:4"))
138
+ assert_equal(false, PatternExpander.valid_flow?("::2:4"))
139
+ assert_equal(false, PatternExpander.valid_flow?("::2:"))
140
+ assert_equal(false, PatternExpander.valid_flow?("::2:::"))
141
+ end
142
+ end
@@ -3,42 +3,38 @@ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
3
3
  require 'test/includes'
4
4
 
5
5
  class SongTest < Test::Unit::TestCase
6
- DEFAULT_TEMPO = 120
7
-
6
+ FIXTURES = [:repeats_not_specified,
7
+ :pattern_with_overflow,
8
+ :example_no_kit,
9
+ :example_with_kit]
10
+
8
11
  def generate_test_data
9
- kit = Kit.new("test/sounds")
10
- kit.add("bass.wav", "bass_mono_8.wav")
11
- kit.add("snare.wav", "snare_mono_8.wav")
12
- kit.add("hh_closed.wav", "hh_closed_mono_8.wav")
13
- kit.add("ride.wav", "ride_mono_8.wav")
14
-
15
12
  test_songs = {}
16
13
  base_path = File.dirname(__FILE__) + "/.."
17
14
 
18
- test_songs[:blank] = Song.new(base_path)
19
-
20
- test_songs[:no_structure] = Song.new(base_path)
21
- verse = test_songs[:no_structure].pattern :verse
22
- verse.track "bass.wav", kit.get_sample_data("bass.wav"), "X.......X......."
23
- verse.track "snare.wav", kit.get_sample_data("snare.wav"), "....X.......X..."
24
- verse.track "hh_closed.wav", kit.get_sample_data("hh_closed.wav"), "X.X.X.X.X.X.X.X."
25
-
26
- test_songs[:repeats_not_specified] = SongParser.new().parse(base_path, YAML.load_file("test/fixtures/valid/repeats_not_specified.txt"))
27
- test_songs[:overflow] = SongParser.new().parse(base_path, YAML.load_file("test/fixtures/valid/pattern_with_overflow.txt"))
28
- test_songs[:from_valid_yaml_string] = SongParser.new().parse(base_path, YAML.load_file("test/fixtures/valid/example_no_kit.txt"))
29
- test_songs[:from_valid_yaml_string_with_kit] = SongParser.new().parse(base_path, YAML.load_file("test/fixtures/valid/example_with_kit.txt"))
30
-
31
- test_songs[:from_code] = Song.new(base_path)
15
+ test_songs[:blank] = Song.new()
16
+
17
+ test_songs[:no_flow] = Song.new()
18
+ verse = test_songs[:no_flow].pattern :verse
19
+ verse.track "bass.wav", "X.......X......."
20
+ verse.track "snare.wav", "....X.......X..."
21
+ verse.track "hh_closed.wav", "X.X.X.X.X.X.X.X."
22
+
23
+ song_parser = SongParser.new()
24
+ FIXTURES.each do |fixture_name|
25
+ test_songs[fixture_name], throwaway_kit = song_parser.parse(base_path, File.read("test/fixtures/valid/#{fixture_name}.txt"))
26
+ end
27
+
28
+ test_songs[:from_code] = Song.new()
32
29
  verse = test_songs[:from_code].pattern :verse
33
- verse.track "bass.wav", kit.get_sample_data("bass.wav"), "X.......X......."
34
- verse.track "snare.wav", kit.get_sample_data("snare.wav"), "....X.......X..."
35
- verse.track "hh_closed.wav", kit.get_sample_data("hh_closed.wav"), "X.X.X.X.X.X.X.X."
30
+ verse.track "bass.wav", "X.......X......."
31
+ verse.track "snare.wav", "....X.......X..."
32
+ verse.track "hh_closed.wav", "X.X.X.X.X.X.X.X."
36
33
  chorus = test_songs[:from_code].pattern :chorus
37
- chorus.track "bass.wav", kit.get_sample_data("bass.wav"), "X......."
38
- chorus.track "snare.wav", kit.get_sample_data("snare.wav"), "....X..X"
39
- chorus.track "ride.wav", kit.get_sample_data("ride.wav"), "X.....X."
40
- test_songs[:from_code].structure = [:verse, :chorus, :verse, :chorus, :chorus]
41
- test_songs[:from_code].kit = kit
34
+ chorus.track "bass.wav", "X......."
35
+ chorus.track "snare.wav", "....X..X"
36
+ chorus.track "ride.wav", "X.....X."
37
+ test_songs[:from_code].flow = [:verse, :chorus, :verse, :chorus, :chorus]
42
38
 
43
39
  return test_songs
44
40
  end
@@ -46,119 +42,125 @@ class SongTest < Test::Unit::TestCase
46
42
  def test_initialize
47
43
  test_songs = generate_test_data()
48
44
 
49
- assert_equal([], test_songs[:blank].structure)
50
- assert_equal((Song::SAMPLE_RATE * Song::SECONDS_PER_MINUTE) / DEFAULT_TEMPO / 4.0,
51
- test_songs[:blank].tick_sample_length)
52
-
53
- assert_equal([], test_songs[:no_structure].structure)
54
- assert_equal((Song::SAMPLE_RATE * Song::SECONDS_PER_MINUTE) / DEFAULT_TEMPO / 4.0,
55
- test_songs[:no_structure].tick_sample_length)
56
-
57
- assert_equal([:verse, :chorus, :verse, :chorus, :chorus], test_songs[:from_code].structure)
58
- assert_equal((Song::SAMPLE_RATE * Song::SECONDS_PER_MINUTE) / DEFAULT_TEMPO / 4.0,
59
- test_songs[:from_code].tick_sample_length)
45
+ assert_equal([], test_songs[:blank].flow)
46
+ assert_equal([], test_songs[:no_flow].flow)
47
+ assert_equal([:verse, :chorus, :verse, :chorus, :chorus], test_songs[:from_code].flow)
60
48
  end
61
49
 
62
50
  def test_total_tracks
63
51
  test_songs = generate_test_data()
64
52
 
65
53
  assert_equal(0, test_songs[:blank].total_tracks)
66
- assert_equal(3, test_songs[:no_structure].total_tracks)
54
+ assert_equal(3, test_songs[:no_flow].total_tracks)
67
55
  assert_equal(3, test_songs[:from_code].total_tracks)
68
56
  assert_equal(1, test_songs[:repeats_not_specified].total_tracks)
69
- assert_equal(1, test_songs[:overflow].total_tracks)
70
- assert_equal(5, test_songs[:from_valid_yaml_string].total_tracks)
57
+ assert_equal(1, test_songs[:pattern_with_overflow].total_tracks)
58
+ assert_equal(5, test_songs[:example_no_kit].total_tracks)
59
+ assert_equal(5, test_songs[:example_with_kit].total_tracks)
71
60
  end
72
61
 
73
62
  def test_track_names
74
63
  test_songs = generate_test_data()
75
64
 
76
65
  assert_equal([], test_songs[:blank].track_names)
77
- assert_equal(["bass.wav", "hh_closed.wav", "snare.wav"], test_songs[:no_structure].track_names)
66
+ assert_equal(["bass.wav", "hh_closed.wav", "snare.wav"], test_songs[:no_flow].track_names)
78
67
  assert_equal(["bass.wav", "hh_closed.wav", "ride.wav", "snare.wav"], test_songs[:from_code].track_names)
79
68
  assert_equal(["test/sounds/bass_mono_8.wav"], test_songs[:repeats_not_specified].track_names)
80
- assert_equal(["test/sounds/snare_mono_8.wav"], test_songs[:overflow].track_names)
69
+ assert_equal(["test/sounds/snare_mono_8.wav"], test_songs[:pattern_with_overflow].track_names)
81
70
  assert_equal(["test/sounds/bass_mono_8.wav",
82
71
  "test/sounds/hh_closed_mono_8.wav",
83
72
  "test/sounds/hh_open_mono_8.wav",
84
73
  "test/sounds/ride_mono_8.wav",
85
74
  "test/sounds/snare_mono_8.wav"],
86
- test_songs[:from_valid_yaml_string].track_names)
75
+ test_songs[:example_no_kit].track_names)
76
+ assert_equal(["bass",
77
+ "hhclosed",
78
+ "hhopen",
79
+ "snare",
80
+ "test/sounds/hh_closed_mono_8.wav",
81
+ "test/sounds/ride_mono_8.wav"],
82
+ test_songs[:example_with_kit].track_names)
87
83
  end
88
84
 
89
- def test_sample_length
85
+ def test_copy_ignoring_patterns_and_flow
90
86
  test_songs = generate_test_data()
91
-
92
- assert_equal(0, test_songs[:blank].sample_length)
93
- assert_equal(0, test_songs[:no_structure].sample_length)
87
+ original_song = test_songs[:example_no_kit]
88
+ cloned_song = original_song.copy_ignoring_patterns_and_flow()
94
89
 
95
- assert_equal((test_songs[:from_code].tick_sample_length * 16 * 2) +
96
- (test_songs[:from_code].tick_sample_length * 8 * 3),
97
- test_songs[:from_code].sample_length)
98
-
99
- assert_equal(test_songs[:repeats_not_specified].tick_sample_length,
100
- test_songs[:repeats_not_specified].sample_length)
101
-
102
- assert_equal(test_songs[:overflow].tick_sample_length * 8, test_songs[:overflow].sample_length)
90
+ assert_not_equal(cloned_song, original_song)
91
+ assert_equal(cloned_song.tempo, original_song.tempo)
92
+ assert_equal([], cloned_song.flow)
93
+ assert_equal({}, cloned_song.patterns)
103
94
  end
104
95
 
105
- def test_sample_length_with_overflow
96
+ def test_remove_patterns_except
97
+ # Remove an existing pattern.
106
98
  test_songs = generate_test_data()
107
-
108
- assert_equal(0, test_songs[:blank].sample_length_with_overflow)
109
- assert_equal(0, test_songs[:no_structure].sample_length_with_overflow)
110
-
111
- snare_overflow =
112
- (test_songs[:from_code].kit.get_sample_data("snare.wav").length -
113
- test_songs[:from_code].tick_sample_length).ceil
114
- assert_equal(test_songs[:from_code].sample_length + snare_overflow, test_songs[:from_code].sample_length_with_overflow)
115
-
116
- assert_equal(test_songs[:repeats_not_specified].tick_sample_length,
117
- test_songs[:repeats_not_specified].sample_length_with_overflow)
118
-
119
- snare_overflow =
120
- (test_songs[:overflow].kit.get_sample_data("test/sounds/snare_mono_8.wav").length -
121
- test_songs[:overflow].tick_sample_length).ceil
122
- assert_equal((test_songs[:overflow].tick_sample_length * 8) + snare_overflow,
123
- test_songs[:overflow].sample_length_with_overflow)
124
-
125
- snare_overflow =
126
- (test_songs[:from_valid_yaml_string].kit.get_sample_data("test/sounds/snare_mono_8.wav").length -
127
- test_songs[:from_valid_yaml_string].tick_sample_length).ceil
128
- assert_equal(test_songs[:from_valid_yaml_string].sample_length + snare_overflow,
129
- test_songs[:from_valid_yaml_string].sample_length_with_overflow)
99
+ test_songs[:example_with_kit].remove_patterns_except(:chorus)
100
+ assert_equal([:chorus], test_songs[:example_with_kit].flow)
101
+ assert_equal([:chorus], test_songs[:example_with_kit].patterns.keys)
102
+
103
+ # Try to remove a non-existent pattern. Error city.
104
+ test_songs = generate_test_data()
105
+ assert_raise(StandardError) do
106
+ test_songs[:example_with_kit].remove_patterns_except(:iamnotapattern)
107
+ end
130
108
  end
131
-
132
- def test_copy_ignoring_patterns_and_structure
109
+
110
+ def test_split
133
111
  test_songs = generate_test_data()
134
- original_song = test_songs[:from_valid_yaml_string]
135
- cloned_song = original_song.copy_ignoring_patterns_and_structure()
112
+ split_songs = test_songs[:example_with_kit].split()
136
113
 
137
- assert_not_equal(cloned_song, original_song)
138
- assert_equal(cloned_song.tempo, original_song.tempo)
139
- assert_equal(cloned_song.kit, original_song.kit)
140
- assert_equal(cloned_song.tick_sample_length, original_song.tick_sample_length)
141
- assert_equal([], cloned_song.structure)
142
- assert_equal({}, cloned_song.patterns)
114
+ assert_equal(Hash, split_songs.class)
115
+ assert_equal(6, split_songs.length)
116
+
117
+ song_names = split_songs.keys.sort
118
+ assert_equal(["bass",
119
+ "hhclosed",
120
+ "hhopen",
121
+ "snare",
122
+ "test/sounds/hh_closed_mono_8.wav",
123
+ "test/sounds/ride_mono_8.wav"],
124
+ song_names)
125
+
126
+ song_names.each do |song_name|
127
+ song = split_songs[song_name]
128
+ assert_equal(99, song.tempo)
129
+ assert_equal(3, song.patterns.length)
130
+ assert_equal([:verse, :verse, :chorus, :chorus, :verse, :verse, :chorus, :chorus, :chorus, :chorus,
131
+ :bridge, :chorus, :chorus, :chorus, :chorus],
132
+ song.flow)
133
+
134
+ song.patterns.each do |pattern_name, pattern|
135
+ assert_equal(1, pattern.tracks.length)
136
+ assert_equal([song_name], pattern.tracks.keys)
137
+ assert_equal(song_name, pattern.tracks[song_name].name)
138
+ end
139
+ end
143
140
  end
144
141
 
145
142
  def test_remove_unused_patterns
146
143
  test_songs = generate_test_data()
147
144
 
148
- assert_equal(1, test_songs[:no_structure].patterns.length)
149
- test_songs[:no_structure].remove_unused_patterns()
150
- assert_equal({}, test_songs[:no_structure].patterns)
145
+ assert_equal(1, test_songs[:no_flow].patterns.length)
146
+ test_songs[:no_flow].remove_unused_patterns()
147
+ assert_equal({}, test_songs[:no_flow].patterns)
151
148
 
152
- assert_equal(3, test_songs[:from_valid_yaml_string].patterns.length)
153
- test_songs[:from_valid_yaml_string].remove_unused_patterns()
154
- assert_equal(3, test_songs[:from_valid_yaml_string].patterns.length)
155
- assert_equal(Hash, test_songs[:from_valid_yaml_string].patterns.class)
149
+ assert_equal(3, test_songs[:example_no_kit].patterns.length)
150
+ test_songs[:example_no_kit].remove_unused_patterns()
151
+ assert_equal(3, test_songs[:example_no_kit].patterns.length)
152
+ assert_equal(Hash, test_songs[:example_no_kit].patterns.class)
156
153
  end
157
154
 
158
155
  def test_to_yaml
159
156
  test_songs = generate_test_data()
160
- result = test_songs[:from_valid_yaml_string_with_kit].to_yaml
157
+ kit = Kit.new("test/sounds", {"bass" => "bass_mono_8.wav",
158
+ "snare" => "snare_mono_8.wav",
159
+ "hhclosed" => "hh_closed_mono_8.wav",
160
+ "hhopen" => "hh_open_mono_8.wav"})
161
+
162
+ result = test_songs[:example_with_kit].to_yaml(kit)
161
163
 
162
164
  assert_equal(File.read("test/fixtures/yaml/song_yaml.txt"), result)
163
165
  end
164
- end
166
+ end