├── .gitignore ├── gp-parser-core ├── src │ ├── test │ │ ├── resources │ │ │ ├── configFile.txt │ │ │ ├── inputfile.txt │ │ │ ├── gp4 │ │ │ │ ├── rythme.gp4 │ │ │ │ ├── rythme2.gp4 │ │ │ │ ├── solfege.gp4 │ │ │ │ ├── test_gp4.gp4 │ │ │ │ └── rythme_blues.gp4 │ │ │ ├── midi │ │ │ │ ├── rythme.mid │ │ │ │ └── rythme2.mid │ │ │ ├── testng.xml │ │ │ ├── test_musicXml.xml │ │ │ └── svg │ │ │ │ └── note.svg │ │ └── java │ │ │ └── net │ │ │ └── sourceforge │ │ │ └── musicsvg │ │ │ └── io │ │ │ └── gp │ │ │ └── GP4ParserTest.java │ └── main │ │ ├── java │ │ └── net │ │ │ └── sourceforge │ │ │ └── musicsvg │ │ │ └── io │ │ │ ├── Parser.java │ │ │ └── gp │ │ │ ├── GP3Parser.java │ │ │ ├── GP5Parser.java │ │ │ ├── ParserHelper.java │ │ │ ├── listeners │ │ │ └── GP4ParserListener.java │ │ │ └── GP4Parser.java │ │ ├── assemblies │ │ └── netbeans-run.xml │ │ └── resources │ │ └── GP4Format.html ├── manifest.mf ├── nbactions.xml ├── pom.xml ├── build.xml └── COPYING.txt ├── gp-parser-example ├── manifest.mf ├── src │ └── main │ │ ├── assemblies │ │ └── netbeans-run.xml │ │ └── java │ │ └── org │ │ └── sourceforge │ │ └── musicsvg │ │ └── example │ │ ├── MainClass.java │ │ └── SystemOutputGP4ParserListenerImpl.java ├── pom.xml ├── nbactions.xml ├── build.xml └── COPYING.txt ├── gp-parser-model ├── src │ ├── test │ │ ├── resources │ │ │ ├── rythme.gp4 │ │ │ ├── rythme2.gp4 │ │ │ ├── solfege.gp4 │ │ │ ├── test_gp4.gp4 │ │ │ ├── famous_song.gp4 │ │ │ └── rythme_blues.gp4 │ │ └── java │ │ │ └── com │ │ │ └── github │ │ │ └── gp │ │ │ └── parser │ │ │ └── model │ │ │ ├── beats │ │ │ └── BeatTest.java │ │ │ ├── measures │ │ │ └── MeasureTest.java │ │ │ └── ParserToModelListenerTest.java │ └── main │ │ └── java │ │ └── com │ │ └── github │ │ └── gp │ │ └── parser │ │ └── model │ │ ├── tracks │ │ ├── TrackId.java │ │ ├── Track.java │ │ ├── TrackBuilder.java │ │ ├── TrackHeader.java │ │ └── TrackHeaderBuilder.java │ │ ├── beats │ │ ├── BeatBuilder.java │ │ └── Beat.java │ │ ├── measures │ │ ├── MeasureId.java │ │ ├── MeasureHeader.java │ │ ├── MeasureHeaderBuilder.java │ │ ├── MeasureBuilder.java │ │ └── Measure.java │ │ ├── header │ │ ├── PieceInformation.java │ │ ├── PieceInformationBuilder.java │ │ ├── Headers.java │ │ └── HeadersBuilder.java │ │ ├── MeasureTrackKey.java │ │ └── ParserToModelListener.java └── pom.xml ├── nbactions.xml ├── README.md └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | */target/* 3 | *.iml -------------------------------------------------------------------------------- /gp-parser-core/src/test/resources/configFile.txt: -------------------------------------------------------------------------------- 1 | height = 200 2 | width = 150 -------------------------------------------------------------------------------- /gp-parser-core/src/test/resources/inputfile.txt: -------------------------------------------------------------------------------- 1 | 2 4 2 | 4 3 3 | 6 7 4 | 2 2 5 | 4 8 -------------------------------------------------------------------------------- /gp-parser-core/manifest.mf: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | X-COMMENT: Main-Class will be added automatically by build 3 | 4 | -------------------------------------------------------------------------------- /gp-parser-example/manifest.mf: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | X-COMMENT: Main-Class will be added automatically by build 3 | 4 | -------------------------------------------------------------------------------- /gp-parser-model/src/test/resources/rythme.gp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwursteisen/gp-parser/HEAD/gp-parser-model/src/test/resources/rythme.gp4 -------------------------------------------------------------------------------- /gp-parser-core/src/test/resources/gp4/rythme.gp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwursteisen/gp-parser/HEAD/gp-parser-core/src/test/resources/gp4/rythme.gp4 -------------------------------------------------------------------------------- /gp-parser-model/src/test/resources/rythme2.gp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwursteisen/gp-parser/HEAD/gp-parser-model/src/test/resources/rythme2.gp4 -------------------------------------------------------------------------------- /gp-parser-model/src/test/resources/solfege.gp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwursteisen/gp-parser/HEAD/gp-parser-model/src/test/resources/solfege.gp4 -------------------------------------------------------------------------------- /gp-parser-model/src/test/resources/test_gp4.gp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwursteisen/gp-parser/HEAD/gp-parser-model/src/test/resources/test_gp4.gp4 -------------------------------------------------------------------------------- /gp-parser-core/src/test/resources/gp4/rythme2.gp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwursteisen/gp-parser/HEAD/gp-parser-core/src/test/resources/gp4/rythme2.gp4 -------------------------------------------------------------------------------- /gp-parser-core/src/test/resources/gp4/solfege.gp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwursteisen/gp-parser/HEAD/gp-parser-core/src/test/resources/gp4/solfege.gp4 -------------------------------------------------------------------------------- /gp-parser-core/src/test/resources/gp4/test_gp4.gp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwursteisen/gp-parser/HEAD/gp-parser-core/src/test/resources/gp4/test_gp4.gp4 -------------------------------------------------------------------------------- /gp-parser-core/src/test/resources/midi/rythme.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwursteisen/gp-parser/HEAD/gp-parser-core/src/test/resources/midi/rythme.mid -------------------------------------------------------------------------------- /gp-parser-core/src/test/resources/midi/rythme2.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwursteisen/gp-parser/HEAD/gp-parser-core/src/test/resources/midi/rythme2.mid -------------------------------------------------------------------------------- /gp-parser-model/src/test/resources/famous_song.gp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwursteisen/gp-parser/HEAD/gp-parser-model/src/test/resources/famous_song.gp4 -------------------------------------------------------------------------------- /gp-parser-model/src/test/resources/rythme_blues.gp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwursteisen/gp-parser/HEAD/gp-parser-model/src/test/resources/rythme_blues.gp4 -------------------------------------------------------------------------------- /gp-parser-core/src/test/resources/gp4/rythme_blues.gp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwursteisen/gp-parser/HEAD/gp-parser-core/src/test/resources/gp4/rythme_blues.gp4 -------------------------------------------------------------------------------- /gp-parser-core/src/main/java/net/sourceforge/musicsvg/io/Parser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | 6 | package net.sourceforge.musicsvg.io; 7 | 8 | import java.io.File; 9 | import java.io.IOException; 10 | 11 | /** 12 | * @author Dav 13 | */ 14 | public interface Parser { 15 | 16 | void openFile(File file) throws IOException; 17 | 18 | void close(); 19 | } 20 | -------------------------------------------------------------------------------- /gp-parser-core/nbactions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | run 5 | 6 | jar 7 | 8 | 9 | compile 10 | exec:exec 11 | 12 | 13 | bidule 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /nbactions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CUSTOM-build-dist 5 | build-dist 6 | 7 | clean 8 | install 9 | 10 | 11 | true 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /gp-parser-model/src/main/java/com/github/gp/parser/model/tracks/TrackId.java: -------------------------------------------------------------------------------- 1 | package com.github.gp.parser.model.tracks; 2 | 3 | 4 | import com.google.common.primitives.Ints; 5 | 6 | public class TrackId implements Comparable { 7 | 8 | private final int trackIndex; 9 | 10 | public TrackId(int trackIndex) { 11 | this.trackIndex = trackIndex; 12 | } 13 | 14 | @Override 15 | public int compareTo(TrackId o) { 16 | return Ints.compare(trackIndex, o.trackIndex); 17 | } 18 | 19 | public int getIndex() { 20 | return trackIndex; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /gp-parser-core/src/main/assemblies/netbeans-run.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | netbeans 4 | false 5 | 6 | 7 | target 8 | 9 | 10 | *.jar 11 | 12 | 13 | 14 | 15 | 16 | lib 17 | false 18 | runtime 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /gp-parser-example/src/main/assemblies/netbeans-run.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | netbeans 4 | false 5 | 6 | 7 | target 8 | 9 | 10 | *.jar 11 | 12 | 13 | 14 | 15 | 16 | lib 17 | false 18 | runtime 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /gp-parser-core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | dwursteisen.github.com 5 | gp-parser-core 6 | Guitar Pro file Parser 7 | 1.0-SNAPSHOT 8 | 9 | dwursteisen.github.com 10 | gp-parser 11 | 1.0-SNAPSHOT 12 | 13 | http://musicsvg.sourceforge.net/ 14 | 15 | 16 | log4j 17 | log4j 18 | 1.2.14 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /gp-parser-model/src/test/java/com/github/gp/parser/model/beats/BeatTest.java: -------------------------------------------------------------------------------- 1 | package com.github.gp.parser.model.beats; 2 | 3 | import org.testng.annotations.Test; 4 | 5 | import static org.fest.assertions.Assertions.assertThat; 6 | 7 | /** 8 | * User: Wursteisen David 9 | * Date: 03/09/12 10 | * Time: 22:10 11 | */ 12 | public class BeatTest { 13 | @Test 14 | public void testCompareTo() throws Exception { 15 | Beat beat1 = new Beat(0, 2, 0, 5); 16 | Beat beat2 = new Beat(0, 3, 0, 5); 17 | Beat beat3 = new Beat(1, 3, 0, 5); 18 | 19 | assertThat(beat1.compareTo(beat2)).isLessThan(0); 20 | assertThat(beat1.compareTo(beat3)).isLessThan(0); 21 | assertThat(beat1.compareTo(beat3)).isLessThan(0); 22 | assertThat(beat1.compareTo(beat1)).isEqualTo(0); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /gp-parser-core/src/test/resources/testng.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /gp-parser-model/src/main/java/com/github/gp/parser/model/beats/BeatBuilder.java: -------------------------------------------------------------------------------- 1 | package com.github.gp.parser.model.beats; 2 | 3 | public class BeatBuilder { 4 | private int beatIndex; 5 | 6 | private int fret; 7 | 8 | private int string; 9 | 10 | private int duration; 11 | 12 | public BeatBuilder withBeatIndex(int beatIndex) { 13 | this.beatIndex = beatIndex; 14 | return this; 15 | } 16 | 17 | public BeatBuilder withFret(int fret) { 18 | this.fret = fret; 19 | return this; 20 | } 21 | 22 | public BeatBuilder withString(int string) { 23 | this.string = string; 24 | return this; 25 | } 26 | 27 | public BeatBuilder withDuration(int duration) { 28 | this.duration = duration; 29 | return this; 30 | } 31 | 32 | public Beat createBeat() { 33 | return new Beat(beatIndex, string, fret, duration); 34 | } 35 | } -------------------------------------------------------------------------------- /gp-parser-model/src/main/java/com/github/gp/parser/model/tracks/Track.java: -------------------------------------------------------------------------------- 1 | package com.github.gp.parser.model.tracks; 2 | 3 | import com.github.gp.parser.model.measures.Measure; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | public class Track { 9 | private final TrackId trackIndex; 10 | 11 | private final List measures; 12 | 13 | private final TrackHeader header; 14 | 15 | public Track(TrackId trackIndex, List measures, TrackHeader header) { 16 | this.trackIndex = trackIndex; 17 | this.measures = measures; 18 | this.header = header; 19 | } 20 | 21 | public TrackId getTrackIndex() { 22 | return trackIndex; 23 | } 24 | 25 | public List getMeasures() { 26 | return new ArrayList(measures); 27 | } 28 | 29 | public TrackHeader getHeader() { 30 | return header; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /gp-parser-model/src/main/java/com/github/gp/parser/model/tracks/TrackBuilder.java: -------------------------------------------------------------------------------- 1 | package com.github.gp.parser.model.tracks; 2 | 3 | import com.github.gp.parser.model.measures.Measure; 4 | 5 | import java.util.List; 6 | 7 | public class TrackBuilder { 8 | private int trackIndex; 9 | 10 | private List measures; 11 | 12 | private TrackHeader header; 13 | 14 | public TrackBuilder withTrackIndex(int trackIndex) { 15 | this.trackIndex = trackIndex; 16 | return this; 17 | } 18 | 19 | public TrackBuilder withMeasures(List measures) { 20 | this.measures = measures; 21 | return this; 22 | } 23 | 24 | public TrackBuilder withHeader(TrackHeader header) { 25 | this.header = header; 26 | return this; 27 | } 28 | 29 | public Track createTrack() { 30 | return new Track(new TrackId(trackIndex), measures, header); 31 | } 32 | } -------------------------------------------------------------------------------- /gp-parser-model/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | dwursteisen.github.com 5 | gp-parser-model 6 | Guitar Pro file Parser model 7 | 1.0-SNAPSHOT 8 | 9 | dwursteisen.github.com 10 | gp-parser 11 | 1.0-SNAPSHOT 12 | 13 | 14 | 15 | 16 | dwursteisen.github.com 17 | gp-parser-core 18 | ${project.version} 19 | 20 | 21 | 22 | com.google.guava 23 | guava 24 | 13.0 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /gp-parser-example/src/main/java/org/sourceforge/musicsvg/example/MainClass.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | 6 | package org.sourceforge.musicsvg.example; 7 | 8 | import net.sourceforge.musicsvg.io.gp.GP4Parser; 9 | 10 | import java.io.File; 11 | import java.io.IOException; 12 | 13 | /** 14 | * @author david 15 | */ 16 | public class MainClass { 17 | 18 | public static void main(String[] args) { 19 | if (args.length == 0) { 20 | System.err.println("Please give a Guitar Pro file."); 21 | return; 22 | } 23 | GP4Parser parser = new GP4Parser(); 24 | parser.setListener(new SystemOutputGP4ParserListenerImpl()); 25 | try { 26 | parser.openFile(new File(args[0])); 27 | } catch (IOException ex) { 28 | System.err.println("Error with the file !!"); 29 | ex.printStackTrace(System.err); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /gp-parser-model/src/main/java/com/github/gp/parser/model/measures/MeasureId.java: -------------------------------------------------------------------------------- 1 | package com.github.gp.parser.model.measures; 2 | 3 | import com.google.common.primitives.Ints; 4 | 5 | public class MeasureId implements Comparable { 6 | private final int index; 7 | 8 | public MeasureId(int index) { 9 | this.index = index; 10 | } 11 | 12 | @Override 13 | public boolean equals(Object o) { 14 | if (this == o) return true; 15 | if (o == null || getClass() != o.getClass()) return false; 16 | 17 | MeasureId measureId = (MeasureId) o; 18 | 19 | if (index != measureId.index) return false; 20 | 21 | return true; 22 | } 23 | 24 | @Override 25 | public int hashCode() { 26 | return index; 27 | } 28 | 29 | @Override 30 | public int compareTo(MeasureId o) { 31 | if (o == null) { 32 | return 1; 33 | } 34 | return Ints.compare(index, o.index); 35 | } 36 | 37 | public int getIndex() { 38 | return index; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /gp-parser-core/src/main/java/net/sourceforge/musicsvg/io/gp/GP3Parser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | 6 | package net.sourceforge.musicsvg.io.gp; 7 | 8 | import com.google.inject.Inject; 9 | import net.sourceforge.musicsvg.io.Parser; 10 | import net.sourceforge.musicsvg.io.gp.listeners.GP4ParserListener; 11 | 12 | import java.io.File; 13 | import java.io.FileInputStream; 14 | import java.io.IOException; 15 | 16 | /** 17 | * @author Dav 18 | */ 19 | public class GP3Parser implements Parser { 20 | 21 | protected FileInputStream is; 22 | protected GP4ParserListener listener; 23 | 24 | public void openFile(File file) throws IOException { 25 | throw new UnsupportedOperationException("Not supported yet."); 26 | } 27 | 28 | public void close() { 29 | throw new UnsupportedOperationException("Not supported yet."); 30 | } 31 | 32 | @Inject 33 | public void setListener(GP4ParserListener listener) { 34 | this.listener = listener; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /gp-parser-core/src/main/java/net/sourceforge/musicsvg/io/gp/GP5Parser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | 6 | package net.sourceforge.musicsvg.io.gp; 7 | 8 | import com.google.inject.Inject; 9 | import net.sourceforge.musicsvg.io.Parser; 10 | import net.sourceforge.musicsvg.io.gp.listeners.GP4ParserListener; 11 | 12 | import java.io.File; 13 | import java.io.FileInputStream; 14 | import java.io.IOException; 15 | 16 | /** 17 | * @author Dav 18 | */ 19 | public class GP5Parser implements Parser { 20 | 21 | protected FileInputStream is; 22 | protected GP4ParserListener listener; 23 | 24 | public void openFile(File file) throws IOException { 25 | throw new UnsupportedOperationException("Not supported yet."); 26 | } 27 | 28 | public void close() { 29 | throw new UnsupportedOperationException("Not supported yet."); 30 | } 31 | 32 | 33 | @Inject 34 | public void setListener(GP4ParserListener listener) { 35 | this.listener = listener; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /gp-parser-model/src/main/java/com/github/gp/parser/model/header/PieceInformation.java: -------------------------------------------------------------------------------- 1 | package com.github.gp.parser.model.header; 2 | 3 | /** 4 | * User: Wursteisen David 5 | * Date: 02/09/12 6 | * Time: 22:09 7 | */ 8 | public class PieceInformation { 9 | private final int tempo; 10 | private final int key; // TODO: replace with enum 11 | private final int octave; 12 | private final int numberOfMeasure; 13 | private final int numberOfTrack; 14 | 15 | public PieceInformation(int tempo, int key, int octave, int numberOfMeasure, int numberOfTrack) { 16 | this.tempo = tempo; 17 | this.key = key; 18 | this.octave = octave; 19 | this.numberOfMeasure = numberOfMeasure; 20 | this.numberOfTrack = numberOfTrack; 21 | } 22 | 23 | 24 | public int getTempo() { 25 | return tempo; 26 | } 27 | 28 | public int getKey() { 29 | return key; 30 | } 31 | 32 | public int getOctave() { 33 | return octave; 34 | } 35 | 36 | public int getNumberOfMeasure() { 37 | return numberOfMeasure; 38 | } 39 | 40 | public int getNumberOfTrack() { 41 | return numberOfTrack; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /gp-parser-model/src/main/java/com/github/gp/parser/model/header/PieceInformationBuilder.java: -------------------------------------------------------------------------------- 1 | package com.github.gp.parser.model.header; 2 | 3 | public class PieceInformationBuilder { 4 | private int tempo; 5 | private int key; 6 | private int octave; 7 | private int numberOfMeasure; 8 | private int numberOfTrack; 9 | 10 | public PieceInformationBuilder withTempo(int tempo) { 11 | this.tempo = tempo; 12 | return this; 13 | } 14 | 15 | public PieceInformationBuilder withKey(int key) { 16 | this.key = key; 17 | return this; 18 | } 19 | 20 | public PieceInformationBuilder withOctave(int octave) { 21 | this.octave = octave; 22 | return this; 23 | } 24 | 25 | public PieceInformationBuilder withNumberOfMeasure(int numberOfMeasure) { 26 | this.numberOfMeasure = numberOfMeasure; 27 | return this; 28 | } 29 | 30 | public PieceInformationBuilder withNumberOfTrack(int numberOfTrack) { 31 | this.numberOfTrack = numberOfTrack; 32 | return this; 33 | } 34 | 35 | public PieceInformation createPieceInformation() { 36 | return new PieceInformation(tempo, key, octave, numberOfMeasure, numberOfTrack); 37 | } 38 | } -------------------------------------------------------------------------------- /gp-parser-model/src/main/java/com/github/gp/parser/model/MeasureTrackKey.java: -------------------------------------------------------------------------------- 1 | package com.github.gp.parser.model; 2 | 3 | /** 4 | * User: Wursteisen David 5 | * Date: 02/09/12 6 | * Time: 23:38 7 | */ 8 | class MeasureTrackKey { 9 | private final int measureIndex; 10 | private final int trackIndex; 11 | 12 | MeasureTrackKey(int trackIndex, int measureIndex) { 13 | this.measureIndex = measureIndex; 14 | this.trackIndex = trackIndex; 15 | } 16 | 17 | public int getMeasureIndex() { 18 | return measureIndex; 19 | } 20 | 21 | public int getTrackIndex() { 22 | return trackIndex; 23 | } 24 | 25 | @Override 26 | public boolean equals(Object o) { 27 | if (this == o) return true; 28 | if (o == null || getClass() != o.getClass()) return false; 29 | 30 | MeasureTrackKey that = (MeasureTrackKey) o; 31 | 32 | if (measureIndex != that.measureIndex) return false; 33 | if (trackIndex != that.trackIndex) return false; 34 | 35 | return true; 36 | } 37 | 38 | @Override 39 | public int hashCode() { 40 | int result = measureIndex; 41 | result = 31 * result + trackIndex; 42 | return result; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Guitar Pro file parser 2 | ====================== 3 | 4 | Main purpose 5 | ------------ 6 | This Java library is here to help you to parse Guitar Pro file (v4, ...) 7 | 8 | 9 | How to use it ? 10 | --------------- 11 | Add this library to your java project. Create a parser for your Guitar pro file 12 | 13 | GP4Parser parser = new GP4Parser(); 14 | 15 | Give it your own class which implement GP4ParserListener. This listener will be aware then the parser read the song name, 16 | when the parser read a note, .... With this information, you'll be able to retrieve informations that you'll 17 | need into your application 18 | 19 | parser.setListener(yourListener); 20 | 21 | Then just read your Guitar Pro file : 22 | 23 | parser.openFile(yourFile); 24 | 25 | Have you got an easy-to-use example ? 26 | -------------------------------------- 27 | Just check the example project avaible in this repository 28 | 29 | 30 | How to compile it ? 31 | ------------------- 32 | Clone this repository, and perform this [maven](http://maven.apache.org/) command to compile/test/package it ! 33 | 34 | mvn install 35 | 36 | The packaged java library will be located into the target directory that will be created by [maven](http://maven.apache.org/). 37 | -------------------------------------------------------------------------------- /gp-parser-model/src/main/java/com/github/gp/parser/model/beats/Beat.java: -------------------------------------------------------------------------------- 1 | package com.github.gp.parser.model.beats; 2 | 3 | public class Beat implements Comparable { 4 | private final int beatIndex; 5 | 6 | private final int fret; 7 | 8 | private final int string; 9 | 10 | private final int duration; // should be an enum ? 11 | 12 | public Beat(int beatIndex, int string, int fret, int duration) { 13 | this.beatIndex = beatIndex; 14 | this.fret = fret; 15 | this.string = string; 16 | this.duration = duration; 17 | } 18 | 19 | public int getBeatIndex() { 20 | return beatIndex; 21 | } 22 | 23 | public int getFret() { 24 | return fret; 25 | } 26 | 27 | public int getString() { 28 | return string; 29 | } 30 | 31 | public int getDuration() { 32 | return duration; 33 | } 34 | 35 | @Override 36 | public int compareTo(Beat o) { 37 | if (beatIndex > o.beatIndex) { 38 | return 1; 39 | } else if (beatIndex < o.beatIndex) { 40 | return -1; 41 | } 42 | 43 | if (string > o.string) { 44 | return 1; 45 | } else if (string < o.string) { 46 | return -1; 47 | } 48 | return 0; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /gp-parser-model/src/main/java/com/github/gp/parser/model/header/Headers.java: -------------------------------------------------------------------------------- 1 | package com.github.gp.parser.model.header; 2 | 3 | /** 4 | * User: Wursteisen David 5 | * Date: 02/09/12 6 | * Time: 21:05 7 | */ 8 | public class Headers { 9 | private final String version; 10 | private final String title; 11 | private final String subtitle; 12 | private final String interpret; 13 | private final String album; 14 | private final String songAuthor; 15 | 16 | public Headers(String version, String title, String subtitle, String interpret, String album, String songAuthor) { 17 | this.version = version; 18 | this.title = title; 19 | this.subtitle = subtitle; 20 | this.interpret = interpret; 21 | this.album = album; 22 | this.songAuthor = songAuthor; 23 | } 24 | 25 | public String getVersion() { 26 | return version; 27 | } 28 | 29 | public String getTitle() { 30 | return title; 31 | } 32 | 33 | public String getSubtitle() { 34 | return subtitle; 35 | } 36 | 37 | public String getInterpret() { 38 | return interpret; 39 | } 40 | 41 | public String getAlbum() { 42 | return album; 43 | } 44 | 45 | public String getSongAuthor() { 46 | return songAuthor; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /gp-parser-model/src/main/java/com/github/gp/parser/model/header/HeadersBuilder.java: -------------------------------------------------------------------------------- 1 | package com.github.gp.parser.model.header; 2 | 3 | public class HeadersBuilder { 4 | private String version; 5 | private String title; 6 | private String subtitle; 7 | private String interpret; 8 | private String album; 9 | private String songAuthor; 10 | 11 | public HeadersBuilder withVersion(String version) { 12 | this.version = version; 13 | return this; 14 | } 15 | 16 | public HeadersBuilder withTitle(String title) { 17 | this.title = title; 18 | return this; 19 | } 20 | 21 | public HeadersBuilder withSubtitle(String subtitle) { 22 | this.subtitle = subtitle; 23 | return this; 24 | } 25 | 26 | public HeadersBuilder withInterpret(String interpret) { 27 | this.interpret = interpret; 28 | return this; 29 | } 30 | 31 | public HeadersBuilder withAlbum(String album) { 32 | this.album = album; 33 | return this; 34 | } 35 | 36 | public HeadersBuilder withSongAuthor(String songAuthor) { 37 | this.songAuthor = songAuthor; 38 | return this; 39 | } 40 | 41 | public Headers createHeaders() { 42 | return new Headers(version, title, subtitle, interpret, album, songAuthor); 43 | } 44 | } -------------------------------------------------------------------------------- /gp-parser-model/src/main/java/com/github/gp/parser/model/measures/MeasureHeader.java: -------------------------------------------------------------------------------- 1 | package com.github.gp.parser.model.measures; 2 | 3 | /** 4 | * User: Wursteisen David Date: 02/09/12 Time: 22:39 5 | */ 6 | public class MeasureHeader { 7 | 8 | private final boolean doubleBar; 9 | 10 | private final boolean repeat; 11 | 12 | private final int numberOfAlternateEnding; 13 | 14 | private final int numberOfRepeats; 15 | 16 | private final MeasureId measureIndex; 17 | 18 | public MeasureHeader(MeasureId measureIndex, boolean doubleBar, boolean repeat, 19 | int numberOfAlternateEnding, int numberOfRepeats) { 20 | this.doubleBar = doubleBar; 21 | this.repeat = repeat; 22 | this.numberOfAlternateEnding = numberOfAlternateEnding; 23 | this.numberOfRepeats = numberOfRepeats; 24 | this.measureIndex = measureIndex; 25 | } 26 | 27 | public MeasureId getMeasureIndex() { 28 | return measureIndex; 29 | } 30 | 31 | public boolean isDoubleBar() { 32 | return doubleBar; 33 | } 34 | 35 | public boolean isRepeat() { 36 | return repeat; 37 | } 38 | 39 | public int getNumberOfAlternateEnding() { 40 | return numberOfAlternateEnding; 41 | } 42 | 43 | public int getNumberOfRepeats() { 44 | return numberOfRepeats; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /gp-parser-model/src/main/java/com/github/gp/parser/model/measures/MeasureHeaderBuilder.java: -------------------------------------------------------------------------------- 1 | package com.github.gp.parser.model.measures; 2 | 3 | public class MeasureHeaderBuilder { 4 | private boolean doubleBar; 5 | 6 | private boolean repeat; 7 | 8 | private int numberOfAlternateEnding; 9 | 10 | private int numberOfRepeats; 11 | 12 | private int measureIndex; 13 | 14 | public MeasureHeaderBuilder withDoubleBar(boolean doubleBar) { 15 | this.doubleBar = doubleBar; 16 | return this; 17 | } 18 | 19 | public MeasureHeaderBuilder withRepeat(boolean repeat) { 20 | this.repeat = repeat; 21 | return this; 22 | } 23 | 24 | public MeasureHeaderBuilder withNumberOfAlternateEnding(int numberOfAlternateEnding) { 25 | this.numberOfAlternateEnding = numberOfAlternateEnding; 26 | return this; 27 | } 28 | 29 | public MeasureHeaderBuilder withNumberOfRepeats(int numberOfRepeats) { 30 | this.numberOfRepeats = numberOfRepeats; 31 | return this; 32 | } 33 | 34 | public MeasureHeaderBuilder withMeasureIndex(int index) { 35 | this.measureIndex = index; 36 | return this; 37 | } 38 | 39 | public MeasureHeader createMeasureHeader() { 40 | return new MeasureHeader(new MeasureId(measureIndex), doubleBar, repeat, numberOfAlternateEnding, 41 | numberOfRepeats); 42 | } 43 | } -------------------------------------------------------------------------------- /gp-parser-model/src/test/java/com/github/gp/parser/model/measures/MeasureTest.java: -------------------------------------------------------------------------------- 1 | package com.github.gp.parser.model.measures; 2 | 3 | import org.testng.annotations.Test; 4 | 5 | import static org.fest.assertions.Assertions.assertThat; 6 | 7 | /** 8 | * User: Wursteisen David Date: 02/09/12 Time: 23:59 9 | */ 10 | public class MeasureTest { 11 | @Test 12 | public void testCompareTo() throws Exception { 13 | Measure measure1 = new Measure(0, new MeasureId(1), 5, null, null); 14 | Measure measure2 = new Measure(0, new MeasureId(2), 5, null, null); 15 | Measure measure3 = new Measure(1, new MeasureId(1), 5, null, null); 16 | Measure measure4 = new Measure(1, new MeasureId(2), 5, null, null); 17 | 18 | // expected = 1,3,2,4 19 | assertThat(measure1.compareTo(measure1)).isEqualTo(0); 20 | assertThat(measure1.compareTo(measure2)).isLessThan(0); 21 | assertThat(measure1.compareTo(measure3)).isLessThan(0); 22 | assertThat(measure1.compareTo(measure4)).isLessThan(0); 23 | 24 | assertThat(measure2.compareTo(measure3)).isGreaterThan(0); 25 | assertThat(measure2.compareTo(measure4)).isLessThan(0); 26 | 27 | assertThat(measure4.compareTo(measure1)).isGreaterThan(0); 28 | assertThat(measure4.compareTo(measure2)).isGreaterThan(0); 29 | assertThat(measure4.compareTo(measure3)).isGreaterThan(0); 30 | assertThat(measure4.compareTo(measure4)).isEqualTo(0); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /gp-parser-model/src/main/java/com/github/gp/parser/model/measures/MeasureBuilder.java: -------------------------------------------------------------------------------- 1 | package com.github.gp.parser.model.measures; 2 | 3 | import com.github.gp.parser.model.beats.Beat; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | public class MeasureBuilder { 9 | private int trackIndex; 10 | 11 | private int measureIndex; 12 | 13 | private int numberOfBeats; 14 | 15 | private MeasureHeader header; 16 | private List beats; 17 | 18 | public int getMeasureIndex() { 19 | return measureIndex; 20 | } 21 | 22 | public int getTrackIndex() { 23 | return trackIndex; 24 | } 25 | 26 | public MeasureBuilder withTrackIndex(int trackIndex) { 27 | this.trackIndex = trackIndex; 28 | return this; 29 | } 30 | 31 | public MeasureBuilder withMeasureIndex(int measureIndex) { 32 | this.measureIndex = measureIndex; 33 | return this; 34 | } 35 | 36 | public MeasureBuilder withNumberOfBeats(int numberOfBeats) { 37 | this.numberOfBeats = numberOfBeats; 38 | return this; 39 | } 40 | 41 | public MeasureBuilder withHeader(MeasureHeader header) { 42 | this.header = header; 43 | return this; 44 | } 45 | 46 | public MeasureBuilder withBeats(List beats) { 47 | this.beats = new ArrayList(beats); 48 | return this; 49 | } 50 | 51 | public Measure createMeasure() { 52 | return new Measure(trackIndex, new MeasureId(measureIndex), numberOfBeats, header, beats); 53 | } 54 | } -------------------------------------------------------------------------------- /gp-parser-model/src/main/java/com/github/gp/parser/model/tracks/TrackHeader.java: -------------------------------------------------------------------------------- 1 | package com.github.gp.parser.model.tracks; 2 | 3 | /** 4 | * User: Wursteisen David Date: 02/09/12 Time: 23:04 5 | */ 6 | public class TrackHeader { 7 | private final TrackId trackIndex; 8 | 9 | private final String name; 10 | 11 | private final int numberOfString; 12 | 13 | private final int numberOfFrets; 14 | 15 | private final int capodastrePosition; 16 | 17 | private final boolean drumTrack; 18 | 19 | private final boolean banjoTrack; 20 | 21 | private final boolean twelveStringTrack; 22 | 23 | public TrackHeader(TrackId trackIndex, String name, int numberOfString, int numberOfFrets, 24 | int capodastrePosition, boolean drumTrack, boolean banjoTrack, 25 | boolean twelveStringTrack) { 26 | this.trackIndex = trackIndex; 27 | this.name = name; 28 | this.numberOfString = numberOfString; 29 | this.numberOfFrets = numberOfFrets; 30 | this.capodastrePosition = capodastrePosition; 31 | this.drumTrack = drumTrack; 32 | this.banjoTrack = banjoTrack; 33 | this.twelveStringTrack = twelveStringTrack; 34 | } 35 | 36 | public TrackId getTrackIndex() { 37 | return trackIndex; 38 | } 39 | 40 | public String getName() { 41 | return name; 42 | } 43 | 44 | public int getNumberOfString() { 45 | return numberOfString; 46 | } 47 | 48 | public int getNumberOfFrets() { 49 | return numberOfFrets; 50 | } 51 | 52 | public int getCapodastrePosition() { 53 | return capodastrePosition; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /gp-parser-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | dwursteisen.github.com 5 | gp-parser-example 6 | Guitar Pro file example 7 | 1.0-SNAPSHOT 8 | 9 | dwursteisen.github.com 10 | gp-parser 11 | 1.0-SNAPSHOT 12 | 13 | 14 | http://musicsvg.sourceforge.net/ 15 | 16 | 17 | 18 | 19 | 20 | 21 | org.codehaus.mojo 22 | exec-maven-plugin 23 | 1.2.1 24 | 25 | java 26 | 27 | -classpath 28 | 30 | 31 | net.sourceforge.musicsvg.example.MainClass 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | dwursteisen.github.com 40 | gp-parser-core 41 | ${project.version} 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /gp-parser-model/src/main/java/com/github/gp/parser/model/measures/Measure.java: -------------------------------------------------------------------------------- 1 | package com.github.gp.parser.model.measures; 2 | 3 | import com.github.gp.parser.model.beats.Beat; 4 | import com.google.common.primitives.Ints; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * User: Wursteisen David Date: 02/09/12 Time: 23:35 10 | */ 11 | public class Measure implements Comparable { 12 | 13 | private final int trackIndex; 14 | 15 | private final MeasureId measureIndex; 16 | 17 | private final int numberOfBeats; 18 | 19 | private final MeasureHeader header; 20 | 21 | private final List beats; 22 | 23 | public Measure(int trackIndex, MeasureId measureIndex, int numberOfBeats, MeasureHeader header, List beats) { 24 | this.trackIndex = trackIndex; 25 | this.measureIndex = measureIndex; 26 | this.numberOfBeats = numberOfBeats; 27 | this.header = header; 28 | this.beats = beats; 29 | } 30 | 31 | public int getTrackIndex() { 32 | return trackIndex; 33 | } 34 | 35 | public MeasureId getMeasureIndex() { 36 | return measureIndex; 37 | } 38 | 39 | public int getNumberOfBeats() { 40 | return numberOfBeats; 41 | } 42 | 43 | public MeasureHeader getHeader() { 44 | return header; 45 | } 46 | 47 | public List getBeats() { 48 | return beats; 49 | } 50 | 51 | public int compareTo(Measure o) { 52 | 53 | int measureCompare = this.measureIndex.compareTo(o.measureIndex); 54 | if (measureCompare != 0) { 55 | return measureCompare; 56 | } 57 | 58 | return Ints.compare(this.trackIndex, o.trackIndex); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /gp-parser-example/nbactions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | run 5 | 6 | compile 7 | exec:exec 8 | 9 | 10 | bidule 11 | -classpath %classpath org.sourceforge.musicsvg.example.MainClass 12 | ../musicsvg-parser/src/test/resources/gp4/test_gp4.gp4 13 | 14 | 15 | 16 | 17 | debug 18 | 19 | process-classes 20 | org.codehaus.mojo:exec-maven-plugin:1.1.1:exec 21 | 22 | 23 | runtime 24 | -Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -classpath %classpath 25 | org.sourceforge.musicsvg.example.MainClass ../musicsvg-parser/src/test/resources/gp4/test_gp4.gp4 26 | 27 | true 28 | java 29 | 30 | 31 | 32 | profile 33 | 34 | process-classes 35 | org.codehaus.mojo:exec-maven-plugin:1.1.1:exec 36 | 37 | 38 | ${profiler.args} -classpath %classpath org.sourceforge.musicsvg.example.MainClass 39 | ../musicsvg-parser/src/test/resources/gp4/test_gp4.gp4 40 | 41 | profile 42 | ${profiler.java} 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /gp-parser-model/src/main/java/com/github/gp/parser/model/tracks/TrackHeaderBuilder.java: -------------------------------------------------------------------------------- 1 | package com.github.gp.parser.model.tracks; 2 | 3 | public class TrackHeaderBuilder { 4 | private int trackIndex; 5 | 6 | private String name; 7 | 8 | private int numberOfString; 9 | 10 | private int numberOfFrets; 11 | 12 | private int capodastrePosition; 13 | 14 | private boolean drumTrack; 15 | 16 | private boolean banjoTrack; 17 | 18 | private boolean twelveStringTrack; 19 | 20 | public TrackHeaderBuilder withTrackIndex(int trackIndex) { 21 | this.trackIndex = trackIndex; 22 | return this; 23 | } 24 | 25 | public TrackHeaderBuilder withName(String name) { 26 | this.name = name; 27 | return this; 28 | } 29 | 30 | public TrackHeaderBuilder withNumberOfString(int numberOfString) { 31 | this.numberOfString = numberOfString; 32 | return this; 33 | } 34 | 35 | public TrackHeaderBuilder withNumberOfFrets(int numberOfFrets) { 36 | this.numberOfFrets = numberOfFrets; 37 | return this; 38 | } 39 | 40 | public TrackHeaderBuilder withCapodastrePosition(int capodastrePosition) { 41 | this.capodastrePosition = capodastrePosition; 42 | return this; 43 | } 44 | 45 | public TrackHeader createTrackHeader() { 46 | return new TrackHeader(new TrackId(trackIndex), name, numberOfString, numberOfFrets, 47 | capodastrePosition, drumTrack, banjoTrack, twelveStringTrack); 48 | } 49 | 50 | public TrackHeaderBuilder withDrumTrack(boolean drumTrack) { 51 | this.drumTrack = drumTrack; 52 | return this; 53 | } 54 | 55 | public TrackHeaderBuilder withBanjoTrack(boolean banjoTrack) { 56 | this.banjoTrack = banjoTrack; 57 | return this; 58 | } 59 | 60 | public TrackHeaderBuilder withTwelveStringTrack(boolean twelveStringTrack) { 61 | this.twelveStringTrack = twelveStringTrack; 62 | return this; 63 | } 64 | } -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | dwursteisen.github.com 5 | gp-parser 6 | Guitar Pro Parser 7 | 1.0-SNAPSHOT 8 | pom 9 | https://github.com/dwursteisen/gp-parser 10 | 11 | gp-parser-core 12 | gp-parser-model 13 | gp-parser-example 14 | 15 | 16 | 17 | UTF-8 18 | 19 | 20 | 21 | 22 | 23 | 24 | com.google.inject 25 | guice 26 | 3.0 27 | 28 | 29 | 30 | org.mockito 31 | mockito-all 32 | 1.9.0 33 | test 34 | 35 | 36 | 37 | org.easytesting 38 | fest-assert 39 | 1.4 40 | test 41 | 42 | 43 | 44 | org.testng 45 | testng 46 | 6.7 47 | test 48 | 49 | 50 | 51 | 52 | 53 | maven-compiler-plugin 54 | 2.5.1 55 | 56 | 1.6 57 | 1.6 58 | 59 | 60 | 61 | 62 | org.apache.maven.plugins 63 | maven-source-plugin 64 | 2.2 65 | 66 | 67 | attach-sources 68 | verify 69 | 70 | jar 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /gp-parser-core/src/main/java/net/sourceforge/musicsvg/io/gp/ParserHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | 6 | package net.sourceforge.musicsvg.io.gp; 7 | 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | 11 | /** 12 | * @author Dav 13 | */ 14 | public class ParserHelper { 15 | protected static final int BITMASK_1 = 0x01; 16 | protected static final int BITMASK_2 = 0x02; 17 | protected static final int BITMASK_3 = 0x04; 18 | protected static final int BITMASK_4 = 0x08; 19 | protected static final int BITMASK_5 = 0x10; 20 | protected static final int BITMASK_6 = 0x20; 21 | protected static final int BITMASK_7 = 0x40; 22 | protected static final int BITMASK_8 = 0x80; 23 | 24 | protected byte readByte(InputStream is) throws IOException { 25 | return (byte) is.read(); 26 | } 27 | 28 | protected int readInt(InputStream is) throws IOException { 29 | int integer = 0; 30 | byte[] b = {0, 0, 0, 0}; 31 | 32 | is.read(b); 33 | integer = ((b[3] & 0xff) << 24) | ((b[BITMASK_2] & 0xff) << BITMASK_5) | ((b[BITMASK_1] & 0xff) << BITMASK_4) | (b[0] & 0xff); 34 | 35 | return integer; 36 | } 37 | 38 | protected boolean readBoolean(InputStream is) throws IOException { 39 | return (is.read() == BITMASK_1); 40 | } 41 | 42 | protected String readStringByte(InputStream is, int expectedLength) throws IOException { 43 | byte[] bytes; 44 | int realLength = readUnsignedByte(is); 45 | 46 | if (expectedLength != 0) { 47 | bytes = new byte[expectedLength]; 48 | } else { 49 | bytes = new byte[realLength]; 50 | } 51 | is.read(bytes); 52 | 53 | realLength = (realLength >= 0) ? realLength : expectedLength; 54 | return new String(bytes, 0, realLength); 55 | } 56 | 57 | protected String readStringInteger(InputStream is) throws IOException { 58 | byte[] b; 59 | String str; 60 | int length = readInt(is); 61 | 62 | b = new byte[length]; 63 | is.read(b); 64 | 65 | str = new String(b); 66 | return str; 67 | } 68 | 69 | protected String readStringIntegerPlusOne(InputStream is) throws IOException { 70 | byte[] b; 71 | String str; 72 | int lengthPlusOne = readInt(is); 73 | int length = lengthPlusOne - 1; 74 | 75 | if (length != is.read()) { 76 | throw new IOException("Unable to read a field from the file because of a wrong size"); 77 | } 78 | 79 | b = new byte[length]; 80 | is.read(b); 81 | 82 | str = new String(b); 83 | return str; 84 | } 85 | 86 | protected int readUnsignedByte(InputStream is) throws IOException { 87 | return is.read(); 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /gp-parser-core/src/main/java/net/sourceforge/musicsvg/io/gp/listeners/GP4ParserListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * GP4ParserListener.java Created on 11 ao�t 2007, 10:25 See the enclosed file COPYING for license 3 | * information (LGPL). If you did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. 4 | */ 5 | package net.sourceforge.musicsvg.io.gp.listeners; 6 | 7 | import java.io.File; 8 | 9 | /** 10 | * @author Dav 11 | */ 12 | public interface GP4ParserListener { 13 | 14 | void open(File file); 15 | 16 | void close(); 17 | 18 | void readVersion(String version); 19 | 20 | void readTitle(String title); 21 | 22 | void readSubTitle(String subtitle); 23 | 24 | void readArtist(String artist); 25 | 26 | void readAlbum(String album); 27 | 28 | void readSongAuthor(String songAuthor); 29 | 30 | void readCopyright(String copyright); 31 | 32 | void readPieceAuthor(String pieceAuthor); 33 | 34 | void readInstruction(String instructions); 35 | 36 | void readNumberOfNotices(int nbNotes); 37 | 38 | void readNotice(String note); 39 | 40 | void readIsTripleFeel(boolean isTripleFeel); 41 | 42 | void readTempoValue(int tempo); 43 | 44 | void readKey(int key); 45 | 46 | void readOctave(int octave); 47 | 48 | void readMidiChannel(int port, int channel, int instrument, byte volume, byte balance, 49 | byte chorus, byte reverb, byte phaser, byte tremolo); 50 | 51 | void readNumberOfTracks(int numberOfTracks); 52 | 53 | void readNumberOfMesures(int numberOfMesures); 54 | 55 | void readMesureMarker(int number, String name, int r, int g, int b); 56 | 57 | void readMeasureTonality(int tonality); 58 | 59 | void readMeasureHeader(int number, int numerator, int denominator, boolean repeatStart, 60 | boolean doubleBar, int numberOfAlternateEnding, int numberOfRepetitions); 61 | 62 | void readTrackMidiParameter(int trackIndex, int port, int channelIndex, int effects, 63 | int numberOfFrets, int capo, int r, int g, int b); 64 | 65 | void readTrackParameter(int trackIndex, String name, int numberOfStrings, 66 | boolean isDrumsTrack, boolean is12StringedGuitarTrack, boolean isBanjoTrack); 67 | 68 | void readStringTunning(int number, int stringIndex, int tunning); 69 | 70 | void readBeat(int track, int mesure, int beat, int duration, boolean dottedNotes); 71 | 72 | void readEmptyBeat(int track, int mesure, int beat, boolean emptyBeat, boolean restBeat); 73 | 74 | void readTuplet(int track, int mesure, int beat, int tuplet); 75 | 76 | void readNumberOfBeats(int track, int mesure, int numberOfBeats); 77 | 78 | void readStringPlayed(int track, int mesure, int beat, int stringsPlayed); 79 | 80 | void readNote(int track, int mesure, int beat, int stringPlayer, int numberOfFret, 81 | int duration); 82 | 83 | void readNoteParameter(int track, int mesure, int beat, boolean accentuated, 84 | boolean ghostNote, boolean dotted); 85 | 86 | void endOfParsing(File file); 87 | } 88 | -------------------------------------------------------------------------------- /gp-parser-core/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Builds, tests, and runs the project musicSVG. 7 | 8 | 69 | 70 | -------------------------------------------------------------------------------- /gp-parser-example/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Builds, tests, and runs the project musicSVG. 7 | 8 | 69 | 70 | -------------------------------------------------------------------------------- /gp-parser-core/src/test/resources/test_musicXml.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Guitar Pro 5 8 | MusicXML 1.0 9 | 10 | 11 | 12 | 13 | 14 | Track 1 15 | 16 | 17 | 18 | 19 | 1 20 | 25 21 | 22 | 23 | 24 | 25 | 26 | 27 | 1 28 | 29 | 0 30 | major 31 | 32 | 36 | 37 | TAB 38 | 5 39 | 40 | 41 | 6 42 | 43 | E 44 | 5 45 | 46 | 47 | B 48 | 4 49 | 50 | 51 | G 52 | 4 53 | 54 | 55 | D 56 | 4 57 | 58 | 59 | A 60 | 3 61 | 62 | 63 | E 64 | 3 65 | 66 | 67 | 68 | 69 | 70 | heavy-light 71 | 72 | 73 | 1 74 | 1 75 | quarter 76 | 77 | 78 | 79 | 80 | 81 | 5 82 | 3 83 | 84 | 85 | 86 | 87 | 1 88 | 1 89 | quarter 90 | 91 | 92 | 93 | 94 | 95 | 5 96 | 5 97 | 98 | 99 | 100 | 101 | 1 102 | 1 103 | quarter 104 | 105 | 106 | 107 | 108 | 109 | 5 110 | 7 111 | 112 | 113 | 114 | 115 | 1 116 | 1 117 | quarter 118 | 119 | 120 | 121 | 122 | 123 | 5 124 | 8 125 | 126 | 127 | 128 | 129 | 130 | 131 | light-heavy 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /gp-parser-model/src/test/java/com/github/gp/parser/model/ParserToModelListenerTest.java: -------------------------------------------------------------------------------- 1 | package com.github.gp.parser.model; 2 | 3 | import com.github.gp.parser.model.header.Headers; 4 | import com.github.gp.parser.model.header.PieceInformation; 5 | import com.github.gp.parser.model.measures.Measure; 6 | import com.github.gp.parser.model.measures.MeasureHeader; 7 | import com.github.gp.parser.model.measures.MeasureHeaderBuilder; 8 | import com.github.gp.parser.model.measures.MeasureId; 9 | import com.github.gp.parser.model.tracks.Track; 10 | import com.github.gp.parser.model.tracks.TrackHeader; 11 | import net.sourceforge.musicsvg.io.gp.GP4Parser; 12 | import org.testng.annotations.BeforeTest; 13 | import org.testng.annotations.DataProvider; 14 | import org.testng.annotations.Test; 15 | 16 | import java.io.File; 17 | import java.io.IOException; 18 | import java.lang.reflect.Method; 19 | import java.net.URISyntaxException; 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | import static org.fest.assertions.Assertions.assertThat; 25 | 26 | /** 27 | * User: Wursteisen David Date: 02/09/12 Time: 21:52 28 | */ 29 | public class ParserToModelListenerTest { 30 | 31 | private ParserToModelListener listener; 32 | 33 | @BeforeTest 34 | public void setUp() throws URISyntaxException, IOException { 35 | File file = new File(getClass().getResource("/test_gp4.gp4").toURI()); 36 | GP4Parser parser = new GP4Parser(); 37 | listener = new ParserToModelListener(); 38 | 39 | parser.setListener(listener); 40 | parser.openFile(file); 41 | parser.close(); 42 | 43 | } 44 | 45 | @DataProvider(name = "filename") 46 | public Object[][] createData(Method method) { 47 | return new Object[][]{{"/test_gp4.gp4"}, {"/rythme.gp4"}, {"/rythme2.gp4"}, 48 | {"/rythme_blues.gp4"}, {"/solfege.gp4"}, {"/famous_song.gp4"}}; 49 | } 50 | 51 | @Test(dataProvider = "filename") 52 | public void readFiles(String filename) throws Exception { 53 | File file = new File(getClass().getResource(filename).toURI()); 54 | GP4Parser parser = new GP4Parser(); 55 | ParserToModelListener listener = new ParserToModelListener(); 56 | 57 | parser.setListener(listener); 58 | parser.openFile(file); 59 | parser.close(); 60 | 61 | assertThat(listener.getPieceInformation()).isNotNull(); 62 | assertThat(listener.getHeaders()).isNotNull(); 63 | assertThat(listener.getTrackHeaders()).isNotNull(); 64 | assertThat(listener.getMeasureHeaders()).isNotNull(); 65 | assertThat(listener.getMeasures()).isNotNull(); 66 | assertThat(listener.getTracks()).isNotNull(); 67 | } 68 | 69 | @Test 70 | public void testGetHeaders() throws Exception { 71 | Headers headers = listener.getHeaders(); 72 | assertThat(headers.getVersion()).isEqualTo("FICHIER GUITAR PRO v4.06"); 73 | assertThat(headers.getTitle()).isEqualTo("title"); 74 | } 75 | 76 | @Test 77 | public void testGetPieceInformation() { 78 | PieceInformation pieceInformation = listener.getPieceInformation(); 79 | assertThat(pieceInformation.getTempo()).isEqualTo(120); 80 | assertThat(pieceInformation.getNumberOfTrack()).isEqualTo(1); 81 | assertThat(pieceInformation.getNumberOfMeasure()).isEqualTo(3); 82 | } 83 | 84 | @Test 85 | public void testGetMeasureHeaders() { 86 | List measureHeaders = listener.getMeasureHeaders(); 87 | assertThat(measureHeaders).hasSize(3); 88 | } 89 | 90 | @Test 91 | public void testGetTrackHeaders() { 92 | List trackHeaders = listener.getTrackHeaders(); 93 | assertThat(trackHeaders).hasSize(1); 94 | TrackHeader header = trackHeaders.get(0); 95 | assertThat(header.getNumberOfFrets()).isEqualTo(24); 96 | assertThat(header.getNumberOfString()).isEqualTo(6); 97 | assertThat(header.getName()).isEqualTo("Track 1"); 98 | } 99 | 100 | @Test 101 | public void testGetMeasures() { 102 | List measures = listener.getMeasures(); 103 | assertThat(measures).hasSize(3); 104 | assertThat(measures.get(1).getNumberOfBeats()).isEqualTo(1); 105 | assertThat(measures.get(0).getMeasureIndex()).isEqualTo(new MeasureId(0)); 106 | assertThat(measures.get(1).getMeasureIndex()).isEqualTo(new MeasureId(1)); 107 | assertThat(measures.get(2).getMeasureIndex()).isEqualTo(new MeasureId(2)); 108 | 109 | assertThat(measures.get(0).getBeats()).hasSize(5); 110 | } 111 | 112 | @Test 113 | public void testGetTracks() { 114 | List tracks = listener.getTracks(); 115 | assertThat(tracks).hasSize(1); 116 | 117 | Track firstTrack = tracks.get(0); 118 | 119 | assertThat(firstTrack.getMeasures()).hasSize(3); 120 | 121 | } 122 | 123 | @Test 124 | public void shouldBuildMapMeasureHeaders() { 125 | List headersBuilder = new ArrayList(); 126 | headersBuilder.add(new MeasureHeaderBuilder().withMeasureIndex(1)); 127 | Map result = listener.buildMapMeasureHeaders(headersBuilder); 128 | 129 | assertThat(result).hasSize(1); 130 | assertThat(result.get(new MeasureId(1))).isNotNull(); 131 | } 132 | 133 | } 134 | -------------------------------------------------------------------------------- /gp-parser-example/src/main/java/org/sourceforge/musicsvg/example/SystemOutputGP4ParserListenerImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates and open the template in the editor. 3 | */ 4 | 5 | package org.sourceforge.musicsvg.example; 6 | 7 | import net.sourceforge.musicsvg.io.gp.listeners.GP4ParserListener; 8 | 9 | import java.io.File; 10 | 11 | /** 12 | * @author david 13 | */ 14 | public class SystemOutputGP4ParserListenerImpl implements GP4ParserListener { 15 | 16 | private void print(String title, String... content) { 17 | StringBuilder builder = new StringBuilder(); 18 | 19 | for (String str : content) { 20 | builder.append(str); 21 | builder.append(" "); 22 | } 23 | 24 | System.out 25 | .print("+--------------------+------------------------------------------------------------+\n"); 26 | System.out.format("|%20s|%60s|\n", title, builder.toString()); 27 | 28 | } 29 | 30 | private void print(String title, boolean... booleans) { 31 | String strings[] = new String[booleans.length]; 32 | for (int i = 0; i < booleans.length; i++) { 33 | strings[i] = booleans[i] ? "Yes" : "No"; 34 | } 35 | print(title, strings); 36 | } 37 | 38 | private void print(String title, int... integers) { 39 | String strings[] = new String[integers.length]; 40 | for (int i = 0; i < integers.length; i++) { 41 | strings[i] = "" + integers[i]; 42 | } 43 | print(title, strings); 44 | } 45 | 46 | public void open(File file) { 47 | System.out.println("===================================="); 48 | System.out.println("Opening the file..." + file.getName()); 49 | } 50 | 51 | public void close() { 52 | System.out.println("Closing the file..."); 53 | } 54 | 55 | public void readVersion(String version) { 56 | print("Version", version); 57 | } 58 | 59 | public void readTitle(String title) { 60 | print("Title", title); 61 | } 62 | 63 | public void readSubTitle(String subtitle) { 64 | print("subTitle", subtitle); 65 | } 66 | 67 | public void readArtist(String artist) { 68 | print("artist", artist); 69 | } 70 | 71 | public void readAlbum(String album) { 72 | print("album", album); 73 | } 74 | 75 | public void readSongAuthor(String songAuthor) { 76 | print("song author", songAuthor); 77 | } 78 | 79 | public void readCopyright(String copyright) { 80 | print("copyright", copyright); 81 | } 82 | 83 | public void readPieceAuthor(String pieceAuthor) { 84 | print("pieceAuthor", pieceAuthor); 85 | } 86 | 87 | public void readInstruction(String instructions) { 88 | print("instructions", instructions); 89 | } 90 | 91 | public void readNumberOfNotices(int nbNotes) { 92 | print("number of Notices", "" + nbNotes); 93 | } 94 | 95 | public void readNotice(String note) { 96 | print("notice", note); 97 | } 98 | 99 | public void readIsTripleFeel(boolean isTripleFeel) { 100 | print("is Tripe Feel ?", isTripleFeel); 101 | } 102 | 103 | public void readTempoValue(int tempo) { 104 | print("tempo value", tempo); 105 | } 106 | 107 | public void readKey(int key) { 108 | print("key", key); 109 | } 110 | 111 | public void readOctave(int octave) { 112 | print("octave", octave); 113 | } 114 | 115 | public void readMidiChannel(int port, int channel, int instrument, byte volume, 116 | byte balance, byte chorus, byte reverb, byte phaser, byte tremolo) { 117 | print("Midi Channel[0]", port, channel, instrument, volume, balance); 118 | print("Midi Channel[1]", chorus, reverb, phaser, tremolo); 119 | } 120 | 121 | public void readNumberOfTracks(int numberOfTracks) { 122 | print("number of tracks", numberOfTracks); 123 | } 124 | 125 | public void readNumberOfMesures(int numberOfMesures) { 126 | print("number of mesures", numberOfMesures); 127 | } 128 | 129 | public void readMesureMarker(int number, String name, int r, int g, int b) { 130 | 131 | } 132 | 133 | public void readMeasureTonality(int tonality) { 134 | 135 | } 136 | 137 | public void readMeasureHeader(int number, int numerator, int denominator, 138 | boolean repeatStart, boolean doubleBar, int numberOfAlternateEnding, 139 | int numberOfRepetitions) { 140 | 141 | } 142 | 143 | public void readTrackMidiParameter(int trackIndex, int port, int channelIndex, int effects, 144 | int numberOfFrets, int capo, int r, int g, int b) { 145 | 146 | } 147 | 148 | public void readTrackParameter(int trackIndex, String name, int numberOfStrings, 149 | boolean isDrumsTrack, boolean is12StringedGuitarTrack, boolean isBanjoTrack) { 150 | 151 | } 152 | 153 | public void readStringTunning(int number, int stringIndex, int tunning) { 154 | 155 | } 156 | 157 | public void readBeat(int track, int mesure, int beat, int duration, boolean dottedNotes) { 158 | 159 | } 160 | 161 | public void readEmptyBeat(int track, int mesure, int beat, boolean emptyBeat, 162 | boolean restBeat) { 163 | 164 | } 165 | 166 | public void readTuplet(int track, int mesure, int beat, int tuplet) { 167 | 168 | } 169 | 170 | public void readNumberOfBeats(int track, int mesure, int numberOfBeats) { 171 | 172 | } 173 | 174 | public void readStringPlayed(int track, int mesure, int beat, int stringsPlayed) { 175 | 176 | } 177 | 178 | public void readNote(int track, int mesure, int beat, int stringPlayer, int numberOfFret, 179 | int duration) { 180 | 181 | } 182 | 183 | public void readNoteParameter(int track, int mesure, int beat, boolean accentuated, 184 | boolean ghostNote, boolean dotted) { 185 | 186 | } 187 | 188 | @Override 189 | public void endOfParsing(File file) { 190 | System.out.printf("end of parsing"); 191 | } 192 | 193 | } 194 | -------------------------------------------------------------------------------- /gp-parser-core/COPYING.txt: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /gp-parser-example/COPYING.txt: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /gp-parser-model/src/main/java/com/github/gp/parser/model/ParserToModelListener.java: -------------------------------------------------------------------------------- 1 | package com.github.gp.parser.model; 2 | 3 | import com.github.gp.parser.model.beats.Beat; 4 | import com.github.gp.parser.model.beats.BeatBuilder; 5 | import com.github.gp.parser.model.header.Headers; 6 | import com.github.gp.parser.model.header.HeadersBuilder; 7 | import com.github.gp.parser.model.header.PieceInformation; 8 | import com.github.gp.parser.model.header.PieceInformationBuilder; 9 | import com.github.gp.parser.model.measures.*; 10 | import com.github.gp.parser.model.tracks.*; 11 | import com.google.common.base.Predicate; 12 | import com.google.common.collect.Collections2; 13 | import net.sourceforge.musicsvg.io.gp.listeners.GP4ParserListener; 14 | 15 | import java.io.File; 16 | import java.util.*; 17 | 18 | /** 19 | * User: Wursteisen David Date: 02/09/12 Time: 21:12 20 | */ 21 | public class ParserToModelListener implements GP4ParserListener { 22 | 23 | private final HeadersBuilder headersBuilder = new HeadersBuilder(); 24 | 25 | private final PieceInformationBuilder pieceInformationBuilder = 26 | new PieceInformationBuilder(); 27 | 28 | private final List measureHeaderBuilders = 29 | new ArrayList(); 30 | 31 | private final List trackHeaderBuilders = 32 | new ArrayList(); 33 | 34 | private final Map measureBuilderMap = 35 | new HashMap(); 36 | 37 | private final Map> beatBuilderMap = 38 | new HashMap>(); 39 | 40 | private Headers headers; 41 | 42 | private PieceInformation pieceInformation; 43 | 44 | private List measureHeaders; 45 | 46 | private List trackHeaders; 47 | 48 | private List measures; 49 | 50 | private List tracks; 51 | 52 | public Headers getHeaders() { 53 | return headers; 54 | } 55 | 56 | public PieceInformation getPieceInformation() { 57 | return pieceInformation; 58 | } 59 | 60 | public List getMeasureHeaders() { 61 | return new ArrayList(measureHeaders); 62 | } 63 | 64 | public List getTrackHeaders() { 65 | return new ArrayList(trackHeaders); 66 | } 67 | 68 | public List getMeasures() { 69 | return new ArrayList(measures); 70 | } 71 | 72 | public List getTracks() { 73 | return new ArrayList(tracks); 74 | } 75 | 76 | public void open(File file) { 77 | 78 | } 79 | 80 | public void close() { 81 | 82 | } 83 | 84 | public void readVersion(String version) { 85 | headersBuilder.withVersion(version); 86 | } 87 | 88 | public void readTitle(String title) { 89 | headersBuilder.withTitle(title); 90 | } 91 | 92 | public void readSubTitle(String subtitle) { 93 | headersBuilder.withSubtitle(subtitle); 94 | } 95 | 96 | public void readArtist(String artist) { 97 | headersBuilder.withInterpret(artist); 98 | } 99 | 100 | public void readAlbum(String album) { 101 | headersBuilder.withAlbum(album); 102 | } 103 | 104 | public void readSongAuthor(String songAuthor) { 105 | headersBuilder.withSongAuthor(songAuthor); 106 | } 107 | 108 | public void readCopyright(String copyright) { 109 | 110 | } 111 | 112 | public void readPieceAuthor(String pieceAuthor) { 113 | 114 | } 115 | 116 | public void readInstruction(String instructions) { 117 | 118 | } 119 | 120 | public void readNumberOfNotices(int nbNotes) { 121 | 122 | } 123 | 124 | public void readNotice(String note) { 125 | 126 | } 127 | 128 | public void readIsTripleFeel(boolean isTripleFeel) { 129 | 130 | } 131 | 132 | public void readTempoValue(int tempo) { 133 | pieceInformationBuilder.withTempo(tempo); 134 | } 135 | 136 | public void readKey(int key) { 137 | pieceInformationBuilder.withKey(key); 138 | } 139 | 140 | public void readOctave(int octave) { 141 | pieceInformationBuilder.withOctave(octave); 142 | } 143 | 144 | public void readMidiChannel(int port, int channel, int instrument, byte volume, 145 | byte balance, byte chorus, byte reverb, byte phaser, byte tremolo) { 146 | 147 | } 148 | 149 | public void readNumberOfTracks(int numberOfTracks) { 150 | pieceInformationBuilder.withNumberOfTrack(numberOfTracks); 151 | for (int trackIndex = 0; trackIndex < numberOfTracks; trackIndex++) { 152 | trackHeaderBuilders.add(new TrackHeaderBuilder()); 153 | } 154 | 155 | } 156 | 157 | public void readNumberOfMesures(int numberOfMesures) { 158 | pieceInformationBuilder.withNumberOfMeasure(numberOfMesures); 159 | for (int measureIndex = 0; measureIndex < numberOfMesures; measureIndex++) { 160 | measureHeaderBuilders.add(new MeasureHeaderBuilder()); 161 | } 162 | 163 | // trackHeaders.size may not be the best to know the number of tracks 164 | for (int trackIndex = 0; trackIndex < trackHeaderBuilders.size(); trackIndex++) { 165 | for (int measureIndex = 0; measureIndex < numberOfMesures; measureIndex++) { 166 | MeasureBuilder builder = 167 | new MeasureBuilder().withMeasureIndex(measureIndex).withTrackIndex( 168 | trackIndex); 169 | measureBuilderMap.put(new MeasureTrackKey(trackIndex, measureIndex), builder); 170 | } 171 | } 172 | } 173 | 174 | public void readMesureMarker(int number, String name, int r, int g, int b) { 175 | 176 | } 177 | 178 | public void readMeasureTonality(int tonality) { 179 | 180 | } 181 | 182 | public void readMeasureHeader(int measureIndex, int numerator, int denominator, 183 | boolean repeatStart, boolean doubleBar, int numberOfAlternateEnding, 184 | int numberOfRepetitions) { 185 | measureHeaderBuilders.get(measureIndex).withMeasureIndex(measureIndex).withRepeat( 186 | repeatStart).withDoubleBar(doubleBar).withNumberOfAlternateEnding( 187 | numberOfAlternateEnding).withNumberOfRepeats(numberOfRepetitions); 188 | } 189 | 190 | public void readTrackMidiParameter(int trackIndex, int port, int channelIndex, int effects, 191 | int numberOfFrets, int capo, int r, int g, int b) { 192 | trackHeaderBuilders.get(trackIndex).withCapodastrePosition(capo).withNumberOfFrets( 193 | numberOfFrets); 194 | } 195 | 196 | public void readTrackParameter(int trackIndex, String name, int numberOfStrings, 197 | boolean isDrumsTrack, boolean is12StringedGuitarTrack, boolean isBanjoTrack) { 198 | trackHeaderBuilders.get(trackIndex).withTrackIndex(trackIndex).withName(name) 199 | .withNumberOfString(numberOfStrings).withDrumTrack(isDrumsTrack) 200 | .withBanjoTrack(isBanjoTrack).withTwelveStringTrack(is12StringedGuitarTrack); 201 | 202 | } 203 | 204 | public void readStringTunning(int number, int stringIndex, int tunning) { 205 | 206 | } 207 | 208 | public void readBeat(int track, int mesure, int beat, int duration, boolean dottedNotes) { 209 | 210 | } 211 | 212 | public void readEmptyBeat(int track, int mesure, int beat, boolean emptyBeat, 213 | boolean restBeat) { 214 | 215 | } 216 | 217 | public void readTuplet(int track, int mesure, int beat, int tuplet) { 218 | 219 | } 220 | 221 | public void readNumberOfBeats(int track, int mesure, int numberOfBeats) { 222 | MeasureTrackKey key = new MeasureTrackKey(track, mesure); 223 | measureBuilderMap.get(key).withNumberOfBeats( 224 | numberOfBeats); 225 | 226 | beatBuilderMap.put(key, new ArrayList(numberOfBeats)); 227 | } 228 | 229 | public void readStringPlayed(int track, int mesure, int beat, int stringsPlayed) { 230 | 231 | } 232 | 233 | public void readNote(int track, int mesure, int beat, int stringPlayer, int numberOfFret, 234 | int duration) { 235 | 236 | BeatBuilder builder = new BeatBuilder(); 237 | builder.withBeatIndex(beat).withDuration(duration).withFret(numberOfFret).withString(stringPlayer); 238 | beatBuilderMap.get(new MeasureTrackKey(track, mesure)).add(builder); 239 | } 240 | 241 | public void readNoteParameter(int track, int mesure, int beat, boolean accentuated, 242 | boolean ghostNote, boolean dotted) { 243 | 244 | } 245 | 246 | 247 | @Override 248 | public void endOfParsing(File file) { 249 | 250 | // TODO: refactoring. the code is not enough clear 251 | // (but it build object graph) 252 | headers = headersBuilder.createHeaders(); 253 | pieceInformation = pieceInformationBuilder.createPieceInformation(); 254 | 255 | Map measureHeaderMap = buildMapMeasureHeaders(measureHeaderBuilders); 256 | measureHeaders = new ArrayList(measureHeaderMap.values()); 257 | 258 | Map trackHeaderMap = buildMapTrackHeards(trackHeaderBuilders); 259 | trackHeaders = new ArrayList(trackHeaderMap.values()); 260 | 261 | measures = new ArrayList(measureBuilderMap.size()); 262 | for (MeasureBuilder builder : measureBuilderMap.values()) { 263 | 264 | MeasureTrackKey key = new MeasureTrackKey(builder.getTrackIndex(), builder.getMeasureIndex()); 265 | List builders = beatBuilderMap.get(key); 266 | 267 | List beats = new ArrayList(builders.size()); 268 | for (BeatBuilder beatBuilder : builders) { 269 | beats.add(beatBuilder.createBeat()); 270 | } 271 | Collections.sort(beats); 272 | 273 | MeasureHeader measureHeader = measureHeaderMap.get(new MeasureId(builder.getMeasureIndex())); 274 | builder.withHeader(measureHeader); 275 | builder.withBeats(beats); 276 | measures.add(builder.createMeasure()); 277 | } 278 | Collections.sort(measures); 279 | 280 | tracks = new ArrayList(trackHeaders.size()); 281 | for (TrackHeader trackHeader : trackHeaders) { 282 | 283 | TrackBuilder trackBuilder = new TrackBuilder(); 284 | List measureOfTrack = 285 | new ArrayList(Collections2.filter(measures, 286 | new MeasuresOnTrackPredicate(trackHeader.getTrackIndex().getIndex()))); 287 | 288 | trackBuilder.withHeader(trackHeader).withTrackIndex(trackHeader.getTrackIndex().getIndex()) 289 | .withMeasures(measureOfTrack); 290 | 291 | tracks.add(trackBuilder.createTrack()); 292 | 293 | } 294 | 295 | } 296 | 297 | Map buildMapMeasureHeaders(Collection headersBuilder) { 298 | Map result = new HashMap(headersBuilder.size()); 299 | for (MeasureHeaderBuilder builder : headersBuilder) { 300 | MeasureHeader header = builder.createMeasureHeader(); 301 | result.put(header.getMeasureIndex(), header); 302 | } 303 | return result; 304 | } 305 | 306 | Map buildMapTrackHeards(Collection builders) { 307 | Map result = new HashMap(); 308 | for (TrackHeaderBuilder builder : builders) { 309 | TrackHeader header = builder.createTrackHeader(); 310 | result.put(header.getTrackIndex(), header); 311 | } 312 | return result; 313 | } 314 | 315 | private class MeasuresOnTrackPredicate implements Predicate { 316 | private final int trackIndex; 317 | 318 | public MeasuresOnTrackPredicate(int trackIndex) { 319 | this.trackIndex = trackIndex; 320 | } 321 | 322 | @Override 323 | public boolean apply(Measure measure) { 324 | return measure.getTrackIndex() == trackIndex; 325 | } 326 | } 327 | 328 | 329 | } 330 | -------------------------------------------------------------------------------- /gp-parser-core/src/test/java/net/sourceforge/musicsvg/io/gp/GP4ParserTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * GP4ParserTest.java 3 | * JUnit based test 4 | * 5 | * Created on 11 ao�t 2007, 11:14 6 | */ 7 | package net.sourceforge.musicsvg.io.gp; 8 | 9 | import net.sourceforge.musicsvg.io.gp.listeners.GP4ParserListener; 10 | import org.mockito.Mock; 11 | import org.mockito.Mockito; 12 | import org.mockito.MockitoAnnotations; 13 | import org.testng.Assert; 14 | import org.testng.annotations.AfterMethod; 15 | import org.testng.annotations.BeforeMethod; 16 | import org.testng.annotations.Test; 17 | 18 | import java.io.File; 19 | 20 | /** 21 | * @author Dav 22 | */ 23 | public class GP4ParserTest { 24 | 25 | private GP4Parser instance; 26 | public static final String SIMPLE_FILE = "/gp4/test_gp4.gp4"; 27 | public static final String SOLFEGE_FILE = "/gp4/solfege.gp4"; 28 | public static final String BLUES_FILE = "/gp4/rythme_blues.gp4"; 29 | public static final String RYTHME_FILE = "/gp4/rythme.gp4"; 30 | 31 | private File simpleFile; 32 | private File solfegeFile; 33 | private File bluesFile; 34 | private File rythmeFile; 35 | 36 | @Mock 37 | private GP4ParserListener listener; 38 | 39 | @BeforeMethod 40 | public void setUp() throws Exception { 41 | MockitoAnnotations.initMocks(this); //This could be pulled up into a shared base class 42 | 43 | simpleFile = new File(this.getClass().getResource(SIMPLE_FILE).toURI()); 44 | bluesFile = new File(this.getClass().getResource(BLUES_FILE).toURI()); 45 | solfegeFile = new File(this.getClass().getResource(SOLFEGE_FILE).toURI()); 46 | rythmeFile = new File(this.getClass().getResource(RYTHME_FILE).toURI()); 47 | instance = new GP4Parser(); 48 | instance.setListener(listener); 49 | } 50 | 51 | @AfterMethod 52 | public void tearDown() { 53 | instance.close(); 54 | } 55 | 56 | @Test 57 | public void testReadFileHeaders() throws Exception { 58 | instance.openFile(simpleFile); 59 | 60 | // verify 61 | Mockito.verify(listener).readVersion("FICHIER GUITAR PRO v4.06"); 62 | Mockito.verify(listener).readTitle("title"); 63 | Mockito.verify(listener).readSubTitle("subtitle"); 64 | Mockito.verify(listener).readArtist("artist"); 65 | Mockito.verify(listener).readAlbum("album"); 66 | Mockito.verify(listener).readSongAuthor("music"); 67 | Mockito.verify(listener).readCopyright("copyright"); 68 | // listener.readPieceAuthor(String pieceAuthor); 69 | Mockito.verify(listener).readInstruction("instructions"); 70 | Mockito.verify(listener).readNumberOfNotices(1); 71 | Mockito.verify(listener).readNotice("notice"); 72 | Mockito.verify(listener).readIsTripleFeel(false); 73 | // listener.readTempoValue(120); 74 | 75 | } 76 | 77 | @Test 78 | public void testReadOtherInformations() throws Exception { 79 | 80 | instance.openFile(simpleFile); 81 | 82 | // verify 83 | Mockito.verify(listener).readTempoValue(120); 84 | /** 85 | * Bb (bb)= -2 86 | * F (b) = -1 87 | * C = 0 88 | * G (#) = 1 89 | */ 90 | Mockito.verify(listener).readKey(0); 91 | Mockito.verify(listener).readOctave(0); // not used by guitar pro 92 | // listener.readChannel(channel, effectChannel, instrument, volume, balance, chorus, reverb, phaser, tremolo, solo, mute) 93 | 94 | Mockito.verify(listener).readMidiChannel(0, 0, 25, (byte) 7, (byte) 3, (byte) 0, (byte) 0, (byte) 0, (byte) 0); 95 | Mockito.verify(listener).readMidiChannel(0, 1, 25, (byte) 7, (byte) 3, (byte) 0, (byte) 0, (byte) 0, (byte) 0); 96 | Mockito.verify(listener).readNumberOfMesures(3); 97 | Mockito.verify(listener).readNumberOfTracks(1); 98 | 99 | } 100 | 101 | @Test 102 | public void testReadMesureHeader() throws Exception { 103 | 104 | 105 | instance.openFile(simpleFile); 106 | 107 | Mockito.verify(listener).readMesureMarker(0, "Section 1", 255, 0, 0); 108 | Mockito.verify(listener).readMeasureTonality(0); 109 | Mockito.verify(listener).readMeasureHeader(0, 4, 4, false, false, 0, 0); 110 | Mockito.verify(listener).readMeasureHeader(1, 0, 0, false, false, 0, 0); 111 | Mockito.verify(listener).readMeasureHeader(2, 3, 8, false, false, 0, 0); 112 | 113 | } 114 | 115 | @Test 116 | public void testReadTrack() throws Exception { 117 | 118 | 119 | instance.openFile(simpleFile); 120 | 121 | Mockito.verify(listener).readTrackParameter(0, "Track 1", 6, false, false, false); 122 | 123 | } 124 | 125 | @Test 126 | public void testReadStringTunning() throws Exception { 127 | 128 | instance.openFile(simpleFile); 129 | Mockito.verify(listener).readStringTunning(0, 0, 64); 130 | Mockito.verify(listener).readStringTunning(0, 1, 59); 131 | Mockito.verify(listener).readStringTunning(0, 2, 55); 132 | Mockito.verify(listener).readStringTunning(0, 3, 50); 133 | Mockito.verify(listener).readStringTunning(0, 4, 45); 134 | Mockito.verify(listener).readStringTunning(0, 5, 40); 135 | 136 | } 137 | 138 | @Test 139 | public void testReadTrackMidiParameter() throws Exception { 140 | instance.openFile(simpleFile); 141 | Mockito.verify(listener).readTrackMidiParameter(0, 1, 1, 2, 24, 0, 255, 0, 0); 142 | } 143 | 144 | @Test 145 | public void testReadNumberOfBeats() throws Exception { 146 | instance.openFile(simpleFile); 147 | Mockito.verify(listener).readNumberOfBeats(0, 0, 4); 148 | Mockito.verify(listener).readNumberOfBeats(0, 1, 1); // this beat can be empty 149 | 150 | Mockito.verify(listener).readNumberOfBeats(0, 2, 1); 151 | 152 | } 153 | 154 | @Test 155 | public void testReadEmtpyBeat() throws Exception { 156 | 157 | instance.openFile(simpleFile); 158 | 159 | Mockito.verify(listener).readEmptyBeat(0, 1, 0, true, false); 160 | Mockito.verify(listener).readEmptyBeat(0, 2, 0, true, false); 161 | 162 | } 163 | 164 | @Test 165 | public void testReadStringsPlayed() throws Exception { 166 | /** 167 | * stringsPlayer : 168 | * field of beat (on the base of 7 strings !) 169 | * 0000000 170 | * eBGDAE (the first 0 is the bit for the 7th string) 171 | * if 2 strings is played in the same time, each byte of each strings 172 | * are set to 1 173 | * 0001100 for example 174 | */ 175 | instance.openFile(simpleFile); 176 | Mockito.verify(listener).readStringPlayed(0, 0, 0, 0xC); 177 | Mockito.verify(listener).readStringPlayed(0, 0, 1, 0x4); 178 | Mockito.verify(listener).readStringPlayed(0, 0, 2, 0x4); 179 | Mockito.verify(listener).readStringPlayed(0, 0, 3, 0x4); 180 | Mockito.verify(listener).readStringPlayed(0, 1, 0, 0x0); // silence 181 | 182 | } 183 | 184 | @Test 185 | public void testReadNote() throws Exception { 186 | instance.openFile(simpleFile); 187 | // First mesure ( 0 on each string) 188 | Mockito.verify(listener).readNote(0, 0, 0, 3, (byte) 5, 0); 189 | Mockito.verify(listener).readNote(0, 0, 0, 2, (byte) 3, 0); 190 | Mockito.verify(listener).readNote(0, 0, 1, 2, (byte) 5, 0); 191 | Mockito.verify(listener).readNote(0, 0, 2, 2, (byte) 7, 0); 192 | Mockito.verify(listener).readNote(0, 0, 3, 2, (byte) 8, 0); 193 | } 194 | 195 | @Test 196 | public void testReadBeat() throws Exception { 197 | instance.openFile(rythmeFile); 198 | // First mesure ( 0 on each string) 199 | Mockito.verify(listener).readBeat(0, 0, 0, -1, false); 200 | Mockito.verify(listener).readBeat(0, 0, 1, 0, false); 201 | Mockito.verify(listener).readBeat(0, 0, 2, 1, false); 202 | Mockito.verify(listener).readBeat(0, 0, 3, 2, false); 203 | Mockito.verify(listener).readBeat(0, 0, 4, 2, false); 204 | } 205 | 206 | 207 | @Test 208 | public void testNbStringPlayed() { 209 | 210 | int stringCode = 2; 211 | int result; 212 | int expResult = 1; 213 | 214 | result = instance.nbPlayerString(stringCode); 215 | Assert.assertEquals(result, expResult); 216 | 217 | stringCode = 4; 218 | result = instance.nbPlayerString(stringCode); 219 | Assert.assertEquals(result, expResult); 220 | 221 | stringCode = 8; 222 | result = instance.nbPlayerString(stringCode); 223 | Assert.assertEquals(result, expResult); 224 | 225 | stringCode = 32; 226 | result = instance.nbPlayerString(stringCode); 227 | Assert.assertEquals(result, expResult); 228 | 229 | stringCode = 64; 230 | result = instance.nbPlayerString(stringCode); 231 | Assert.assertEquals(result, expResult); 232 | 233 | stringCode = 0xC; 234 | expResult = 2; 235 | result = instance.nbPlayerString(stringCode); 236 | Assert.assertEquals(result, expResult); 237 | } 238 | 239 | @Test 240 | public void testGetStringIndexFromStringCode() { 241 | int stringCode = 0; 242 | int index = 0; 243 | int stringIndex = 0; 244 | 245 | stringCode = 2; 246 | stringIndex = instance.getStringIndexFromStringCode(stringCode, index); 247 | Assert.assertEquals(stringIndex, 1); 248 | 249 | stringCode = 4; 250 | stringIndex = instance.getStringIndexFromStringCode(stringCode, index); 251 | Assert.assertEquals(stringIndex, 2); 252 | 253 | stringCode = 8; 254 | stringIndex = instance.getStringIndexFromStringCode(stringCode, index); 255 | Assert.assertEquals(stringIndex, 3); 256 | 257 | stringCode = 64; 258 | stringIndex = instance.getStringIndexFromStringCode(stringCode, index); 259 | Assert.assertEquals(stringIndex, 6); 260 | 261 | index = 0; 262 | stringCode = 0xC; 263 | stringIndex = instance.getStringIndexFromStringCode(stringCode, index); 264 | Assert.assertEquals(stringIndex, 2); 265 | 266 | stringCode = 0xC; 267 | index = 1; 268 | stringIndex = instance.getStringIndexFromStringCode(stringCode, index); 269 | Assert.assertEquals(stringIndex, 3); 270 | 271 | // invalid index 272 | stringIndex = instance.getStringIndexFromStringCode(2, 1); 273 | Assert.assertEquals(stringIndex, -1); 274 | 275 | } 276 | 277 | @Test 278 | public void testReadNote_blues_file() throws Exception { 279 | instance.openFile(bluesFile); 280 | 281 | listener.readNumberOfTracks(3); 282 | listener.readNumberOfMesures(20); 283 | 284 | } 285 | 286 | @Test 287 | public void testReadNote_solfege_file() throws Exception { 288 | instance.openFile(solfegeFile); 289 | // First mesure ( 0 on each string) 290 | Mockito.verify(listener).readNote(0, 0, 0, 1, (byte) 0, 0); 291 | Mockito.verify(listener).readNote(0, 0, 1, 2, (byte) 0, 0); 292 | Mockito.verify(listener).readNote(0, 0, 2, 3, (byte) 0, 0); 293 | Mockito.verify(listener).readNote(0, 0, 3, 4, (byte) 0, 0); 294 | Mockito.verify(listener).readNote(0, 0, 4, 5, (byte) 0, 0); 295 | Mockito.verify(listener).readNote(0, 0, 5, 6, (byte) 0, 0); 296 | Mockito.verify(listener).readNote(0, 0, 6, 5, (byte) 0, 0); 297 | Mockito.verify(listener).readNote(0, 0, 7, 4, (byte) 0, 0); 298 | 299 | // second mesure (1, 2, 3, on each string) 300 | Mockito.verify(listener).readNote(0, 1, 0, 1, (byte) 1, 0); 301 | Mockito.verify(listener).readNote(0, 1, 1, 2, (byte) 2, 0); 302 | Mockito.verify(listener).readNote(0, 1, 2, 3, (byte) 3, 0); 303 | Mockito.verify(listener).readNote(0, 1, 3, 4, (byte) 4, 0); 304 | Mockito.verify(listener).readNote(0, 1, 4, 5, (byte) 5, 0); 305 | Mockito.verify(listener).readNote(0, 1, 5, 6, (byte) 6, 0); 306 | Mockito.verify(listener).readNote(0, 1, 6, 5, (byte) 7, 0); 307 | Mockito.verify(listener).readNote(0, 1, 7, 4, (byte) 8, 0); 308 | 309 | // third mesure (chord) 310 | Mockito.verify(listener).readNote(0, 2, 0, 2, (byte) 2, 0); 311 | Mockito.verify(listener).readNote(0, 2, 0, 1, (byte) 0, 0); 312 | 313 | Mockito.verify(listener).readNote(0, 2, 1, 3, (byte) 2, 0); 314 | Mockito.verify(listener).readNote(0, 2, 1, 2, (byte) 0, 0); 315 | 316 | Mockito.verify(listener).readNote(0, 2, 2, 4, (byte) 2, 0); 317 | Mockito.verify(listener).readNote(0, 2, 2, 3, (byte) 0, 0); 318 | 319 | Mockito.verify(listener).readNote(0, 2, 3, 5, (byte) 2, 0); 320 | Mockito.verify(listener).readNote(0, 2, 3, 4, (byte) 0, 0); 321 | 322 | Mockito.verify(listener).readNote(0, 2, 4, 6, (byte) 2, 0); 323 | Mockito.verify(listener).readNote(0, 2, 4, 5, (byte) 0, 0); 324 | 325 | Mockito.verify(listener).readNote(0, 2, 5, 3, (byte) 5, 0); 326 | Mockito.verify(listener).readNote(0, 2, 5, 2, (byte) 5, 0); 327 | Mockito.verify(listener).readNote(0, 2, 5, 1, (byte) 3, 0); 328 | 329 | Mockito.verify(listener).readNote(0, 2, 6, 4, (byte) 5, 0); 330 | Mockito.verify(listener).readNote(0, 2, 6, 3, (byte) 5, 0); 331 | Mockito.verify(listener).readNote(0, 2, 6, 2, (byte) 3, 0); 332 | 333 | Mockito.verify(listener).readNote(0, 2, 7, 5, (byte) 5, 0); 334 | Mockito.verify(listener).readNote(0, 2, 7, 4, (byte) 5, 0); 335 | Mockito.verify(listener).readNote(0, 2, 7, 3, (byte) 3, 0); 336 | 337 | 338 | } 339 | 340 | } 341 | -------------------------------------------------------------------------------- /gp-parser-core/src/test/resources/svg/note.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | 23 | 24 | 26 | image/svg+xml 27 | 29 | 30 | 31 | 32 | 50 | 52 | 55 | 67 | 68 | 71 | 78 | 79 | 81 | 88 | 96 | 97 | 101 | 106 | 107 | 110 | 117 | 118 | 121 | 125 | 126 | 129 | 136 | 143 | 144 | 146 | 150 | 151 | 153 | 157 | 158 | 160 | 164 | 165 | 167 | 171 | 172 | 174 | 178 | 179 | 180 | -------------------------------------------------------------------------------- /gp-parser-core/src/main/java/net/sourceforge/musicsvg/io/gp/GP4Parser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * GP4Parser.java Created on 11 ao�t 2007, 10:25 See the enclosed file COPYING for license 3 | * information (LGPL). If you did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. 4 | */ 5 | package net.sourceforge.musicsvg.io.gp; 6 | 7 | import com.google.inject.Inject; 8 | import net.sourceforge.musicsvg.io.Parser; 9 | import net.sourceforge.musicsvg.io.gp.listeners.GP4ParserListener; 10 | 11 | import java.io.File; 12 | import java.io.FileInputStream; 13 | import java.io.FileNotFoundException; 14 | import java.io.IOException; 15 | import java.io.InputStream; 16 | 17 | /** 18 | * @author Dav 19 | * @see GP4 Specification 20 | */ 21 | public class GP4Parser implements Parser { 22 | 23 | protected static final int GP4_NUMBER_OF_STRING = 7; 24 | 25 | public static final int VERSION_LENGTH = 30; 26 | 27 | private int numberOfTracks; 28 | 29 | private int numberOfMeasures; 30 | 31 | protected FileInputStream is; 32 | 33 | protected GP4ParserListener listener; 34 | 35 | private final ParserHelper helper = new ParserHelper(); 36 | 37 | public void close() { 38 | if (listener != null) { 39 | listener.close(); 40 | } 41 | } 42 | 43 | public void openFile(File file) throws IOException { 44 | 45 | try { 46 | this.is = new FileInputStream(file); 47 | } 48 | catch (FileNotFoundException ex) { 49 | throw new IOException("File " + file.getAbsolutePath() + "Not Found", ex); 50 | } 51 | 52 | listener.open(file); 53 | readFileHeaders(this.is); 54 | readLyrics(this.is); 55 | readOtherInformations(this.is); 56 | readMeasures(this.is); 57 | readTracks(this.is); 58 | readMeasuresTracksPair(this.is); 59 | listener.endOfParsing(file); 60 | 61 | } 62 | 63 | /** 64 | * @param is 65 | * @throws java.io.IOException 66 | * @see GP4 67 | * specification 68 | */ 69 | private void readFileHeaders(InputStream is) throws IOException { 70 | 71 | String version = helper.readStringByte(is, VERSION_LENGTH); 72 | this.listener.readVersion(version); 73 | 74 | String title = helper.readStringIntegerPlusOne(is); 75 | this.listener.readTitle(title); 76 | 77 | String subtitle = helper.readStringIntegerPlusOne(is); 78 | this.listener.readSubTitle(subtitle); 79 | 80 | String interpret = helper.readStringIntegerPlusOne(is); 81 | this.listener.readArtist(interpret); 82 | 83 | String album = helper.readStringIntegerPlusOne(is); 84 | this.listener.readAlbum(album); 85 | 86 | String songAuthor = helper.readStringIntegerPlusOne(is); 87 | this.listener.readSongAuthor(songAuthor); 88 | 89 | String copyright = helper.readStringIntegerPlusOne(is); 90 | this.listener.readCopyright(copyright); 91 | 92 | String pieceAuthor = helper.readStringIntegerPlusOne(is); 93 | this.listener.readPieceAuthor(pieceAuthor); 94 | 95 | String instructions = helper.readStringIntegerPlusOne(is); 96 | this.listener.readInstruction(instructions); 97 | 98 | int numberOfNotice = helper.readInt(is); 99 | this.listener.readNumberOfNotices(numberOfNotice); 100 | 101 | for (int i = 0; i < numberOfNotice; i++) { 102 | String notice = helper.readStringIntegerPlusOne(is); 103 | this.listener.readNotice(notice); 104 | } 105 | 106 | boolean tripletFeel = helper.readBoolean(is); 107 | this.listener.readIsTripleFeel(tripletFeel); 108 | 109 | } 110 | 111 | /** 112 | * @param is 113 | * @throws java.io.IOException 114 | * @see GP4 Specification 115 | */ 116 | private void readLyrics(InputStream is) throws IOException { 117 | 118 | // ----lyrics---- 119 | int lyricTrack = helper.readInt(is); 120 | // Lyric lyric = new Lyric(readInt(),readStringInteger()); 121 | helper.readInt(is); 122 | helper.readStringInteger(is); 123 | for (int i = 0; i < 4; i++) { 124 | int measureNumber = helper.readInt(is); 125 | String lines = helper.readStringInteger(is); 126 | } 127 | } 128 | 129 | /** 130 | * @param is 131 | * @throws java.io.IOException 132 | * @see GP4 133 | * Specification 134 | */ 135 | private void readMeasuresTracksPair(InputStream is) throws IOException { 136 | for (int mesure = 0; mesure < numberOfMeasures; mesure++) { 137 | for (int track = 0; track < numberOfTracks; track++) { 138 | readMeasureComponents(is, track, mesure); 139 | } 140 | } 141 | } 142 | 143 | /** 144 | * @param is 145 | * @throws java.io.IOException 146 | * @see GP4 148 | * Specification 149 | */ 150 | private void readOtherInformations(InputStream is) throws IOException { 151 | 152 | int tempoValue = helper.readInt(is); 153 | this.listener.readTempoValue(tempoValue); 154 | 155 | int key = helper.readByte(is); 156 | this.listener.readKey(key); 157 | 158 | int octave = helper.readInt(is); 159 | this.listener.readOctave(octave); 160 | 161 | // 4 ports 162 | // 16 channels 163 | final int NUMBER_OF_PORTS = 4; 164 | final int NUMBER_OF_CHANNELS = 16; 165 | for (int port = 0; port < NUMBER_OF_PORTS; port++) { 166 | for (int channel = 0; channel < NUMBER_OF_CHANNELS; channel++) { 167 | int instrument = helper.readInt(is); 168 | byte volume = helper.readByte(is); 169 | byte balance = helper.readByte(is); 170 | byte chorus = helper.readByte(is); 171 | byte reverb = helper.readByte(is); 172 | byte phaser = helper.readByte(is); 173 | byte tremolo = helper.readByte(is); 174 | byte blank1 = helper.readByte(is); // Backward compatibility with version 3.0 175 | byte blank2 = helper.readByte(is); // Backward compatibility with version 3.0 176 | listener.readMidiChannel(port, channel, instrument, volume, balance, chorus, 177 | reverb, phaser, tremolo); 178 | } 179 | } 180 | 181 | numberOfMeasures = helper.readInt(is); 182 | numberOfTracks = helper.readInt(is); 183 | 184 | this.listener.readNumberOfTracks(numberOfTracks); 185 | this.listener.readNumberOfMesures(numberOfMeasures); 186 | } 187 | 188 | private void readMeasures(InputStream is) throws IOException { 189 | 190 | if (numberOfMeasures <= 0) { 191 | return; 192 | } 193 | 194 | for (int measureIndex = 0; measureIndex < numberOfMeasures; measureIndex++) { 195 | readMeasureHeader(is, measureIndex); 196 | } 197 | 198 | } 199 | 200 | /** 201 | * @param is 202 | * @param measureIndex 203 | * @throws java.io.IOException 204 | * @see GP4 Specification 205 | */ 206 | private void readMeasureHeader(InputStream is, int measureIndex) throws IOException { 207 | int header = helper.readUnsignedByte(is); 208 | 209 | boolean repeatStart = ((header & ParserHelper.BITMASK_3) != 0); 210 | boolean doubleBar = ((header & ParserHelper.BITMASK_8) != 0); 211 | 212 | int numerator = 0; 213 | if ((header & ParserHelper.BITMASK_1) != 0) { 214 | numerator = helper.readByte(is); 215 | } 216 | 217 | int denominator = 0; 218 | if ((header & ParserHelper.BITMASK_2) != 0) { 219 | denominator = helper.readByte(is); 220 | } 221 | 222 | int numberOfRepeats = 0; 223 | if ((header & ParserHelper.BITMASK_4) != 0) { 224 | numberOfRepeats = helper.readByte(is); 225 | } 226 | 227 | int numberOfAlternateEnding = 0; 228 | if ((header & ParserHelper.BITMASK_5) != 0) { 229 | numberOfAlternateEnding = helper.readByte(is); 230 | } 231 | 232 | if ((header & ParserHelper.BITMASK_6) != 0) { 233 | String name = helper.readStringIntegerPlusOne(is); 234 | 235 | int r = helper.readUnsignedByte(is); 236 | int g = helper.readUnsignedByte(is); 237 | int b = helper.readUnsignedByte(is); 238 | int white = helper.readUnsignedByte(is); // always 0x00 239 | 240 | this.listener.readMesureMarker(measureIndex, name, r, g, b); 241 | 242 | } 243 | 244 | if ((header & ParserHelper.BITMASK_7) != 0) { 245 | int tonality = helper.readByte(is); 246 | helper.readByte(is); // WTF ? 247 | this.listener.readMeasureTonality(tonality); 248 | } 249 | 250 | this.listener.readMeasureHeader(measureIndex, numerator, denominator, repeatStart, 251 | doubleBar, numberOfAlternateEnding, numberOfRepeats); 252 | } 253 | 254 | /** 255 | * @param is 256 | * @param trackIndex 257 | * @throws java.io.IOException 258 | * @see GP4 Specification 259 | */ 260 | private void readTrack(InputStream is, int trackIndex) throws IOException { 261 | int header = helper.readUnsignedByte(is); 262 | 263 | boolean isDrumsTrack = ((header & ParserHelper.BITMASK_1) != 0); 264 | boolean is12StringedGuitarTrack = ((header & ParserHelper.BITMASK_2) != 0); 265 | boolean isBanjoTrack = ((header & ParserHelper.BITMASK_3) != 0); 266 | 267 | String name = helper.readStringByte(is, 40); 268 | 269 | int numberOfStrings = helper.readInt(is); 270 | this.listener.readTrackParameter(trackIndex, name, numberOfStrings, isDrumsTrack, 271 | is12StringedGuitarTrack, isBanjoTrack); 272 | 273 | for (int stringIndex = 0; stringIndex < GP4_NUMBER_OF_STRING; stringIndex++) { 274 | int tunning = helper.readInt(is); 275 | // WTF ?? 276 | // if (numberOfStrings > stringIndex) { 277 | this.listener.readStringTunning(trackIndex, stringIndex, tunning); 278 | // } 279 | } 280 | 281 | int midiPort = helper.readInt(is); 282 | 283 | int midiChannel = helper.readInt(is); 284 | 285 | int midiChannelEffect = helper.readInt(is); 286 | 287 | int numberOfFrets = helper.readInt(is); 288 | 289 | int capo = helper.readInt(is); 290 | 291 | int r = helper.readUnsignedByte(is); 292 | int g = helper.readUnsignedByte(is); 293 | int b = helper.readUnsignedByte(is); 294 | int white = helper.readUnsignedByte(is); 295 | 296 | this.listener.readTrackMidiParameter(trackIndex, midiPort, midiChannel, 297 | midiChannelEffect, numberOfFrets, capo, r, g, b); 298 | } 299 | 300 | /* 301 | * private SongChannel parseChannel(List channels, int channelIndex,int effectChannel) { 302 | * SongChannel channel = (SongChannel) channels.get(channelIndex - 1); int instrument = 303 | * channel.getInstrument(); if (instrument == -1) { channel.setInstrument((short)0); } 304 | * if(!channel.isPercusionChannel()){ channel.setEffectChannel((short)(effectChannel - 1)); } 305 | * return channel; } 306 | */ 307 | private void readMeasureComponents(InputStream is, int track, int mesure) 308 | throws IOException { 309 | int numberOfBeats = helper.readInt(is); 310 | this.listener.readNumberOfBeats(track, mesure, numberOfBeats); 311 | for (int beat = 0; beat < numberOfBeats; beat++) { 312 | readNotes(this.is, track, mesure, beat); 313 | } 314 | 315 | } 316 | 317 | /** 318 | * @param is 319 | * @param track 320 | * @param mesure 321 | * @param beat 322 | * @throws java.io.IOException 323 | * @see GP4 Specification 324 | */ 325 | private void readNotes(InputStream is, int track, int mesure, int beat) throws IOException { 326 | 327 | int header = helper.readUnsignedByte(is); 328 | boolean dottedNotes = ((header & ParserHelper.BITMASK_1) != 0); 329 | 330 | if ((header & ParserHelper.BITMASK_7) != 0) { 331 | int beatStatus = helper.readUnsignedByte(is); 332 | boolean emptyBeat = (beatStatus == 0x00); 333 | boolean restBeat = (beatStatus == ParserHelper.BITMASK_2); 334 | this.listener.readEmptyBeat(track, mesure, beat, emptyBeat, restBeat); 335 | } 336 | 337 | int beatDuration = helper.readByte(is); 338 | if ((header & ParserHelper.BITMASK_6) != 0) { 339 | int tuplet = helper.readInt(is); 340 | this.listener.readTuplet(track, mesure, beat, tuplet); 341 | } 342 | 343 | this.listener.readBeat(track, mesure, beat, beatDuration, dottedNotes); 344 | 345 | if ((header & ParserHelper.BITMASK_2) != 0) { 346 | readChordDiagram(this.is, track, mesure, beat); 347 | } 348 | 349 | if ((header & ParserHelper.BITMASK_3) != 0) { 350 | String text = helper.readStringIntegerPlusOne(is); 351 | } 352 | 353 | if ((header & ParserHelper.BITMASK_4) != 0) { 354 | readBeatEffects(this.is); 355 | } 356 | 357 | if ((header & ParserHelper.BITMASK_5) != 0) { 358 | readMixChange(this.is); 359 | } 360 | 361 | int stringsPlayed = helper.readUnsignedByte(is); 362 | 363 | this.listener.readStringPlayed(track, mesure, beat, stringsPlayed); 364 | int numberOfStringPlayed = nbPlayerString(stringsPlayed); 365 | for (int index = numberOfStringPlayed - 1; index >= 0; index--) { 366 | // It can be a better idea to give the absolute index of the string 367 | // ie: 1 = E ; A = 2 ; D = 3 368 | // than relative index 369 | // ie: 0 = first string, 1, second string in the chord 370 | int stringIndex = getStringIndexFromStringCode(stringsPlayed, index); 371 | parseNote(this.is, track, mesure, beat, stringIndex); 372 | } 373 | 374 | } 375 | 376 | protected int nbPlayerString(int stringsPlayer) { 377 | int res = 0; 378 | 379 | for (int i = 0; i < GP4_NUMBER_OF_STRING; i++) { 380 | if ((stringsPlayer & (1 << i)) != 0) { 381 | res++; 382 | } 383 | } 384 | return res; 385 | } 386 | 387 | protected int getStringIndexFromStringCode(int stringCode, int index) { 388 | int tmpIndex = index; 389 | for (int i = 0; i < GP4_NUMBER_OF_STRING; i++) { 390 | if ((stringCode & (1 << i)) != 0) { 391 | if (tmpIndex == 0) { 392 | return i; 393 | } 394 | else { 395 | tmpIndex--; 396 | } 397 | } 398 | } 399 | return -1; 400 | } 401 | 402 | void parseNote(InputStream is, int track, int mesure, int beat, int stringPlayer) 403 | throws IOException { 404 | int header = helper.readUnsignedByte(is); 405 | 406 | boolean accentuated = ((header & ParserHelper.BITMASK_7) != 0); 407 | boolean ghostNote = ((header & ParserHelper.BITMASK_3) != 0); 408 | boolean dotted = ((header & ParserHelper.BITMASK_2) != 0); 409 | 410 | boolean tiedNote = false; 411 | boolean deadNote = false; 412 | if ((header & ParserHelper.BITMASK_6) != 0) { 413 | int noteType = helper.readUnsignedByte(is); 414 | tiedNote = (noteType == ParserHelper.BITMASK_2); 415 | // effect.setDeadNote((noteType == 0x03)); 416 | } 417 | 418 | /** 419 | * -2: Whole Note; -1: Half note; 0: Quarter note; 1: Eighth note; 2: Sixteenth note; 3: 420 | * Thirty-second note; 421 | */ 422 | byte duration = 0; 423 | if ((header & ParserHelper.BITMASK_1) != 0) { 424 | duration = helper.readByte(is); 425 | byte tuplet = helper.readByte(is); 426 | } 427 | 428 | // int velocity = VelocityValues.DEFAULT; 429 | if ((header & ParserHelper.BITMASK_5) != 0) { 430 | helper.readByte(is); 431 | // velocity = (VelocityValues.MIN_VELOCITY + (VelocityValues.VELOCITY_INCREMENT * 432 | // readByte())) - VelocityValues.VELOCITY_INCREMENT; 433 | } 434 | 435 | int fretIndex = 0; 436 | if ((header & ParserHelper.BITMASK_6) != 0) { 437 | fretIndex = helper.readUnsignedByte(is); 438 | } 439 | 440 | if ((header & ParserHelper.BITMASK_8) != 0) { 441 | byte fingeringLeftHand = helper.readByte(is); 442 | byte fingeringRightHand = helper.readByte(is); 443 | } 444 | 445 | if ((header & ParserHelper.BITMASK_4) != 0) { 446 | readNoteEffects(this.is); 447 | } 448 | 449 | if (fretIndex >= 0 || tiedNote) { 450 | if (tiedNote) { 451 | // value = getTiedNoteValue(string.getNumber(), currMeasureNotes, 452 | // currTrackMeasures); 453 | } 454 | 455 | // return new Note(value, start, (Duration) currDuration.clone(), velocity, 456 | // string.getNumber(),tiedNote,effect); 457 | } 458 | this.listener.readNote(track, mesure, beat, stringPlayer, fretIndex, duration); 459 | this.listener.readNoteParameter(track, mesure, beat, accentuated, ghostNote, dotted); 460 | // return null; 461 | } 462 | 463 | private void readNoteEffects(InputStream is) throws IOException { 464 | int header1; 465 | int header2; 466 | int b; 467 | 468 | header1 = helper.readUnsignedByte(is); 469 | header2 = helper.readUnsignedByte(is); 470 | 471 | if ((header1 & ParserHelper.BITMASK_1) != 0) { 472 | readBend(this.is); 473 | } 474 | 475 | if ((header1 & ParserHelper.BITMASK_5) != 0) { 476 | readGraceNote(this.is); 477 | } 478 | 479 | if ((header2 & ParserHelper.BITMASK_3) != 0) { 480 | int duration = helper.readUnsignedByte(is); 481 | } 482 | 483 | if ((header2 & ParserHelper.BITMASK_4) != 0) { 484 | // noteEffect.setSlide(true); 485 | helper.readByte(is); 486 | } 487 | 488 | if ((header2 & ParserHelper.BITMASK_5) != 0) { 489 | b = helper.readByte(is); 490 | } 491 | 492 | // trill 493 | if ((header2 & ParserHelper.BITMASK_6) != 0) { 494 | byte fret = helper.readByte(is); 495 | byte period = helper.readByte(is); 496 | } 497 | 498 | if ((header1 & ParserHelper.BITMASK_4) != 0) { 499 | } 500 | 501 | // hammer 502 | // noteEffect.setHammer(((header1 & 0x02) != 0)); 503 | 504 | // vibrato 505 | // noteEffect.setVibrato(((header2 & 0x40) != 0) || noteEffect.isVibrato()); 506 | 507 | // palm-mute 508 | // noteEffect.setPalmMute(((header2 & 0x02) != 0)); 509 | 510 | // staccato 511 | // noteEffect.setStaccato(((header2 & 0x01) != 0)); 512 | 513 | } 514 | 515 | private void readGraceNote(InputStream is) throws IOException { 516 | int fret = helper.readUnsignedByte(is); 517 | int velocity = helper.readUnsignedByte(is); 518 | int transition = helper.readUnsignedByte(is); 519 | int duration = helper.readUnsignedByte(is); 520 | 521 | // dead 522 | boolean dead = (fret == 255); 523 | 524 | // fret 525 | fret = ((!dead) ? fret : 0); 526 | 527 | // velocity 528 | // velocity = (VelocityValues.MIN_VELOCITY + (VelocityValues.VELOCITY_INCREMENT * 529 | // velocity)) - VelocityValues.VELOCITY_INCREMENT; 530 | 531 | // transition 532 | /* 533 | * if(transition == 0){ transition = GraceEffect.TRANSITION_NONE; } else if(transition == 534 | * 1){ transition = GraceEffect.TRANSITION_SLIDE; } else if(transition == 2){ transition = 535 | * GraceEffect.TRANSITION_BEND; } else if(transition == 3){ transition = 536 | * GraceEffect.TRANSITION_HAMMER; } 537 | */ 538 | // effect.setGrace(new GraceEffect(fret,duration,velocity,transition,false,dead)); 539 | } 540 | 541 | private void readBend(InputStream is) throws IOException { 542 | byte type = helper.readByte(is); 543 | int value = helper.readInt(is); 544 | 545 | int numPoints = helper.readInt(is); 546 | for (int i = 0; i < numPoints; i++) { 547 | int bendPosition = helper.readInt(is); 548 | int bendValue = helper.readInt(is); 549 | byte bendVibrato = helper.readByte(is); 550 | 551 | } 552 | 553 | } 554 | 555 | private void readMixChange(InputStream is) throws IOException { 556 | int pos[] = new int[8]; 557 | int i; 558 | int n; 559 | int aux; 560 | n = 0; 561 | for (i = 0; i < GP4_NUMBER_OF_STRING; i++) { 562 | aux = helper.readByte(is); 563 | if ((i != 0) && (aux != -1)) { 564 | pos[n] = i; 565 | n++; 566 | } 567 | } 568 | aux = helper.readInt(is); 569 | if (aux != -1) { 570 | // tempo.setValue(aux); 571 | pos[n] = i; 572 | n++; 573 | } 574 | 575 | for (i = 0; i < n; i++) { 576 | aux = helper.readByte(is); 577 | } 578 | int applyToAllTracks = helper.readUnsignedByte(is); 579 | } 580 | 581 | private void readTracks(InputStream is) throws IOException { 582 | 583 | for (int trackIndex = 0; trackIndex < numberOfTracks; trackIndex++) { 584 | readTrack(is, trackIndex); 585 | } 586 | } 587 | 588 | private void readTremoloBar(InputStream is) throws IOException { 589 | byte type = helper.readByte(is); 590 | int value = helper.readInt(is); 591 | 592 | // TremoloBarEffect tremoloBar = new TremoloBarEffect(); 593 | int numPoints = helper.readInt(is); 594 | for (int i = 0; i < numPoints; i++) { 595 | int bendPosition = helper.readInt(is); 596 | int bendValue = helper.readInt(is); 597 | byte bendVibrato = helper.readByte(is); 598 | 599 | // tremoloBar.addPoint((int)(bendPosition * TremoloBarEffect.MAX_POSITION_LENGTH / 600 | // GP_BEND_POSITION),(bendValue * TremoloBarEffect.SEMITONE_LENGTH / 601 | // GP_BEND_SEMITONE)); 602 | } 603 | 604 | } 605 | 606 | private void readBeatEffects(InputStream is) throws IOException { 607 | int header[] = { 0, 0 }; 608 | 609 | header[0] = helper.readUnsignedByte(is); 610 | header[1] = helper.readUnsignedByte(is); 611 | 612 | // noteEffect.setFadeIn(((header[0] & 0x10) != 0)); 613 | // vnoteEffect.setVibrato(((header[0] & 0x02) != 0)); 614 | 615 | if ((header[0] & ParserHelper.BITMASK_6) != 0) { 616 | int effect = helper.readUnsignedByte(is); 617 | // noteEffect.setTapping(effect == 1); 618 | // noteEffect.setSlapping(effect == 2); 619 | // noteEffect.setPopping(effect == 3); 620 | } 621 | 622 | if ((header[1] & ParserHelper.BITMASK_3) != 0) { 623 | readTremoloBar(is); 624 | } 625 | 626 | if ((header[0] & ParserHelper.BITMASK_7) != 0) { 627 | // Upstroke - Downstroke 628 | helper.readByte(is); 629 | helper.readByte(is); 630 | } 631 | 632 | if ((header[1] & ParserHelper.BITMASK_1) != 0) { 633 | // Rasgueado 634 | } 635 | 636 | if ((header[1] & ParserHelper.BITMASK_2) != 0) { 637 | // Pickstroke 638 | helper.readByte(is); 639 | } 640 | 641 | } 642 | 643 | private void readChordDiagram(InputStream is, int track, int measure, int beat) 644 | throws IOException { 645 | int header = helper.readUnsignedByte(is); 646 | 647 | if ((header & ParserHelper.BITMASK_1) == 0) { 648 | // old chord diagram (deprecated) 649 | String name = helper.readStringIntegerPlusOne(is); 650 | int base = helper.readInt(is); 651 | 652 | if (base != 0) { 653 | int fret0 = helper.readInt(is); 654 | int fret1 = helper.readInt(is); 655 | int fret2 = helper.readInt(is); 656 | int fret3 = helper.readInt(is); 657 | int fret4 = helper.readInt(is); 658 | int fret5 = helper.readInt(is); 659 | // this.listener.readChordDiagram(track, mesure, beat, name, base, fret1, fret2, 660 | // fret3, fret4, fret5); 661 | } 662 | } 663 | else { 664 | 665 | boolean sharp = helper.readBoolean(is); 666 | 667 | is.skip(3); 668 | 669 | helper.readByte(is); // readRoot(); 670 | 671 | helper.readUnsignedByte(is); // chord type 672 | 673 | int nineElevenThirteen = helper.readUnsignedByte(is); 674 | 675 | int bass = helper.readInt(is); 676 | 677 | helper.readInt(is); // readTonalityType(4); 678 | 679 | int addedNote = helper.readUnsignedByte(is); 680 | 681 | String name = helper.readStringByte(is, 20); 682 | 683 | is.skip(2); 684 | 685 | helper.readUnsignedByte(is); // readTonalityType(1); 686 | 687 | helper.readUnsignedByte(is); // readTonalityType(1); 688 | 689 | helper.readUnsignedByte(is); // readTonalityType(1); 690 | 691 | int baseFret = helper.readInt(is); 692 | 693 | int fret1 = helper.readInt(is); 694 | int fret2 = helper.readInt(is); 695 | int fret3 = helper.readInt(is); 696 | int fret4 = helper.readInt(is); 697 | int fret5 = helper.readInt(is); 698 | int fret6 = helper.readInt(is); 699 | int fret7 = helper.readInt(is); 700 | 701 | int numBarres = helper.readUnsignedByte(is); 702 | 703 | for (int i = 1; i <= 5; i++) { 704 | int fretOfBarre = helper.readUnsignedByte(is); 705 | } 706 | for (int i = 1; i <= 5; i++) { 707 | int barreStart = helper.readUnsignedByte(is); 708 | } 709 | for (int i = 1; i <= 5; i++) { 710 | int barreEnd = helper.readUnsignedByte(is); 711 | } 712 | 713 | is.skip(8); 714 | 715 | for (int i = 1; i <= GP4_NUMBER_OF_STRING; i++) { 716 | int fingering = helper.readByte(is); 717 | } 718 | 719 | boolean chordFingeringDisplayed = helper.readBoolean(is); 720 | } 721 | } 722 | 723 | private String readChordName(InputStream is) throws IOException { 724 | byte[] nameB; 725 | char[] nameC; 726 | int i; 727 | int max; 728 | 729 | nameB = new byte[21]; 730 | nameC = new char[20]; 731 | is.read(nameB, 0, 21); 732 | max = 20; 733 | if (nameB[0] < max) { 734 | max = nameB[0]; 735 | } 736 | 737 | for (i = 1; i <= max; i++) { 738 | nameC[i - 1] = (char) nameB[i]; 739 | } 740 | return (String.valueOf(nameC, 0, max)); 741 | } 742 | 743 | @Inject 744 | public void setListener(GP4ParserListener listener) { 745 | this.listener = listener; 746 | } 747 | } 748 | -------------------------------------------------------------------------------- /gp-parser-core/src/main/resources/GP4Format.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Guitar Pro 4.06 File Format Description 5 | 7 | 8 | 10 | 11 | 12 | 14 | 15 | 16 | 43 | 44 | 45 | 96 | 97 | 98 | 190 | 191 | 192 | 426 | 427 | 428 | 434 | 435 | 436 |
17 |

Guitar Pro 4.06 File Format Description

18 |
GUITAR PRO FILE FORMAT v4.06

Version: 1.0RC1 English
Author: Laurent Vromman
Translator: Avery Ceo, Matthieu Wipliez
Conversion to HTML: Mauricio Gracia Gutiérrez (corrections, added information)
Property Of: Arobas-Music
25 |
26 |

Summary

27 |

I. GENERAL
II. VERSIONS
III. FILE STRUCTURE
IV. HEADERS
1. Version
2. Information about the piece
3. Lyrics
4. Other information about the piece
V. FILE BODY
1. Measures
2. Tracks
3. Measure-Track pairs
4. Beats
5. Chord diagrams
6. Effects on the beats
7. Mix table change event
8. Notes
9. Effects on the notes
a. Effects on the notes
b. Grace notes
10. Bends
VI. CHORDS DIAGRAMS

42 |
46 |

I. GENERAL

47 |
48 | Values of type "integer" are stored in 4 bytes.
50 | Values of type "short int" are stored in 2 bytes.
52 | Values of type "byte" are stored in 1 byte.
54 |
55 | Values of type "integer" and "byte" presented in this document
57 | are written from left to right of the the LSB (least significant 58 | byte)
59 | to the MSB (most significant byte).
60 |
61 | The colors 62 | are stored in 4 bytes in the following way, the data is written from 63 | left to right of
64 | the LSB (least significant byte) to the MSB (most 65 | significant byte):
66 |
   __
3 |__| <- White byte, it always evaluates to 0x00;
2 |__| <- Blue;
1 |__| <- Green;
0 |__| <- Red.
67 | When this document uses the expression "character string," it means a 69 | couple of
70 | a first byte encoding the number 'n' of characters in the string 71 | (consequently limited to 255 characters),
72 | followed by the 'n' 73 | characters themselves.
74 |
75 | The musical notes are stored as integers. The 76 | value of the C(0) is 0, and each incrementation of
77 | the variable represents a half tone:
78 |
- C#(0) = 1;
- C (1) = 12;
- E (2) = 28 ...
79 |
Summary
80 |
81 |

II. VERSIONS

82 | The Guitar Pro format has evolved with the program to integrate the new 83 | functionalities that it provides.
84 |
85 | This document describes the structure of the Guitar Pro version 4.06 86 | files only.
87 |

88 |
Summary
90 |
91 |

III. File Structure

92 |

_______________________________________________________
| | |
| | Version |
| |_______________________________________________|
| | |
| | Tablature |
| |_______________________________________________|
|Headers| |
| | Lyrics |
| |_______________________________________________|
| | |
| | Other Tablature Information |
|_______|_______________________________________________|
File | | |
| | Measures |
| |_______________________________________________|
| | |
| | Tracks |
| |_______________________________________________|
| | | | |
| | | | Note 1 |
|Body | | Beat 1 |_______________|
| | | | |
| | | | Note i ... |
| | Measure-Track |_______________|_______________|
| | Pairs | | |
| | | | Note 1 |
| | | Beat i ... |_______________|
| | | | |
| | | | Note i ... |
|_______|_______________|_______________|_______________|
| |
| Chord Diagrams |
|_______________________________________________________|

Summary
94 |
95 |
99 |

IV. HEADERS

100 |

The difficulty in reading about the Guitar Pro files resides in the variable
size of the file's 101 | header. Reading the file must therefore be done sequentially.

102 |
103 |
	Structure
_
|
| Version
|_
|
| Tablature Information
|_
|
| Lyrics
|_
|
| Other Tablature Information
|_

Summary
108 |
109 |

1. Version

110 |

0x00000000: 30 character string (not counting the byte announcing the real length of
the string as explained in I. GENERAL) representing the version number. Only the first n
characters (n being given by the value described previously) characters are considered.
112 |
The different values possible at this time are:
FICHIER GUITARE PRO v1
FICHIER GUITARE PRO v1.01
FICHIER GUITARE PRO v1.02
FICHIER GUITARE PRO v1.03
FICHIER GUITARE PRO v1.04
FICHIER GUITAR PRO v2.20
FICHIER GUITAR PRO v2.21
FICHIER GUITAR PRO v3.00
FICHIER GUITAR PRO v4.00
FICHIER GUITAR PRO v4.06
FICHIER GUITAR PRO L4.06
113 |
114 |
*Translator's Note: "Fichier" is French for "File".  It is left untranslated above, as 
the program expects the string in French.
116 |
Only the specifications relating to version "FICHIER GUITAR PRO v4.06" are described here.
117 |
After this point (0x0000001F), the data is written sequentially without a precise address.

118 |
119 |
Summary
121 |
122 |

2. Information 123 | About the Piece

124 |

The follollowing information is presented in the form of a block of data containing:
- an integer representing the size of the stored information + 1;
- the string of characters representing the data
127 |
This structure requires that a null string be written 01 00 00 00 00 in the file.
128 |
The information concerned is, in order of reading within the file:
- The title of the piece;
- The subtitle of the piece;
- The interpret of the piece;
- The album from which the piece was taken;
- The author of the piece;
- The copyright;
- The name of the author of the tablature;
- An 'instructional' line about the tablature.
136 |
The following section contains information regarding the 'notice' (note) field in the piece's properties.
It begins with an integer containing the number of lines of Nb_Notice notes, then Nb_Notice instances of
the structure previously described, each containing lines of notes.
139 |
The file then contains a byte determining the 'TripletFeel' attribute of the piece.  
If TripletFeel is activated, the value is 1. If not, the integer value is 0.
143 |
144 |
Summary
146 |
147 |

3. Lyrics

148 |
	
The next section of the file contains the lyrics associated with the piece.
150 |
WARNING: The strings presented in this section and in this section only do not conform to the 
format presented in "I. General", but are written directly.
152 |
The lyrics section begins with an integer giving the number of the track with which the 
lyrics are associated.
154 |
Then, for each of the 5 lines of lyrics generated by Guitar Pro 4, the file contains an 
integer representing the number of characters in the string followed by the character string itself.
157 |
158 |
Summary
160 |
161 |

4. Other 162 | information about the piece

163 |
	
The next data is:

The tempo: Integer

The key: Byte
This value encodes the key (signature) at the beginning of the piece. It is encoded as:
- 0: C
- 1: G (#)
- 2: D (##)
- -1: F (b) ...

The Octave: Byte
The standard 169 | value is 0. It becomes 8 if the sheet is to be played one octave higher (8va).

This functionality is not yet used, but is presented as a preview of a revision of the GP4 format.

Midi Channels:
Table of midi channels. There are 4 ports and 16 channels, the channels are stored in this order:
port1/channel1 - port1/channel2 ... port1/channel16 - port2/channel1 ...

Each element of the table has the following form:
Instrument: Integer
Volume: Byte
Balance: Byte
Chorus: Byte
Reverb: Byte
Phaser: Byte
Tremolo: Byte

blank1: byte => Backward compatibility with version 3.0
blank2: byte => Backward compatibility with version 3.0

Number of Measures: Integer
Number of Tracks: Integer
185 |
186 |
Summary
188 |
189 |
193 |

V. FILE BODY

194 |
	 _________________________________
|
| Mesures
|_________________________________
|
| Tracks
|_________________________________
| | |
| | | Note 1
| | Beat 1 |_
| | |
| | | Note i ...
| Measure-track |_______________|_
| Pairs | |
| | | Note 1
| | Beat i ... |_
| | |
| | | Note i ...
|_______________|_______________|_



Summary
196 |
197 |

1. Measures

198 |
	
The measures are written one after another, their number having been specified previously.

The first byte is the measure's header. It lists the data given in the current measure.
__
7 |__| <- Presence of a double bar;
6 |__| <- Tonality of the measure;
5 |__| <- Presence of a marker;
4 |__| <- Number of alternate ending;
3 |__| <- End of repeat;
2 |__| <- Beginning of repeat;
1 |__| <- Denominator of the (key) signature;
0 |__| <- Numerator of the (key) signature.

Each of these elements is present only if the corresponding bit is a 1.

The different elements are written (if they are present) from lowest to highest bit.

Exceptions are made for the double bar and the beginning of repeat whose sole presence
is enough, complementary data is not necessary.

Numerator of the (key) signature: Byte
Numerator of the (key) signature of the piece

Denominator of the (key) signature: Byte
Denominator of the (key) signature of the piece

End of repeat: Byte
Number of repeats until the previous Beginning of repeat.
Nombre de renvoi jusqu'au début de renvoi précédent.

Number of alternate ending: Byte
The number of alternate ending.

Marker:
The markers are written in two steps. First is written an integer equal to
the marker's name length + 1, and then a string containing the marker's
name. Finally the marker's color is written.

Tonality of the measure: Byte
This value encodes a key (signature) change on the current piece.
It is encoded as:
- 0: C
- 1: G (#)
- 2: D (##)
- -1: F (b) ...

Summary
210 |
211 |

2. Tracks

212 |

The tracks are written one after another, their number having been specified previously.

The first byte is the track's header. It precises the track's attributes:
__
7 |__| <- Blank bit;
6 |__| <- Blank bit;
5 |__| <- Blank bit;
4 |__| <- Blank bit;
3 |__| <- Blank bit;
2 |__| <- Banjo track;
1 |__| <- 12 stringed guitar track;
0 |__| <- Drums track.

Name: String
A 40 characters long string containing the track's name.

Number of strings: Integer
An integer equal to the number of strings of the track.

Tuning of the strings: Table of integers
The tuning of the strings is stored as a 7-integers table, the "Number of
strings" first integers being really used. The strings are stored from
the highest to the lowest.

Port: Integer
The number of the MIDI port used.

Channel: Integer
The number of the MIDI channel used. The channel 10 is the drums channel.

ChannelE: Integer
The number of the MIDI channel used for effects.

Number of frets: Integer
The number of frets of the instrument.

Height of the capo: Integer
The number of the fret on which a capo is present. If no capo is used, the
value is 0x00000000.

Track's color: Color
The track's displayed color in Guitar Pro.

Summary
235 |
236 |

3. Measures-Tracks pairs

237 |

The list of beats per track and per measure is then written to the file in the
following order:

Measure 1/Track 1
Measure 1/Track 2
...
Measure 1/Track M
Measure 2/Track 1
...
Measure 2/Track M
...
Measure N/Track 1
Measure N/Track 2
...
Measure N/Track M

A measure-track pair is written in two steps. We first write the number of beats
in the current pair:

Number of beats: Integer
Integer indicating the number of beats the measure-track pair contains.

After what we directly write the beat details (which are described in the next section).

Summary
242 |
243 |

4. A beat

244 |

The first byte is the beat header. It lists the data present in the current beat:
__
7 |__| <- Blank bit;
6 |__| <- Status: True if the beat is empty of if it is a rest;
5 |__| <- The beat is a n-tuplet;
4 |__| <- Presence of a mix table change event;
3 |__| <- Presence of effects;
2 |__| <- Presence of a text;
1 |__| <- Presence of a chord diagram;
0 |__| <- Dotted notes.


Status: Byte
If the bit 6 is true, we start by writing the beat status. The value is
0x00 if the beat is empty and 0x02 if it is a rest.

Beat duration: Byte
The basic beat duration is a eighth note, which is equivalent to a
time duration of 1. We thus obtain the following relations:
* -2: Whole note;
* -1: Half note;
* 0: Quarter note;
* 1: Eighth note;
* 2: Sixteenth note;
* 3: Thirty-second note;
* ...

N-tuplet: Integer
If the bit 5 of the header byte is true, this integer corresponds to the
'n' in 'n-tuplet': 3, 5, 6, 7, 9, 10, 11, 12 and 13.

Chord diagram:
If the presence of a chord diagram is indicated by the bit 1 of the
header, it is then written here. The detail of this operation is specified
in paragraph V.5 Chords diagrams.

Text:
If the presence of a text is indicated by the bit 2 of the header, it is
written here. It behaves like most of the previous strings. We
first find an integer coding the text length + 1, followed by the string
containing the text (at the format described in I. GENERAL).

Effect on beats:
If the presence of an effect is indicated by the bit 3 of the header, it
is written at this place. The detail of this operation is specified in the
paragraph V.6 Effects on 259 | beats. Effects on beats include tremolo bars,
bends...

Mix table change event:
If the presence of an event linked to the mix table is indicated by the
bit 4 of the header, it is written here. The detail of this operaion is
specified in the paragraph V.7 Mix table change event.

Note:
The note itself is written here. The detail of this operation is specified
in the paragraph V.8 Note.

Summary
265 |
266 |

5. 267 | Chords diagrams

268 |

Header: Byte
This value is 0x01, indicating a Guitar Pro 4 format chord.

Sharp: Byte
Determines if the chord is displayed sharp or flat.

Blank1,
Blank2,
Blank3: Bytes
Blank bytes needed for ascendant compatibility with versions 3 of the software.

Root: Byte
* -1 for the customized chords
* 0: C
* 1: C#...

Major/minor: Byte
Determines the chord type as followed:
- 0: M
- 1: 7
- 2: 7M
- 3: 6
- 4: m
- 5: m7
- 6: m7M
- 7: m6
- 8: sus2
- 9: sus4
- 10: 7sus2
- 11: 7sus4
- 12: dim
- 13: aug
- 14: 5

Nine, Eleven of Thirteen: Byte
Determines if the chord goes until the ninth, the eleventh, or the thirteenth.

Bass: Integer
Lowest note of the chord. It gives the chord inversions.

Diminished/Augmented Integer
Tonality linked with 9/11/13:
0: perfect ("juste")
1: augmented
2: diminished

add: Byte
Allows to determine if a 'add' (added note) is present in the chord.

Name: String
20 characters long string containing the chord name.


Blank4,
Blank5: Bytes
Blank bytes needed for ascendant compatibility with versions 3 of the software.

Fifth: Byte
Tonality of the fifth:
0: perfect ("juste")
1: augmented
2: diminished

Ninth: Byte
Tonality of the ninth:
0: perfect ("juste")
1: augmented
2: diminished
This tonality is valid only if the value "Nine, Eleven or Thirteen" is 11 or 13.

Eleventh: Byte
Tonality of the eleventh:
0: perfect ("juste")
1: augmented
2: diminished
This tonality is valid only if the value "Nine, Eleven or Thirteen" is 13.

Base fret: Integer
Shows the fret from which the chord is displayed.

Frets: List of 7 integers.
Corresponds to the fret number played on each string, from the highest to the lowest.
-1 means a string unplayed.
0 means a string played "blank" (ie no fret).

Number of barres: Byte
Indicates the number of barres there are in the chord. A chord can contain up to 5 barres.

Fret of the barre: List of 5 Bytes
Indicates the fret number of each possible barre.

Barre start: List of 5 Bytes
Indicates the first string of the barre, 1 being the highest.
The list order matches the chord different barres frets list order.

Barre end: List of 5 Bytes
Indicates the first string of the barre, 1 being the lowest.
The list order matches the chord different barres frets list order.

Omission1,
Omission3,
Omission5,
Omission7,
Omission9,
Omission11,
Omission13: Bytes
Gives the notes there are in the chord.
If the value is 0x00, the note is not in the chord, and if the value is
0x01, the note is in the chord. 9, 11 or 13 can only be present
for a "Nine, Eleven or Thirteen" big enough.

Blank6: Byte
Blank byte needed for ascendant compatibility with versions 3 of the software.

Fingering: List of 7 Bytes
Describes the fingering used to play the chord.
Below is given the fingering from the highest string to the lowest:
-2: unknown;
-1: X or 0 (no finger);
0: thumb;
1: index;
2: middle finger;
3: annular;
4: little finger.

ShowDiagFingering: Byte
If it is 0x01, the chord fingering is displayed.
If it is 0x00, the chord fingering is masked.

Summary
323 |
324 |

6. Effects on beats

325 |

The first byte is the header of effects linked to beats. It gives information about existing effects:
__
7 |__| <- Blank bit;
6 |__| <- Stroke effect;
5 |__| <- Tapping, popping or slapping effect;
4 |__| <- unused bit -> remainings of version 3;
3 |__| <- unused bit -> remainings of version 3;
2 |__| <- unused bit -> remainings of version 3;
1 |__| <- unused bit -> remainings of version 3;
0 |__| <- unused bit -> remainings of version 3.

The 2nd byte is linked with effects new to the version 4 of the software.
__
7 |__| <- Blank bit;
6 |__| <- Blank bit;
5 |__| <- Blank bit;
4 |__| <- Blank bit;
3 |__| <- Blank bit;
2 |__| <- Tremolo Bar;
1 |__| <- Pickstroke;
0 |__| <- Rasguedo.

The effects, if any, are then written in the following order:

Tapping/Popping/Slapping: Byte
The presence of this effect is set by the bit 5 of the first header byte.
It is written as:
0: None
1: Tapping
2: Slapping
3: Popping (bass guitar)

Tremolo Bar: Bend
The presence of this effect is set by the bit 2 of the second header byte.
The tremolo bar is saved as a BEND, as described in the paragraph V.10 Bends.

UpStroke: Byte
The presence of this effect is set by the bit 6 of the first header byte.
It can take different values depending on the stroke speed:
0: none;
1: hundred twenty eighth note;
2: sixty-fourth note;
3: thirty-second note;
4: sixteenth note;
5: eighth note;
6: quarter note.

DownStroke: Byte
The presence of this effect is set by the bit 6 of the first header byte.
It can take different values depending on the stroke speed:
0: none;
1: hundred twenty eighth note;
2: sixty-fourth note;
3: thirty-second note;
4: sixteenth note;
5: eighth note;
6: quarter note.

Rasguedo:
The rasguedo is set if the bit 0 of the second header byte is set. It is
a complement to the strokes, so it does not need any additional data.


Pickstroke: Byte
The presence of this effect is set by the bit 1 of the second header byte.
It can take different values:
0: none;
1: going up;
2: going down.


Summary
336 |
337 |

7. Mix table change 339 | event

340 |
 		
Instrument: Byte
Gives the number of the new instrument. The value is -1 if no instrument change occurs.

Volume: Byte
Gives the new volume value. The value is -1 if no volume change occurs.

Pan: Byte
Gives the new pan value. The value is -1 if no pan change occurs.

Chorus: Byte
Gives the new chorus value. The value is -1 if no chorus change occurs.

Reverb: Byte
Gives the new reverb value. The value is -1 if no reverb change occurs.

Phaser: Byte
Gives the new phaser value. The value is -1 if no phaser change occurs.

Tremolo: Byte
Gives the new tremolo value. The value is -1 if no tremolo change occurs.

Tempo: Integer
Gives the new tempo value. The value is -1 if no tempo change occurs.

Volume change duration: Byte
Gives the volume change duration in beats.

Pan change duration: Byte
Gives the pan change duration in beats.

Chorus change duration: Byte
Gives the chorus change duration in beats.

Reverb change duration: Byte
Gives the reverb change duration in beats.

Phaser change duration: Byte
Gives the phaser change duration in beats.

Tremolo change duration: Byte
Gives the tremolo change duration in beats.

Tempo change duration: Byte
Gives the tempo change duration in beats.

The next byte precises if the changes apply only to the current track (if the
matching bit is 0), or to every track (if it is 1).
__
7 |__| <- Blank bit;
6 |__| <- Blank bit;
5 |__| <- Tremolo;
4 |__| <- Phaser;
3 |__| <- Reverb;
2 |__| <- Chorus;
1 |__| <- Pan;
0 |__| <- Volume.

Summary
358 |
359 |

8. Note

360 |

The first byte is the note header. It lists the information about the different
parameters linked to the note:
__
7 |__| <- Right hand or left hand fingering;
6 |__| <- Accentuated note;
5 |__| <- Note type (rest, empty note, normal note);
4 |__| <- Note dynamic;
3 |__| <- Presence of effects linked to the note;
2 |__| <- Ghost note;
1 |__| <- Dotted note;
0 |__| <- Time-independent duration.

Note type: Short Int
If the bit 5 is true, we start by writing the note type. The value is:
0x0100 if the note is normal;
0x0200 if the note is a ghost note;
0x0300 if the note is a tie note.

Note duration:
If the bit 0 is true, we write the 2 following information linked to the
note duration.

Time duration: Byte
The basic time duration is the quarter note, which is equivalent
to a time duration of 1. Therefore, we obtain the relations:
* -2: Whole Note;
* -1: Half note;
* 0: Quarter note;
* 1: Eighth note;
* 2: Sixteenth note;
* 3: Thirty-second note;
* ...

N-tuplet: Byte
This int matches the N in "N-tuplet" (ie 3, 5, 6, 7, 9, 10, 11, 12, 13).

Note dynamic: Byte
If the bit 4 of the header byte is true, we write here the note strength
with the following rule:
- 1: ppp
- 2: pp
- 3: p
- 4: mp
- 5: mf
- 7: f
- 8: ff
- 9: fff
If the bit 4 is false, we then consider that the note is forte (value 6).

Fret number: Byte
If the bit 5 is true, we write here the number of the fret on which the note
is applied.

Fingering: List of 2 bytes
If the bit 7 is true, we write here successively the fingerings left hand,
then right hand, each of them being written on one byte. The fingering
is coded this way:
-1: nothing;
0: thumb;
1: index;
2: middle finger;
3: annular;
4: little finger.

Effects on the note:
If the presence of an effect is indicated by the bit 3 of the header, it
is saved at this place. The details of this operation is specified in the
next paragraph. Those include for example vibratos, palm muting,
slides, harmonices...

Summary
372 |
373 |

9. Effects on the notes

374 |
a. Effects on the notes
375 |

The effects presence for the current note is set by the 2 header bytes.

First byte:
__
7 |__| <- Blank bit;
6 |__| <- Blank bit;
5 |__| <- Blank bit;
4 |__| <- Grace note presence;
3 |__| <- Let ring;
2 |__| <- Presence of a slide from the current note (version 3);
1 |__| <- Presence of a hammer-on or a pull-off from the current note;
0 |__| <- Presence of a bend.

Second byte:
__
7 |__| <- Blank bit;
6 |__| <- Left hand vibrato;
5 |__| <- Trill;
4 |__| <- Harmonic note;
3 |__| <- Presence of a slide from the current note;
2 |__| <- Tremolo picking;
1 |__| <- Palm Mute;
0 |__| <- Note played staccato.

Bend:
If the bit 0 of the first header byte is true, we write here the bend as
described in section V.10. Bends.

Grace Note:
If the bit 4 of the first header byte is true, we write here the data
relative to the Grace Note, as described in section V.9.b Grace Notes.

Tremolo Picking: Byte
If the bit 2 of the second header byte is true, the information linked to
tremolo picking are saved here. It is encoded like this:
- 1: eighth note;
- 2: sixteenth note;
- 3: thirty-second note.

Slide: Byte
If the bit 3 of the second header byte is true, the information linked to
the slide is stored here and is coded like this:
* -2: slide into from above
* -1: slide into from below
* 0: no slide
* 1: shift slide
* 2: legato slide
* 3: slide out of downwards
* 4: slide out of upwards

Harmonics: Byte
If the bit 4 of the second header byte is true, the information linked to
the harmonics is stored here and is coded like this:
- 0: None
- 1: Natural
- 15: Artificial+5
- 17: Artificial+7
- 22: Artificial+12
- 3: Tapped
- 4: Pitch
- 5: Semi

Trill:
If the bit 5 of the second header byte is true, the information linked to
the Trill effect is stored here. It is written in two steps:
Fret: Byte
The fret the trill is made with.

Period: Byte
The period between each note. The value is encoded as:
- 0: Quarter note;
- 1: Eighth note;
- 2: Sixteenth note.

The following effects are present if the bit of the header is true:
- Let ring
- Presence of a hammer-on or a pull-off from the current note
- Left hand vibrato
- Palm Mute
- Note played staccato.

Summary
396 |
397 |

b. 398 | Grace notes

399 |

The grace notes are stored in the file with 4 variables, written in the following
order.

Fret: Byte
The fret number the grace note is made from.

Dynamic: Byte
The grace note dynamic is coded like this:
- 1: ppp
- 2: pp
- 3: p
- 4: mp
- 5: mf
- 6: f
- 7: ff
- 8: fff
The default value is 6.

Transition: Byte
This variable determines the transition type used to make the grace note:
- 0: None
- 1: Slide
- 2: Bend
- 3: Hammer

Duration: Byte
Determines the grace note duration, coded this way:
- 3: Sixteenth note.
- 2: Twenty-fourth note.
- 1: Thirty-second note.


Summary
407 |
408 |

10. Bends

409 |
 		
Type: Byte
Gives the bend type. Different types are allowed and are context-dependent (tremolo bar or bend).
The model list is:
Common:
- 0: None

Bend specific:
- 1: Bend
- 2: Bend and Release
- 3: Bend and Release and Bend
- 4: Prebend
- 5: Prebend and Release

Tremolo bar specific:
- 6: Dip
- 7: Dive
- 8: Release (up)
- 9: Inverted dip
-10: Return
-11: Release (down)

Value: Integer
Bend height. It is 100 per tone and goes by quarter tone.
* Normal position: 0;
* Quarter tone: 25;
* Half tone: 50;
* Three-quarters tone: 75;
* Whole tone: 100;
... until
* Three tones: 300.


Number of points: Integer
Number of points used to display the bend. Is followed by the list of points.

List of points:
Each point is written like this:
Absolute time position Integer
Gives the point position from the previous point. This value goes between 0 and 60
and represents sixties of the note duration.

Vertical position Integer
It is 100 per tone and goes by quarter tone.
* Normal position: 0;
* Quarter tone: 25;
* Half tone: 50;
* Three-quarters tone: 75;
* Whole tone: 100;
... until
* Three tones: 300.

Vibrato Byte
Determines how to play the section, with different vibrato types:
- 0: none
- 1: fast
- 2: average
- 3: slow

Summary
424 |
425 |
429 |

VI. CHORDS DIAGRAMS

430 |

Number of chords: Integer
Number of chords to write in the chords diagram list.

Then comes the written chords list, as described in V.5 Chords diagrams.
433 |
437 |


438 |

439 |
440 |
441 |
442 | This page is part of the DGuitar Home Page 443 | 444 | 445 | --------------------------------------------------------------------------------