guitar_pro_parser 0.0.1

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.
Files changed (36) hide show
  1. data/.gitignore +18 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +72 -0
  6. data/Rakefile +7 -0
  7. data/guitar_pro_parser.gemspec +25 -0
  8. data/lib/guitar_pro_parser/bar.rb +29 -0
  9. data/lib/guitar_pro_parser/bar_settings.rb +74 -0
  10. data/lib/guitar_pro_parser/beat.rb +42 -0
  11. data/lib/guitar_pro_parser/channel.rb +25 -0
  12. data/lib/guitar_pro_parser/chord_diagram.rb +14 -0
  13. data/lib/guitar_pro_parser/guitar_pro_helper.rb +73 -0
  14. data/lib/guitar_pro_parser/io/input_stream.rb +110 -0
  15. data/lib/guitar_pro_parser/io/reader.rb +759 -0
  16. data/lib/guitar_pro_parser/note.rb +71 -0
  17. data/lib/guitar_pro_parser/page_setup.rb +34 -0
  18. data/lib/guitar_pro_parser/song.rb +113 -0
  19. data/lib/guitar_pro_parser/track.rb +125 -0
  20. data/lib/guitar_pro_parser/version.rb +3 -0
  21. data/lib/guitar_pro_parser.rb +25 -0
  22. data/spec/lib/guitar_pro_parser/bar_settings_spec.rb +176 -0
  23. data/spec/lib/guitar_pro_parser/beat_spec.rb +79 -0
  24. data/spec/lib/guitar_pro_parser/channel_spec.rb +44 -0
  25. data/spec/lib/guitar_pro_parser/guitar_pro_helper_spec.rb +11 -0
  26. data/spec/lib/guitar_pro_parser/io/input_stream_spec.rb +101 -0
  27. data/spec/lib/guitar_pro_parser/note_spec.rb +55 -0
  28. data/spec/lib/guitar_pro_parser/page_setup_spec.rb +26 -0
  29. data/spec/lib/guitar_pro_parser/song_spec.rb +121 -0
  30. data/spec/lib/guitar_pro_parser/track_spec.rb +211 -0
  31. data/spec/lib/guitar_pro_parser_spec.rb +51 -0
  32. data/spec/spec_helper.rb +23 -0
  33. data/spec/tabs/tab.gp4 +0 -0
  34. data/spec/tabs/tab.gp5 +0 -0
  35. data/spec/tabs/test_musical_directions.gp5 +0 -0
  36. metadata +144 -0
