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