lygre 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c100850289adec3dc56f49db675050c9363706e0
4
- data.tar.gz: a47121a23251de440329e1866dbacb532dd07152
3
+ metadata.gz: b246c70e332e42827f7747ab0439d890b368b720
4
+ data.tar.gz: 6029592482f7d71440f9a5dd402715ad4f504f12
5
5
  SHA512:
6
- metadata.gz: 38b9473ca607f631bd91e10138d5492bb5b72e4ecaceab71d70c13ee7bc8caa521e494f2b1f30889c81412e495dfdf1eae144539982b1e56af80315453fb9d10
7
- data.tar.gz: f697b60699d01c32a0eeb2150351e4765357fbba409917a940b7c1c421a37bf90c4061c1b38a83661412ccf3b336054ca7f269f5fc2c6727cbd1da666b3ffeb9
6
+ metadata.gz: b6bb4e396985f00612b94be4e3b53bbdc4adfdaebd2f7a950e66824aa7d979d966008fb08eb69678e2850e3680352dc562052e7646d8d841f783a77242b53c81
7
+ data.tar.gz: 2fca20a9e491d4b5d33f87d95cdd1a6239a65b49ca797f0cb236dd435595da19112b813a8dc5adc84debebad70bbb8c49ce046a789cb7b6e84bb38dd99616020
@@ -4,10 +4,7 @@
4
4
  gabcscore
5
5
  gabcsemantics
6
6
  gabcpitchreader
7
+ gabcparser
7
8
  lilypondconvertor
9
+ musictheory
8
10
  }.each {|f| require_relative File.join('lygre', f)}
9
-
10
- # gabc parser
11
- require 'polyglot'
12
- require 'treetop'
13
- Treetop.load File.expand_path('../lib/lygre/gabcgrammar', File.dirname(__FILE__))
@@ -0,0 +1,4 @@
1
+ # load treetop grammar, emit class GabcParser
2
+ require 'polyglot'
3
+ require 'treetop'
4
+ Treetop.load File.expand_path('gabcgrammar', File.dirname(__FILE__))
@@ -1,7 +1,5 @@
1
1
  # encoding: UTF-8
2
2
 
3
- require 'rb-music-theory'
4
-
5
3
  # responsible for converting the 'visual pitch' information
6
4
  # contained in gabc to absolute musical pitch
7
5
  class GabcPitchReader
@@ -55,18 +53,13 @@ class NoteFactory
55
53
  note = notesym[0]
56
54
  octaves = notesym[1..-1]
57
55
 
58
- n = RBMusicTheory::Note.new note.upcase
59
56
  sign = 0
60
- base_octave_shift = -1 # Note.new('C') returns c'=60, not c=48
57
+ octave = 0
61
58
  if octaves then
62
59
  sign = (octaves[0] == ',' ? -1 : 1)
63
- octave_shift = (octaves.size * sign) + base_octave_shift
64
- else
65
- octave_shift = base_octave_shift
60
+ octave += (octaves.size * sign)
66
61
  end
67
- n += octave_shift * RBMusicTheory::NoteInterval.octave.value # strangely, NoteInterval cannot be multiplied
68
-
69
- return n
62
+ return MusicTheory::Note.new note.to_sym, octave
70
63
  end
71
64
 
72
65
  alias :create_note :create
@@ -78,57 +71,8 @@ class NoteFactory
78
71
  # #create translates lilypond pitch to Note and #lily_abs_pitch
79
72
  # does the reverse translation, so maybe just the class should be renamed
80
73
  def lily_abs_pitch(note)
