musicality 0.7.0 → 0.8.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/README.md +45 -2
- data/bin/lilify +83 -0
- data/bin/midify +7 -1
- data/lib/musicality.rb +5 -4
- data/lib/musicality/composition/convenience_methods.rb +53 -0
- data/lib/musicality/composition/dsl/score_dsl.rb +3 -6
- data/lib/musicality/composition/{note_generation.rb → util/note_generation.rb} +0 -15
- data/lib/musicality/notation/model/note.rb +1 -1
- data/lib/musicality/notation/model/score.rb +2 -1
- data/lib/musicality/printing/lilypond/score_engraver.rb +4 -4
- data/lib/musicality/printing/lilypond/score_engraving.rb +12 -0
- data/lib/musicality/version.rb +1 -1
- data/spec/composition/convenience_methods_spec.rb +60 -0
- data/spec/composition/{note_generation_spec.rb → util/note_generation_spec.rb} +1 -1
- data/spec/notation/model/note_spec.rb +1 -1
- data/spec/notation/model/score_spec.rb +32 -0
- metadata +10 -7
- data/lib/musicality/composition/transposition.rb +0 -8
- data/spec/composition/transposition_spec.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1b76956290ba2ff351587624b43db12c84fc99a5
|
4
|
+
data.tar.gz: 02460a5a7b390c335ffac5c8050b76bb280fd149
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ed2d94a4bd155e24a072481ed45027b362475c68628d41be6cf1e565e08636564fd71375f01936fbb74a7fe13dfcd5bcd22649117b76e5d179ffa83d19031d53
|
7
|
+
data.tar.gz: 05d65518d4f9d8abb5bda61490cdfa18d4458148648b46f6edc4ba518d10caaf6f12c9dea74522cc4615fd650441a0892e43057928d97b358dcdc2eacc6d540a
|
data/README.md
CHANGED
@@ -58,13 +58,56 @@ twinkle = Score::Measured.new(TWO_FOUR, 120) do |s|
|
|
58
58
|
end
|
59
59
|
```
|
60
60
|
|
61
|
-
|
61
|
+
## MIDI Sequencing
|
62
|
+
|
63
|
+
A score can be prepared for MIDI playback using the `ScoreSequencer` class or `#to_midi_seq` method. To continue the previous example,
|
62
64
|
```ruby
|
63
65
|
TEMPO_SAMPLE_RATE = 500
|
64
66
|
seq = twinkle.to_midi_seq TEMPO_SAMPLE_RATE
|
65
67
|
File.open('twinkle.mid', 'wb'){ |fout| seq.write(fout) }
|
66
68
|
```
|
67
|
-
##
|
69
|
+
## Score DSL
|
70
|
+
|
71
|
+
The score DSL is an internal DSL (built on Ruby) that consists of a *score* block with additional blocks inside this to add sections, notes, and tempo/meter/dynamic changes.
|
72
|
+
|
73
|
+
Here is an example of a score file.
|
74
|
+
```ruby
|
75
|
+
measured_score FOUR_FOUR, 120 do
|
76
|
+
title "Twinkle, Twinkle, Little Star"
|
77
|
+
|
78
|
+
Cmaj = [C3,E3,G3]
|
79
|
+
Fmaj = [F2,A2,C3]
|
80
|
+
Gmaj = [G2,B2,D3]
|
81
|
+
section "A" do
|
82
|
+
notes(
|
83
|
+
"rhand" => q(C4,C4,G4,G4,A4,A4) + h(G4) +
|
84
|
+
q(F4,F4,E4,E4,D4,D4) + h(C4),
|
85
|
+
"lhand" => h(Cmaj,Cmaj,Fmaj,Cmaj) +
|
86
|
+
h(Fmaj,Cmaj,Gmaj,Cmaj)
|
87
|
+
)
|
88
|
+
end
|
89
|
+
|
90
|
+
section "B" do
|
91
|
+
notes(
|
92
|
+
"rhand" => q(G4,G4,F4,F4,E4,E4) + h(D4),
|
93
|
+
"lhand" => h(Cmaj,Fmaj,Cmaj,Gmaj)
|
94
|
+
)
|
95
|
+
end
|
96
|
+
repeat "B"
|
97
|
+
repeat "A"
|
98
|
+
end
|
99
|
+
```
|
100
|
+
|
101
|
+
The above score file is processed by the `ScoreDSL.load` method, as in:
|
102
|
+
```ruby
|
103
|
+
require 'musicality'
|
104
|
+
include Musicality
|
105
|
+
include Meters
|
106
|
+
include Pitches
|
107
|
+
|
108
|
+
dsl = ScoreDSL.load 'twinkle.score'
|
109
|
+
score = dsl.score
|
110
|
+
```
|
68
111
|
|
69
112
|
## Contributing
|
70
113
|
|
data/bin/lilify
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
exe_name = File.basename(__FILE__)
|
4
|
+
|
5
|
+
doc = <<DOCOPT
|
6
|
+
Loads a musicality score from YAML file, and converts it to a Lilypond file for engraving.
|
7
|
+
|
8
|
+
Usage:
|
9
|
+
#{exe_name} <input> [PART TITLE] ... [options]
|
10
|
+
#{exe_name} -h | --help
|
11
|
+
#{exe_name} --version
|
12
|
+
|
13
|
+
Arguments:
|
14
|
+
input A musicality score file (may be packed as a hash) in YAML format
|
15
|
+
PART name of a part in the score (e.g. "lhand")
|
16
|
+
TITLE The title to give the part (e.g. "Left Hand")
|
17
|
+
|
18
|
+
Options:
|
19
|
+
--all Select all parts for engraving, and use part name as the title if not given
|
20
|
+
-h --help Show this screen.
|
21
|
+
--version Show version.
|
22
|
+
--outfile=OUTF Name of output Lilypond file
|
23
|
+
|
24
|
+
DOCOPT
|
25
|
+
|
26
|
+
require 'docopt'
|
27
|
+
begin
|
28
|
+
args = Docopt::docopt(doc)
|
29
|
+
puts args
|
30
|
+
rescue Docopt::Exit => e
|
31
|
+
puts e.message
|
32
|
+
exit
|
33
|
+
end
|
34
|
+
|
35
|
+
require 'musicality'
|
36
|
+
|
37
|
+
if args["--version"]
|
38
|
+
puts "#{exe_name} from musicality v#{Musicality::VERSION}"
|
39
|
+
exit
|
40
|
+
end
|
41
|
+
|
42
|
+
require 'yaml'
|
43
|
+
include Musicality
|
44
|
+
|
45
|
+
fin_name = args["<input>"]
|
46
|
+
File.open(fin_name) do |fin|
|
47
|
+
print "Reading file '#{fin_name}'..."
|
48
|
+
score = YAML.load(fin.read)
|
49
|
+
|
50
|
+
if score.is_a? Hash
|
51
|
+
score = Score.unpack(score)
|
52
|
+
end
|
53
|
+
puts "done"
|
54
|
+
|
55
|
+
if score.valid?
|
56
|
+
part_names = args["PART"]
|
57
|
+
part_titles = args["TITLE"]
|
58
|
+
name_title_map =
|
59
|
+
|
60
|
+
make_lilypond_args = {
|
61
|
+
:part_titles => Hash[[part_names,part_titles].transpose]
|
62
|
+
}
|
63
|
+
unless args["--all"]
|
64
|
+
make_lilypond_args[:selected_parts] = part_names
|
65
|
+
end
|
66
|
+
|
67
|
+
print "Making Lilypond instructions..."
|
68
|
+
engraver = ScoreEngraver.new(score)
|
69
|
+
lilypond_text = engraver.make_lilypond(make_lilypond_args)
|
70
|
+
puts "done"
|
71
|
+
|
72
|
+
fout_name = args["--outfile"]
|
73
|
+
if fout_name.nil?
|
74
|
+
fout_name = "#{File.dirname(fin_name)}/#{File.basename(fin_name,File.extname(fin_name))}.ly"
|
75
|
+
end
|
76
|
+
print "Writing Lilypond file '#{fout_name}'..."
|
77
|
+
File.write(fout_name, lilypond_text)
|
78
|
+
puts "done"
|
79
|
+
else
|
80
|
+
puts "Score is not valid. See errors:"
|
81
|
+
puts score.errors.join("\n")
|
82
|
+
end
|
83
|
+
end
|
data/bin/midify
CHANGED
@@ -33,8 +33,14 @@ rescue Docopt::Exit => e
|
|
33
33
|
exit
|
34
34
|
end
|
35
35
|
|
36
|
-
require 'yaml'
|
37
36
|
require 'musicality'
|
37
|
+
|
38
|
+
if args["--version"]
|
39
|
+
puts "#{exe_name} in musicality v#{Musicality::VERSION}"
|
40
|
+
exit
|
41
|
+
end
|
42
|
+
|
43
|
+
require 'yaml'
|
38
44
|
include Musicality
|
39
45
|
|
40
46
|
fin_name = args["<input>"]
|
data/lib/musicality.rb
CHANGED
@@ -69,6 +69,7 @@ require 'musicality/composition/util/adding_sequence'
|
|
69
69
|
require 'musicality/composition/util/compound_sequence'
|
70
70
|
require 'musicality/composition/util/random_sampler'
|
71
71
|
require 'musicality/composition/util/probabilities'
|
72
|
+
require 'musicality/composition/util/note_generation'
|
72
73
|
|
73
74
|
require 'musicality/composition/model/pitch_class'
|
74
75
|
require 'musicality/composition/model/pitch_classes'
|
@@ -76,15 +77,14 @@ require 'musicality/composition/model/scale'
|
|
76
77
|
require 'musicality/composition/model/scale_class'
|
77
78
|
require 'musicality/composition/model/scale_classes'
|
78
79
|
|
79
|
-
require 'musicality/composition/note_generation'
|
80
|
-
require 'musicality/composition/transposition'
|
81
|
-
|
82
80
|
require 'musicality/composition/generation/counterpoint_generator'
|
83
81
|
require 'musicality/composition/generation/random_rhythm_generator'
|
84
82
|
|
85
83
|
require 'musicality/composition/dsl/score_methods'
|
86
84
|
require 'musicality/composition/dsl/score_dsl'
|
87
85
|
|
86
|
+
require 'musicality/composition/convenience_methods'
|
87
|
+
|
88
88
|
#
|
89
89
|
# Performance
|
90
90
|
#
|
@@ -115,4 +115,5 @@ require 'musicality/printing/lilypond/errors'
|
|
115
115
|
require 'musicality/printing/lilypond/pitch_engraving'
|
116
116
|
require 'musicality/printing/lilypond/note_engraving'
|
117
117
|
require 'musicality/printing/lilypond/meter_engraving'
|
118
|
-
require 'musicality/printing/lilypond/score_engraver'
|
118
|
+
require 'musicality/printing/lilypond/score_engraver'
|
119
|
+
require 'musicality/printing/lilypond/score_engraving'
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Musicality
|
2
|
+
|
3
|
+
def transpose notes, diff
|
4
|
+
notes.map {|n| n.transpose(diff) }
|
5
|
+
end
|
6
|
+
module_function :transpose
|
7
|
+
|
8
|
+
def s(*pitch_groups)
|
9
|
+
pitch_groups.map {|pg| Note.sixteenth(pg) }
|
10
|
+
end
|
11
|
+
module_function :s
|
12
|
+
|
13
|
+
def ds(*pitch_groups)
|
14
|
+
pitch_groups.map {|pg| Note.dotted_sixteenth(pg) }
|
15
|
+
end
|
16
|
+
module_function :ds
|
17
|
+
|
18
|
+
def e(*pitch_groups)
|
19
|
+
pitch_groups.map {|pg| Note.eighth(pg) }
|
20
|
+
end
|
21
|
+
module_function :e
|
22
|
+
|
23
|
+
def de(*pitch_groups)
|
24
|
+
pitch_groups.map {|pg| Note.dotted_eighth(pg) }
|
25
|
+
end
|
26
|
+
module_function :e
|
27
|
+
|
28
|
+
def q(*pitch_groups)
|
29
|
+
pitch_groups.map {|pg| Note.quarter(pg) }
|
30
|
+
end
|
31
|
+
module_function :q
|
32
|
+
|
33
|
+
def dq(*pitch_groups)
|
34
|
+
pitch_groups.map {|pg| Note.dotted_quarter(pg) }
|
35
|
+
end
|
36
|
+
module_function :dq
|
37
|
+
|
38
|
+
def h(*pitch_groups)
|
39
|
+
pitch_groups.map {|pg| Note.half(pg) }
|
40
|
+
end
|
41
|
+
module_function :h
|
42
|
+
|
43
|
+
def dh(*pitch_groups)
|
44
|
+
pitch_groups.map {|pg| Note.dotted_half(pg) }
|
45
|
+
end
|
46
|
+
module_function :dh
|
47
|
+
|
48
|
+
def w(*pitch_groups)
|
49
|
+
pitch_groups.map {|pg| Note.whole(pg) }
|
50
|
+
end
|
51
|
+
module_function :w
|
52
|
+
|
53
|
+
end
|
@@ -1,24 +1,21 @@
|
|
1
1
|
module Musicality
|
2
2
|
|
3
|
-
class ScoreDSL
|
3
|
+
class ScoreDSL
|
4
4
|
def self.load fname
|
5
5
|
dsl = ScoreDSL.new
|
6
6
|
dsl.instance_eval(File.read(fname), fname)
|
7
7
|
dsl
|
8
8
|
end
|
9
9
|
|
10
|
+
attr_reader :score
|
10
11
|
def initialize
|
11
12
|
@score = nil
|
12
13
|
end
|
13
14
|
|
14
|
-
def
|
15
|
+
def measured_score start_meter, start_tempo, &block
|
15
16
|
@score = Score::Measured.new(start_meter,start_tempo)
|
16
17
|
@score.instance_eval(&block)
|
17
18
|
end
|
18
|
-
|
19
|
-
def score_yaml
|
20
|
-
@score.pack.to_yaml
|
21
|
-
end
|
22
19
|
end
|
23
20
|
|
24
21
|
end
|
@@ -28,19 +28,4 @@ def make_notes rhythm, pitch_groups
|
|
28
28
|
end
|
29
29
|
module_function :make_notes
|
30
30
|
|
31
|
-
def e(pitch_groups)
|
32
|
-
pitch_groups.map {|pg| Note.eighth(pg) }
|
33
|
-
end
|
34
|
-
module_function :e
|
35
|
-
|
36
|
-
def q(pitch_groups)
|
37
|
-
pitch_groups.map {|pg| Note.quarter(pg) }
|
38
|
-
end
|
39
|
-
module_function :q
|
40
|
-
|
41
|
-
def dq(pitch_groups)
|
42
|
-
pitch_groups.map {|pg| Note.dotted_quarter(pg) }
|
43
|
-
end
|
44
|
-
module_function :dq
|
45
|
-
|
46
31
|
end
|
@@ -44,7 +44,7 @@ class ScoreEngraver
|
|
44
44
|
output += " \\time #{@start_meter.to_lilypond}\n"
|
45
45
|
end
|
46
46
|
|
47
|
-
line = ""
|
47
|
+
line = " "
|
48
48
|
part.notes.each_index do |i|
|
49
49
|
note = part.notes[i]
|
50
50
|
begin
|
@@ -54,12 +54,12 @@ class ScoreEngraver
|
|
54
54
|
end
|
55
55
|
|
56
56
|
if (line.size + str.size) > MAX_LINE_LEN
|
57
|
-
output +=
|
58
|
-
line = ""
|
57
|
+
output += line + "\n"
|
58
|
+
line = " "
|
59
59
|
end
|
60
60
|
line += str
|
61
61
|
end
|
62
|
-
output +=
|
62
|
+
output += line + "\n"
|
63
63
|
|
64
64
|
output += " }\n"
|
65
65
|
end
|
data/lib/musicality/version.rb
CHANGED
@@ -0,0 +1,60 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe 'transpose' do
|
4
|
+
it 'should map given notes to new notes, transposing by given diff' do
|
5
|
+
notes = "/4A2,C2 /4D2,F2,Gb2 /8 /8E4".to_notes
|
6
|
+
semitones = 3
|
7
|
+
notes2 = transpose(notes,semitones)
|
8
|
+
|
9
|
+
notes2.size.should eq(notes.size)
|
10
|
+
notes2.each_index do |i|
|
11
|
+
notes2[i].pitches.each_with_index do |pitch2,j|
|
12
|
+
pitch = notes[i].pitches[j]
|
13
|
+
pitch2.diff(pitch).should eq(semitones)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
{
|
20
|
+
:s => "1/16".to_r,
|
21
|
+
:ds => "3/32".to_r,
|
22
|
+
:e => "1/8".to_r,
|
23
|
+
:de => "3/16".to_r,
|
24
|
+
:q => "1/4".to_r,
|
25
|
+
:dq => "3/8".to_r,
|
26
|
+
:h => "1/2".to_r,
|
27
|
+
:dh => "3/4".to_r,
|
28
|
+
:w => '1'.to_r
|
29
|
+
}.each do |method,dur|
|
30
|
+
describe method do
|
31
|
+
context 'given no args' do
|
32
|
+
it 'should produce an empty array' do
|
33
|
+
send(method).should eq([])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'given one pitch' do
|
38
|
+
it 'should produce an array with one note, with proper duration' do
|
39
|
+
send(method,*[C2]).should eq([Note.new(dur,C2)])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'given one pitch group' do
|
44
|
+
it 'should produce an array with one note, given pitch group, and with proper duration' do
|
45
|
+
send(method,*[[C2,E2,G2]]).should eq([Note.new(dur,[C2,E2,G2])])
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'given many pitch groups' do
|
50
|
+
it 'should produce an array of notes with same pitch groups, and with proper duration' do
|
51
|
+
pg1 = A3
|
52
|
+
pg2 = [B3,G3]
|
53
|
+
pg3 = F4
|
54
|
+
send(method,*[pg1,pg2,pg3]).should eq([
|
55
|
+
Note.new(dur,pg1), Note.new(dur,pg2), Note.new(dur,pg3)
|
56
|
+
])
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -1,6 +1,38 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
2
|
|
3
3
|
describe Score do
|
4
|
+
describe '#title' do
|
5
|
+
context 'given no arg' do
|
6
|
+
it 'should return the title' do
|
7
|
+
Score.new(:title => "MyTitle").title.should eq("MyTitle")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'given an arg' do
|
12
|
+
it 'should assign the given value to title' do
|
13
|
+
score = Score.new(:title => "MyTitle")
|
14
|
+
score.title("A Better Title")
|
15
|
+
score.title.should eq("A Better Title")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#composer' do
|
21
|
+
context 'given no arg' do
|
22
|
+
it 'should return the composer' do
|
23
|
+
Score.new(:composer => "Beethoven").composer.should eq("Beethoven")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'given an arg' do
|
28
|
+
it 'should assign the given value to composer' do
|
29
|
+
score = Score.new(:composer => "Beethoven")
|
30
|
+
score.composer("Mozart")
|
31
|
+
score.composer.should eq("Mozart")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
4
36
|
describe '#collated?' do
|
5
37
|
context 'has program with more than one segment' do
|
6
38
|
it 'should return false' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: musicality
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Tunnell
|
@@ -116,6 +116,7 @@ description: "The library is based around an abstract representation for music n
|
|
116
116
|
email:
|
117
117
|
- jamestunnell@gmail.com
|
118
118
|
executables:
|
119
|
+
- lilify
|
119
120
|
- midify
|
120
121
|
extensions: []
|
121
122
|
extra_rdoc_files: []
|
@@ -128,6 +129,7 @@ files:
|
|
128
129
|
- LICENSE.txt
|
129
130
|
- README.md
|
130
131
|
- Rakefile
|
132
|
+
- bin/lilify
|
131
133
|
- bin/midify
|
132
134
|
- examples/composition/auto_counterpoint.rb
|
133
135
|
- examples/composition/part_generator.rb
|
@@ -137,6 +139,7 @@ files:
|
|
137
139
|
- examples/notation/song1.rb
|
138
140
|
- examples/notation/song2.rb
|
139
141
|
- lib/musicality.rb
|
142
|
+
- lib/musicality/composition/convenience_methods.rb
|
140
143
|
- lib/musicality/composition/dsl/score_dsl.rb
|
141
144
|
- lib/musicality/composition/dsl/score_methods.rb
|
142
145
|
- lib/musicality/composition/generation/counterpoint_generator.rb
|
@@ -146,11 +149,10 @@ files:
|
|
146
149
|
- lib/musicality/composition/model/scale.rb
|
147
150
|
- lib/musicality/composition/model/scale_class.rb
|
148
151
|
- lib/musicality/composition/model/scale_classes.rb
|
149
|
-
- lib/musicality/composition/note_generation.rb
|
150
|
-
- lib/musicality/composition/transposition.rb
|
151
152
|
- lib/musicality/composition/util/adding_sequence.rb
|
152
153
|
- lib/musicality/composition/util/biinfinite_sequence.rb
|
153
154
|
- lib/musicality/composition/util/compound_sequence.rb
|
155
|
+
- lib/musicality/composition/util/note_generation.rb
|
154
156
|
- lib/musicality/composition/util/probabilities.rb
|
155
157
|
- lib/musicality/composition/util/random_sampler.rb
|
156
158
|
- lib/musicality/composition/util/repeating_sequence.rb
|
@@ -233,18 +235,19 @@ files:
|
|
233
235
|
- lib/musicality/printing/lilypond/part_engraver.rb
|
234
236
|
- lib/musicality/printing/lilypond/pitch_engraving.rb
|
235
237
|
- lib/musicality/printing/lilypond/score_engraver.rb
|
238
|
+
- lib/musicality/printing/lilypond/score_engraving.rb
|
236
239
|
- lib/musicality/validatable.rb
|
237
240
|
- lib/musicality/version.rb
|
238
241
|
- musicality.gemspec
|
242
|
+
- spec/composition/convenience_methods_spec.rb
|
239
243
|
- spec/composition/generation/random_rhythm_generator_spec.rb
|
240
244
|
- spec/composition/model/pitch_class_spec.rb
|
241
245
|
- spec/composition/model/pitch_classes_spec.rb
|
242
246
|
- spec/composition/model/scale_class_spec.rb
|
243
247
|
- spec/composition/model/scale_spec.rb
|
244
|
-
- spec/composition/note_generation_spec.rb
|
245
|
-
- spec/composition/transposition_spec.rb
|
246
248
|
- spec/composition/util/adding_sequence_spec.rb
|
247
249
|
- spec/composition/util/compound_sequence_spec.rb
|
250
|
+
- spec/composition/util/note_generation_spec.rb
|
248
251
|
- spec/composition/util/probabilities_spec.rb
|
249
252
|
- spec/composition/util/random_sampler_spec.rb
|
250
253
|
- spec/composition/util/repeating_sequence_spec.rb
|
@@ -323,15 +326,15 @@ signing_key:
|
|
323
326
|
specification_version: 4
|
324
327
|
summary: Music notation, composition, and performance
|
325
328
|
test_files:
|
329
|
+
- spec/composition/convenience_methods_spec.rb
|
326
330
|
- spec/composition/generation/random_rhythm_generator_spec.rb
|
327
331
|
- spec/composition/model/pitch_class_spec.rb
|
328
332
|
- spec/composition/model/pitch_classes_spec.rb
|
329
333
|
- spec/composition/model/scale_class_spec.rb
|
330
334
|
- spec/composition/model/scale_spec.rb
|
331
|
-
- spec/composition/note_generation_spec.rb
|
332
|
-
- spec/composition/transposition_spec.rb
|
333
335
|
- spec/composition/util/adding_sequence_spec.rb
|
334
336
|
- spec/composition/util/compound_sequence_spec.rb
|
337
|
+
- spec/composition/util/note_generation_spec.rb
|
335
338
|
- spec/composition/util/probabilities_spec.rb
|
336
339
|
- spec/composition/util/random_sampler_spec.rb
|
337
340
|
- spec/composition/util/repeating_sequence_spec.rb
|
@@ -1,17 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
-
|
3
|
-
describe 'transpose' do
|
4
|
-
it 'should map given notes to new notes, transposing by given diff' do
|
5
|
-
notes = "/4A2,C2 /4D2,F2,Gb2 /8 /8E4".to_notes
|
6
|
-
semitones = 3
|
7
|
-
notes2 = transpose(notes,semitones)
|
8
|
-
|
9
|
-
notes2.size.should eq(notes.size)
|
10
|
-
notes2.each_index do |i|
|
11
|
-
notes2[i].pitches.each_with_index do |pitch2,j|
|
12
|
-
pitch = notes[i].pitches[j]
|
13
|
-
pitch2.diff(pitch).should eq(semitones)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|