mirror of
https://github.com/microtherion/VocalEasel.git
synced 2024-12-22 11:14:00 +00:00
Read harmony elements
This commit is contained in:
parent
81cfec4fea
commit
48798ae5a1
|
@ -28,6 +28,75 @@ SYLL = {
|
|||
'middle' => 3
|
||||
}
|
||||
|
||||
CHORD = {
|
||||
#
|
||||
# Triads
|
||||
#
|
||||
'major' => VL::Chord::Maj,
|
||||
'minor' => VL::Chord::Min,
|
||||
'augmented' => VL::Chord::Aug,
|
||||
'diminished' => VL::Chord::Dim,
|
||||
#
|
||||
# 7ths
|
||||
#
|
||||
'dominant' => VL::Chord::Dom7,
|
||||
'major-seventh' => VL::Chord::Maj7,
|
||||
'minor-seventh' => VL::Chord::Min7,
|
||||
'diminished-seventh' => VL::Chord::Dim7,
|
||||
'augmented-seventh' => VL::Chord::Aug7,
|
||||
'half-diminished' => VL::Chord::M7b5,
|
||||
'major-minor' => VL::Chord::MMin7,
|
||||
#
|
||||
# 6ths
|
||||
#
|
||||
'major-sixth' => VL::Chord::Maj6,
|
||||
'minor-sixth' => VL::Chord::Min6,
|
||||
#
|
||||
# 9ths
|
||||
#
|
||||
'dominant-ninth' => VL::Chord::Dom9,
|
||||
'major-ninth' => VL::Chord::Maj9,
|
||||
'minor-ninth' => VL::Chord::Min9,
|
||||
#
|
||||
# 11ths
|
||||
#
|
||||
'dominant-11th' => VL::Chord::Dom11,
|
||||
'major-11th' => VL::Chord::Maj11,
|
||||
'minor-11th' => VL::Chord::Min11,
|
||||
#
|
||||
# 13ths
|
||||
#
|
||||
'dominant-13th' => VL::Chord::Dom13,
|
||||
'major-13th' => VL::Chord::Maj13,
|
||||
'minor-13th' => VL::Chord::Min13,
|
||||
#
|
||||
# Suspended
|
||||
#
|
||||
'suspended-second' => VL::Chord::Sus2,
|
||||
'suspended-fourth' => VL::Chord::Sus4,
|
||||
#
|
||||
# Varia
|
||||
#
|
||||
'other' => VL::Unison,
|
||||
'none' => 0
|
||||
}
|
||||
|
||||
DEGREE = [
|
||||
[VL::Unison, VL::Unison],
|
||||
[VL::Min2nd+VL::Maj2nd, VL::Maj2nd],
|
||||
[VL::Min3rd+VL::Maj3rd, VL::Maj3rd],
|
||||
[VL::Fourth, VL::Fourth],
|
||||
[VL::Fifth, VL::Fifth],
|
||||
[VL::Aug5th+VL::Dim7th, VL::Dim7th],
|
||||
[VL::Min7th+VL::Maj7th, VL::Min7th],
|
||||
[VL::Octave, VL::Octave],
|
||||
[VL::Min9th+VL::Maj9th, VL::Maj9th],
|
||||
[VL::Aug9th+VL::Dim11th, VL::Dim11th],
|
||||
[VL::Eleventh, VL::Eleventh],
|
||||
[VL::Aug11th+VL::Dim13th, VL::Dim13th],
|
||||
[VL::Min13th+VL::Maj13th, VL::Maj13th]
|
||||
];
|
||||
|
||||
class MusicXMLListener
|
||||
include REXML::StreamListener
|
||||
|
||||
|
@ -72,7 +141,9 @@ class MusicXMLListener
|
|||
@measNo = -1
|
||||
when 'measure' then
|
||||
@notes= []
|
||||
@harm = []
|
||||
@chord= false
|
||||
@at = 0
|
||||
if a = attrs['number']
|
||||
@measNo = a.to_i-1
|
||||
else
|
||||
|
@ -117,11 +188,21 @@ class MusicXMLListener
|
|||
when 'beat-type' then
|
||||
@kind = 'prop'
|
||||
@key = 'timeDenom'
|
||||
when 'harmony' then
|
||||
@note = { 'pitch' => VL::NoPitch, 'steps' => 0, 'root' => VL::NoPitch,
|
||||
'at' => @at }
|
||||
when 'degree' then
|
||||
@degree_value = 0
|
||||
@degree_alter = 0
|
||||
@degree_type = "alter"
|
||||
when 'note' then
|
||||
@note = { 'pitch' => 0, 'durNum' => 0, 'durDenom' => 0 }
|
||||
when 'rest' then
|
||||
@note['pitch'] = -128
|
||||
when 'mode', 'step', 'alter', 'octave', 'duration', 'syllabic', 'text' then
|
||||
@note['pitch'] = VL::NoPitch
|
||||
when 'mode', 'step', 'alter', 'octave', 'duration', 'syllabic', 'text',
|
||||
'root-step', 'root-alter', 'bass-step', 'bass-alter', 'kind',
|
||||
'degree-value', 'degree-alter', 'degree-type'
|
||||
then
|
||||
@kind = tag
|
||||
when 'tie' then
|
||||
@note['tied'] ||= 0
|
||||
|
@ -146,12 +227,12 @@ class MusicXMLListener
|
|||
|
||||
def makeChords(chords)
|
||||
chords.each do |chord|
|
||||
chord['root'] = -128
|
||||
chord['root'] = VL::NoPitch
|
||||
st = [*chord['pitch']].sort
|
||||
pitch = st[0]
|
||||
if pitch > 0 && pitch < 60
|
||||
chord['root'] = st.shift
|
||||
pitch = st[0] || -128
|
||||
pitch = st[0] || VL::NoPitch
|
||||
end
|
||||
steps = 0
|
||||
if pitch > 0
|
||||
|
@ -166,6 +247,24 @@ class MusicXMLListener
|
|||
return chords
|
||||
end
|
||||
|
||||
def makeHarmChords(harm)
|
||||
chords = []
|
||||
durDenom = @prop['divisions']*4
|
||||
if harm[0]['at'] > 0
|
||||
chords.push({'pitch' => VL::NoPitch, 'steps' => 0, 'root' => VL::NoPitch,
|
||||
'durNum' => harm[0]['at'], 'durDenom' => durDenom})
|
||||
end
|
||||
(0..harm.length-1).each do |i|
|
||||
chord = harm[i]
|
||||
nextAt = i+1 < harm.length ? harm[i+1]['at'] : @at
|
||||
chord['durNum'] = nextAt - chord.delete('at')
|
||||
chord['durDenom'] = durDenom
|
||||
chords.push(chord)
|
||||
end
|
||||
|
||||
return chords
|
||||
end
|
||||
|
||||
def makeVolta(number)
|
||||
volta = 0
|
||||
number.split(/,\s*/).each do |v|
|
||||
|
@ -184,20 +283,38 @@ class MusicXMLListener
|
|||
when 'textProp' then
|
||||
OUTPUT[@key] = @text
|
||||
when 'dateProp' then
|
||||
begin
|
||||
OUTPUT[@key] = Time.parse(@text)
|
||||
rescue
|
||||
OUTPUT[@key] = Time.now
|
||||
end
|
||||
when 'prop' then
|
||||
@prop[@key] = @text.to_i
|
||||
when 'mode' then
|
||||
@prop['mode'] = @text == 'minor' ? -1 : 1
|
||||
when 'step' then
|
||||
@note['pitch'] += PITCH[@text]
|
||||
when 'alter' then
|
||||
when 'alter', 'root-alter' then
|
||||
@note['pitch'] += @text.to_i
|
||||
when 'octave' then
|
||||
@note['pitch'] += (@text.to_i+1)*12
|
||||
when 'duration' then
|
||||
@note['durNum'] = @text.to_i
|
||||
@note['durDenom'] = @prop['divisions']*4
|
||||
when 'root-step' then
|
||||
@note['pitch'] = PITCH[@text]
|
||||
when 'bass-step' then
|
||||
@note['root'] = PITCH[@text]
|
||||
when 'bass-alter' then
|
||||
@note['root'] += @text.to_i
|
||||
when 'kind' then
|
||||
@note['steps'] = CHORD[@text]
|
||||
when 'degree-value' then
|
||||
@degree_value = @text.to_i-1
|
||||
when 'degree-alter' then
|
||||
@degree_alter = @text.to_i
|
||||
when 'degree-type' then
|
||||
@degree_type = @text
|
||||
when 'syllabic' then
|
||||
@lyric['kind'] = SYLL[@text]
|
||||
when 'text' then
|
||||
|
@ -220,7 +337,35 @@ class MusicXMLListener
|
|||
@chord = false
|
||||
else
|
||||
@notes.push(@note)
|
||||
@at += @note['durNum']
|
||||
end
|
||||
when 'degree' then
|
||||
oldSteps = @note['steps']
|
||||
oldValue = @degree_value
|
||||
case @degree_type
|
||||
when 'subtract' then
|
||||
@note['steps'] &= ~DEGREE[@degree_value][0]
|
||||
when 'add' then
|
||||
@degree_value = DEGREE[@degree_value][1]
|
||||
if @degree_alter < 0
|
||||
@degree_value >>= -@degree_alter
|
||||
elsif @degree_alter > 0
|
||||
@degree_value <<= @degree_alter
|
||||
end
|
||||
@note['steps'] |= @degree_value
|
||||
when 'alter' then
|
||||
@degree_value = @note['steps'] & DEGREE[@degree_value][0]
|
||||
@note['steps'] ^= @degree_value
|
||||
if @degree_alter < 0
|
||||
@degree_value >>= -@degree_alter
|
||||
elsif @degree_alter > 0
|
||||
@degree_value <<= @degree_alter
|
||||
end
|
||||
@note['steps'] |= @degree_value
|
||||
end
|
||||
# $stderr.puts "#{@degree_type} #{oldValue} #{@degree_alter} (#{oldSteps} -> #{@note['steps']})"
|
||||
when 'harmony' then
|
||||
@harm.push(@note)
|
||||
when 'barline' then
|
||||
case @type
|
||||
when 'start' then
|
||||
|
@ -233,20 +378,25 @@ class MusicXMLListener
|
|||
'last' => @type == 'discontinue'
|
||||
}
|
||||
else
|
||||
if @times
|
||||
if @times > 0
|
||||
@meas['end-repeat'] = {
|
||||
'times' => @times
|
||||
}
|
||||
elsif @times == 0
|
||||
else @times == 0
|
||||
@meas['begin-repeat'] = {}
|
||||
end
|
||||
end
|
||||
end
|
||||
when 'measure' then
|
||||
@meas['properties'] = @props.length-1 unless @props.empty?
|
||||
if @part == 'HARM'
|
||||
@meas['chords'] = makeChords(@notes)
|
||||
else
|
||||
@meas['melody'] = @notes
|
||||
unless @harm.empty?
|
||||
@meas['chords'] = makeHarmChords(@harm)
|
||||
end
|
||||
end
|
||||
when 'part' then
|
||||
OUTPUT['properties'] = @props unless @part == 'HARM'
|
||||
|
|
|
@ -8,4 +8,75 @@ class VL
|
|||
TiedWithNext = 1
|
||||
TiedWithPrev = 2
|
||||
InChord = 4
|
||||
|
||||
Unison = 1<<0
|
||||
Min2nd = 1<<1
|
||||
Maj2nd = 1<<2
|
||||
Min3rd = 1<<3
|
||||
Maj3rd = 1<<4
|
||||
Fourth = 1<<5
|
||||
Dim5th = 1<<6
|
||||
Fifth = 1<<7
|
||||
Aug5th = 1<<8
|
||||
Dim7th = 1<<9
|
||||
Min7th = 1<<10
|
||||
Maj7th = 1<<11
|
||||
Octave = 1<<12
|
||||
Min9th = 1<<13
|
||||
Maj9th = 1<<14
|
||||
Aug9th = 1<<15
|
||||
Dim11th = 1<<16
|
||||
Eleventh = 1<<17
|
||||
Aug11th = 1<<18
|
||||
Dim13th = 1<<19
|
||||
Min13th = 1<<20
|
||||
Maj13th = 1<<21
|
||||
|
||||
class Chord
|
||||
#
|
||||
# Triads
|
||||
#
|
||||
Maj = VL::Unison+VL::Maj3rd+VL::Fifth
|
||||
Min = VL::Unison+VL::Min3rd+VL::Fifth
|
||||
Aug = VL::Unison+VL::Maj3rd+VL::Aug5th
|
||||
Dim = VL::Unison+VL::Min3rd+VL::Dim5th
|
||||
#
|
||||
# 7ths
|
||||
#
|
||||
Dom7 = Maj+VL::Min7th
|
||||
Maj7 = Maj+VL::Maj7th
|
||||
Min7 = Min+VL::Min7th
|
||||
Dim7 = Dim+VL::Dim7th
|
||||
Aug7 = Aug+VL::Min7th
|
||||
M7b5 = Dim+VL::Min7th
|
||||
MMin7 = Min+VL::Maj7th
|
||||
#
|
||||
# 6ths
|
||||
#
|
||||
Maj6 = Maj+VL::Dim7th
|
||||
Min6 = Min+VL::Dim7th
|
||||
#
|
||||
# 9ths
|
||||
#
|
||||
Dom9 = Dom7+VL::Maj9th
|
||||
Maj9 = Maj7+VL::Maj9th
|
||||
Min9 = Min7+VL::Maj9th
|
||||
#
|
||||
# 11ths
|
||||
#
|
||||
Dom11 = Dom9+VL::Eleventh
|
||||
Maj11 = Maj9+VL::Eleventh
|
||||
Min11 = Min9+VL::Eleventh
|
||||
#
|
||||
# 13ths
|
||||
#
|
||||
Dom13 = Dom11+VL::Maj13th
|
||||
Maj13 = Maj11+VL::Maj13th
|
||||
Min13 = Min11+VL::Maj13th
|
||||
#
|
||||
# Suspended
|
||||
#
|
||||
Sus4 = VL::Unison+VL::Fourth+VL::Fifth
|
||||
Sus2 = VL::Unison+VL::Maj2nd+VL::Fifth
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue
Block a user