81
- octave_shifts = ''
82
- octave_diff = note.value - create('c').value
83
-
84
- octave_value = RBMusicTheory::NoteInterval.octave.value
85
- octave_shift = octave_diff.abs / octave_value
86
- if octave_diff < 0 and (octave_diff.abs % octave_value) > 0 then
87
- octave_shift += 1
88
- end
89
-
90
- octave_signs = (octave_diff >= 0 ? "'" : ",") * octave_shift
91
- note.name.downcase + octave_signs
92
- end
93
- end
94
- end
95
-
96
- # monkey-patch Note to add step arithmetics
97
- module RBMusicTheory
98
-
99
- class Note
100
-
101
- def diatonic_steps(steps, scale=nil)
102
- if scale.nil? then
103
- scale = self.class.new('C').major_scale
104
- end
105
-
106
- deg = self.degree_in(scale)
107
-
108
- return scale.degree(deg + steps)
109
- end
110
-
111
- # note's degree in a scale
112
- def degree_in(scale)
113
- degree = scale.note_names.index(self.name)
114
- if degree.nil? then
115
- raise ArgumentError.new("#{name} is not a member of #{scale.note_names} scale")
116
- end
117
- degree += 1 # degrees start with 1
118
-
119
- in_base_octave = scale.degree(degree)
120
- octave_steps = scale.note_names.size
121
- octave_value = RBMusicTheory::NoteInterval.octave.value
122
-
123
- value_difference = self.value - in_base_octave.value
124
- octave_difference = value_difference.abs / octave_value
125
- if value_difference < 0 then
126
- octave_difference *= -1
127
- end
128
-
129
- degree += octave_difference * octave_steps
130
-
131
- return degree
74
+ octave_signs = (note.octave >= 0 ? "'" : ",") * note.octave.abs
75
+ note.pitch.to_s + octave_signs
132
76
  end
133
77
  end
134
78
  end
@@ -15,6 +15,8 @@ class Immutable
15
15
 
16
16
  freeze
17
17
  end
18
+
19
+ attr_accessor :text_value
18
20
  end
19
21
 
20
22
  # clean and easy to use music data produced by
@@ -100,16 +100,19 @@ module Gabc
100
100
  if ele.is_a? NoteNode then
101
101
  arr << GabcNote.new do |n|
102
102
  n.pitch = ele.note_pitch.text_value.downcase.to_sym
103
+ n.text_value = ele.text_value
103
104
  end
104
105
  elsif ele.is_a? DivisioNode then
105
106
  arr << GabcDivisio.new do |d|
106
107
  d.type = ele.text_value
108
+ d.text_value = ele.text_value
107
109
  end
108
110
  elsif ele.is_a? ClefNode then
109
111
  arr << GabcClef.new do |c|
110
112
  c.pitch = ele.clef_symbol.text_value.to_sym
111
113
  c.bemol = ele.bemol.text_value == 'b'
112
114
  c.line = ele.line_number.text_value.to_i
115
+ c.text_value = ele.text_value
113
116
  end
114
117
  else
115
118
  collect_notes ele, arr
@@ -0,0 +1,44 @@
1
+ # Simple diatonic music theory necessary for parsing of Gregorian chant scores
2
+ module MusicTheory
3
+ PITCHES = [:c, :d, :e, :f, :g, :a, :b]
4
+ VALUES = [0, 2, 4, 5, 7, 9, 11]
5
+
6
+ class Note
7
+ def initialize(pitch=:c, octave=1)
8
+ @pitch = pitch
9
+ @pitch_numeric = PITCHES.index @pitch
10
+ @octave = octave
11
+
12
+ if @pitch_numeric.nil?
13
+ raise ArgumentError.new("Invalid pitch #{pitch.inspect}")
14
+ end
15
+ end
16
+
17
+ attr_reader :pitch, :octave
18
+
19
+ def diatonic_steps(steps)
20
+ base_steps = steps % PITCHES.size
21
+ octaves = steps / PITCHES.size
22
+ new_step = @pitch_numeric + base_steps
23
+ if new_step >= PITCHES.size
24
+ new_step -= PITCHES.size
25
+ octaves += 1
26
+ end
27
+ new_pitch = PITCHES[new_step]
28
+ self.class.new(new_pitch, @octave + octaves)
29
+ end
30
+
31
+ def value
32
+ (@octave + 4) * 12 + VALUES[@pitch_numeric]
33
+ end
34
+
35
+ def ==(other)
36
+ other.pitch == @pitch &&
37
+ other.octave == @octave
38
+ end
39
+
40
+ def hash
41
+ [@pitch, @octave].hash
42
+ end
43
+ end
44
+ end
@@ -1,4 +1,5 @@
1
1
  # encoding: UTF-8