@@ -0,0 +1,101 @@
1
+ require 'spec_helper'
2
+
3
+ describe GuitarProParser::InputStream do
4
+ subject { GuitarProParser::InputStream.new(test_tab_path(5)) }
5
+
6
+ describe '#read_byte' do
7
+ let!(:result) { subject.read_byte }
8
+
9
+ its(:offset) { should == 1}
10
+ specify { result.should == 24 }
11
+ end
12
+
13
+ describe '#read_boolean' do
14
+ let!(:result) { subject.read_boolean }
15
+
16
+ its(:offset) { should == 1}
17
+ specify { result.should == true }
18
+ end
19
+
20
+ describe '#read_integer' do
21
+ before (:each) do
22
+ subject.offset = 31
23
+ end
24
+
25
+ let!(:result) { subject.read_integer }
26
+
27
+ its(:offset) { should == 35}
28
+ specify { result.should == 11 }
29
+ end
30
+
31
+ describe '#read_short_integer' do
32
+ before (:each) do
33
+ subject.offset = 357
34
+ end
35
+
36
+ let!(:result) { subject.read_short_integer }
37
+
38
+ its(:offset) { should == 359}
39
+ specify { result.should == 511 }
40
+ end
41
+
42
+ shared_examples 'read_string and read_chunk' do
43
+ its(:offset) { should == 46 }
44
+ specify { result.should == 'Song Title' }
45
+ end
46
+
47
+ describe '#read_string' do
48
+ before (:each) do
49
+ subject.offset = 36
50
+ end
51
+
52
+ let!(:result) { subject.read_string 10 }
53
+
54
+ it_behaves_like 'read_string and read_chunk'
55
+ end
56
+
57
+ describe '#read_bitmask' do
58
+ let!(:result) { subject.read_bitmask }
59
+
60
+ its(:offset) { should == 1}
61
+ specify { result.should == [false, false, false, true, true, false, false, false] }
62
+ end
63
+
64
+ describe '#read_chunk' do
65
+ before (:each) do
66
+ subject.offset = 31
67
+ end
68
+
69
+ let!(:result) { subject.read_chunk }
70
+
71
+ it_behaves_like 'read_string and read_chunk'
72
+ end
73
+
74
+ describe '#increment_offset' do
75
+ it 'changes offset' do
76
+ subject.increment_offset 5
77
+ subject.offset.should == 5
78
+ end
79
+ end
80
+
81
+ describe '#skip_integer' do
82
+ it 'changes offset' do
83
+ subject.skip_integer
84
+ subject.offset.should == 4
85
+ end
86
+ end
87
+
88
+ describe '#skip_short_integer' do
89
+ it 'changes offset' do
90
+ subject.skip_short_integer
91
+ subject.offset.should == 2
92
+ end
93
+ end
94
+
95
+ describe '#skip_byte' do
96
+ it 'changes offset' do
97
+ subject.skip_byte
98
+ subject.offset.should == 1
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ # TODO: Rewrite these test when it will be possible to read all the beats and notes.
4
+
5
+ def test_note(type)
6
+ refs = {
7
+ first: [0, '5']
8
+ }
9
+ beat_number = refs.fetch(type).fetch(0)
10
+ string_number = refs.fetch(type).fetch(1)
11
+ subject { song.tracks[0].bars[0].get_beat(beat_number).strings[string_number] }
12
+ end
13
+
14
+ describe GuitarProParser::Note do
15
+
16
+
17
+ shared_examples 'any Guitar Pro version' do
18
+
19
+ context 'note of the 1 beat, 1 bar, 1 track' do
20
+ test_note :first
21
+
22
+ # Tested features
23
+ its(:accentuated) { should == false }
24
+ its(:ghost) { should == false }
25
+ its(:fingers) { should == { left: nil, right: nil } }
26
+ its(:dynamic) { should == 'f' }
27
+ its(:type) { should == :normal }
28
+ its(:fret) { should == 3 }
29
+ its(:hammer_or_pull) { should == false }
30
+ its(:let_ring) { should == false }
31
+ its(:bend) { should be_nil }
32
+ its(:grace) { should be_nil }
33
+ its(:staccato) { should == false }
34
+ its(:palm_mute) { should == false }
35
+ its(:tremolo) { should be_nil }
36
+ its(:slide) { should be_nil }
37
+ its(:harmonic) { should be_nil }
38
+ its(:vibrato) { should == false }
39
+ its(:trill) { should be_nil }
40
+ end
41
+
42
+ end
43
+
44
+ context 'Guitar Pro 5' do
45
+ subject(:song) { GuitarProParser::Song.new test_tab_path 5 }
46
+ it_behaves_like 'any Guitar Pro version'
47
+ end
48
+
49
+ context 'Guitar Pro 4' do
50
+ subject(:song) { GuitarProParser::Song.new test_tab_path 4 }
51
+ it_behaves_like 'any Guitar Pro version'
52
+ end
53
+
54
+
55
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe GuitarProParser::PageSetup do
4
+ subject { GuitarProParser::Song.new(test_tab_path(5)).page_setup }
5
+
6
+ its(:page_format_length) { should == 210 }
7
+ its(:page_format_width) { should == 297 }
8
+ its(:left_margin) { should == 10 }
9
+ its(:right_margin) { should == 10 }
10
+ its(:top_margin) { should == 15 }
11
+ its(:bottom_margin) { should == 10 }
12
+ its(:score_size) { should == 100 }
13
+
14
+ its(:title) { should == '%TITLE%' }
15
+ its(:subtitle) { should == '%SUBTITLE%' }
16
+ its(:artist) { should == '%ARTIST%' }
17
+ its(:album) { should == '%ALBUM%' }
18
+ its(:lyrics_author) { should == 'Words by %WORDS%' }
19
+ its(:music_author) { should == 'Music by %MUSIC%' }
20
+ its(:lyrics_and_music_author) { should == 'Words & Music by %WORDSMUSIC%' }
21
+ its(:copyright_line_1) { should == 'Copyright %COPYRIGHT%' }
22
+ its(:copyright_line_2) { should == 'All Rights Reserved - International Copyright Secured' }
23
+ its(:page_number) { should == 'Page %N%/%P%' }
24
+
25
+ its(:displayed_fields) { should == [:title, :subtitle, :artist, :album, :lyrics_author, :music_author, :lyrics_and_music_author, :copyright, :page_number] }
26
+ end
@@ -0,0 +1,121 @@
1
+ require 'spec_helper'
2
+
3
+ describe GuitarProParser::Song do
4
+
5
+ shared_examples 'Any Guitar Pro version' do
6
+ its(:title) { should == 'Song Title' }
7
+ its(:subtitle) { should == 'Song Subtitle' }
8
+ its(:artist) { should == 'Artist' }
9
+ its(:composer) { should == 'Composer' }
10
+ its(:copyright) { should == 'Copyright' }
11
+ its(:transcriber) { should == 'Transcriber' }
12
+ its(:instructions) { should == 'Instructions' }
13
+ its(:notices) { should include('Notice 1', 'Notice 2', 'Notice 3') }
14
+ its(:master_volume) { should == 100 }
15
+ its(:tempo) { should == 'Moderate' }
16
+ its(:bpm) { should == 120 }
17
+ its(:page_setup) { should be_kind_of GuitarProParser::PageSetup }
18
+ its('channels.count') { should == 4 }
19
+ its('musical_directions.count') { should == 19 }
20
+ its(:equalizer) { should == Array.new(11, 0) }
21
+
22
+ its('bars_settings.count') { should == 18 }
23
+ its('tracks.count') { should == 10 }
24
+ end
25
+
26
+ shared_examples 'Guitar Pro 4 and 5' do
27
+ its(:lyrics_track) { should == 1 }
28
+
29
+ it 'should determine lyrics' do
30
+ 5.times do |i|
31
+ subject.lyrics.should include( {text: "Lyrics line #{i+1}", bar: i+1} )
32
+ end
33
+ end
34
+
35
+ its(:key) { should == 1 }
36
+ its(:octave) { should == 0 }
37
+ end
38
+
39
+ shared_examples 'Guitar Pro 3 and 4' do
40
+ its(:lyricist) { should == '' }
41
+ its(:triplet_feel) { should == true }
42
+ its(:master_reverb) { should == 0 }
43
+ end
44
+
45
+
46
+ describe 'Guitar Pro 5' do
47
+ subject { GuitarProParser::Song.new test_tab_path 5 }
48
+
49
+ it_behaves_like 'Any Guitar Pro version'
50
+ it_behaves_like 'Guitar Pro 4 and 5'
51
+
52
+ its(:version) { should == 5.1 }
53
+ its(:lyricist) { should == 'Lyricist' }
54
+ its(:triplet_feel) { should == true }
55
+
56
+ it 'has proper musical directions' do
57
+ subject.musical_directions.each do |key, value|
58
+ value.should == nil
59
+ end
60
+ end
61
+
62
+ its(:master_reverb) { should == 1 }
63
+ end
64
+
65
+ describe 'Guitar Pro 4' do
66
+ subject { GuitarProParser::Song.new test_tab_path 4 }
67
+
68
+ it_behaves_like 'Any Guitar Pro version'
69
+ it_behaves_like 'Guitar Pro 3 and 4'
70
+ it_behaves_like 'Guitar Pro 4 and 5'
71
+
72
+ its(:version) { should == 4.06 }
73
+ end
74
+
75
+ describe 'Musical directions' do
76
+ subject { GuitarProParser::Song.new test_tab_path 5, 'test_musical_directions' }
77
+
78
+ it 'has proper musical directions' do
79
+ correct_values = {
80
+ coda: 1,
81
+ double_coda: 2,
82
+ segno: 3,
83
+ segno_segno: 4,
84
+ fine: 5,
85
+ da_capo: 6,
86
+ da_capo_al_coda: 7,
87
+ da_capo_al_double_coda: 8,
88
+ da_capo_al_fine: 9,
89
+ da_segno: 10,
90
+ da_segno_segno: 11,
91
+ da_segno_al_coda: 12,
92
+ da_segno_al_double_coda: 13,
93
+ da_segno_segno_al_coda: 14,
94
+ da_segno_segno_al_double_coda: 15,
95
+ da_segno_al_fine: 16,
96
+ da_segno_segno_al_fine: 17,
97
+ da_coda: 18,
98
+ da_double_coda: 19
99
+ }
100
+
101
+ subject.musical_directions.each do |key, value|
102
+ value.should == correct_values[key]
103
+ end
104
+ end
105
+ end
106
+
107
+ # TODO: Create GP3 file for testing purposes
108
+ # describe 'Guitar Pro 3' do
109
+ # subject { GuitarProParser::Song.new test_tab_path 3 }
110
+
111
+ # it_behaves_like 'Any Guitar Pro version'
112
+ # it_behaves_like 'Guitar Pro 3 and 4'
113
+
114
+ # its(:version) { should == 3.0 }
115
+ # its(:lyrics_track) { should be_nil }
116
+ # its(:lyrics) { should be_nil }
117
+ # its(:key) { should == 0 }
118
+ # its(:octave) { should be_nil }
119
+
120
+ # end
121
+ end
@@ -0,0 +1,211 @@
1
+ require 'spec_helper'
2
+
3
+ def test_track(test_type)
4
+ refs = {
5
+ n1: 0,
6
+ n2: 1,
7
+ percussion: 2,
8
+ seven_strings: 3,
9
+ green_colored: 3,
10
+ drop_d: 4,
11
+ with_more_frets: 4,
12
+ with_capo: 4,
13
+ twelve_strings: 5,
14
+ banjo: 6,
15
+ with_all_styles: 7,
16
+ auto_let_ring: 3,
17
+ auto_brush: 4,
18
+ with_custom_midi_bank: 8,
19
+ with_human_playing: 9,
20
+ with_auto_accentuation: 9,
21
+ with_equalizer: 9,
22
+ with_custom_sound_bank: 9,
23
+ muted: 4
24
+ }
25
+
26
+ subject {song.tracks[refs[test_type]]}
27
+ end
28
+
29
+ describe GuitarProParser::Track do
30
+
31
+ shared_examples 'default track of any version' do
32
+ its(:drums) { should == false }
33
+ its(:twelve_stringed_guitar) { should == false }
34
+ its(:banjo) { should == false }
35
+ its(:solo_playback) { should == false }
36
+ its(:mute_playback) { should == false }
37
+ its(:rse_playback) { should == false }
38
+ its(:indicate_tuning) { should == false }
39
+ its(:strings) { should == %w(E5 B4 G4 D4 A3 E3) }
40
+ its(:midi_port) { should == 1 }
41
+ its(:frets_count) { should == 24 }
42
+ its(:capo) { should == 0 }
43
+ its(:color) { should == [255, 0, 0] }
44
+ end
45
+
46
+ shared_examples 'default track v5' do
47
+ its(:diagrams_below_the_standard_notation) { should == false }
48
+ its(:show_rythm_with_tab) { should == false }
49
+ its(:force_horizontal_beams) { should == false }
50
+ its(:force_channels_11_to_16) { should == false }
51
+ its(:diagrams_list_on_top_of_score) { should == true }
52
+ its(:diagrams_in_the_score) { should == false }
53
+ its(:extend_rhytmic_inside_the_tab) { should == false }
54
+ its(:auto_let_ring) { should == false }
55
+ its(:auto_brush) { should == false }
56
+
57
+
58
+ its(:midi_bank) { should == 0 }
59
+ its(:human_playing) { should == 0 }
60
+ its(:auto_accentuation) { should == 0 }
61
+ its(:sound_bank) { should == 255 }
62
+ its(:equalizer) { should == [0, 0, 0, 0] }
63
+
64
+ end
65
+
66
+ shared_examples 'Any Guitar Pro version' do
67
+
68
+ context 'track 1' do
69
+ test_track :n1
70
+ it_behaves_like 'default track of any version'
71
+ its(:name) { should == 'Track 1' }
72
+ its(:midi_channel) { should == 1 }
73
+ its(:midi_channel_for_effects) { should == 2 }
74
+ end
75
+
76
+ context 'track 2' do
77
+ test_track :n2
78
+ it_behaves_like 'default track of any version'
79
+ its(:name) { should == 'Track 2' }
80
+ its(:midi_channel) { should == 3 }
81
+ its(:midi_channel_for_effects) { should == 4 }
82
+ end
83
+
84
+ context 'percussion' do
85
+ test_track :percussion
86
+ its(:drums) { should == true }
87
+ its(:name) { should == 'Percussion' }
88
+ its(:midi_channel) { should == 10 }
89
+ its(:midi_channel_for_effects) { should == 10 }
90
+ end
91
+
92
+ context '7 strings guitar' do
93
+ test_track :seven_strings
94
+ its(:name) { should == '7 string guitar' }
95
+ its(:strings) { should == %w(E5 B4 G4 D4 A3 E3 B2) }
96
+ end
97
+
98
+ context 'green colored' do
99
+ test_track :green_colored
100
+ its(:color) { should == [0, 255, 0] }
101
+ end
102
+
103
+ context 'drop D' do
104
+ test_track :drop_d
105
+ its(:strings) { should == %w(D5 A4 F4 C4 G3 C3) } # actually it is drop C
106
+ end
107
+
108
+ context 'with more frets' do
109
+ test_track :with_more_frets
110
+ its(:frets_count) { should == 27 }
111
+ end
112
+
113
+ context 'with capo' do
114
+ test_track :with_capo
115
+ its(:capo) { should == 3 }
116
+ end
117
+
118
+ context '12 strings' do
119
+ test_track :twelve_strings
120
+ its(:name) { should == '12 stringed guitar' }
121
+ its('strings.count') { should == 6 }
122
+ its(:twelve_stringed_guitar) { should == true }
123
+ end
124
+
125
+ context 'banjo' do
126
+ test_track :banjo
127
+ its(:name) { should == 'Banjo' }
128
+ its('strings.count') { should == 5 }
129
+ its(:banjo) { should == true }
130
+ end
131
+ end
132
+
133
+
134
+ describe 'Guitar Pro 5' do
135
+ subject(:song) { GuitarProParser::Song.new test_tab_path 5 }
136
+
137
+ it_behaves_like 'Any Guitar Pro version'
138
+
139
+ context 'track 1' do
140
+ test_track :n1
141
+ it_behaves_like 'default track v5'
142
+ its(:instrument_effect_1) { should == 'American Clean - Pi Distortion' }
143
+ its(:instrument_effect_2) { should == 'Amp Tones' }
144
+ end
145
+
146
+ context 'track 2' do
147
+ test_track :n2
148
+ it_behaves_like 'default track v5'
149
+ its(:instrument_effect_1) { should == 'Acoustic - Default' }
150
+ its(:instrument_effect_2) { should == 'Acoustic Tones' }
151
+ end
152
+
153
+ context 'with all styles' do
154
+ test_track :with_all_styles
155
+ its(:diagrams_below_the_standard_notation) { should == true }
156
+ its(:show_rythm_with_tab) { should == true }
157
+ its(:force_horizontal_beams) { should == true }
158
+ its(:diagrams_list_on_top_of_score) { should == true }
159
+ its(:diagrams_in_the_score) { should == true }
160
+ its(:extend_rhytmic_inside_the_tab) { should == true }
161
+ end
162
+
163
+ context 'auto let ring' do
164
+ test_track :auto_let_ring
165
+ its(:auto_let_ring) { should == true }
166
+ end
167
+
168
+ context 'auto brush' do
169
+ test_track :auto_brush
170
+ its(:auto_brush) { should == true }
171
+ end
172
+
173
+ context 'with custom midi bank' do
174
+ test_track :with_custom_midi_bank
175
+ its(:midi_bank) { should == 5 }
176
+ end
177
+
178
+ context 'with human playing' do
179
+ test_track :with_human_playing
180
+ its(:human_playing) { should == 15 }
181
+ end
182
+
183
+ pending 'with auto accentuation'
184
+
185
+ context 'with equalizer' do
186
+ test_track :with_equalizer
187
+ its(:equalizer) { should == [226, 60, 231, 246] }
188
+ end
189
+
190
+ context 'with custom sound bank' do
191
+ test_track :with_custom_sound_bank
192
+ its(:sound_bank) { should == 2 }
193
+ end
194
+
195
+ context 'muted' do
196
+ test_track :muted
197
+ its(:mute_playback) { should == true }
198
+ end
199
+ end
200
+
201
+ describe 'Guitar Pro 4' do
202
+ subject(:song) { GuitarProParser::Song.new test_tab_path 4 }
203
+ it_behaves_like 'Any Guitar Pro version'
204
+
205
+ context 'muted' do
206
+ test_track :muted
207
+ its(:mute_playback) { should == false }
208
+ end
209
+ end
210
+
211
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe GuitarProParser do
4
+ it 'should has a version' do
5
+ GuitarProParser::VERSION.should_not be_nil
6
+ end
7
+
8
+ shared_examples 'all Guitar Pro versions' do
9
+ it 'is a song object' do
10
+ subject.should be_kind_of GuitarProParser::Song
11
+ end
12
+
13
+ its(:title) { should == 'Song Title'}
14
+ its('tracks.count') { should == 10 }
15
+ end
16
+
17
+ shared_examples 'file with headers only' do
18
+ it 'has no data about notes' do
19
+ subject.tracks.each do |track|
20
+ track.bars.should be_empty
21
+ end
22
+ end
23
+ end
24
+
25
+
26
+ describe '.read_file' do
27
+ context 'Guitar Pro 5' do
28
+ subject { GuitarProParser.read_file(test_tab_path(5)) }
29
+ it_behaves_like 'all Guitar Pro versions'
30
+ end
31
+
32
+ context 'Guitar Pro 4' do
33
+ subject { GuitarProParser.read_file(test_tab_path(4)) }
34
+ it_behaves_like 'all Guitar Pro versions'
35
+ end
36
+ end
37
+
38
+ describe '.read_headers' do
39
+ context 'Header only Guitar Pro 5' do
40
+ subject { GuitarProParser.read_headers(test_tab_path(5)) }
41
+ it_behaves_like 'all Guitar Pro versions'
42
+ it_behaves_like 'file with headers only'
43
+ end
44
+
45
+ context 'Header only Guitar Pro 4' do
46
+ subject { GuitarProParser.read_headers(test_tab_path(4)) }
47
+ it_behaves_like 'all Guitar Pro versions'
48
+ it_behaves_like 'file with headers only'
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,23 @@
1
+ require 'guitar_pro_parser'
2
+
3
+ # This file was generated by the `rspec --init` command. Conventionally, all
4
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
5
+ # Require this file using `require "spec_helper"` to ensure that it is only
6
+ # loaded once.
7
+ #
8
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
9
+ RSpec.configure do |config|
10
+ config.treat_symbols_as_metadata_keys_with_true_values = true
11
+ config.run_all_when_everything_filtered = true
12
+ config.filter_run :focus
13
+
14
+ # Run specs in random order to surface order dependencies. If you find an
15
+ # order dependency and want to debug it, you can fix the order by providing
16
+ # the seed, which is printed after each run.
17
+ # --seed 1234
18
+ config.order = 'random'
19
+ end
20
+
21
+ def test_tab_path version, filename = 'tab'
22
+ "spec/tabs/#{filename}.gp#{version.to_s}"
23
+ end
data/spec/tabs/tab.gp4 ADDED
Binary file
data/spec/tabs/tab.gp5 ADDED
Binary file