Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
incompleteopus committed Dec 22, 2012
0 parents commit 6ee0548
Show file tree
Hide file tree
Showing 18 changed files with 11,966 additions and 0 deletions.
373 changes: 373 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

66 changes: 66 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# VexABC

ABC notation parser and renderer for VexFlow

Copyright (c) 2012 Mikael Nousiainen

## See VexABC in action and try it

* [VexABC interactive editor](http://test.incompleteopus.net/vexabc/test/editor.html)
* [VexABC tests](http://test.incompleteopus.net/vexabc/test/test.html)

## VexABC features

* VexABC is a work in progress, which means that many features of the ABC music standard are incomplete or completely missing
* Many of the basic constructs and features of the ABC music standard are already working
* See the [VexABC tests](http://test.incompleteopus.net/vexabc/test/test.html) to find out features implemented and working
* Currently, only one voice and a single stave can be used
* Multi-voice and multi-stave (system) support will be implemented eventually
* The current VexFlow API imposes some restrictions on how notation can be rendered
* Clefs, key signatures and time signatures can be rendered only at the beginning of a measure
* Voltas (e.g. variant endings) can only begin and end on measure boundaries
* Slurs are not supported
* Grace notes are not supported
* Some ABC decorations can not be rendered yet
* VexABC aims to implement [ABC music standard 2.1](http://abcnotation.com/wiki/abc:standard:v2.1)

## VexABC dependencies

Main dependencies:
* [VexFlow](http://github.com/0xfe/vexflow/) (latest GIT master branch) to render the notation
* [PEG.js](http://github.com/dmajda/pegjs/) (latest GIT master branch) for parsing ABC notation text
* jQuery 1.8

Test dependencies:
* QUnit 1.10.0 for running unit tests
* Twitter Bootstrap 2.2 is used in the web pages for tests

## What is ABC notation?

ABC notation is a text-based music notation system.

* [ABC notation home](http://abcnotation.com/)
* [ABC notation examples](http://abcnotation.com/examples)
* [ABC music standard 2.1](http://abcnotation.com/wiki/abc:standard:v2.1)

## What is VexFlow?

VexFlow is an open-source web-based music notation rendering API.

* [VexFlow Home](http://vexflow.com/)
* [VexFlow GitHub repository](http://github.com/0xfe/vexflow/)
* [VexFlow Google Group](https://groups.google.com/forum/?fromgroups#!forum/vexflow)

## What is PEG.js?

PEG.js is a simple parser generator for JavaScript.

* [PEG.js Home](http://pegjs.majda.cz/)
* [PEG.js GitHub repository](http://github.com/dmajda/pegjs/)

## VexABC license

Mozilla Public License, version 2.0 - http://www.mozilla.org/MPL/2.0/

* [License FAQ](http://www.mozilla.org/MPL/2.0/FAQ.html)

2 changes: 2 additions & 0 deletions lib/jquery-1.8.3.min.js

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions lib/peg-0.7.0.min.js

Large diffs are not rendered by default.

360 changes: 360 additions & 0 deletions lib/vexflow-min.js

Large diffs are not rendered by default.

328 changes: 328 additions & 0 deletions src/vexabc-common.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,328 @@
/*
* VexABC - ABC notation parser and renderer for VexFlow
*
* Copyright (c) 2012 Mikael Nousiainen
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

VexAbc.Def = function() {
};

VexAbc.Util = function() {
};

VexAbc.Def.DURATION_RESOLUTION = 262144;
VexAbc.Def.DEFAULT_VOICE_ID = "default";

VexAbc.Util.isDataNotePitchEqual = function(dataNote1, dataNote2) {
return ((dataNote1.pitch == dataNote2.pitch) && (dataNote1.octave == dataNote2.octave));
}

VexAbc.Util.findEqualDataNotePitchIndices = function(dataNotes1, dataNotes2, fromIndices) {
var result = {
firstIndices: [],
secondIndices: []
};

var length;
if (fromIndices) {
length = fromIndices.length;
} else {
length = dataNotes2.length;
}

for (var i = 0; i < length; i++) {
var index;
if (fromIndices) {
index = fromIndices[i];
} else {
index = i;
}

var dataNote1 = dataNotes1[index];

for (var j = 0; j < dataNotes2.length; j++) {
var dataNote2 = dataNotes2[j];

if (VexAbc.Util.isDataNotePitchEqual(dataNote1, dataNote2)) {
result.firstIndices.push(index);
result.secondIndices.push(j);
}
}
}

return result;
}

VexAbc.Def.fractionDurationToVexFlowDuration = {};

// TODO: This kind of array definition is really inflexible, so find a better way to deduce duration!
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 1] =
{ value: "1", dots: 0 };
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 2 + VexAbc.Def.DURATION_RESOLUTION / 4 + VexAbc.Def.DURATION_RESOLUTION / 8 + VexAbc.Def.DURATION_RESOLUTION / 16] =
{ value: "2", dots: 3 };
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 2 + VexAbc.Def.DURATION_RESOLUTION / 4 + VexAbc.Def.DURATION_RESOLUTION / 8] =
{ value: "2", dots: 2 };
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 2 + VexAbc.Def.DURATION_RESOLUTION / 4] =
{ value: "2", dots: 1 };
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 2] =
{ value: "2", dots: 0 };
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 4 + VexAbc.Def.DURATION_RESOLUTION / 8 + VexAbc.Def.DURATION_RESOLUTION / 16 + VexAbc.Def.DURATION_RESOLUTION / 32] =
{ value: "4", dots: 3 };
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 4 + VexAbc.Def.DURATION_RESOLUTION / 8 + VexAbc.Def.DURATION_RESOLUTION / 16] =
{ value: "4", dots: 2 };
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 4 + VexAbc.Def.DURATION_RESOLUTION / 8] =
{ value: "4", dots: 1 };
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 4] =
{ value: "4", dots: 0 };
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 8 + VexAbc.Def.DURATION_RESOLUTION / 16 + VexAbc.Def.DURATION_RESOLUTION / 32 + VexAbc.Def.DURATION_RESOLUTION / 64] =
{ value: "8", dots: 3 };
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 8 + VexAbc.Def.DURATION_RESOLUTION / 16 + VexAbc.Def.DURATION_RESOLUTION / 32] =
{ value: "8", dots: 2 };
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 8 + VexAbc.Def.DURATION_RESOLUTION / 16] =
{ value: "8", dots: 1 };
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 8] =
{ value: "8", dots: 0 };
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 16 + VexAbc.Def.DURATION_RESOLUTION / 32 + VexAbc.Def.DURATION_RESOLUTION / 64 + VexAbc.Def.DURATION_RESOLUTION / 128] =
{ value: "16", dots: 3 };
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 16 + VexAbc.Def.DURATION_RESOLUTION / 32 + VexAbc.Def.DURATION_RESOLUTION / 64] =
{ value: "16", dots: 2 };
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 16 + VexAbc.Def.DURATION_RESOLUTION / 32] =
{ value: "16", dots: 1 };
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 16] =
{ value: "16", dots: 0 };
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 32 + VexAbc.Def.DURATION_RESOLUTION / 64 + VexAbc.Def.DURATION_RESOLUTION / 128 + VexAbc.Def.DURATION_RESOLUTION / 256] =
{ value: "32", dots: 3 };
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 32 + VexAbc.Def.DURATION_RESOLUTION / 64 + VexAbc.Def.DURATION_RESOLUTION / 128] =
{ value: "32", dots: 2 };
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 32 + VexAbc.Def.DURATION_RESOLUTION / 64] =
{ value: "32", dots: 1 };
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 32] =
{ value: "32", dots: 0 };
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 64 + VexAbc.Def.DURATION_RESOLUTION / 128 + VexAbc.Def.DURATION_RESOLUTION / 256 + VexAbc.Def.DURATION_RESOLUTION / 512] =
{ value: "64", dots: 3 };
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 64 + VexAbc.Def.DURATION_RESOLUTION / 128 + VexAbc.Def.DURATION_RESOLUTION / 256] =
{ value: "64", dots: 2 };
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 64 + VexAbc.Def.DURATION_RESOLUTION / 128] =
{ value: "64", dots: 1 };
VexAbc.Def.fractionDurationToVexFlowDuration[VexAbc.Def.DURATION_RESOLUTION / 64] =
{ value: "64", dots: 0 };

// TODO: How to handle unknown durations?
VexAbc.Util.convertFractionDurationToVexFlowDuration = function(multiplier, noteValue) {
var factor = VexAbc.Def.DURATION_RESOLUTION / noteValue;
var durationTicks = multiplier * factor;

var result = VexAbc.Def.fractionDurationToVexFlowDuration[durationTicks];
if (!result) {
return null;
}

result.beamable = (durationTicks < (VexAbc.Def.DURATION_RESOLUTION / 4));

return result;
}

VexAbc.Util.isBeamedDuration = function(multiplier, noteValue) {
var factor = VexAbc.Def.DURATION_RESOLUTION / noteValue;
var durationTicks = multiplier * factor;
return (durationTicks < (VexAbc.Def.DURATION_RESOLUTION / 4));
}

// Aim for stave center :)
VexAbc.Def.restNoteKeyForClef = {
"treble": "b/4",
"alto": "c/4",
"tenor": "a/3",
"bass": "d/3",
"perc": "b/4"
};

VexAbc.Util.getRestNoteKeyForClef = function(clef) {
var key = VexAbc.Def.restNoteKeyForClef[clef];
if (!key) {
return "b/4";
}

return key;
}

VexAbc.Def.abcDecorationToVexFlowArticulation = {
"staccato": "a.", // staccato
"staccatissimo": "av", // staccatissimo (non-standard)
"accent": "a>", // accent
"emphasis": "a>", // accent
">": "a>", // accent
"tenuto": "a-", // tenuto
"marcato": "a^", // marcato (marcatissimo?) (non-standard)
"+": "a+", // left hand pizzicato
"plus": "a+", // left hand pizzicato
"snap": "ao", // snap pizzicato
"thumb:": "ao", // snap pizzicato
"fermata": "a@a", // fermata above staff
"invertedfermata": "a@u", // fermata below staff
"upbow": "a|", // up-bown - up stroke
"downbow": "am" // down-bow - down stroke
};

VexAbc.Util.convertAbcDecorationToVexFlowArticulation = function (decoration) {
return VexAbc.Def.abcDecorationToVexFlowArticulation[decoration];
}

VexAbc.Def.vexFlowAnnotationStyle = {
"text": {
fontName: "Times",
fontSize: 12,
fontWeight: "",
verticalPosition: "above",
justification: "center"
},
"dynamics": {
fontName: "Times",
fontSize: 14,
fontWeight: "italic",
verticalPosition: "below",
justification: "center"
},
"other": {
fontName: "Times",
fontSize: 14,
fontWeight: "italic",
verticalPosition: "above",
justification: "center"
},
"chordSymbol": {
fontName: "Times",
fontSize: 14,
fontWeight: "bold",
verticalPosition: "above",
justification: "center"
},
"fingering": {
fontName: "Times",
fontSize: 10,
fontWeight: "",
verticalPosition: "above",
justification: "center"
}
};

VexAbc.Util.getVexFlowAnnotationStyle = function(id) {
return VexAbc.Def.vexFlowAnnotationStyle[id];
}

VexAbc.Def.abcDecorationToVexFlowAnnotation = {
"0": {
type: "annotation",
style: "fingering",
value: "0"
},
"1": {
type: "annotation",
style: "fingering",
value: "1"
},
"2": {
type: "annotation",
style: "fingering",
value: "2"
},
"3": {
type: "annotation",
style: "fingering",
value: "3"
},
"4": {
type: "annotation",
style: "fingering",
value: "4"
},
"5": {
type: "annotation",
style: "fingering",
value: "5"
},
"pppp": {
type: "annotation",
style: "dynamics",
value: "pppp"
},
"ppp": {
type: "annotation",
style: "dynamics",
value: "ppp"
},
"pp": {
type: "annotation",
style: "dynamics",
value: "pp"
},
"p": {
type: "annotation",
style: "dynamics",
value: "p"
},
"mp": {
type: "annotation",
style: "dynamics",
value: "mp"
},
"mf": {
type: "annotation",
style: "dynamics",
value: "mf"
},
"f": {
type: "annotation",
style: "dynamics",
value: "f"
},
"ff": {
type: "annotation",
style: "dynamics",
value: "ff"
},
"fff": {
type: "annotation",
style: "dynamics",
value: "fff"
},
"ffff": {
type: "annotation",
style: "dynamics",
value: "ffff"
},
"sfz": {
type: "annotation",
style: "dynamics",
value: "sfz"
},
"trill": {
type: "annotation",
style: "other",
value: "tr"
}
};

VexAbc.Util.convertAbcDecorationToVexFlowAnnotation = function (decoration) {
return VexAbc.Def.abcDecorationToVexFlowAnnotation[decoration];
}

/*
TODO: decorations using text annotations:
!D.S.! the letters D.S. (=Da Segno)
!D.C.! the letters D.C. (=either Da Coda or Da Capo)
!dacoda! the word "Da" followed by a Coda sign
!dacapo! the words "Da Capo"
!fine! the word "fine"
TODO: VexFlow probably supports these too:
!segno! 2 ornate s-like symbols separated by a diagonal line
!coda! a ring with a cross in it
*/

Loading

0 comments on commit 6ee0548

Please sign in to comment.