2
+ require 'spec_helper'
2
3
 
3
4
  describe GabcPitchReader do
4
5
 
@@ -70,9 +71,9 @@ describe NoteFactory do
70
71
  end
71
72
 
72
73
  describe '.lily_abs_pitch' do
73
- it 'operates exactly reverse to .create' do
74
+ describe 'operates exactly reverse to .create' do
74
75
  %w{ c d g c' f' a' b' g'' d''' c, c,, c,,, d, e, e,, b, }.each do |lypitch|
75
- @f.lily_abs_pitch(@f[lypitch]).should eq lypitch
76
+ it { @f.lily_abs_pitch(@f[lypitch]).should eq lypitch }
76
77
  end
77
78
  end
78
79
  end
@@ -82,55 +83,3 @@ describe NoteFactory do
82
83
  it { @f["c''"].value.should eq 72 }
83
84
  end
84
85
  end
85
-
86
- describe 'monkey-patched RBMusicTheory' do
87
-
88
- before :each do
89
- @f = NoteFactory
90
- @s = @f["c''"].major_scale
91
- end
92
-
93
- describe 'Note#diatonic_steps' do
94
- it { @f["c'"].diatonic_steps(1).should eq @f["d'"] }
95
- it { @f["c'"].diatonic_steps(0).should eq @f["c'"] }
96
- it { @f["c'"].diatonic_steps(7).should eq @f["c''"] }
97
- it { @f["c'"].diatonic_steps(8).should eq @f["d''"] }
98
- it { @f["c'"].diatonic_steps(-2).should eq @f["a"] }
99
- it { @f["c''"].diatonic_steps(-9).should eq @f["a"] }
100
- it { @f["c'''"].diatonic_steps(-9).should eq @f["a'"] }
101
- it { @f["c,"].diatonic_steps(-9).should eq @f["a,,,"] }
102
- it { @f["c,"].diatonic_steps(-10).should eq @f["g,,,"] }
103
- end
104
-
105
- describe 'Note#degree_in' do
106
- it { @f["c''"].degree_in(@s).should eq 1 }
107
- it { @f["d''"].degree_in(@s).should eq 2 }
108
-
109
- it { @f["c'''"].degree_in(@s).should eq 8 }
110
- it { @f["e'''"].degree_in(@s).should eq 10 }
111
- it { @f["b'"].degree_in(@s).should eq 0 }
112
- it { @f["a'"].degree_in(@s).should eq -1 }
113
- it { @f["a"].degree_in(@s).should eq -8 }
114
-
115
- it 'behaves consistently with Scale#degree' do
116
- [2, 8, -1, -12].each do |deg|
117
- @s.degree(deg).degree_in(@s).should eq deg
118
- end
119
- end
120
- end
121
-
122
- describe 'Scale#degree' do
123
- describe 'for positive degrees it behaves as expected' do
124
- it { @s.degree(1).should eq @f["c''"] }
125
- it { @s.degree(2).should eq @f["d''"] }
126
- it { @s.degree(8).should eq @f["c'''"] }
127
- end
128
-
129
- describe 'and then there is zero and negative numbers' do
130
- it { @s.degree(0).should eq @f["b'"] }
131
- it { @s.degree(-1).should eq @f["a'"] }
132
- it { @s.degree(-8).should eq @f["a"] }
133
- it { @s.degree(-15).should eq @f["a,"] }
134
- end
135
- end
136
- end
@@ -0,0 +1,44 @@
1
+ # encoding: UTF-8
2
+ require 'spec_helper'
3
+
4
+ describe MusicTheory do
5
+ describe MusicTheory::Note do
6
+ let(:c1) { described_class.new(:c) }
7
+ let(:c2) { described_class.new(:c, 2) }
8
+
9
+ describe '#diatonic_steps' do
10
+ it 'step in the base octave' do
11
+ c1.diatonic_steps(1).should eq described_class.new(:d)
12
+ end
13
+
14
+ it 'octave step' do
15
+ c1.diatonic_steps(7).should eq c2
16
+ end
17
+
18
+ it 'single step to the next octave' do
19
+ b = described_class.new(:b)
20
+ b.diatonic_steps(1).should eq c2
21
+ end
22
+
23
+ it 'single step to the previous octave' do
24
+ c1.diatonic_steps(-1).should eq described_class.new(:b, 0)
25
+ end
26
+
27
+ it 'preserve octave' do
28
+ c = described_class.new(:c, -1)
29
+ c.diatonic_steps(1).should eq described_class.new(:d, -1)
30
+ end
31
+ end
32
+
33
+ describe '#value' do
34
+ it { c1.value.should eq 60 }
35
+ it { described_class.new(:d).value.should eq 62 }
36
+ it { described_class.new(:e).value.should eq 64 }
37
+ it { described_class.new(:f).value.should eq 65 }
38
+ it { described_class.new(:g).value.should eq 67 }
39
+ it { described_class.new(:a).value.should eq 69 }
40
+ it { described_class.new(:b).value.should eq 71 }
41
+ it { described_class.new(:c, 2).value.should eq 72 }
42
+ end
43
+ end
44
+ end
@@ -15,17 +15,8 @@ RSpec.configure do |config|
15
15
  config.order = 'random'
16
16
  end
17
17
 
18
- require 'polyglot'
19
- require 'treetop'
20
-
21
18
  require_relative 'matchers'
22
19
 
23
-
24
- $: << '../lib'
25
- require 'grely'
26
-
27
- Treetop.load File.expand_path('../lib/lygre/gabcgrammar', File.dirname(__FILE__))
28
-
29
20
  def load_example(fname)
30
21
  File.read(
31
22
  File.expand_path(
@@ -34,3 +25,6 @@ def load_example(fname)
34
25
  )
35
26
  )
36
27
  end
28
+
29
+ # load the tested code
30
+ require_relative '../lib/grely'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lygre
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jakub Pavlík
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-02 00:00:00.000000000 Z
11
+ date: 2016-12-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: treetop
@@ -38,20 +38,6 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0.3'
41
- - !ruby/object:Gem::Dependency
42
- name: rb-music-theory
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '0.1'
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '0.1'
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: rspec
57
43
  requirement: !ruby/object:Gem::Requirement
@@ -74,10 +60,6 @@ description: |
74
60
  input format (gabc) to simple LilyPond input.
75
61
 
76
62
  In future another tool for the other direction of conversion may be added.
77
-
78
- As rb-music-theory is not at RubyGems, either install it before
79
- attempting to 'gem install lygre', or get lygre's source from github
80
- and install the dependencies by 'bundle install'.
81
63
  email: jkb.pavlik@gmail.com
82
64
  executables:
83
65
  - grely.rb
@@ -87,16 +69,19 @@ files:
87
69
  - bin/grely.rb
88
70
  - lib/grely.rb
89
71
  - lib/lygre/gabcgrammar.treetop
72
+ - lib/lygre/gabcparser.rb
90
73
  - lib/lygre/gabcpitchreader.rb
91
74
  - lib/lygre/gabcscore.rb
92
75
  - lib/lygre/gabcsemantics.rb
93
76
  - lib/lygre/lilypondconvertor.rb
77
+ - lib/lygre/musictheory.rb
94
78
  - spec/gabcgrammar_spec.rb
95
79
  - spec/gabcparser_spec.rb
96
80
  - spec/gabcpitchreader_spec.rb
97
81
  - spec/gabcscore_spec.rb
98
82
  - spec/lilypondconvertor_spec.rb
99
83
  - spec/matchers.rb
84
+ - spec/musictheory_spec.rb
100
85
  - spec/spec_helper.rb
101
86
  homepage: http://github.com/igneus/lygre
102
87
  licenses:
@@ -119,7 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
104
  version: '0'
120
105
  requirements: []
121
106
  rubyforge_project:
122
- rubygems_version: 2.4.8
107
+ rubygems_version: 2.2.0
123
108
  signing_key:
124
109
  specification_version: 4
125
110
  summary: converts music formats gabc -> lilypond