guitar_pro_parser 0.0.1 → 0.0.2
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.
- data/lib/guitar_pro_parser/bar.rb +4 -9
- data/lib/guitar_pro_parser/bar_settings.rb +1 -1
- data/lib/guitar_pro_parser/chord_diagram.rb +39 -2
- data/lib/guitar_pro_parser/guitar_pro_helper.rb +30 -3
- data/lib/guitar_pro_parser/io/reader.rb +89 -22
- data/lib/guitar_pro_parser/song.rb +95 -57
- data/lib/guitar_pro_parser/version.rb +1 -1
- data/spec/lib/guitar_pro_parser/beat_spec.rb +1 -1
- data/spec/lib/guitar_pro_parser/chord_diagram_spec.rb +81 -0
- data/spec/lib/guitar_pro_parser/note_spec.rb +45 -8
- data/spec/tabs/tab.gp4 +0 -0
- data/spec/tabs/tab.gp5 +0 -0
- metadata +4 -2
@@ -2,17 +2,12 @@ module GuitarProParser
|
|
2
2
|
|
3
3
|
# This class represents bars as containers of notes.
|
4
4
|
#
|
5
|
-
# == Attributes
|
6
|
-
#
|
7
|
-
# All attributes are read-only
|
8
|
-
#
|
9
|
-
# * +voices+ (hash) Voices of this bar.
|
10
|
-
# Guitar Pro 5 files has :lead and :bass voices.
|
11
|
-
# Guitar Pro 4 and less files has only :lead voice.
|
12
|
-
#
|
13
|
-
#
|
14
5
|
class Bar
|
15
6
|
|
7
|
+
# Hash of voices of this bar.
|
8
|
+
# Guitar Pro 5 files has :lead and :bass voices.
|
9
|
+
# Guitar Pro 4 and less files has only :lead voice.
|
10
|
+
# Each voice is array of beats.
|
16
11
|
attr_accessor :voices
|
17
12
|
|
18
13
|
def initialize
|
@@ -4,7 +4,7 @@ module GuitarProParser
|
|
4
4
|
#
|
5
5
|
# == Attributes
|
6
6
|
#
|
7
|
-
#
|
7
|
+
# * +new_time_signature+ (hash) Info about new time signature in format
|
8
8
|
# { numerator: 4, denominator: 4, beam_eight_notes_by_values: [2, 2, 2, 2] }
|
9
9
|
# or nil if doesn't present
|
10
10
|
#
|
@@ -2,12 +2,49 @@ module GuitarProParser
|
|
2
2
|
|
3
3
|
class ChordDiagram
|
4
4
|
|
5
|
-
attr_accessor :name,
|
5
|
+
attr_accessor :name,
|
6
|
+
:base_fret,
|
7
|
+
:frets,
|
8
|
+
:display_as,
|
9
|
+
:root,
|
10
|
+
:type
|
11
|
+
|
12
|
+
# Determines if the chord goes until the ninth, the eleventh, or the thirteenth.
|
13
|
+
attr_accessor :nine_eleven_thirteen
|
14
|
+
|
15
|
+
attr_accessor :bass,
|
16
|
+
:tonality,
|
17
|
+
:add,
|
18
|
+
:fifth_tonality,
|
19
|
+
:ninth_tonality,
|
20
|
+
:eleventh_tonality,
|
21
|
+
:barres,
|
22
|
+
:intervals,
|
23
|
+
:fingers,
|
24
|
+
:display_fingering
|
6
25
|
|
7
26
|
def initialize
|
8
27
|
@name = ''
|
9
|
-
@
|
28
|
+
@base_fret = 0
|
10
29
|
@frets = []
|
30
|
+
@display_as = :sharp
|
31
|
+
@root = nil
|
32
|
+
@type = 'M'
|
33
|
+
@nine_eleven_thirteen = 0
|
34
|
+
@bass = nil
|
35
|
+
@tonality = :perfect
|
36
|
+
@add = false
|
37
|
+
@fifth_tonality = :perfect
|
38
|
+
@ninth_tonality = :perfect
|
39
|
+
@eleventh_tonality = :perfect
|
40
|
+
@barres = []
|
41
|
+
@intervals = []
|
42
|
+
@fingers = []
|
43
|
+
@display_fingering = false
|
44
|
+
end
|
45
|
+
|
46
|
+
def add_barre(fret, start_string, end_string)
|
47
|
+
@barres << { fret: fret, start_string: start_string, end_string: end_string }
|
11
48
|
end
|
12
49
|
|
13
50
|
end
|
@@ -1,5 +1,19 @@
|
|
1
1
|
module GuitarProHelper
|
2
2
|
|
3
|
+
# Possible versions of Guitar Pro file
|
4
|
+
VERSIONS = { 'FICHIER GUITARE PRO v1' => 1.0,
|
5
|
+
'FICHIER GUITARE PRO v1.01' => 1.01,
|
6
|
+
'FICHIER GUITARE PRO v1.02' => 1.02,
|
7
|
+
'FICHIER GUITARE PRO v1.03' => 1.03,
|
8
|
+
'FICHIER GUITARE PRO v1.04' => 1.04,
|
9
|
+
'FICHIER GUITAR PRO v2.20' => 2.2,
|
10
|
+
'FICHIER GUITAR PRO v2.21' =>2.21,
|
11
|
+
'FICHIER GUITAR PRO v3.00' => 3.0,
|
12
|
+
'FICHIER GUITAR PRO v4.00' => 4.0,
|
13
|
+
'FICHIER GUITAR PRO v4.06' => 4.06,
|
14
|
+
'FICHIER GUITAR PRO L4.06' => 4.06,
|
15
|
+
'FICHIER GUITAR PRO v5.10' => 5.1 }
|
16
|
+
|
3
17
|
NOTES = %w(C C# D D# E F F# G G# A A# B)
|
4
18
|
VOICES = [:lead, :bass]
|
5
19
|
FINGERS = [:thumb, :index, :middle, :ring, :pinky]
|
@@ -33,10 +47,23 @@ module GuitarProHelper
|
|
33
47
|
|
34
48
|
SLIDE_TYPES = [:no_slide, :shift_slide, :legato_slide, :slide_out_and_downwards, :slide_out_and_upwards, :slide_in_from_below, :slide_in_from_above]
|
35
49
|
MAP_SLIDE_TYPES_GP5 = { '0'=>0, '1'=>1, '2'=>2, '4'=>3, '8'=>4, '16'=>5, '32'=>6 }
|
36
|
-
MAP_SLIDE_TYPES_GP4 = { '-2'=>
|
37
|
-
|
50
|
+
MAP_SLIDE_TYPES_GP4 = { '-2'=>6, '-1'=>5, '0'=>0, '1'=>1, '2'=>2, '3'=>3, '4'=>4 }
|
51
|
+
|
38
52
|
HARMONIC_TYPES = [:none, :natural, :artificial, :tapped, :pinch, :semi]
|
39
|
-
TRILL_PERIODS =
|
53
|
+
TRILL_PERIODS = { '1' => 4, '2' => 8, '3' => 16 }
|
54
|
+
CHORD_TYPES = %w(M 7 7M 6 m m7 m7M m6 sus2 sus4 7sus2 7sus4 dim aug 5)
|
55
|
+
NINE_ELEVEN_THIRTEEN = [0, 9, 11, 13]
|
56
|
+
|
57
|
+
# Strange moment here. In format specification is written:
|
58
|
+
# 0: perfect
|
59
|
+
# 1: augmented
|
60
|
+
# 2: diminished
|
61
|
+
# But actually (after tests) it seems to be:
|
62
|
+
# 0: perfect
|
63
|
+
# 1: diminished
|
64
|
+
# 2: augmented
|
65
|
+
CHORD_TONALITIES = [:perfect, :diminished, :augmented]
|
66
|
+
|
40
67
|
|
41
68
|
# Macros to create boolean instance variables' getters like this:
|
42
69
|
# attr_boolean :complete
|
@@ -69,9 +69,8 @@ module GuitarProParser
|
|
69
69
|
def read_version
|
70
70
|
length = @input.read_byte
|
71
71
|
version_string = @input.read_string length
|
72
|
-
# TODO:
|
73
|
-
|
74
|
-
@version = version_string.to_f
|
72
|
+
# TODO: Raise exception for unsupported or wrong versions here
|
73
|
+
@version = GuitarProHelper::VERSIONS.fetch(version_string)
|
75
74
|
@song.version = @version
|
76
75
|
|
77
76
|
# Skip first 31 bytes that are reserved for version data
|
@@ -273,7 +272,7 @@ module GuitarProParser
|
|
273
272
|
bits = @input.read_bitmask
|
274
273
|
bits.count.times { |i| bars_settings.alternate_endings << (i+1) if bits[i] }
|
275
274
|
else
|
276
|
-
|
275
|
+
bars_settings.alternate_endings << @input.read_byte
|
277
276
|
end
|
278
277
|
end
|
279
278
|
|
@@ -398,7 +397,7 @@ module GuitarProParser
|
|
398
397
|
beat.rest = GuitarProHelper::REST_TYPES.fetch(@input.read_byte.to_s) if is_rest
|
399
398
|
beat.duration = GuitarProHelper::DURATIONS.fetch(@input.read_signed_byte.to_s)
|
400
399
|
beat.tuplet = @input.read_integer if is_tuplet
|
401
|
-
read_chord_diagram(track) if has_chord_diagram
|
400
|
+
read_chord_diagram(beat, track.strings.count) if has_chord_diagram
|
402
401
|
beat.text = @input.read_chunk if has_text
|
403
402
|
read_beat_effects(beat) if has_effects
|
404
403
|
read_mix_table(beat) if has_mix_table_change
|
@@ -439,19 +438,84 @@ module GuitarProParser
|
|
439
438
|
end
|
440
439
|
end
|
441
440
|
|
442
|
-
def read_chord_diagram(
|
441
|
+
def read_chord_diagram(beat, strings_count)
|
443
442
|
beat.chord_diagram = ChordDiagram.new
|
444
443
|
|
445
|
-
format = @input.
|
446
|
-
|
447
|
-
if format == 0 # Guitar Pro 3 format
|
444
|
+
format = @input.read_bitmask
|
445
|
+
if format[0] == false # Guitar Pro 3 format
|
448
446
|
beat.chord_diagram.name = @input.read_chunk
|
449
|
-
beat.chord_diagram.
|
450
|
-
unless beat.chord_diagram.
|
451
|
-
|
447
|
+
beat.chord_diagram.base_fret = @input.read_integer
|
448
|
+
unless beat.chord_diagram.base_fret.zero?
|
449
|
+
strings_count.times { beat.chord_diagram.frets << @input.read_integer }
|
452
450
|
end
|
453
|
-
else # Guitar Pro 4 format
|
454
|
-
@input.
|
451
|
+
else # Guitar Pro 4 and 5 format
|
452
|
+
beat.chord_diagram.display_as = @input.read_boolean ? :sharp : :flat
|
453
|
+
@input.increment_offset(3)
|
454
|
+
|
455
|
+
root = @input.read_byte
|
456
|
+
beat.chord_diagram.root = GuitarProHelper::NOTES[root] unless root == 12
|
457
|
+
|
458
|
+
beat.chord_diagram.type = GuitarProHelper::CHORD_TYPES[@input.read_byte]
|
459
|
+
beat.chord_diagram.nine_eleven_thirteen = GuitarProHelper::NINE_ELEVEN_THIRTEEN.fetch(@input.read_byte)
|
460
|
+
|
461
|
+
bass = @input.read_integer
|
462
|
+
beat.chord_diagram.bass = GuitarProHelper::NOTES[bass] if bass >= 0
|
463
|
+
|
464
|
+
beat.chord_diagram.tonality = GuitarProHelper::CHORD_TONALITIES[@input.read_integer]
|
465
|
+
beat.chord_diagram.add = @input.read_boolean
|
466
|
+
|
467
|
+
name_length = @input.read_byte
|
468
|
+
beat.chord_diagram.name = @input.read_string(name_length)
|
469
|
+
@input.increment_offset(20 - name_length) if name_length < 20
|
470
|
+
|
471
|
+
@input.increment_offset(2)
|
472
|
+
beat.chord_diagram.fifth_tonality = GuitarProHelper::CHORD_TONALITIES[@input.read_byte]
|
473
|
+
beat.chord_diagram.ninth_tonality = GuitarProHelper::CHORD_TONALITIES[@input.read_byte]
|
474
|
+
beat.chord_diagram.eleventh_tonality = GuitarProHelper::CHORD_TONALITIES[@input.read_byte]
|
475
|
+
|
476
|
+
beat.chord_diagram.base_fret = @input.read_integer
|
477
|
+
|
478
|
+
strings_count.times { beat.chord_diagram.frets << @input.read_integer }
|
479
|
+
(7 - strings_count).times { @input.skip_integer }
|
480
|
+
|
481
|
+
barres_count = @input.read_byte
|
482
|
+
barres_frets = []
|
483
|
+
barres_starts = []
|
484
|
+
barres_ends = []
|
485
|
+
5.times { barres_frets << @input.read_byte }
|
486
|
+
5.times { barres_starts << @input.read_byte }
|
487
|
+
5.times { barres_ends << @input.read_byte }
|
488
|
+
barres_count.times do |i|
|
489
|
+
beat.chord_diagram.add_barre(barres_frets[i],
|
490
|
+
barres_starts[i],
|
491
|
+
barres_ends[i])
|
492
|
+
end
|
493
|
+
|
494
|
+
# TODO: I don't know why but it looks inverted
|
495
|
+
beat.chord_diagram.intervals << 1 if @input.read_byte == 0x01
|
496
|
+
beat.chord_diagram.intervals << 3 if @input.read_byte == 0x01
|
497
|
+
beat.chord_diagram.intervals << 5 if @input.read_byte == 0x01
|
498
|
+
beat.chord_diagram.intervals << 7 if @input.read_byte == 0x01
|
499
|
+
beat.chord_diagram.intervals << 9 if @input.read_byte == 0x01
|
500
|
+
beat.chord_diagram.intervals << 11 if @input.read_byte == 0x01
|
501
|
+
beat.chord_diagram.intervals << 13 if @input.read_byte == 0x01
|
502
|
+
@input.skip_byte
|
503
|
+
|
504
|
+
strings_count.times do |i|
|
505
|
+
finger_id = @input.read_signed_byte
|
506
|
+
finger = nil
|
507
|
+
if finger_id == -2
|
508
|
+
finger = :unknown
|
509
|
+
elsif finger_id == -1
|
510
|
+
finger = :no
|
511
|
+
else
|
512
|
+
finger = GuitarProHelper::FINGERS[finger_id]
|
513
|
+
end
|
514
|
+
beat.chord_diagram.fingers << finger
|
515
|
+
end
|
516
|
+
@input.increment_offset(7 - strings_count) if strings_count < 7
|
517
|
+
|
518
|
+
beat.chord_diagram.display_fingering = @input.read_boolean
|
455
519
|
end
|
456
520
|
end
|
457
521
|
|
@@ -622,11 +686,11 @@ module GuitarProParser
|
|
622
686
|
note.fret = @input.read_byte
|
623
687
|
|
624
688
|
if has_fingering
|
625
|
-
left_finger = @input.
|
626
|
-
right_finger = @input.
|
689
|
+
left_finger = @input.read_signed_byte
|
690
|
+
right_finger = @input.read_signed_byte
|
627
691
|
|
628
|
-
note.add_left_hand_finger(FINGERS.fetch(left_finger)) unless left_finger == -1
|
629
|
-
note.add_right_hand_finger(FINGERS.fetch(right_finger)) unless right_finger == -1
|
692
|
+
note.add_left_hand_finger(GuitarProHelper::FINGERS.fetch(left_finger)) unless left_finger == -1
|
693
|
+
note.add_right_hand_finger(GuitarProHelper::FINGERS.fetch(right_finger)) unless right_finger == -1
|
630
694
|
end
|
631
695
|
|
632
696
|
# Ignore time-independed duration data for Guitar Pro 5
|
@@ -688,16 +752,19 @@ module GuitarProParser
|
|
688
752
|
note.add_tremolo(GuitarProHelper::TREMOLO_PICKING_SPEEDS.fetch(@input.read_byte.to_s)) if has_tremolo
|
689
753
|
|
690
754
|
if has_slide
|
691
|
-
value = @input.
|
692
|
-
|
693
|
-
|
755
|
+
value = @input.read_signed_byte.to_s
|
756
|
+
if @version >= 5.0
|
757
|
+
note.slide = GuitarProHelper::SLIDE_TYPES.fetch(GuitarProHelper::MAP_SLIDE_TYPES_GP5.fetch(value))
|
758
|
+
else
|
759
|
+
note.slide = GuitarProHelper::SLIDE_TYPES.fetch(GuitarProHelper::MAP_SLIDE_TYPES_GP4.fetch(value))
|
760
|
+
end
|
694
761
|
end
|
695
762
|
|
696
763
|
read_harmonic(note) if has_harmonic
|
697
764
|
|
698
765
|
if has_trill
|
699
766
|
fret = @input.read_byte
|
700
|
-
period = GuitarProHelper::TRILL_PERIODS.fetch(@input.read_byte)
|
767
|
+
period = GuitarProHelper::TRILL_PERIODS.fetch(@input.read_byte.to_s)
|
701
768
|
note.add_trill(fret, period)
|
702
769
|
end
|
703
770
|
end
|
@@ -3,69 +3,108 @@ require 'guitar_pro_parser/io/reader'
|
|
3
3
|
module GuitarProParser
|
4
4
|
|
5
5
|
# This class represents the content of Guitar Pro file.
|
6
|
-
# It can be initialized by path to .gp[3,4,5] file.
|
6
|
+
# It can be initialized by path to .gp[3,4,5] file. Then it will automatically parse its data.
|
7
7
|
# Or it can be just instantiated with default values of the attributes.
|
8
8
|
#
|
9
|
-
# == Attributes
|
10
|
-
#
|
11
|
-
#
|
12
|
-
# * +version+ (float) Version of Guitar Pro
|
13
|
-
# * +title+ (string)
|
14
|
-
# * +subtitle+ (string)
|
15
|
-
# * +artist+ (string)
|
16
|
-
# * +album+ (string)
|
17
|
-
# * +lyricist+ (string) Author of lyrics (>= 5.0 only)
|
18
|
-
# * +composer+ (string) Author of music
|
19
|
-
# * +copyright+ (string)
|
20
|
-
# * +transcriber+ (string) Author of tabulature
|
21
|
-
# * +instructions+ (string)
|
22
|
-
# * +notices+ (array) Array of notices (each notice is a string)
|
23
|
-
# * +triplet_feel+ (boolean) Shuffle rhythm feel (< 5.0 only)
|
24
|
-
# * +lyrics_track+ (integer) Associated track for the lyrics (>= 4.0 only)
|
25
|
-
# * +lyrics+ (array) Lyrics data represented as array of hashes with 5 elements
|
26
|
-
# (for lyrics lines from 1 to 5). Each line has lyrics' text
|
27
|
-
# and number of bar where it starts: {text: "Some text", bar: 1}
|
28
|
-
# (>= 4.0 only)
|
29
|
-
# * +master_volume+ (integer) Master volume (value from 0 - 200, default is 100) (>= 5.0 only)
|
30
|
-
# * +equalizer+ (array) Array of equalizer settings.
|
31
|
-
# Each one is represented as number of increments of .1dB the volume for
|
32
|
-
# 32Hz band is lowered
|
33
|
-
# 60Hz band is lowered
|
34
|
-
# 125Hz band is lowered
|
35
|
-
# 250Hz band is lowered
|
36
|
-
# 500Hz band is lowered
|
37
|
-
# 1KHz band is lowered
|
38
|
-
# 2KHz band is lowered
|
39
|
-
# 4KHz band is lowered
|
40
|
-
# 8KHz band is lowered
|
41
|
-
# 16KHz band is lowered
|
42
|
-
# overall volume is lowered (gain)
|
43
|
-
# * +page_setup+ (object) Object of PageSetup class that contains data about page setup (>= 5.0 only)
|
44
|
-
# * +tempo+ (string) Tempo as string
|
45
|
-
# * +bpm+ (integer) Tempo as beats per minute
|
46
|
-
# * +key+ (integer) #TODO: convert digit to something readable (has different format for GP3 and GP4/5)
|
47
|
-
# * +octave+ (integer) (>= 4.0 only)
|
48
|
-
# * +channels+ (array) Table of midi channels. There are 4 ports and 16 channels, the channels are stored in this order:
|
49
|
-
# port1/channel1 - port1/channel2 ... port1/channel16 - port2/channel1 ...
|
50
|
-
# * +musical_directions+ (hash) Hash of musical directions definitions.
|
51
|
-
# Each symbol is represented as the bar number at which it is placed.
|
52
|
-
# If the symbol is not presented its value is nil.
|
53
|
-
# There is full list of supported symbols in GuitarProHelper::MUSICAL_DIRECTIONS array (>= 5.0 only)
|
54
|
-
# * +master_reverb+ (integer) Selected master reverb setting (in Score information, value from 0 to 60) (>= 5.0 only) #TODO represent as names
|
55
|
-
# * +bars_settings+ (array) Array of settings of bars. Doesn't represent bars as containers for notes (look at Bar class for it)
|
56
|
-
# * +tracks+ (array) Array of tracks
|
57
|
-
#
|
58
9
|
class Song
|
59
10
|
|
60
11
|
include GuitarProHelper
|
61
12
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
13
|
+
# Guitar Pro version
|
14
|
+
attr_accessor :version
|
15
|
+
|
16
|
+
# Song information
|
17
|
+
attr_accessor :title, :subtitle, :artist, :album, :lyricist,
|
18
|
+
:composer, :copyright, :transcriber, :instructions
|
19
|
+
|
20
|
+
# Array of notices
|
21
|
+
attr_accessor :notices
|
22
|
+
|
23
|
+
# (Boolean) Shuffle rhythm feel. < 5.0 only.
|
24
|
+
# In version 5 of the format it is true when
|
25
|
+
# there is at least 1 bar with triplet feel.
|
26
|
+
attr_accessor :triplet_feel
|
27
|
+
|
28
|
+
# Associated track for the lyrics (>= 4.0 only)
|
29
|
+
attr_accessor :lyrics_track
|
30
|
+
|
31
|
+
# Lyrics represented as array of hashes with 5 elements
|
32
|
+
# (for lyrics lines from 1 to 5).
|
33
|
+
# Each line has lyrics' text and number of bar where it starts
|
34
|
+
# {text: "Some text", bar: 1}
|
35
|
+
# (>= 4.0 only)
|
36
|
+
attr_accessor :lyrics
|
37
|
+
|
38
|
+
# Master volume (value from 0 - 200, default is 100) (>= 5.0 only)
|
39
|
+
attr_accessor :master_volume
|
40
|
+
|
41
|
+
# Array of equalizer settings.
|
42
|
+
# Each one is represented as number of increments of .1dB the volume for
|
43
|
+
# * 32Hz band is lowered
|
44
|
+
# * 60Hz band is lowered
|
45
|
+
# * 125Hz band is lowered
|
46
|
+
# * 250Hz band is lowered
|
47
|
+
# * 500Hz band is lowered
|
48
|
+
# * 1KHz band is lowered
|
49
|
+
# * 2KHz band is lowered
|
50
|
+
# * 4KHz band is lowered
|
51
|
+
# * 8KHz band is lowered
|
52
|
+
# * 16KHz band is lowered
|
53
|
+
# * overall volume is lowered (gain)
|
54
|
+
attr_accessor :equalizer
|
55
|
+
|
56
|
+
# (PageSetup) Data about page setup such as paddings, width, height, etc. (>= 5.0 only)
|
57
|
+
attr_accessor :page_setup
|
66
58
|
|
59
|
+
# (String) Tempo text
|
60
|
+
attr_accessor :tempo
|
61
|
+
|
62
|
+
# Tempo as beats per minute
|
63
|
+
attr_accessor :bpm
|
64
|
+
|
65
|
+
# Key (signature) at the beginning of the piece.
|
66
|
+
# It is encoded as:
|
67
|
+
# * ...
|
68
|
+
# * -1: F (b)
|
69
|
+
# * 0: C
|
70
|
+
# * 1: G (#)
|
71
|
+
# * 2: D (##)
|
72
|
+
# * ...
|
73
|
+
# TODO: convert digit to something readable
|
74
|
+
attr_accessor :key
|
75
|
+
|
76
|
+
# Octave. Default value is 0.
|
77
|
+
# It becomes 8 if the sheet is to be played one octave higher (8va).
|
78
|
+
attr_accessor :octave
|
79
|
+
|
80
|
+
# Table of midi channels. There are 4 ports and 16 channels, the channels are stored in this order:
|
81
|
+
# port1/channel1 - port1/channel2 ... port1/channel16 - port2/channel1 ...
|
82
|
+
# in array with the format:
|
83
|
+
# [[1,2,...16], [1,2,...16], [1,2,...16], [1,2,...16]]
|
84
|
+
attr_accessor :channels
|
85
|
+
|
86
|
+
# (Hash) Musical directions definitions.
|
87
|
+
# Each symbol is represented as the bar number at which it is placed.
|
88
|
+
# If the symbol is not presented its value is nil.
|
89
|
+
# There is full list of supported symbols in GuitarProHelper::MUSICAL_DIRECTIONS array (>= 5.0 only)
|
90
|
+
attr_accessor :musical_directions
|
91
|
+
|
92
|
+
# Selected master reverb setting (in Score information, value from 0 to 60) (>= 5.0 only)
|
93
|
+
# TODO: Represent as names
|
94
|
+
attr_accessor :master_reverb
|
95
|
+
|
96
|
+
# Array of settings of bars. Doesn't represent bars as containers for notes (look at Bar class for it)
|
97
|
+
attr_accessor :bars_settings
|
98
|
+
|
99
|
+
# Array of tracks
|
100
|
+
attr_accessor :tracks
|
101
|
+
|
102
|
+
# Initializes new Song instance.
|
103
|
+
# Parameters:
|
104
|
+
# (String) +file_path+ Path to file to read. If is not specified default song instance will be created.
|
105
|
+
# (Boolean) +headers_only+ Read only headers information from file if true (much faster than reading every note)
|
67
106
|
def initialize(file_path = nil, headers_only = false)
|
68
|
-
|
107
|
+
@version = 5.1
|
69
108
|
@title = ''
|
70
109
|
@title = ''
|
71
110
|
@subtitle = ''
|
@@ -90,11 +129,10 @@ module GuitarProParser
|
|
90
129
|
@channels = []
|
91
130
|
@musical_directions = Hash[GuitarProHelper::MUSICAL_DIRECTIONS.collect { |elem| [elem, nil] }]
|
92
131
|
@master_reverb = 0
|
93
|
-
|
94
132
|
@bars_settings = []
|
95
133
|
@tracks = []
|
96
134
|
|
97
|
-
# Read data from file
|
135
|
+
# Read data from file if it is specified
|
98
136
|
Reader.new(self, file_path, headers_only) unless file_path.nil?
|
99
137
|
end
|
100
138
|
|
@@ -20,7 +20,7 @@ describe GuitarProParser::Beat do
|
|
20
20
|
test_beat :first
|
21
21
|
|
22
22
|
its(:dotted) { should == false }
|
23
|
-
its(:chord_diagram) { should
|
23
|
+
its(:chord_diagram) { should be_kind_of GuitarProParser::ChordDiagram }
|
24
24
|
its(:tuplet) { should be_nil }
|
25
25
|
its(:rest) { should be_nil }
|
26
26
|
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GuitarProParser::ChordDiagram do
|
4
|
+
|
5
|
+
shared_examples 'any Guitar Pro version' do
|
6
|
+
context 'F#m11/9-' do
|
7
|
+
subject { song.tracks[0].bars[0].get_beat(0).chord_diagram }
|
8
|
+
its(:name) { should == 'F#m11/9-' }
|
9
|
+
its(:base_fret) { should == 1 }
|
10
|
+
its(:frets) { should == [3, 2, 4, 2, 0, 2] }
|
11
|
+
its(:display_as) { should == :sharp }
|
12
|
+
its(:root) { should == 'F#' }
|
13
|
+
its(:type) { should == 'm' }
|
14
|
+
its(:nine_eleven_thirteen) { should == 11 }
|
15
|
+
its(:bass) { should == 'F#' }
|
16
|
+
its(:tonality) { should == :perfect }
|
17
|
+
its(:add) { should == false }
|
18
|
+
its(:fifth_tonality) { should == :perfect }
|
19
|
+
its(:ninth_tonality) { should == :diminished }
|
20
|
+
its(:eleventh_tonality) { should == :perfect }
|
21
|
+
its(:barres) { should == [{ fret: 2, start_string: 1, end_string: 4 }] }
|
22
|
+
its(:intervals) { should == [13] }
|
23
|
+
its(:fingers) { should == [:ring, :middle, :pinky, :middle, :no, :index] }
|
24
|
+
its(:display_fingering) { should == true }
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'Asus2add13' do
|
28
|
+
subject { song.tracks[0].bars[0].get_beat(4).chord_diagram }
|
29
|
+
its(:name) { should == 'Asus2add13' }
|
30
|
+
its(:base_fret) { should == 1 }
|
31
|
+
its(:frets) { should == [2, 0, 2, 2, 2, -1] }
|
32
|
+
its(:display_as) { should == :sharp }
|
33
|
+
its(:root) { should == 'A' }
|
34
|
+
its(:type) { should == 'sus2' }
|
35
|
+
its(:nine_eleven_thirteen) { should == 13 }
|
36
|
+
its(:bass) { should == 'B' }
|
37
|
+
its(:tonality) { should == :perfect }
|
38
|
+
its(:add) { should == true }
|
39
|
+
its(:fifth_tonality) { should == :perfect }
|
40
|
+
its(:ninth_tonality) { should == :perfect }
|
41
|
+
its(:eleventh_tonality) { should == :perfect }
|
42
|
+
its(:barres) { should == [] }
|
43
|
+
its(:intervals) { should == [7, 9, 11] }
|
44
|
+
its(:fingers) { should == [:pinky, :no, :ring, :middle, :index, :no] }
|
45
|
+
its(:display_fingering) { should == true }
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'C7M13+/9-/11-' do
|
49
|
+
subject { song.tracks[0].bars[1].get_beat(0).chord_diagram }
|
50
|
+
its(:name) { should == 'C7M13+/9-/11-' }
|
51
|
+
its(:base_fret) { should == 8 }
|
52
|
+
its(:frets) { should == [9, 11, 9, 9, 10, 8] }
|
53
|
+
its(:display_as) { should == :sharp }
|
54
|
+
its(:root) { should == 'C' }
|
55
|
+
its(:type) { should == '7M' }
|
56
|
+
its(:nine_eleven_thirteen) { should == 13 }
|
57
|
+
its(:bass) { should == 'C' }
|
58
|
+
its(:tonality) { should == :augmented }
|
59
|
+
its(:add) { should == false }
|
60
|
+
its(:fifth_tonality) { should == :perfect }
|
61
|
+
its(:ninth_tonality) { should == :diminished }
|
62
|
+
its(:eleventh_tonality) { should == :diminished }
|
63
|
+
its(:barres) { should == [{ fret: 9, start_string: 1, end_string: 4 }] }
|
64
|
+
its(:intervals) { should == [] }
|
65
|
+
its(:fingers) { should == [:middle, :pinky, :middle, :middle, :ring, :index] }
|
66
|
+
its(:display_fingering) { should == true }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'Guitar Pro 5' do
|
71
|
+
subject(:song) { GuitarProParser::Song.new test_tab_path 5 }
|
72
|
+
it_behaves_like 'any Guitar Pro version'
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'Guitar Pro 4' do
|
76
|
+
subject(:song) { GuitarProParser::Song.new test_tab_path 4 }
|
77
|
+
it_behaves_like 'any Guitar Pro version'
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
end
|
@@ -1,19 +1,27 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
# TODO:
|
3
|
+
# TODO: It would be nice to add more tests for notes and test :bass voice
|
4
4
|
|
5
5
|
def test_note(type)
|
6
|
-
|
7
|
-
first: [0, '5']
|
6
|
+
notes = {
|
7
|
+
first: [0, 0, 0, '5'],
|
8
|
+
legato_slide: [0, 15, 0, '2'],
|
9
|
+
shift_slide: [0, 15, 2, '2'],
|
10
|
+
slide_in_from_below: [0, 15, 4, '2'],
|
11
|
+
slide_in_from_above: [0, 15, 5, '2'],
|
12
|
+
slide_out_and_downwards: [0, 15, 6, '2'],
|
13
|
+
slide_out_and_upwards: [0, 15, 7, '2'],
|
8
14
|
}
|
9
|
-
|
10
|
-
|
11
|
-
|
15
|
+
note = notes.fetch(type)
|
16
|
+
track_number = note[0]
|
17
|
+
bar_number = note[1]
|
18
|
+
beat_number = note[2]
|
19
|
+
string_number = note[3]
|
20
|
+
subject { song.tracks[track_number].bars[bar_number].get_beat(beat_number).strings[string_number] }
|
12
21
|
end
|
13
22
|
|
14
23
|
describe GuitarProParser::Note do
|
15
24
|
|
16
|
-
|
17
25
|
shared_examples 'any Guitar Pro version' do
|
18
26
|
|
19
27
|
context 'note of the 1 beat, 1 bar, 1 track' do
|
@@ -39,6 +47,36 @@ describe GuitarProParser::Note do
|
|
39
47
|
its(:trill) { should be_nil }
|
40
48
|
end
|
41
49
|
|
50
|
+
context 'legato slide' do
|
51
|
+
test_note :legato_slide
|
52
|
+
its(:slide) { should == :legato_slide }
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'shift slide' do
|
56
|
+
test_note :shift_slide
|
57
|
+
its(:slide) { should == :shift_slide }
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'slide in from below' do
|
61
|
+
test_note :slide_in_from_below
|
62
|
+
its(:slide) { should == :slide_in_from_below }
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'slide in from above' do
|
66
|
+
test_note :slide_in_from_above
|
67
|
+
its(:slide) { should == :slide_in_from_above }
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'slide out and downwards' do
|
71
|
+
test_note :slide_out_and_downwards
|
72
|
+
its(:slide) { should == :slide_out_and_downwards }
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'slide out and upwards' do
|
76
|
+
test_note :slide_out_and_upwards
|
77
|
+
its(:slide) { should == :slide_out_and_upwards }
|
78
|
+
end
|
79
|
+
|
42
80
|
end
|
43
81
|
|
44
82
|
context 'Guitar Pro 5' do
|
@@ -50,6 +88,5 @@ describe GuitarProParser::Note do
|
|
50
88
|
subject(:song) { GuitarProParser::Song.new test_tab_path 4 }
|
51
89
|
it_behaves_like 'any Guitar Pro version'
|
52
90
|
end
|
53
|
-
|
54
91
|
|
55
92
|
end
|
data/spec/tabs/tab.gp4
CHANGED
Binary file
|
data/spec/tabs/tab.gp5
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: guitar_pro_parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-07-
|
12
|
+
date: 2013-07-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -90,6 +90,7 @@ files:
|
|
90
90
|
- spec/lib/guitar_pro_parser/bar_settings_spec.rb
|
91
91
|
- spec/lib/guitar_pro_parser/beat_spec.rb
|
92
92
|
- spec/lib/guitar_pro_parser/channel_spec.rb
|
93
|
+
- spec/lib/guitar_pro_parser/chord_diagram_spec.rb
|
93
94
|
- spec/lib/guitar_pro_parser/guitar_pro_helper_spec.rb
|
94
95
|
- spec/lib/guitar_pro_parser/io/input_stream_spec.rb
|
95
96
|
- spec/lib/guitar_pro_parser/note_spec.rb
|
@@ -131,6 +132,7 @@ test_files:
|
|
131
132
|
- spec/lib/guitar_pro_parser/bar_settings_spec.rb
|
132
133
|
- spec/lib/guitar_pro_parser/beat_spec.rb
|
133
134
|
- spec/lib/guitar_pro_parser/channel_spec.rb
|
135
|
+
- spec/lib/guitar_pro_parser/chord_diagram_spec.rb
|
134
136
|
- spec/lib/guitar_pro_parser/guitar_pro_helper_spec.rb
|
135
137
|
- spec/lib/guitar_pro_parser/io/input_stream_spec.rb
|
136
138
|
- spec/lib/guitar_pro_parser/note_spec.rb
|