stretto 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.markdown +0 -0
- data/README.markdown +67 -0
- data/Rakefile +9 -0
- data/lib/stretto.rb +14 -0
- data/lib/stretto/grammar/channel_pressure_grammar.treetop +9 -0
- data/lib/stretto/grammar/chord_grammar.treetop +60 -0
- data/lib/stretto/grammar/controller_change_grammar.treetop +9 -0
- data/lib/stretto/grammar/duration_grammar.treetop +60 -0
- data/lib/stretto/grammar/grammar_helper.rb +6 -0
- data/lib/stretto/grammar/harmonic_chord_grammar.treetop +15 -0
- data/lib/stretto/grammar/harmony_grammar.treetop +15 -0
- data/lib/stretto/grammar/instrument_grammar.treetop +9 -0
- data/lib/stretto/grammar/key_signature_grammar.treetop +10 -0
- data/lib/stretto/grammar/layer_change_grammar.treetop +9 -0
- data/lib/stretto/grammar/measure_grammar.treetop +7 -0
- data/lib/stretto/grammar/note_grammar.treetop +32 -0
- data/lib/stretto/grammar/pitch_bend_grammar.treetop +7 -0
- data/lib/stretto/grammar/polyphonic_pressure_grammar.treetop +9 -0
- data/lib/stretto/grammar/rest_grammar.treetop +9 -0
- data/lib/stretto/grammar/stretto_grammar.treetop +62 -0
- data/lib/stretto/grammar/tempo_grammar.treetop +9 -0
- data/lib/stretto/grammar/timing_grammar.treetop +9 -0
- data/lib/stretto/grammar/tokens/attack_decay_token.rb +42 -0
- data/lib/stretto/grammar/tokens/chord_token.rb +67 -0
- data/lib/stretto/grammar/tokens/controller_change_token.rb +26 -0
- data/lib/stretto/grammar/tokens/duration_token.rb +55 -0
- data/lib/stretto/grammar/tokens/harmonic_chord_token.rb +25 -0
- data/lib/stretto/grammar/tokens/harmony_with_melody_token.rb +66 -0
- data/lib/stretto/grammar/tokens/hash_token.rb +15 -0
- data/lib/stretto/grammar/tokens/key_signature_token.rb +30 -0
- data/lib/stretto/grammar/tokens/measure_token.rb +21 -0
- data/lib/stretto/grammar/tokens/modifier_token.rb +99 -0
- data/lib/stretto/grammar/tokens/note_string_token.rb +106 -0
- data/lib/stretto/grammar/tokens/note_token.rb +25 -0
- data/lib/stretto/grammar/tokens/pattern_token.rb +26 -0
- data/lib/stretto/grammar/tokens/polyphonic_pressure_token.rb +28 -0
- data/lib/stretto/grammar/tokens/rest_token.rb +21 -0
- data/lib/stretto/grammar/tokens/value_token.rb +28 -0
- data/lib/stretto/grammar/tokens/variable_definition_token.rb +30 -0
- data/lib/stretto/grammar/value_grammar.treetop +45 -0
- data/lib/stretto/grammar/variable_grammar.treetop +10 -0
- data/lib/stretto/grammar/voice_change_grammar.treetop +9 -0
- data/lib/stretto/music_elements/channel_pressure.rb +44 -0
- data/lib/stretto/music_elements/chord.rb +194 -0
- data/lib/stretto/music_elements/controller_change.rb +49 -0
- data/lib/stretto/music_elements/harmonic_chord.rb +56 -0
- data/lib/stretto/music_elements/harmony.rb +37 -0
- data/lib/stretto/music_elements/instrument.rb +57 -0
- data/lib/stretto/music_elements/key_signature.rb +110 -0
- data/lib/stretto/music_elements/layer.rb +22 -0
- data/lib/stretto/music_elements/layer_change.rb +39 -0
- data/lib/stretto/music_elements/measure.rb +38 -0
- data/lib/stretto/music_elements/melody.rb +72 -0
- data/lib/stretto/music_elements/modifiers/attack_decay.rb +55 -0
- data/lib/stretto/music_elements/modifiers/chord_intervals.rb +44 -0
- data/lib/stretto/music_elements/modifiers/duration.rb +180 -0
- data/lib/stretto/music_elements/modifiers/value.rb +172 -0
- data/lib/stretto/music_elements/modifiers/variables.rb +365 -0
- data/lib/stretto/music_elements/music_element.rb +88 -0
- data/lib/stretto/music_elements/note.rb +282 -0
- data/lib/stretto/music_elements/pattern.rb +100 -0
- data/lib/stretto/music_elements/pitch_bend.rb +46 -0
- data/lib/stretto/music_elements/polyphonic_pressure.rb +62 -0
- data/lib/stretto/music_elements/rest.rb +26 -0
- data/lib/stretto/music_elements/tempo.rb +42 -0
- data/lib/stretto/music_elements/timing.rb +33 -0
- data/lib/stretto/music_elements/variable.rb +49 -0
- data/lib/stretto/music_elements/voice.rb +49 -0
- data/lib/stretto/music_elements/voice_change.rb +39 -0
- data/lib/stretto/parsers/exceptions.rb +11 -0
- data/lib/stretto/parsers/parser.rb +89 -0
- data/lib/stretto/renderers/midiator/player.rb +200 -0
- data/lib/stretto/util/jfugue_format_parser.rb +20 -0
- data/lib/stretto/util/node.rb +5 -0
- data/lib/stretto/util/utils.rb +41 -0
- data/lib/stretto/version.rb +3 -0
- metadata +203 -0
data/CHANGELOG.markdown
ADDED
File without changes
|
data/README.markdown
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
Stretto
|
2
|
+
=======
|
3
|
+
|
4
|
+
Stretto is Ruby's implementation of [JFugue][1], an open source library originally written in Java by [David Koelle][2] for programming MIDI.
|
5
|
+
|
6
|
+
Motivation
|
7
|
+
----------
|
8
|
+
|
9
|
+
JFugue's syntax is great for producing both a human readable and parseable implementation of the MIDI specification. By detaching it from the Java sound engine, it can become an specification and be implemented in several languages/platforms. This implementation aims to be compatible with JFugue as well as serve as the basis for the format specification.
|
10
|
+
|
11
|
+
Installation
|
12
|
+
------------
|
13
|
+
|
14
|
+
gem install stretto
|
15
|
+
|
16
|
+
|
17
|
+
MIDI Playback
|
18
|
+
-------------
|
19
|
+
|
20
|
+
require 'rubygems'
|
21
|
+
require 'stretto'
|
22
|
+
|
23
|
+
# play a scale
|
24
|
+
player = Stretto::Player.new
|
25
|
+
player.play("C D E F G A B")
|
26
|
+
|
27
|
+
# play a .jfugue file
|
28
|
+
file = File.new(File.dirname(__FILE__) + '/examples/entertainer.jfugue')
|
29
|
+
player.play(file)
|
30
|
+
|
31
|
+
Stretto currently supports the following subset of JFugue's syntax For MIDI playback:
|
32
|
+
|
33
|
+
- notes
|
34
|
+
- rests
|
35
|
+
- measures
|
36
|
+
- chords
|
37
|
+
- harmonies
|
38
|
+
- multiple voices
|
39
|
+
- melodies
|
40
|
+
- variables
|
41
|
+
- tempo changes
|
42
|
+
- channel pressure
|
43
|
+
- polyphonic pressure
|
44
|
+
- instruments
|
45
|
+
- pitch bends
|
46
|
+
- controller changes
|
47
|
+
|
48
|
+
For more on syntax, check out [The Complete Guide to JFugue][3]. The
|
49
|
+
second chapter is free, and covers a good chunk of what is possible with JFugue.
|
50
|
+
|
51
|
+
Stretto uses [midiator][4] for MIDI playback. If you're running OS X,
|
52
|
+
the built-in softsynth driver should just work. You can also try creating a Player with another driver, such as core_audio or alsa:
|
53
|
+
|
54
|
+
player = Stretto::Player.new(:driver => :alsa)
|
55
|
+
|
56
|
+
Contributing
|
57
|
+
------------
|
58
|
+
|
59
|
+
Stretto uses Bundler for dependency management. To run the test suite:
|
60
|
+
|
61
|
+
bundle install
|
62
|
+
rake
|
63
|
+
|
64
|
+
[1]: http://www.jfugue.org/
|
65
|
+
[2]: http://blog.davekoelle.com/
|
66
|
+
[3]: http://www.jfugue.org/book.html
|
67
|
+
[4]: https://github.com/bleything/midiator
|
data/Rakefile
ADDED
data/lib/stretto.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
|
4
|
+
require 'treetop'
|
5
|
+
require 'polyglot'
|
6
|
+
require 'midiator'
|
7
|
+
|
8
|
+
$: << File.dirname(__FILE__)
|
9
|
+
|
10
|
+
require 'stretto/util/utils'
|
11
|
+
require 'stretto/parsers/parser'
|
12
|
+
require 'stretto/parsers/exceptions'
|
13
|
+
require 'stretto/music_elements/pattern'
|
14
|
+
require 'stretto/renderers/midiator/player'
|
@@ -0,0 +1,60 @@
|
|
1
|
+
grammar ChordGrammar
|
2
|
+
|
3
|
+
include NoteGrammar
|
4
|
+
|
5
|
+
rule chord
|
6
|
+
__note_string:note_string __named_chord:named_chord __chord_inversions:chord_inversions? __duration:duration? attack_and_decay <Stretto::Tokens::ChordToken>
|
7
|
+
end
|
8
|
+
|
9
|
+
rule named_chord
|
10
|
+
# Make sure they're in reverse order, so 'maj6' is parsed before 'maj', for instance
|
11
|
+
dom "7>5>9" / dom "7>5<9" / dom "7<5>9" / dom "7<5<9" / min maj "7" / maj "7>5" / maj "7<5" /
|
12
|
+
dom "7>5" / dom "7<5" / maj "13" / min "13" / dom "13" / dom "11" / min "11" /
|
13
|
+
[aA] [dD] [dD] "9" / dim "7" /
|
14
|
+
min "9" / maj "9" / dom "9" / min "6" / maj "6" / sus "2" / sus "4" / min "7" / maj "7" /
|
15
|
+
dom "7" / dim / [aA] [uU] [gG] / min / maj
|
16
|
+
end
|
17
|
+
|
18
|
+
rule maj
|
19
|
+
[mM] [aA] [jJ]
|
20
|
+
end
|
21
|
+
|
22
|
+
rule min
|
23
|
+
[mM] [iI] [nN]
|
24
|
+
end
|
25
|
+
|
26
|
+
rule dom
|
27
|
+
[dD] [oO] [mM]
|
28
|
+
end
|
29
|
+
|
30
|
+
rule sus
|
31
|
+
[sS] [uU] [sS]
|
32
|
+
end
|
33
|
+
|
34
|
+
rule dim
|
35
|
+
[dD] [iI] [mM]
|
36
|
+
end
|
37
|
+
|
38
|
+
rule chord_inversions
|
39
|
+
'^' note_string {
|
40
|
+
def inversions
|
41
|
+
0
|
42
|
+
end
|
43
|
+
|
44
|
+
def pivot_note
|
45
|
+
note_string
|
46
|
+
end
|
47
|
+
}
|
48
|
+
/
|
49
|
+
'^'+ {
|
50
|
+
def inversions
|
51
|
+
text_value.size
|
52
|
+
end
|
53
|
+
|
54
|
+
def pivot_note
|
55
|
+
nil
|
56
|
+
end
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
grammar DurationGrammar
|
2
|
+
|
3
|
+
rule duration
|
4
|
+
_end_of_tie:tie? duration_string _start_of_tie:tie? <Stretto::Tokens::DurationToken>
|
5
|
+
end
|
6
|
+
|
7
|
+
rule duration_string
|
8
|
+
_duration_character:[whqistxoWHQISTXO]+ _dots:('.'*) _tuplet:tuplet? {
|
9
|
+
def duration_character
|
10
|
+
_duration_character.text_value
|
11
|
+
end
|
12
|
+
|
13
|
+
def dots
|
14
|
+
_dots.text_value.size
|
15
|
+
end
|
16
|
+
|
17
|
+
def tuplet
|
18
|
+
_tuplet if _tuplet.text_value.present?
|
19
|
+
end
|
20
|
+
|
21
|
+
def value
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
}
|
25
|
+
/
|
26
|
+
'/' _value:variable_or_decimal {
|
27
|
+
def duration_character
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def dots
|
32
|
+
0
|
33
|
+
end
|
34
|
+
|
35
|
+
def tuplet
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
|
39
|
+
def value
|
40
|
+
_value
|
41
|
+
end
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
rule tuplet
|
46
|
+
'*' _ratio:(_numerator:integer ':' _denominator:integer)? {
|
47
|
+
def numerator
|
48
|
+
_ratio._numerator.text_value if _ratio.text_value.present?
|
49
|
+
end
|
50
|
+
def denominator
|
51
|
+
_ratio._denominator.text_value if _ratio.text_value.present?
|
52
|
+
end
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
rule tie
|
57
|
+
'-'
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
grammar HarmonicChordGrammar
|
2
|
+
|
3
|
+
include NoteGrammar
|
4
|
+
include ChordGrammar
|
5
|
+
|
6
|
+
rule harmonic_chord
|
7
|
+
# Force it to be greedy by putting a lookahead negative assertion.
|
8
|
+
_first_element:chord_or_note _other_elements:('+' _element:chord_or_note)+ ![+_] <Stretto::Tokens::HarmonicChordToken>
|
9
|
+
end
|
10
|
+
|
11
|
+
rule chord_or_note
|
12
|
+
chord / note
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
grammar HarmonyGrammar
|
2
|
+
|
3
|
+
include ChordGrammar
|
4
|
+
include NoteGrammar
|
5
|
+
include RestGrammar
|
6
|
+
|
7
|
+
rule harmony_with_melody
|
8
|
+
_first_element:single_music_element _other_elements:(_sep:[+_] _element:single_music_element)+ <Stretto::Tokens::HarmonyWithMelodyToken>
|
9
|
+
end
|
10
|
+
|
11
|
+
rule single_music_element
|
12
|
+
chord / note / rest
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
grammar NoteGrammar
|
2
|
+
|
3
|
+
include ValueGrammar
|
4
|
+
include DurationGrammar
|
5
|
+
|
6
|
+
rule note
|
7
|
+
note_string __duration:duration? attack_and_decay <Stretto::Tokens::NoteToken>
|
8
|
+
end
|
9
|
+
|
10
|
+
rule note_string
|
11
|
+
note_key _octave:octave? <Stretto::Tokens::NoteKeyAccidentalOctaveToken>
|
12
|
+
/
|
13
|
+
'[' _pitch:integer_or_variable_name ']' <Stretto::Tokens::NotePitchToken>
|
14
|
+
end
|
15
|
+
|
16
|
+
rule note_key
|
17
|
+
key:[A-Ga-g] accidental:accidental?
|
18
|
+
end
|
19
|
+
|
20
|
+
rule accidental
|
21
|
+
"##" / "#" / [bB] [bB] / [bB] / "n" / "N"
|
22
|
+
end
|
23
|
+
|
24
|
+
rule octave
|
25
|
+
integer
|
26
|
+
end
|
27
|
+
|
28
|
+
rule attack_and_decay
|
29
|
+
_attack:([aA] value:variable_or_integer)? _decay:([dD] value:variable_or_integer)? <Stretto::Tokens::AttackDecayToken>
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/grammar_helper'
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/value_grammar'
|
4
|
+
require File.dirname(__FILE__) + '/duration_grammar'
|
5
|
+
require File.dirname(__FILE__) + '/note_grammar'
|
6
|
+
require File.dirname(__FILE__) + '/chord_grammar'
|
7
|
+
require File.dirname(__FILE__) + '/rest_grammar'
|
8
|
+
|
9
|
+
require File.dirname(__FILE__) + '/channel_pressure_grammar'
|
10
|
+
require File.dirname(__FILE__) + '/controller_change_grammar'
|
11
|
+
require File.dirname(__FILE__) + '/instrument_grammar'
|
12
|
+
require File.dirname(__FILE__) + '/harmony_grammar'
|
13
|
+
require File.dirname(__FILE__) + '/harmonic_chord_grammar'
|
14
|
+
require File.dirname(__FILE__) + '/key_signature_grammar'
|
15
|
+
require File.dirname(__FILE__) + '/layer_change_grammar'
|
16
|
+
require File.dirname(__FILE__) + '/measure_grammar'
|
17
|
+
require File.dirname(__FILE__) + '/pitch_bend_grammar'
|
18
|
+
require File.dirname(__FILE__) + '/polyphonic_pressure_grammar'
|
19
|
+
require File.dirname(__FILE__) + '/tempo_grammar'
|
20
|
+
require File.dirname(__FILE__) + '/timing_grammar'
|
21
|
+
require File.dirname(__FILE__) + '/variable_grammar'
|
22
|
+
require File.dirname(__FILE__) + '/voice_change_grammar'
|
23
|
+
|
24
|
+
grammar StrettoGrammar
|
25
|
+
|
26
|
+
include ValueGrammar
|
27
|
+
include DurationGrammar
|
28
|
+
include NoteGrammar
|
29
|
+
include ChordGrammar
|
30
|
+
include RestGrammar
|
31
|
+
|
32
|
+
include ChannelPressureGrammar
|
33
|
+
include ControllerChangeGrammar
|
34
|
+
include InstrumentGrammar
|
35
|
+
include HarmonicChordGrammar
|
36
|
+
include HarmonyGrammar
|
37
|
+
include KeySignatureGrammar
|
38
|
+
include LayerChangeGrammar
|
39
|
+
include MeasureGrammar
|
40
|
+
include PitchBendGrammar
|
41
|
+
include PolyphonicPressureGrammar
|
42
|
+
include TempoGrammar
|
43
|
+
include TimingGrammar
|
44
|
+
include VariableGrammar
|
45
|
+
include VoiceChangeGrammar
|
46
|
+
|
47
|
+
rule notes
|
48
|
+
space? head:music_element? more_elements:(space music_element)* space? <Stretto::Tokens::PatternToken>
|
49
|
+
end
|
50
|
+
|
51
|
+
rule music_element
|
52
|
+
harmonic_chord / harmony_with_melody / single_music_element /
|
53
|
+
measure / key_signature / instrument / voice / layer / tempo /
|
54
|
+
pitch_bend / channel_pressure / polyphonic_pressure / timing /
|
55
|
+
controller_change / variable_definition
|
56
|
+
end
|
57
|
+
|
58
|
+
rule space
|
59
|
+
[\s]+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|