beats 1.2.5 → 1.3.0
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.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/README.markdown +32 -7
- data/bin/beats +6 -0
- data/lib/beats.rb +2 -1
- data/lib/beats/song.rb +1 -1
- data/lib/beats/songparser.rb +11 -1
- data/lib/beats/transforms/song_swinger.rb +54 -0
- data/test/audioengine_test.rb +8 -8
- data/test/audioutils_test.rb +3 -0
- data/test/fixtures/invalid/bad_swing_rate_1.txt +9 -0
- data/test/fixtures/invalid/bad_swing_rate_2.txt +9 -0
- data/test/fixtures/valid/example_swung_16th.txt +18 -0
- data/test/fixtures/valid/example_swung_8th.txt +18 -0
- data/test/fixtures/valid/example_unswung.txt +17 -0
- data/test/fixtures/valid/fractional_tempo.txt +17 -0
- data/test/integration_test.rb +6 -6
- data/test/kit_test.rb +2 -2
- data/test/pattern_test.rb +5 -5
- data/test/song_swinger_test.rb +170 -0
- data/test/song_test.rb +42 -16
- data/test/songoptimizer_test.rb +10 -10
- data/test/songparser_test.rb +45 -3
- data/test/track_test.rb +9 -9
- metadata +21 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc3e2d1d7e7730ec749de9aacb9446ef847cfcbd
|
4
|
+
data.tar.gz: 42bff66e1caa2ff6ff503e57aac501ac36c0d445
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c5782528094a11cd93d7a49fa944787fd8150066ebc8f72a75253c4fd1326ae106c58fdb337591f815f4bf4cc85b58fdae497660e96c86789d365b833a72b15f
|
7
|
+
data.tar.gz: 666d0a00cf0da6f21e7c1476ded37fd97b41db884add895aff0e627a8e0e9bebbd6c8ee6f5f76d4a2f5916e9d9e83c203846082bc9ce0fad78a681000e0c87be
|
data/LICENSE
CHANGED
data/README.markdown
CHANGED
@@ -33,19 +33,44 @@ And [here's what it sounds like](http://beatsdrummachine.com/media/beat.mp3) aft
|
|
33
33
|
Current Status
|
34
34
|
--------------
|
35
35
|
|
36
|
-
The latest stable version of Beats is 1.
|
36
|
+
The latest stable version of Beats is 1.3.0, released on March 4, 2013.
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
38
|
+
This release is for all you swingers out there. A new `Swing` declaration in the song header will cause the song to be played with either a swung 8th note or swung 16th note rhythm. For example, take this song:
|
39
|
+
|
40
|
+
Song:
|
41
|
+
Tempo: 120
|
42
|
+
Flow:
|
43
|
+
- Verse: x4
|
44
|
+
|
45
|
+
Verse:
|
46
|
+
- bass.wav: X...X...X...X...
|
47
|
+
- snare.wav: ....X.......X...
|
48
|
+
- hihat.wav: X.X.X.X.X.X.X.X.
|
49
|
+
|
50
|
+
It will [sound like this](http://beatsdrummachine.com/media/straight.wav).
|
51
|
+
|
52
|
+
You can add an 8th note swing like this (notice the 3rd line, everything else is the same):
|
53
|
+
|
54
|
+
Song:
|
55
|
+
Tempo: 120
|
56
|
+
Swing: 8 # Or, 16
|
57
|
+
Flow:
|
58
|
+
- Verse: x4
|
59
|
+
|
60
|
+
Verse:
|
61
|
+
- bass.wav: X...X...X...X...
|
62
|
+
- snare.wav: ....X.......X...
|
63
|
+
- hihat.wav: X.X.X.X.X.X.X.X.
|
64
|
+
|
65
|
+
And it will now [sound like this](http://beatsdrummachine.com/media/swing.wav).
|
66
|
+
|
67
|
+
This release also includes a small bug fix. When you run the `beats` command with no arguments, it now displays the help screen, rather than an error message.
|
43
68
|
|
44
69
|
|
45
70
|
Installation
|
46
71
|
------------
|
47
72
|
|
48
|
-
To install the latest stable version (1.
|
73
|
+
To install the latest stable version (1.3.0) from [rubygems.org](http://rubygems.org/gems/beats), run the following from the command line:
|
49
74
|
|
50
75
|
gem install beats
|
51
76
|
|
data/bin/beats
CHANGED
data/lib/beats.rb
CHANGED
data/lib/beats/song.rb
CHANGED
@@ -52,7 +52,7 @@ module Beats
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def tempo=(new_tempo)
|
55
|
-
unless new_tempo.class == Fixnum && new_tempo > 0
|
55
|
+
unless (new_tempo.class == Fixnum || new_tempo.class == Float) && new_tempo > 0
|
56
56
|
raise InvalidTempoError, "Invalid tempo: '#{new_tempo}'. Tempo must be a number greater than 0."
|
57
57
|
end
|
58
58
|
|
data/lib/beats/songparser.rb
CHANGED
@@ -36,7 +36,7 @@ module Beats
|
|
36
36
|
base_path = raw_song_components[:folder]
|
37
37
|
end
|
38
38
|
|
39
|
-
song = Song.new
|
39
|
+
song = Song.new
|
40
40
|
|
41
41
|
# 1.) Set tempo
|
42
42
|
begin
|
@@ -66,6 +66,15 @@ module Beats
|
|
66
66
|
set_song_flow(song, raw_song_components[:flow])
|
67
67
|
end
|
68
68
|
|
69
|
+
# 5.) Swing, if swing flag is set
|
70
|
+
if raw_song_components[:swing]
|
71
|
+
begin
|
72
|
+
song = Transforms::SongSwinger.transform(song, raw_song_components[:swing])
|
73
|
+
rescue Transforms::InvalidSwingRateError => detail
|
74
|
+
raise SongParseError, "#{detail}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
69
78
|
return song, kit
|
70
79
|
end
|
71
80
|
|
@@ -104,6 +113,7 @@ module Beats
|
|
104
113
|
raw_song_components[:flow] = raw_structure
|
105
114
|
end
|
106
115
|
|
116
|
+
raw_song_components[:swing] = raw_song_components[:header]["swing"]
|
107
117
|
raw_song_components[:patterns] = raw_song_components[:full_definition].reject {|k, v| k == "song"}
|
108
118
|
|
109
119
|
return raw_song_components
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Beats
|
2
|
+
module Transforms
|
3
|
+
class InvalidSwingRateError < RuntimeError; end
|
4
|
+
|
5
|
+
class SongSwinger
|
6
|
+
def self.transform(song, swing_rate)
|
7
|
+
validate_swing_rate(swing_rate)
|
8
|
+
|
9
|
+
song.patterns.values.each do |pattern|
|
10
|
+
pattern.tracks.values.each do |track|
|
11
|
+
original_rhythm = track.rhythm
|
12
|
+
|
13
|
+
if swing_rate == 8
|
14
|
+
track.rhythm = swing_8(track.rhythm)
|
15
|
+
elsif swing_rate == 16
|
16
|
+
track.rhythm = swing_16(track.rhythm)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
song.tempo *= 1.5
|
22
|
+
|
23
|
+
song
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def self.validate_swing_rate(swing_rate)
|
29
|
+
if swing_rate != 8 && swing_rate != 16
|
30
|
+
raise InvalidSwingRateError, "Invalid swing rate: '#{swing_rate}'. Swing rate must be 8 or 16."
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.swing_8(original_rhythm)
|
35
|
+
original_rhythm.chars.each_slice(4).inject("") do |new_rhythm, slice|
|
36
|
+
if slice.length == 1
|
37
|
+
new_rhythm << "#{slice[0]}."
|
38
|
+
else
|
39
|
+
new_rhythm << "#{slice[0]}.#{slice[1]}.#{slice[2]}#{slice[3]}"
|
40
|
+
end
|
41
|
+
|
42
|
+
new_rhythm
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.swing_16(original_rhythm)
|
47
|
+
original_rhythm.chars.each_slice(2).inject("") do |new_rhythm, slice|
|
48
|
+
new_rhythm << "#{slice[0]}.#{slice[1]}"
|
49
|
+
new_rhythm
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/test/audioengine_test.rb
CHANGED
@@ -27,9 +27,9 @@ class AudioEngineTest < Test::Unit::TestCase
|
|
27
27
|
def load_fixtures
|
28
28
|
test_engines = {}
|
29
29
|
base_path = File.dirname(__FILE__) + "/.."
|
30
|
-
song_parser = SongParser.new
|
30
|
+
song_parser = SongParser.new
|
31
31
|
|
32
|
-
test_engines[:blank] = AudioEngine.new(Song.new
|
32
|
+
test_engines[:blank] = AudioEngine.new(Song.new, Kit.new(base_path, {}))
|
33
33
|
|
34
34
|
FIXTURES.each do |fixture_name|
|
35
35
|
song, kit = song_parser.parse(base_path, File.read("test/fixtures/valid/#{fixture_name}.txt"))
|
@@ -40,7 +40,7 @@ class AudioEngineTest < Test::Unit::TestCase
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def test_initialize
|
43
|
-
test_engines = load_fixtures
|
43
|
+
test_engines = load_fixtures
|
44
44
|
|
45
45
|
assert_equal(5512.5, test_engines[:blank].step_sample_length)
|
46
46
|
assert_equal(6615.0, test_engines[:repeats_not_specified].step_sample_length)
|
@@ -159,7 +159,7 @@ class AudioEngineTest < Test::Unit::TestCase
|
|
159
159
|
|
160
160
|
def helper_generate_track_sample_data(kit, rhythm, step_sample_length, expected_primary, expected_overflow = [])
|
161
161
|
track = Track.new("foo", rhythm)
|
162
|
-
engine = MockAudioEngine.new(Song.new
|
162
|
+
engine = MockAudioEngine.new(Song.new, kit)
|
163
163
|
engine.step_sample_length = step_sample_length
|
164
164
|
actual = engine.generate_track_sample_data(track, kit.get_sample_data("S"))
|
165
165
|
|
@@ -182,7 +182,7 @@ class AudioEngineTest < Test::Unit::TestCase
|
|
182
182
|
|
183
183
|
|
184
184
|
# Simple case, no overflow (stereo)
|
185
|
-
engine = MockAudioEngine.new(Song.new
|
185
|
+
engine = MockAudioEngine.new(Song.new, MONO_KIT)
|
186
186
|
engine.step_sample_length = 4
|
187
187
|
primary, overflow = engine.composite_pattern_tracks(no_overflow_pattern)
|
188
188
|
assert_equal([
|
@@ -196,7 +196,7 @@ class AudioEngineTest < Test::Unit::TestCase
|
|
196
196
|
|
197
197
|
|
198
198
|
# Simple case, no overflow (stereo)
|
199
|
-
engine = MockAudioEngine.new(Song.new
|
199
|
+
engine = MockAudioEngine.new(Song.new, STEREO_KIT)
|
200
200
|
engine.step_sample_length = 4
|
201
201
|
primary, overflow = engine.composite_pattern_tracks(no_overflow_pattern)
|
202
202
|
assert_equal([
|
@@ -222,7 +222,7 @@ class AudioEngineTest < Test::Unit::TestCase
|
|
222
222
|
|
223
223
|
|
224
224
|
# Some overflow (mono)
|
225
|
-
engine = MockAudioEngine.new(Song.new
|
225
|
+
engine = MockAudioEngine.new(Song.new, MONO_KIT)
|
226
226
|
engine.step_sample_length = 3
|
227
227
|
primary, overflow = engine.composite_pattern_tracks(overflow_pattern)
|
228
228
|
assert_equal([
|
@@ -236,7 +236,7 @@ class AudioEngineTest < Test::Unit::TestCase
|
|
236
236
|
|
237
237
|
|
238
238
|
# Some overflow (stereo)
|
239
|
-
engine = MockAudioEngine.new(Song.new
|
239
|
+
engine = MockAudioEngine.new(Song.new, STEREO_KIT)
|
240
240
|
engine.step_sample_length = 3
|
241
241
|
primary, overflow = engine.composite_pattern_tracks(overflow_pattern)
|
242
242
|
assert_equal([
|
data/test/audioutils_test.rb
CHANGED
@@ -39,5 +39,8 @@ class AudioUtilsTest < Test::Unit::TestCase
|
|
39
39
|
assert_equal(6615.0, AudioUtils.step_sample_length(44100, 100))
|
40
40
|
assert_equal(3307.5, AudioUtils.step_sample_length(44100, 200))
|
41
41
|
assert_equal(3307.5, AudioUtils.step_sample_length(22050, 100))
|
42
|
+
|
43
|
+
assert_equal(6874.612880831729, AudioUtils.step_sample_length(44100, 96.2236))
|
44
|
+
assert_equal(3437.3064404158645, AudioUtils.step_sample_length(22050, 96.2236))
|
42
45
|
end
|
43
46
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# An example song
|
2
|
+
|
3
|
+
Song:
|
4
|
+
Tempo: 120
|
5
|
+
Swing: 16
|
6
|
+
Kit:
|
7
|
+
- bass: test/sounds/bass_mono_8.wav
|
8
|
+
- snare: test/sounds/snare_mono_8.wav
|
9
|
+
Flow:
|
10
|
+
- Verse: x2
|
11
|
+
- Chorus: x2
|
12
|
+
|
13
|
+
Verse:
|
14
|
+
- bass: X...X...
|
15
|
+
- snare: ..X...X.
|
16
|
+
Chorus:
|
17
|
+
- bass: XXXXXXXX
|
18
|
+
- snare: .X.X.X.X
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# An example song
|
2
|
+
|
3
|
+
Song:
|
4
|
+
Tempo: 120
|
5
|
+
Swing: 8
|
6
|
+
Kit:
|
7
|
+
- bass: test/sounds/bass_mono_8.wav
|
8
|
+
- snare: test/sounds/snare_mono_8.wav
|
9
|
+
Flow:
|
10
|
+
- Verse: x2
|
11
|
+
- Chorus: x2
|
12
|
+
|
13
|
+
Verse:
|
14
|
+
- bass: X...X...
|
15
|
+
- snare: ..X...X.
|
16
|
+
Chorus:
|
17
|
+
- bass: XXXXXXXX
|
18
|
+
- snare: .X.X.X.X
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# An example song
|
2
|
+
|
3
|
+
Song:
|
4
|
+
Tempo: 120
|
5
|
+
Kit:
|
6
|
+
- bass: test/sounds/bass_mono_8.wav
|
7
|
+
- snare: test/sounds/snare_mono_8.wav
|
8
|
+
Flow:
|
9
|
+
- Verse: x2
|
10
|
+
- Chorus: x2
|
11
|
+
|
12
|
+
Verse:
|
13
|
+
- bass: X...X...
|
14
|
+
- snare: ..X...X.
|
15
|
+
Chorus:
|
16
|
+
- bass: XXXXXXXX
|
17
|
+
- snare: .X.X.X.X
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# An example song
|
2
|
+
|
3
|
+
Song:
|
4
|
+
Tempo: 95.764
|
5
|
+
Kit:
|
6
|
+
- bass: test/sounds/bass_mono_8.wav
|
7
|
+
- snare: test/sounds/snare_mono_8.wav
|
8
|
+
Flow:
|
9
|
+
- Verse: x2
|
10
|
+
- Chorus: x2
|
11
|
+
|
12
|
+
Verse:
|
13
|
+
- bass: X...X...
|
14
|
+
- snare: ..X...X.
|
15
|
+
Chorus:
|
16
|
+
- bass: XXXXXXXX
|
17
|
+
- snare: .X.X.X.X
|
data/test/integration_test.rb
CHANGED
@@ -6,7 +6,7 @@ class IntegrationTest < Test::Unit::TestCase
|
|
6
6
|
|
7
7
|
def setup
|
8
8
|
# Make sure no output from previous tests is still around
|
9
|
-
clean_output_folder
|
9
|
+
clean_output_folder
|
10
10
|
end
|
11
11
|
|
12
12
|
def test_bad_song_errors
|
@@ -21,7 +21,7 @@ class IntegrationTest < Test::Unit::TestCase
|
|
21
21
|
invalid_fixtures.each do |fixture_name|
|
22
22
|
assert_raise(SongParseError) do
|
23
23
|
beats = BeatsRunner.new("test/fixtures/invalid/#{fixture_name}", "doesn't matter", {:split => false})
|
24
|
-
beats.run
|
24
|
+
beats.run
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
@@ -56,7 +56,7 @@ class IntegrationTest < Test::Unit::TestCase
|
|
56
56
|
end
|
57
57
|
|
58
58
|
beats = BeatsRunner.new(song_fixture, actual_output_file, options)
|
59
|
-
beats.run
|
59
|
+
beats.run
|
60
60
|
assert(File.exists?(actual_output_file), "Expected file '#{actual_output_file}' to exist, but it doesn't.")
|
61
61
|
|
62
62
|
# Reading the files this way instead of a plain File.read() for Windows compatibility with binary files
|
@@ -89,7 +89,7 @@ class IntegrationTest < Test::Unit::TestCase
|
|
89
89
|
end
|
90
90
|
|
91
91
|
beats = BeatsRunner.new(song_fixture, actual_output_prefix + ".wav", options)
|
92
|
-
beats.run
|
92
|
+
beats.run
|
93
93
|
TRACK_NAMES.each do |track_name|
|
94
94
|
if(track_name.start_with?("tom"))
|
95
95
|
track_name += "_#{num_channels}_#{bits_per_sample}"
|
@@ -99,8 +99,8 @@ class IntegrationTest < Test::Unit::TestCase
|
|
99
99
|
assert(File.exists?(actual_output_file), "Expected file '#{actual_output_file}' to exist, but it doesn't.")
|
100
100
|
|
101
101
|
# Reading the files this way instead of a plain File.read() for Windows compatibility with binary files
|
102
|
-
expected_output_file_contents = File.open(expected_output_file, "rb") {|f| f.read
|
103
|
-
actual_output_file_contents = File.open(actual_output_file, "rb") {|f| f.read
|
102
|
+
expected_output_file_contents = File.open(expected_output_file, "rb") {|f| f.read }
|
103
|
+
actual_output_file_contents = File.open(actual_output_file, "rb") {|f| f.read }
|
104
104
|
assert_equal(expected_output_file_contents, actual_output_file_contents)
|
105
105
|
|
106
106
|
# Clean up after ourselves
|
data/test/kit_test.rb
CHANGED
@@ -40,7 +40,7 @@ class KitTest < Test::Unit::TestCase
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def test_valid_initialization
|
43
|
-
kits = generate_test_data
|
43
|
+
kits = generate_test_data
|
44
44
|
|
45
45
|
assert_equal(16, kits[:empty].bits_per_sample)
|
46
46
|
assert_equal(1, kits[:empty].num_channels)
|
@@ -93,7 +93,7 @@ class KitTest < Test::Unit::TestCase
|
|
93
93
|
end
|
94
94
|
|
95
95
|
def test_get_sample_data
|
96
|
-
kits = generate_test_data
|
96
|
+
kits = generate_test_data
|
97
97
|
# Should get an error when trying to get a non-existent sound
|
98
98
|
assert_raise(StandardError) { kits[:mono8].get_sample_data("nonexistant") }
|
99
99
|
|
data/test/pattern_test.rb
CHANGED
@@ -27,7 +27,7 @@ class PatternTest < Test::Unit::TestCase
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def test_initialize
|
30
|
-
test_patterns = generate_test_data
|
30
|
+
test_patterns = generate_test_data
|
31
31
|
|
32
32
|
pattern = test_patterns[:blank]
|
33
33
|
assert_equal(pattern.name, :blank)
|
@@ -43,11 +43,11 @@ class PatternTest < Test::Unit::TestCase
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def test_step_count
|
46
|
-
test_patterns = generate_test_data
|
46
|
+
test_patterns = generate_test_data
|
47
47
|
|
48
|
-
assert_equal(0, test_patterns[:blank].step_count
|
49
|
-
assert_equal(32, test_patterns[:verse].step_count
|
50
|
-
assert_equal(4, test_patterns[:staircase].step_count
|
48
|
+
assert_equal(0, test_patterns[:blank].step_count)
|
49
|
+
assert_equal(32, test_patterns[:verse].step_count)
|
50
|
+
assert_equal(4, test_patterns[:staircase].step_count)
|
51
51
|
end
|
52
52
|
|
53
53
|
def test_same_tracks_as?
|
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'includes'
|
2
|
+
|
3
|
+
class SongSwingerTest < Test::Unit::TestCase
|
4
|
+
def test_full_song_swing_rate_8
|
5
|
+
base_path = File.dirname(__FILE__) + "/sounds"
|
6
|
+
song, kit = SongParser.new.parse(base_path, File.read("test/fixtures/valid/example_mono_16_base_path.txt"))
|
7
|
+
|
8
|
+
shuffled_song = Transforms::SongSwinger.transform(song, 8)
|
9
|
+
|
10
|
+
assert_equal(180, shuffled_song.tempo)
|
11
|
+
assert_equal([:verse, :verse, :chorus, :chorus, :chorus, :chorus,
|
12
|
+
:verse, :verse, :chorus, :chorus, :chorus, :chorus],
|
13
|
+
shuffled_song.flow)
|
14
|
+
|
15
|
+
assert_equal([:chorus, :verse], shuffled_song.patterns.keys.sort)
|
16
|
+
|
17
|
+
chorus_pattern = shuffled_song.patterns[:chorus]
|
18
|
+
assert_equal(["bass",
|
19
|
+
"snare",
|
20
|
+
"hh_closed",
|
21
|
+
"hh_closed2",
|
22
|
+
"tom4_mono_16.wav",
|
23
|
+
"tom2_mono_16.wav"],
|
24
|
+
chorus_pattern.tracks.keys)
|
25
|
+
|
26
|
+
assert_equal("X.....X.....X.X...X.....", chorus_pattern.tracks["bass"].rhythm)
|
27
|
+
assert_equal("......X...........X.....", chorus_pattern.tracks["snare"].rhythm)
|
28
|
+
assert_equal("X...XXX...XX............", chorus_pattern.tracks["hh_closed"].rhythm)
|
29
|
+
assert_equal("............X...XX....X.", chorus_pattern.tracks["hh_closed2"].rhythm)
|
30
|
+
assert_equal(".................X......", chorus_pattern.tracks["tom4_mono_16.wav"].rhythm)
|
31
|
+
assert_equal("......................X.", chorus_pattern.tracks["tom2_mono_16.wav"].rhythm)
|
32
|
+
|
33
|
+
verse_pattern = shuffled_song.patterns[:verse]
|
34
|
+
assert_equal(["bass",
|
35
|
+
"snare",
|
36
|
+
"hh_closed",
|
37
|
+
"hh_closed2",
|
38
|
+
"agogo"],
|
39
|
+
verse_pattern.tracks.keys)
|
40
|
+
|
41
|
+
assert_equal("X.....X.....X.....X.....", verse_pattern.tracks["bass"].rhythm)
|
42
|
+
assert_equal("......................X.", verse_pattern.tracks["snare"].rhythm)
|
43
|
+
assert_equal("X...XXX...XX............", verse_pattern.tracks["hh_closed"].rhythm)
|
44
|
+
assert_equal("............X...X.X...X.", verse_pattern.tracks["hh_closed2"].rhythm)
|
45
|
+
assert_equal("......................XX", verse_pattern.tracks["agogo"].rhythm)
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_full_song_swing_rate_16
|
49
|
+
base_path = File.dirname(__FILE__) + "/sounds"
|
50
|
+
song, kit = SongParser.new.parse(base_path, File.read("test/fixtures/valid/example_mono_16_base_path.txt"))
|
51
|
+
|
52
|
+
shuffled_song = Transforms::SongSwinger.transform(song, 16)
|
53
|
+
|
54
|
+
assert_equal(180, shuffled_song.tempo)
|
55
|
+
assert_equal([:verse, :verse, :chorus, :chorus, :chorus, :chorus,
|
56
|
+
:verse, :verse, :chorus, :chorus, :chorus, :chorus],
|
57
|
+
shuffled_song.flow)
|
58
|
+
|
59
|
+
assert_equal([:chorus, :verse], shuffled_song.patterns.keys.sort)
|
60
|
+
|
61
|
+
chorus_pattern = shuffled_song.patterns[:chorus]
|
62
|
+
assert_equal(["bass",
|
63
|
+
"snare",
|
64
|
+
"hh_closed",
|
65
|
+
"hh_closed2",
|
66
|
+
"tom4_mono_16.wav",
|
67
|
+
"tom2_mono_16.wav"],
|
68
|
+
chorus_pattern.tracks.keys)
|
69
|
+
|
70
|
+
assert_equal("X.....X.....X.X...X.....", chorus_pattern.tracks["bass"].rhythm)
|
71
|
+
assert_equal("......X...........X.....", chorus_pattern.tracks["snare"].rhythm)
|
72
|
+
assert_equal("X..X.XX..X.X............", chorus_pattern.tracks["hh_closed"].rhythm)
|
73
|
+
assert_equal("............X..X.X...X..", chorus_pattern.tracks["hh_closed2"].rhythm)
|
74
|
+
assert_equal(".................X......", chorus_pattern.tracks["tom4_mono_16.wav"].rhythm)
|
75
|
+
assert_equal(".....................X..", chorus_pattern.tracks["tom2_mono_16.wav"].rhythm)
|
76
|
+
|
77
|
+
verse_pattern = shuffled_song.patterns[:verse]
|
78
|
+
assert_equal(["bass",
|
79
|
+
"snare",
|
80
|
+
"hh_closed",
|
81
|
+
"hh_closed2",
|
82
|
+
"agogo"],
|
83
|
+
verse_pattern.tracks.keys)
|
84
|
+
|
85
|
+
assert_equal("X.....X.....X.....X.....", verse_pattern.tracks["bass"].rhythm)
|
86
|
+
assert_equal(".....................X..", verse_pattern.tracks["snare"].rhythm)
|
87
|
+
assert_equal("X..X.XX..X.X............", verse_pattern.tracks["hh_closed"].rhythm)
|
88
|
+
assert_equal("............X..X..X..X..", verse_pattern.tracks["hh_closed2"].rhythm)
|
89
|
+
assert_equal(".....................X.X", verse_pattern.tracks["agogo"].rhythm)
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_swing_8_rhythm_conversions
|
93
|
+
test_rhythm_conversions(8, [["XXXXX.X.", "X.X.XXX...X."],
|
94
|
+
["XXXXXXX", "X.X.XXX.X.X"],
|
95
|
+
["XXXX", "X.X.XX"],
|
96
|
+
["....", "......"],
|
97
|
+
["XXX", "X.X.X"],
|
98
|
+
["XX", "X.X."],
|
99
|
+
["X", "X."]])
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_swing_16_rhythm_conversions
|
103
|
+
test_rhythm_conversions(16, [["XXX..X..", "X.XX....X..."],
|
104
|
+
["X..X..X", "X....X...X."],
|
105
|
+
["XX", "X.X"],
|
106
|
+
["X.", "X.."],
|
107
|
+
[".X", "..X"],
|
108
|
+
["..", "..."],
|
109
|
+
["X", "X."],
|
110
|
+
[".", ".."]])
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_tempo_change
|
114
|
+
[8, 16].each do |swing_rate|
|
115
|
+
song = Song.new
|
116
|
+
song.tempo = 140
|
117
|
+
|
118
|
+
song = Transforms::SongSwinger.transform(song, swing_rate)
|
119
|
+
assert_equal(210, song.tempo)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_conversion_to_fractional_tempo
|
124
|
+
[8, 16].each do |swing_rate|
|
125
|
+
song = Song.new
|
126
|
+
song.tempo = 145
|
127
|
+
|
128
|
+
song = Transforms::SongSwinger.transform(song, swing_rate)
|
129
|
+
assert_equal(217.5, song.tempo)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_fractional_tempo
|
134
|
+
[8, 16].each do |swing_rate|
|
135
|
+
song = Song.new
|
136
|
+
song.tempo = 145.325
|
137
|
+
|
138
|
+
song = Transforms::SongSwinger.transform(song, swing_rate)
|
139
|
+
assert_equal(217.98749999999998, song.tempo)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_invalid_swing_rate
|
144
|
+
[7, "abc", "8a", nil, "", [8]].each do |invalid_swing_rate|
|
145
|
+
song = Song.new
|
146
|
+
song.tempo = 100
|
147
|
+
|
148
|
+
assert_raise(Transforms::InvalidSwingRateError) do
|
149
|
+
song = Transforms::SongSwinger.transform(song, invalid_swing_rate)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
private
|
155
|
+
|
156
|
+
def test_rhythm_conversions(swing_rate, expectations)
|
157
|
+
expectations.each do |original_rhythm, expected_rhythm|
|
158
|
+
song = Song.new
|
159
|
+
|
160
|
+
pattern = song.pattern(:my_pattern)
|
161
|
+
pattern.track("track1", original_rhythm)
|
162
|
+
|
163
|
+
song.pattern(pattern)
|
164
|
+
|
165
|
+
swung_song = Transforms::SongSwinger.transform(song, swing_rate)
|
166
|
+
swung_pattern = swung_song.patterns[:my_pattern]
|
167
|
+
assert_equal(expected_rhythm, swung_pattern.tracks["track1"].rhythm)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
data/test/song_test.rb
CHANGED
@@ -10,20 +10,20 @@ class SongTest < Test::Unit::TestCase
|
|
10
10
|
test_songs = {}
|
11
11
|
base_path = File.dirname(__FILE__) + "/.."
|
12
12
|
|
13
|
-
test_songs[:blank] = Song.new
|
13
|
+
test_songs[:blank] = Song.new
|
14
14
|
|
15
|
-
test_songs[:no_flow] = Song.new
|
15
|
+
test_songs[:no_flow] = Song.new
|
16
16
|
verse = test_songs[:no_flow].pattern :verse
|
17
17
|
verse.track "bass.wav", "X.......X......."
|
18
18
|
verse.track "snare.wav", "....X.......X..."
|
19
19
|
verse.track "hh_closed.wav", "X.X.X.X.X.X.X.X."
|
20
20
|
|
21
|
-
song_parser = SongParser.new
|
21
|
+
song_parser = SongParser.new
|
22
22
|
FIXTURES.each do |fixture_name|
|
23
23
|
test_songs[fixture_name], throwaway_kit = song_parser.parse(base_path, File.read("test/fixtures/valid/#{fixture_name}.txt"))
|
24
24
|
end
|
25
25
|
|
26
|
-
test_songs[:from_code] = Song.new
|
26
|
+
test_songs[:from_code] = Song.new
|
27
27
|
verse = test_songs[:from_code].pattern :verse
|
28
28
|
verse.track "bass.wav", "X.......X......."
|
29
29
|
verse.track "snare.wav", "....X.......X..."
|
@@ -38,15 +38,41 @@ class SongTest < Test::Unit::TestCase
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def test_initialize
|
41
|
-
test_songs = generate_test_data
|
41
|
+
test_songs = generate_test_data
|
42
42
|
|
43
43
|
assert_equal([], test_songs[:blank].flow)
|
44
44
|
assert_equal([], test_songs[:no_flow].flow)
|
45
45
|
assert_equal([:verse, :chorus, :verse, :chorus, :chorus], test_songs[:from_code].flow)
|
46
46
|
end
|
47
47
|
|
48
|
+
def test_tempo=
|
49
|
+
song = Song.new
|
50
|
+
|
51
|
+
song.tempo = 150
|
52
|
+
assert_equal(150, song.tempo)
|
53
|
+
|
54
|
+
song.tempo = 145.854
|
55
|
+
assert_equal(145.854, song.tempo)
|
56
|
+
|
57
|
+
assert_raise(InvalidTempoError) do
|
58
|
+
song.tempo = -1
|
59
|
+
end
|
60
|
+
|
61
|
+
assert_raise(InvalidTempoError) do
|
62
|
+
song.tempo = -1.0
|
63
|
+
end
|
64
|
+
|
65
|
+
assert_raise(InvalidTempoError) do
|
66
|
+
song.tempo = "abc"
|
67
|
+
end
|
68
|
+
|
69
|
+
assert_raise(InvalidTempoError) do
|
70
|
+
song.tempo = "150"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
48
74
|
def test_pattern
|
49
|
-
song = Song.new
|
75
|
+
song = Song.new
|
50
76
|
verse1 = song.pattern :Verse
|
51
77
|
|
52
78
|
assert_equal(:Verse, verse1.name)
|
@@ -63,7 +89,7 @@ class SongTest < Test::Unit::TestCase
|
|
63
89
|
end
|
64
90
|
|
65
91
|
def test_total_tracks
|
66
|
-
test_songs = generate_test_data
|
92
|
+
test_songs = generate_test_data
|
67
93
|
|
68
94
|
assert_equal(0, test_songs[:blank].total_tracks)
|
69
95
|
assert_equal(3, test_songs[:no_flow].total_tracks)
|
@@ -75,7 +101,7 @@ class SongTest < Test::Unit::TestCase
|
|
75
101
|
end
|
76
102
|
|
77
103
|
def test_track_names
|
78
|
-
test_songs = generate_test_data
|
104
|
+
test_songs = generate_test_data
|
79
105
|
|
80
106
|
assert_equal([], test_songs[:blank].track_names)
|
81
107
|
assert_equal(["bass.wav", "hh_closed.wav", "snare.wav"], test_songs[:no_flow].track_names)
|
@@ -98,9 +124,9 @@ class SongTest < Test::Unit::TestCase
|
|
98
124
|
end
|
99
125
|
|
100
126
|
def test_copy_ignoring_patterns_and_flow
|
101
|
-
test_songs = generate_test_data
|
127
|
+
test_songs = generate_test_data
|
102
128
|
original_song = test_songs[:example_no_kit]
|
103
|
-
cloned_song = original_song.copy_ignoring_patterns_and_flow
|
129
|
+
cloned_song = original_song.copy_ignoring_patterns_and_flow
|
104
130
|
|
105
131
|
assert_not_equal(cloned_song, original_song)
|
106
132
|
assert_equal(cloned_song.tempo, original_song.tempo)
|
@@ -109,8 +135,8 @@ class SongTest < Test::Unit::TestCase
|
|
109
135
|
end
|
110
136
|
|
111
137
|
def test_split
|
112
|
-
test_songs = generate_test_data
|
113
|
-
split_songs = test_songs[:example_with_kit].split
|
138
|
+
test_songs = generate_test_data
|
139
|
+
split_songs = test_songs[:example_with_kit].split
|
114
140
|
|
115
141
|
assert_equal(Hash, split_songs.class)
|
116
142
|
assert_equal(6, split_songs.length)
|
@@ -141,20 +167,20 @@ class SongTest < Test::Unit::TestCase
|
|
141
167
|
end
|
142
168
|
|
143
169
|
def test_remove_unused_patterns
|
144
|
-
test_songs = generate_test_data
|
170
|
+
test_songs = generate_test_data
|
145
171
|
|
146
172
|
assert_equal(1, test_songs[:no_flow].patterns.length)
|
147
|
-
test_songs[:no_flow].remove_unused_patterns
|
173
|
+
test_songs[:no_flow].remove_unused_patterns
|
148
174
|
assert_equal({}, test_songs[:no_flow].patterns)
|
149
175
|
|
150
176
|
assert_equal(3, test_songs[:example_no_kit].patterns.length)
|
151
|
-
test_songs[:example_no_kit].remove_unused_patterns
|
177
|
+
test_songs[:example_no_kit].remove_unused_patterns
|
152
178
|
assert_equal(3, test_songs[:example_no_kit].patterns.length)
|
153
179
|
assert_equal(Hash, test_songs[:example_no_kit].patterns.class)
|
154
180
|
end
|
155
181
|
|
156
182
|
def test_to_yaml
|
157
|
-
test_songs = generate_test_data
|
183
|
+
test_songs = generate_test_data
|
158
184
|
kit = Kit.new("test/sounds", {"bass" => "bass_mono_8.wav",
|
159
185
|
"snare" => "snare_mono_8.wav",
|
160
186
|
"hhclosed" => "hh_closed_mono_8.wav",
|
data/test/songoptimizer_test.rb
CHANGED
@@ -50,14 +50,14 @@ Verse:
|
|
50
50
|
- snare: ..........X."
|
51
51
|
|
52
52
|
def self.load_fixture(fixture_name)
|
53
|
-
SongParser.new
|
53
|
+
SongParser.new.parse(FIXTURE_BASE_PATH, File.read("test/fixtures/#{fixture_name}"))
|
54
54
|
end
|
55
55
|
|
56
56
|
def test_optimize
|
57
|
-
parser = SongParser.new
|
57
|
+
parser = SongParser.new
|
58
58
|
original_song, kit = parser.parse(File.dirname(__FILE__) + "/..", EXAMPLE_SONG_YAML)
|
59
59
|
|
60
|
-
optimizer = SongOptimizer.new
|
60
|
+
optimizer = SongOptimizer.new
|
61
61
|
optimized_song = optimizer.optimize(original_song, 4)
|
62
62
|
|
63
63
|
assert_equal(optimized_song.tempo, 135)
|
@@ -122,11 +122,11 @@ Verse:
|
|
122
122
|
:chorus_0, :chorus_4, :chorus_8, :chorus_12])
|
123
123
|
end
|
124
124
|
|
125
|
-
def test_optimize_song_nondivisible_max_pattern_length
|
126
|
-
parser = SongParser.new
|
125
|
+
def test_optimize_song_nondivisible_max_pattern_length
|
126
|
+
parser = SongParser.new
|
127
127
|
original_song, kit = parser.parse(File.dirname(__FILE__) + "/..", EXAMPLE_SONG_YAML_EMPTY_SUB_PATTERN)
|
128
128
|
|
129
|
-
optimizer = SongOptimizer.new
|
129
|
+
optimizer = SongOptimizer.new
|
130
130
|
optimized_song = optimizer.optimize(original_song, 7)
|
131
131
|
|
132
132
|
pattern = optimized_song.patterns[:verse_0]
|
@@ -143,17 +143,17 @@ Verse:
|
|
143
143
|
|
144
144
|
def test_pattern_collision
|
145
145
|
original_song, kit = SongOptimizerTest.load_fixture("valid/optimize_pattern_collision.txt")
|
146
|
-
optimizer = SongOptimizer.new
|
146
|
+
optimizer = SongOptimizer.new
|
147
147
|
optimized_song = optimizer.optimize(original_song, 4)
|
148
148
|
|
149
149
|
assert_equal([:verse2_0, :verse_0, :verse_20], optimized_song.patterns.keys.sort {|x, y| x.to_s <=> y.to_s })
|
150
150
|
end
|
151
151
|
|
152
|
-
def test_optimize_song_containing_empty_pattern
|
153
|
-
parser = SongParser.new
|
152
|
+
def test_optimize_song_containing_empty_pattern
|
153
|
+
parser = SongParser.new
|
154
154
|
original_song, kit = parser.parse(File.dirname(__FILE__) + "/..", EXAMPLE_SONG_YAML_EMPTY_SUB_PATTERN)
|
155
155
|
|
156
|
-
optimizer = SongOptimizer.new
|
156
|
+
optimizer = SongOptimizer.new
|
157
157
|
optimized_song = optimizer.optimize(original_song, 4)
|
158
158
|
|
159
159
|
pattern = optimized_song.patterns[:verse_0]
|
data/test/songparser_test.rb
CHANGED
@@ -5,17 +5,23 @@ class SongParserTest < Test::Unit::TestCase
|
|
5
5
|
|
6
6
|
# TODO: Add fixture for track with no rhythm
|
7
7
|
VALID_FIXTURES = [:no_tempo,
|
8
|
+
:fractional_tempo,
|
8
9
|
:repeats_not_specified,
|
9
10
|
:pattern_with_overflow,
|
10
11
|
:example_no_kit,
|
11
12
|
:example_with_kit,
|
12
13
|
:example_with_empty_track,
|
13
14
|
:multiple_tracks_same_sound,
|
14
|
-
:with_structure
|
15
|
+
:with_structure,
|
16
|
+
:example_swung_8th,
|
17
|
+
:example_swung_16th,
|
18
|
+
:example_unswung]
|
15
19
|
|
16
20
|
INVALID_FIXTURES = [:bad_repeat_count,
|
17
21
|
:bad_flow,
|
18
22
|
:bad_tempo,
|
23
|
+
:bad_swing_rate_1,
|
24
|
+
:bad_swing_rate_2,
|
19
25
|
:no_header,
|
20
26
|
:no_flow,
|
21
27
|
:pattern_with_no_tracks,
|
@@ -25,7 +31,7 @@ class SongParserTest < Test::Unit::TestCase
|
|
25
31
|
:sound_in_track_wrong_format]
|
26
32
|
|
27
33
|
def self.load_fixture(fixture_name)
|
28
|
-
SongParser.new
|
34
|
+
SongParser.new.parse(FIXTURE_BASE_PATH, File.read("test/fixtures/#{fixture_name}"))
|
29
35
|
end
|
30
36
|
|
31
37
|
def self.generate_test_data
|
@@ -43,11 +49,14 @@ class SongParserTest < Test::Unit::TestCase
|
|
43
49
|
|
44
50
|
# TODO: Add somes tests to validate the Kits
|
45
51
|
def test_valid_parse
|
46
|
-
test_songs, test_kits = SongParserTest.generate_test_data
|
52
|
+
test_songs, test_kits = SongParserTest.generate_test_data
|
47
53
|
|
48
54
|
assert_equal(120, test_songs[:no_tempo].tempo)
|
49
55
|
assert_equal([:verse], test_songs[:no_tempo].flow)
|
50
56
|
|
57
|
+
assert_equal(95.764, test_songs[:fractional_tempo].tempo)
|
58
|
+
assert_equal([:verse, :verse, :chorus, :chorus], test_songs[:fractional_tempo].flow)
|
59
|
+
|
51
60
|
assert_equal(100, test_songs[:repeats_not_specified].tempo)
|
52
61
|
assert_equal([:verse], test_songs[:repeats_not_specified].flow)
|
53
62
|
|
@@ -93,6 +102,39 @@ class SongParserTest < Test::Unit::TestCase
|
|
93
102
|
assert_equal(1, song.patterns.length)
|
94
103
|
assert_equal(1, song.patterns[:verse].tracks.length)
|
95
104
|
assert_equal("X...X...", song.patterns[:verse].tracks["test/sounds/bass_mono_8.wav"].rhythm)
|
105
|
+
|
106
|
+
song = test_songs[:example_swung_8th]
|
107
|
+
assert_equal(180, song.tempo)
|
108
|
+
assert_equal([:verse, :verse, :chorus, :chorus], song.flow)
|
109
|
+
assert_equal(2, song.patterns.length)
|
110
|
+
assert_equal(2, song.patterns[:verse].tracks.length)
|
111
|
+
assert_equal("X.....X.....", song.patterns[:verse].tracks["bass"].rhythm)
|
112
|
+
assert_equal("....X.....X.", song.patterns[:verse].tracks["snare"].rhythm)
|
113
|
+
assert_equal(2, song.patterns[:chorus].tracks.length)
|
114
|
+
assert_equal("X.X.XXX.X.XX", song.patterns[:chorus].tracks["bass"].rhythm)
|
115
|
+
assert_equal("..X..X..X..X", song.patterns[:chorus].tracks["snare"].rhythm)
|
116
|
+
|
117
|
+
song = test_songs[:example_swung_16th]
|
118
|
+
assert_equal(180, song.tempo)
|
119
|
+
assert_equal([:verse, :verse, :chorus, :chorus], song.flow)
|
120
|
+
assert_equal(2, song.patterns.length)
|
121
|
+
assert_equal(2, song.patterns[:verse].tracks.length)
|
122
|
+
assert_equal("X.....X.....", song.patterns[:verse].tracks["bass"].rhythm)
|
123
|
+
assert_equal("...X.....X..", song.patterns[:verse].tracks["snare"].rhythm)
|
124
|
+
assert_equal(2, song.patterns[:chorus].tracks.length)
|
125
|
+
assert_equal("X.XX.XX.XX.X", song.patterns[:chorus].tracks["bass"].rhythm)
|
126
|
+
assert_equal("..X..X..X..X", song.patterns[:chorus].tracks["snare"].rhythm)
|
127
|
+
|
128
|
+
song = test_songs[:example_unswung]
|
129
|
+
assert_equal(120, song.tempo)
|
130
|
+
assert_equal([:verse, :verse, :chorus, :chorus], song.flow)
|
131
|
+
assert_equal(2, song.patterns.length)
|
132
|
+
assert_equal(2, song.patterns[:verse].tracks.length)
|
133
|
+
assert_equal("X...X...", song.patterns[:verse].tracks["bass"].rhythm)
|
134
|
+
assert_equal("..X...X.", song.patterns[:verse].tracks["snare"].rhythm)
|
135
|
+
assert_equal(2, song.patterns[:chorus].tracks.length)
|
136
|
+
assert_equal("XXXXXXXX", song.patterns[:chorus].tracks["bass"].rhythm)
|
137
|
+
assert_equal(".X.X.X.X", song.patterns[:chorus].tracks["snare"].rhythm)
|
96
138
|
end
|
97
139
|
|
98
140
|
def test_invalid_parse
|
data/test/track_test.rb
CHANGED
@@ -15,7 +15,7 @@ class TrackTest < Test::Unit::TestCase
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def test_initialize
|
18
|
-
test_tracks = generate_test_data
|
18
|
+
test_tracks = generate_test_data
|
19
19
|
|
20
20
|
assert_equal([0], test_tracks[:blank].beats)
|
21
21
|
assert_equal("bass", test_tracks[:blank].name)
|
@@ -40,13 +40,13 @@ class TrackTest < Test::Unit::TestCase
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def test_step_count
|
43
|
-
test_tracks = generate_test_data
|
44
|
-
|
45
|
-
assert_equal(0, test_tracks[:blank].step_count
|
46
|
-
assert_equal(1, test_tracks[:solo].step_count
|
47
|
-
assert_equal(4, test_tracks[:with_overflow].step_count
|
48
|
-
assert_equal(8, test_tracks[:with_barlines].step_count
|
49
|
-
assert_equal(4, test_tracks[:placeholder].step_count
|
50
|
-
assert_equal(32, test_tracks[:complicated].step_count
|
43
|
+
test_tracks = generate_test_data
|
44
|
+
|
45
|
+
assert_equal(0, test_tracks[:blank].step_count)
|
46
|
+
assert_equal(1, test_tracks[:solo].step_count)
|
47
|
+
assert_equal(4, test_tracks[:with_overflow].step_count)
|
48
|
+
assert_equal(8, test_tracks[:with_barlines].step_count)
|
49
|
+
assert_equal(4, test_tracks[:placeholder].step_count)
|
50
|
+
assert_equal(32, test_tracks[:complicated].step_count)
|
51
51
|
end
|
52
52
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: beats
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joel Strait
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-03-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: wavefile
|
@@ -36,6 +36,9 @@ files:
|
|
36
36
|
- LICENSE
|
37
37
|
- README.markdown
|
38
38
|
- Rakefile
|
39
|
+
- bin/beats
|
40
|
+
- ext/mkrf_conf.rb
|
41
|
+
- lib/beats.rb
|
39
42
|
- lib/beats/audioengine.rb
|
40
43
|
- lib/beats/audioutils.rb
|
41
44
|
- lib/beats/beatsrunner.rb
|
@@ -45,9 +48,8 @@ files:
|
|
45
48
|
- lib/beats/songoptimizer.rb
|
46
49
|
- lib/beats/songparser.rb
|
47
50
|
- lib/beats/track.rb
|
48
|
-
- lib/beats.rb
|
51
|
+
- lib/beats/transforms/song_swinger.rb
|
49
52
|
- lib/wavefile/cachingwriter.rb
|
50
|
-
- bin/beats
|
51
53
|
- test/audioengine_test.rb
|
52
54
|
- test/audioutils_test.rb
|
53
55
|
- test/cachingwriter_test.rb
|
@@ -86,6 +88,8 @@ files:
|
|
86
88
|
- test/fixtures/invalid/bad_flow.txt
|
87
89
|
- test/fixtures/invalid/bad_repeat_count.txt
|
88
90
|
- test/fixtures/invalid/bad_rhythm.txt
|
91
|
+
- test/fixtures/invalid/bad_swing_rate_1.txt
|
92
|
+
- test/fixtures/invalid/bad_swing_rate_2.txt
|
89
93
|
- test/fixtures/invalid/bad_tempo.txt
|
90
94
|
- test/fixtures/invalid/no_flow.txt
|
91
95
|
- test/fixtures/invalid/no_header.txt
|
@@ -101,9 +105,13 @@ files:
|
|
101
105
|
- test/fixtures/valid/example_no_kit.txt
|
102
106
|
- test/fixtures/valid/example_stereo_16.txt
|
103
107
|
- test/fixtures/valid/example_stereo_8.txt
|
108
|
+
- test/fixtures/valid/example_swung_16th.txt
|
109
|
+
- test/fixtures/valid/example_swung_8th.txt
|
110
|
+
- test/fixtures/valid/example_unswung.txt
|
104
111
|
- test/fixtures/valid/example_with_empty_track.txt
|
105
112
|
- test/fixtures/valid/example_with_kit.txt
|
106
113
|
- test/fixtures/valid/foo.txt
|
114
|
+
- test/fixtures/valid/fractional_tempo.txt
|
107
115
|
- test/fixtures/valid/multiple_tracks_same_sound.txt
|
108
116
|
- test/fixtures/valid/no_tempo.txt
|
109
117
|
- test/fixtures/valid/optimize_pattern_collision.txt
|
@@ -115,6 +123,7 @@ files:
|
|
115
123
|
- test/integration_test.rb
|
116
124
|
- test/kit_test.rb
|
117
125
|
- test/pattern_test.rb
|
126
|
+
- test/song_swinger_test.rb
|
118
127
|
- test/song_test.rb
|
119
128
|
- test/songoptimizer_test.rb
|
120
129
|
- test/songparser_test.rb
|
@@ -207,7 +216,6 @@ files:
|
|
207
216
|
- test/sounds/tom4_stereo_8.wav
|
208
217
|
- test/sounds/tone.wav
|
209
218
|
- test/track_test.rb
|
210
|
-
- ext/mkrf_conf.rb
|
211
219
|
homepage: http://beatsdrummachine.com/
|
212
220
|
licenses: []
|
213
221
|
metadata: {}
|
@@ -227,7 +235,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
227
235
|
version: '0'
|
228
236
|
requirements: []
|
229
237
|
rubyforge_project:
|
230
|
-
rubygems_version: 2.
|
238
|
+
rubygems_version: 2.2.2
|
231
239
|
signing_key:
|
232
240
|
specification_version: 4
|
233
241
|
summary: A command-line drum machine. Feed it a song notated in YAML, and it will
|
@@ -271,6 +279,8 @@ test_files:
|
|
271
279
|
- test/fixtures/invalid/bad_flow.txt
|
272
280
|
- test/fixtures/invalid/bad_repeat_count.txt
|
273
281
|
- test/fixtures/invalid/bad_rhythm.txt
|
282
|
+
- test/fixtures/invalid/bad_swing_rate_1.txt
|
283
|
+
- test/fixtures/invalid/bad_swing_rate_2.txt
|
274
284
|
- test/fixtures/invalid/bad_tempo.txt
|
275
285
|
- test/fixtures/invalid/no_flow.txt
|
276
286
|
- test/fixtures/invalid/no_header.txt
|
@@ -286,9 +296,13 @@ test_files:
|
|
286
296
|
- test/fixtures/valid/example_no_kit.txt
|
287
297
|
- test/fixtures/valid/example_stereo_16.txt
|
288
298
|
- test/fixtures/valid/example_stereo_8.txt
|
299
|
+
- test/fixtures/valid/example_swung_16th.txt
|
300
|
+
- test/fixtures/valid/example_swung_8th.txt
|
301
|
+
- test/fixtures/valid/example_unswung.txt
|
289
302
|
- test/fixtures/valid/example_with_empty_track.txt
|
290
303
|
- test/fixtures/valid/example_with_kit.txt
|
291
304
|
- test/fixtures/valid/foo.txt
|
305
|
+
- test/fixtures/valid/fractional_tempo.txt
|
292
306
|
- test/fixtures/valid/multiple_tracks_same_sound.txt
|
293
307
|
- test/fixtures/valid/no_tempo.txt
|
294
308
|
- test/fixtures/valid/optimize_pattern_collision.txt
|
@@ -300,6 +314,7 @@ test_files:
|
|
300
314
|
- test/integration_test.rb
|
301
315
|
- test/kit_test.rb
|
302
316
|
- test/pattern_test.rb
|
317
|
+
- test/song_swinger_test.rb
|
303
318
|
- test/song_test.rb
|
304
319
|
- test/songoptimizer_test.rb
|
305
320
|
- test/songparser_test.rb
|