beats 1.2.0 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
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