beats 1.2.0 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +1 -1
- data/README.markdown +28 -10
- data/bin/beats +9 -7
- data/lib/audioengine.rb +172 -0
- data/lib/audioutils.rb +73 -0
- data/lib/beats.rb +14 -15
- data/lib/beatswavefile.rb +17 -37
- data/lib/kit.rb +148 -71
- data/lib/pattern.rb +20 -117
- data/lib/patternexpander.rb +111 -0
- data/lib/song.rb +78 -132
- data/lib/songoptimizer.rb +29 -33
- data/lib/songparser.rb +70 -45
- data/lib/track.rb +11 -82
- data/test/audioengine_test.rb +261 -0
- data/test/audioutils_test.rb +45 -0
- data/test/fixtures/expected_output/example_split_mono_16-hh_closed.wav +0 -0
- data/test/{examples/split-agogo_high.wav → fixtures/expected_output/example_split_mono_16-hh_closed2.wav} +0 -0
- data/test/fixtures/expected_output/example_split_mono_8-hh_closed.wav +0 -0
- data/test/{examples/split-tom4.wav → fixtures/expected_output/example_split_mono_8-hh_closed2.wav} +0 -0
- data/test/fixtures/expected_output/example_split_stereo_16-hh_closed.wav +0 -0
- data/test/fixtures/expected_output/example_split_stereo_16-hh_closed2.wav +0 -0
- data/test/fixtures/expected_output/example_split_stereo_8-hh_closed.wav +0 -0
- data/test/fixtures/expected_output/example_split_stereo_8-hh_closed2.wav +0 -0
- data/test/fixtures/invalid/{bad_structure.txt → bad_flow.txt} +2 -2
- data/test/fixtures/invalid/bad_repeat_count.txt +1 -1
- data/test/fixtures/invalid/bad_rhythm.txt +1 -1
- data/test/fixtures/invalid/bad_tempo.txt +1 -1
- data/test/fixtures/invalid/{no_structure.txt → no_flow.txt} +1 -1
- data/test/fixtures/invalid/pattern_with_no_tracks.txt +1 -1
- data/test/fixtures/invalid/sound_in_kit_not_found.txt +1 -1
- data/test/fixtures/invalid/sound_in_kit_wrong_format.txt +10 -0
- data/test/fixtures/invalid/sound_in_track_not_found.txt +1 -1
- data/test/fixtures/invalid/sound_in_track_wrong_format.txt +8 -0
- data/test/fixtures/invalid/template.txt +1 -1
- data/test/fixtures/valid/example_mono_16.txt +5 -3
- data/test/fixtures/valid/example_mono_8.txt +5 -3
- data/test/fixtures/valid/example_no_kit.txt +1 -1
- data/test/fixtures/valid/example_stereo_16.txt +7 -4
- data/test/fixtures/valid/example_stereo_8.txt +5 -3
- data/test/fixtures/valid/example_with_empty_track.txt +1 -1
- data/test/fixtures/valid/example_with_kit.txt +1 -1
- data/test/fixtures/valid/multiple_tracks_same_sound.txt +33 -0
- data/test/fixtures/valid/no_tempo.txt +1 -1
- data/test/fixtures/valid/optimize_pattern_collision.txt +28 -0
- data/test/fixtures/valid/pattern_with_overflow.txt +1 -1
- data/test/fixtures/valid/repeats_not_specified.txt +2 -2
- data/test/fixtures/valid/with_structure.txt +10 -0
- data/test/fixtures/yaml/song_yaml.txt +5 -5
- data/test/includes.rb +4 -2
- data/test/integration.rb +3 -3
- data/test/kit_test.rb +136 -109
- data/test/pattern_test.rb +31 -131
- data/test/patternexpander_test.rb +142 -0
- data/test/song_test.rb +104 -102
- data/test/songoptimizer_test.rb +52 -38
- data/test/songparser_test.rb +79 -46
- data/test/sounds/composite_snare_mono_8_tom3_mono_16_mono_16.wav +0 -0
- data/test/sounds/composite_snare_mono_8_tom3_mono_8_mono_16.wav +0 -0
- data/test/sounds/composite_snare_stereo_16_tom3_mono_16_stereo_16.wav +0 -0
- data/test/sounds/composite_snare_stereo_8_tom3_mono_16_stereo_16.wav +0 -0
- data/test/track_test.rb +30 -185
- metadata +56 -24
- data/lib/songsplitter.rb +0 -38
- data/test/examples/combined.wav +0 -0
- data/test/examples/split-bass.wav +0 -0
- data/test/examples/split-hh_closed.wav +0 -0
- data/test/examples/split-snare.wav +0 -0
- data/test/examples/split-tom2.wav +0 -0
data/test/pattern_test.rb
CHANGED
@@ -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",
|
23
|
-
pattern.track "snare.wav",
|
24
|
-
pattern.track "hh_closed.wav",
|
25
|
-
pattern.track "hh_open.wav",
|
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",
|
30
|
-
pattern.track "snare.wav",
|
31
|
-
pattern.track "hh_closed.wav",
|
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
|
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].
|
76
|
-
assert_equal(32, test_patterns[:verse].
|
77
|
-
assert_equal(4, test_patterns[:staircase].
|
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",
|
83
|
-
left_pattern.track("snare",
|
84
|
-
left_pattern.track("hh_closed",
|
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",
|
88
|
-
right_pattern.track("snare",
|
89
|
-
right_pattern.track("hh_closed",
|
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",
|
96
|
-
right_pattern.track("hh_closed",
|
97
|
-
right_pattern.track("bass",
|
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",
|
104
|
-
different_names_pattern.track("cymbal",
|
105
|
-
different_names_pattern.track("hh_open",
|
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",
|
112
|
-
different_beats_pattern.track("snare",
|
113
|
-
different_beats_pattern.track("hh_closed",
|
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",
|
120
|
-
something_extra.track("snare",
|
121
|
-
something_extra.track("hh_closed",
|
122
|
-
something_extra.track("extra",
|
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
|
data/test/song_test.rb
CHANGED
@@ -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
|
-
|
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(
|
19
|
-
|
20
|
-
test_songs[:
|
21
|
-
verse = test_songs[:
|
22
|
-
verse.track "bass.wav",
|
23
|
-
verse.track "snare.wav",
|
24
|
-
verse.track "hh_closed.wav",
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
test_songs[:from_code] = Song.new(
|
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",
|
34
|
-
verse.track "snare.wav",
|
35
|
-
verse.track "hh_closed.wav",
|
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",
|
38
|
-
chorus.track "snare.wav",
|
39
|
-
chorus.track "ride.wav",
|
40
|
-
test_songs[:from_code].
|
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].
|
50
|
-
assert_equal(
|
51
|
-
|
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[:
|
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[:
|
70
|
-
assert_equal(5, test_songs[:
|
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[:
|
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[:
|
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[:
|
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
|
85
|
+
def test_copy_ignoring_patterns_and_flow
|
90
86
|
test_songs = generate_test_data()
|
91
|
-
|
92
|
-
|
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
|
-
|
96
|
-
|
97
|
-
|
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
|
96
|
+
def test_remove_patterns_except
|
97
|
+
# Remove an existing pattern.
|
106
98
|
test_songs = generate_test_data()
|
107
|
-
|
108
|
-
assert_equal(
|
109
|
-
assert_equal(
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
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
|
109
|
+
|
110
|
+
def test_split
|
133
111
|
test_songs = generate_test_data()
|
134
|
-
|
135
|
-
cloned_song = original_song.copy_ignoring_patterns_and_structure()
|
112
|
+
split_songs = test_songs[:example_with_kit].split()
|
136
113
|
|
137
|
-
|
138
|
-
assert_equal(
|
139
|
-
|
140
|
-
|
141
|
-
assert_equal([
|
142
|
-
|
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[:
|
149
|
-
test_songs[:
|
150
|
-
assert_equal({}, test_songs[:
|
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[:
|
153
|
-
test_songs[:
|
154
|
-
assert_equal(3, test_songs[:
|
155
|
-
assert_equal(Hash, test_songs[:
|
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
|
-
|
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
|