Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Difference From afc1222e0282b772 To d6636870ae43e9ac
|
2023-01-07
| ||
| 14:29 | modules: nns: fix: add 'roman=2' to %%nns and fix some chords - reported by Robert Bley-Vroman ... (check-in: 8365017fa6 user: jef tags: trunk) | |
| 07:38 | New release v1.22.6 ... (check-in: d6636870ae user: jef tags: trunk, v1.22.6) | |
| 07:35 | source: copyright update ... (check-in: d49a8df607 user: jef tags: trunk) | |
|
2022-02-16
| ||
| 15:53 | core: fix: bad setting of voice parameters in the tune header with possible crash - reported by Hudson Lacerda ... (check-in: 8a9b5595a4 user: jef tags: trunk) | |
|
2022-02-12
| ||
| 17:42 | New release v1.21.6 ... (check-in: afc1222e02 user: jef tags: trunk, v1.21.6) | |
| 15:42 | core: add !caesura!, !tick! and !short! ... (check-in: 21e5a0d63b user: jef tags: trunk) | |
Changes to README.md.
| ︙ | ︙ | |||
12 13 14 15 16 17 18 | The **abc2svg** core is based on the [abcm2ps](https://github.com/lewdlime/abcm2ps) C code which requires compilation on every operating system. The **abc2svg** scripts can run in any system with no compilation on any platform that contains an internet browser. This includes MS-Windows, Apple, and Unix-like systems (Linux, BSD...) as well as portable devices | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | The **abc2svg** core is based on the [abcm2ps](https://github.com/lewdlime/abcm2ps) C code which requires compilation on every operating system. The **abc2svg** scripts can run in any system with no compilation on any platform that contains an internet browser. This includes MS-Windows, Apple, and Unix-like systems (Linux, BSD...) as well as portable devices such as cell phones and tablets. A description of the ABC parameters that relate to both abcm2ps and abc2svg can be found [here][1]. [1]: http://moinejf.free.fr/abcm2ps-doc/index.html "abc2svg documentation" ### 1. Web browser usage |
| ︙ | ︙ | |||
40 41 42 43 44 45 46 | search on the internet the name of the browser and keywords such as 'bookmarklet' and 'javascript in url'). To edit the URL, extract the javascript code by right clicking on one of the bookmarklets below and selecting copy url. Then, paste this code into the URL of your new bookmark in your library. | | | | | 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
search on the internet the name of the browser and keywords such as
'bookmarklet' and 'javascript in url'). To edit the URL, extract
the javascript code
by right clicking on one of the bookmarklets below and selecting
copy url. Then, paste this code into the URL of your new bookmark
in your library.
To use a abc2svg bookmarklet, first, load an ABC file into your
browser either from a web site of from a file on your system.
Once you see the textual abc code, click on the bookmarklet
that you created. After a slight delay depending upon the
complexity of the abc code, it should be replaced by a music
representation or a list of the contents of the ABC file. Here
are two bookmarklets that you can try.
This
<a href="javascript:(function(){var%20s,n=2,d=document,b=d.body;d.head.innerHTML='%3cstyle%3esvg{display:block};@media print{body{margin:0;padding:0;border:0};.nop{display:none}}%3c/style%3e\n';b.innerHTML='%3cscript type=%22text/vnd.abc%22%3e\n'+b.textContent+'%3c/script%3e\n';function%20f(u){s=d.createElement('script');s.src='http://moinejf.free.fr/js/'+u;s.onload=function(){if(--n==0)dom_loaded()};d.head.appendChild(s)};f('abcweb-1.js');f('snd-1.js')})()"
title="Copy me">first abc2svg bookmarklet</a>
renders all the music it finds in the page currently displayed.
Once the music is displayed, clicking inside a tune starts playing it
from the beginning.
Clicking on a particular note or rest starts playing from that point.
To print or convert the music to a PDF file,
simply click on the 'Print' button of the web browser.
(If the 'Print' button does not appear on your browser menu,
try right clicking on the web page.)
Alternatively, if your source contains many tunes, you can
use this
<a href="javascript:(function(){var%20s,n=2,d=document,b=d.body;d.head.innerHTML='%3cstyle%3esvg{display:block};@media print{body{margin:0;padding:0;border:0};.nop{display:none}}%3c/style%3e\n';b.innerHTML='%3cscript type=%22text/vnd.abc%22%3e\n'+b.textContent+'%3c/script%3e\n';function%20f(u){s=d.createElement('script');s.src='http://moinejf.free.fr/js/'+u;s.onload=function(){if(--n==0)dom_loaded()};d.head.appendChild(s)};f('abcweb1-1.js');f('snd-1.js')})()"
title="Copy me">second bookmarklet</a>.
The browser will list the titles of the tunes.
Clicking on a title displays the tune.
Playing and printing work in the same manner as above.
The generated pages contain a yellow menu in the top right corner which permits
you to return to the tune list or to modify the music. With this last option,
you can adjust the page size before printing, correct the ABC syntax or
|
| ︙ | ︙ | |||
105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
If your ABC files contain `%%abc-include`, then you must:
- load the ABC file using the browse button,
- click the include file name button,
- and load the include file using the same previous browse button.
Only one included file is allowed.
If you have a US keyboard, its behaviour can be changed for easier music
entering by one of these bookmarklets:
<a href="javascript:(function(){if(typeof%20abc2svg.loadjs=='function'){abc2svg.loadjs('abckbd-1.js')}else{alert('use%20with%20abc2svg%20editor')}})()"
title="Copy me">keyboard 1</a>
and
<a href="javascript:(function(){if(typeof%20abc2svg.loadjs=='function'){abc2svg.loadjs('abckbd2-1.js')}else{alert('use%20with%20abc2svg%20editor')}})()"
| > > > > > > > > > > > > > | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
If your ABC files contain `%%abc-include`, then you must:
- load the ABC file using the browse button,
- click the include file name button,
- and load the include file using the same previous browse button.
Only one included file is allowed.
If you have installed abc2svg in a site of yours, you may put a file
**pref.js** with the abc2svg scripts. This file may contain various
javascript functions and also ABC parameters.
These parameters must be defined inside the following sequence:
if (typeof abc2svg == "undefined")
var abc2svg = {}
if (!abc2svg.a_inc)
abc2svg.a_inc = {}
abc2svg.a_inc["default.abc"] = `
.. put here the ABC parameters ..
`
If you have a US keyboard, its behaviour can be changed for easier music
entering by one of these bookmarklets:
<a href="javascript:(function(){if(typeof%20abc2svg.loadjs=='function'){abc2svg.loadjs('abckbd-1.js')}else{alert('use%20with%20abc2svg%20editor')}})()"
title="Copy me">keyboard 1</a>
and
<a href="javascript:(function(){if(typeof%20abc2svg.loadjs=='function'){abc2svg.loadjs('abckbd2-1.js')}else{alert('use%20with%20abc2svg%20editor')}})()"
|
| ︙ | ︙ | |||
132 133 134 135 136 137 138 | (Note that, in the example, the paths are relative - see why below.) [4]: http://moinejf.free.fr/abcm2ps-doc/tabac.html "J'ai du bon tabac" As it is apparent, HTML and ABC can be mixed in the same html file. Both are rendered in the order you defined them. | | | | | | > | < | | 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
(Note that, in the example, the paths are relative - see why below.)
[4]: http://moinejf.free.fr/abcm2ps-doc/tabac.html "J'ai du bon tabac"
As it is apparent, HTML and ABC can be mixed in the same html file.
Both are rendered in the order you defined them.
You may also have noticed this style about SVG elements:
` svg { display: block }`
It puts the lines of music on vertical areas.
Without this style, the music is in-lined as in [this other example][5].
[5]: http://moinejf.free.fr/abcm2ps-doc/dansou-i.html "Tune index example"
Global ABC parameters may be added as `parameter=value` in the query string
of the URL of the page. The [following example][16] calls the same
"J'ai du bon tabac" with `pagescale=1.2` (giving `%%pagescale 1.2`).
[16]: http://moinejf.free.fr/abcm2ps-doc/tabac.html?pagescale=1.2 "J'ai du bon tabac"
In the above examples, all the ABC music is generated (displayed
and ready to be played) by means of the script **abcweb-1.js**.
If there is a large collection of tunes, it may be preferable to
link to the other script, **abcweb1-1.js**, which offers a tune selection.
Without an explicit
selection (see below), a list of the tunes is displayed, and,
after a tune has been selected, the whole page is replaced by the music.
(The HTML code, if any, is not displayed.)
You can go back to the list of the tunes thanks to the menu
on the top right corner of the screen. Here is [a real example][6].
[6]: http://moinejf.free.fr/abc/boyvin-2-2.html "J. Boyvin organ tunes"
As you may notice in the menu, the edition of the ABC content is proposed.
This permits you, for example, to transpose the tunes.
This edition is done inside the browser, so, your changes will be lost
after leaving the page.
When accessing such pages, an external selection of the tunes
can be accomplished by ending the URL with the character '`#`'
followed by a [regular expression][7]
to be applied to the tune headers.
|
| ︙ | ︙ | |||
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | #### 1.4 Installing abc2svg on your system or on your server The **abc2svg** package on my server is still being tuned which could change its behaviour at any unknown time; so you may prefer to install and run it from your own system. There are many ways to install abc2svg: - [Guido Gonzato's page](http://abcplus.sourceforge.net/#abc2svg) Guido maintains a ZIP archive of the abc2vg scripts after each release of a new version (many thanks, Guido!). You can just download and unzip this archive. **abc2svg** should run immediately in your machine without connecting to my site. In the same page, you can also find some binaries of QuickJS, a fast javascript interpreter (see below). - tarball From the timeline in the [chisel repository][13], you can get a tarball | > > > > > > > > | | < < < < < < | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 | #### 1.4 Installing abc2svg on your system or on your server The **abc2svg** package on my server is still being tuned which could change its behaviour at any unknown time; so you may prefer to install and run it from your own system. There are many ways to install abc2svg: - [tarball][16] or [.zip archive][17] from my site Both files contain the scripts that are generated from the source when abc2svg is stable enough. The scripts are ready to be used from the root directory. [16]: http://moinejf.free.fr/abc2svg.tar.bz2 "tarball" [17]: http://moinejf.free.fr/abc2svg.zip "ZIP file" - [Guido Gonzato's page](http://abcplus.sourceforge.net/#abc2svg) Guido maintains a ZIP archive of the abc2vg scripts after each release of a new version (many thanks, Guido!). You can just download and unzip this archive. **abc2svg** should run immediately in your machine without connecting to my site. In the same page, you can also find some binaries of QuickJS, a fast javascript interpreter (see below). - tarball From the timeline in the [chisel repository][13], you can get a tarball of any version of the abc2svg source and install it in your system. The abc2svg scripts must then be built from the raw source files described in the section 'Build' below. The disadvantage of this approach is that if you want to use an other or newer version you need to download a new tarball. [13]: https://chiselapp.com/user/moinejf/repository/abc2svg/timeline - fossil clone If you can get the fossil program (one binary) for your system, you may clone the chisel repository by ` fossil clone https://chiselapp.com/user/moinejf/repository/abc2svg abc2svg.fossil` ` fossil open abc2svg.fossil` and get the abc2svg source files containing the last changes between the official versions. Updating your files is done by ` fossil pull` ` fossil update` Building the scripts is done in the same way as with a tarball. The repository is presently over 50Mb. For those unfamiliar with [fossil][14], it is an integrated software management system similar to [git](https://git-scm.com/). Chisel acts like a repository similar to [github](https://github.com/). [14]: https://fossil-scm.org/home/doc/trunk/www/index.wiki Using bookmarklets with a local installation does not work directly because of a cross-domain security hole, but this is possible by running a local HTTP server (you will also have to change the location of the scripts in the bookmarklet code). If you have write access on a remote server, you may put there the abc2svg scripts. There is no automatic process to do that. |
| ︙ | ︙ | |||
258 259 260 261 262 263 264 | #### 2.1 abc2svg shell scripts As you have seen, printing the music can be done easily with any web browser. You can automate the process of creating music sheets with **abc2svg** using shell scripts running a Javascript interpreter. | | | | < | 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 | #### 2.1 abc2svg shell scripts As you have seen, printing the music can be done easily with any web browser. You can automate the process of creating music sheets with **abc2svg** using shell scripts running a Javascript interpreter. The interfaces to the various interpreters are different. Below you will find the scripts I had to built. - `abcqjs` with `qjs` [QuickJS by Fabrice Bellard and Charlie Gordon][10] - `abcmjs` with `js78`, `js60`, `js52` or `js24` (Mozilla JavaScript shell) - `abcjsc` with `jsc` (webkit2gtk) - `abcnode` with `node` (nodeJS without module) [10]: https://bellard.org/quickjs/ Each script gets the abc2svg options and ABC files from the command line and sends the generated file to `stdout` and possible errors to `stderr`. The general syntax of the command line is: ` script [script.js] [options] ABC_file [[options] ABC_file]* [options]` |
| ︙ | ︙ | |||
334 335 336 337 338 339 340 | This script just outputs the abc2svg parameters. #### 2.3 PDF generation `abctopdf` is a shell script which converts ABC to PDF using one of the previous shell scripts and, either a chrome/chromium compatible web browser (settable by the environment variable 'BROWSER'), | | < < < < | | < | 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 | This script just outputs the abc2svg parameters. #### 2.3 PDF generation `abctopdf` is a shell script which converts ABC to PDF using one of the previous shell scripts and, either a chrome/chromium compatible web browser (settable by the environment variable 'BROWSER'), or the program [weasyprint](https://weasyprint.org/). Note also that, with `weasyprint`, the paper size is forced to A4. Instructions for changing this size may be found in the script source. The output PDF document may be specified by the command line argument `-o` (default `abc.pdf`). Example: ` abctopdf my_file.abc -o my_file.pdf` |
| ︙ | ︙ | |||
422 423 424 425 426 427 428 | - The music is displayed as SVG images. There is one image per music line / text block. If you want to move these images to some other files, each one must contain the full CSS and defs. For that, insert ` %%fullsvg x` in the ABC file before rendering (see the | | > | | > | | | > > > > > > > > > > > > > | | > > > > > > > > > > > > > > > > > > > > > > | < < < < < < < | 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 |
- The music is displayed as SVG images. There is one image per
music line / text block.
If you want to move these images to some other files,
each one must contain the full CSS and defs. For that, insert
` %%fullsvg x`
in the ABC file before rendering (see the
[fullsvg documentation](http://moinejf.free.fr/abcm2ps-doc/fullsvg.html)
for more information).
- Playing uses the HTML5 audio and/or the midi APIs.
For audio, by default, abc2svg uses a sound font (format SF2)
which is split into one file
per instrument. This sound font is stored in the subdirectory `Scc1t2/`.
Each instrument file is a base64 encoded javascript array.
Other sound fonts may be used. Some of them are stored in the subdirectory
`sf2/` (`AWE_ROM_gm` and `2MBGMGS`). Two formats are supported: raw SF2 and
SF2 wrapped into javascript (the raw SF2 files can be loaded
only when they are in the same HTTP domain).
The shell script `sf.sh` (in `sf2/`) may be used to create the javacript files
from raw SF2 files.
The sound font to be used for playing may be defined in the ABC code
by the command `%%soundfont`. E.g.:
` %%soundfont http://moinejf.free.fr/js/sf2/AWE_ROM_gm.js`
- The names of the abc2svg scripts have a suffix which is the version of
the core interface (actually '`-1`').
#### 4.3 More about the web scripts
Here are the scripts which are used in a web context:
- `abcweb-1.js`
This script replaces the ABC or MEI sequences found in the (X)HTML file
by SVG images of the music.
The ABC sequences are searched:
- first inside <script> elements with a type
["text/vnd.abc"](https://www.iana.org/assignments/media-types/text/vnd.abc)
(the script tag is replaced by a <div>),
- or inside (X)HTML elements with a class `abc` (lower case letters),
- otherwise on `X:` or `%abc-` at start of line up to a XML tag at start of line.
When a ABC sequence is not included in a <script> and when it contains
the characters '<', '>' or '&',
it must be enclosed in a XML comment or in a CDATA
(%<![CDATA[ .. %]]> - the comment or CDATA must be in a ABC comment).
When using <script>, it is possible to set abc2svg parameters via CSS.
For that, the <style> in the HTML <head> may contain custom
properties (properties starting with '--') and these properties are converted
to abc2svg parameters (starting with '%%') before the ABC sequence.
For instance, in the (<head>) <style> element, you can put:
` .parm {--pagewidth:30cm; --bgcolor : yellow}`
and in some <script ..vnd.abc..>, you set the class:
` <script class="parm" type="text/vnd.abc">`
This defines the page width and the background color of the generated music.
See the
[%%beginml documentation](http://moinejf.free.fr/abcm2ps-doc/beginml.html)
for an example, and here is [how to put inline music in HTML][15].
Playing and highlighting the played notes may be offered loading
the script `snd-1.js` (see below).
[15]: http://moinejf.free.fr/abcm2ps-doc/inline.html "abc2svg - inline music"
This script also accepts a parameter `with_source`.
When this parameter is set, the music source is included before the
SVG images of the music. An argument `nohead` prevents displaying
the source of the first music sequence. The music source is displayed
in a <pre> element of class `source`. The SVG's are included
in a <div> of the same class `source`.
The source may be displayed either above (default) or
at the left side of the music (using a style as
`.source{display: inline-block; vertical-align: top}`).
See the source of
[abcm2ps/abc2svg features](http://moinejf.free.fr/abcm2ps-doc/features.html)
for an example.
The music source may be editable.
To change it, the script contains two functions:
- `abc2svg.get_music` returns the source of the music sequence
(in <script> type "text/vnd.abc", class="abc" or inlined ABC)
Its argument is the HTML <div> element that contains the music.
- `abc2svg.set_music` has two arguments, the HTML <div> element
and the new source of the music.
It generates and replaces the music in the <div>.
- `abcweb1-1.js`
The page body is analyzed as a ABC file and its content is
replaced by music as SVG images.
If the page contains reserved XML characters ('<', '>' and '&'),
the ABC code must be enclosed in a
` <script type="text/vnd.abc"> .. </script>`
sequence.
When there are many tunes in the file, the script displays a list
of the tunes. The list step may be bypassed when the URL of the file
contains a regular expression in the 'hash' value ('#' followed by
a string at the end of the URL).
This string does a
[%%select](http://moinejf.free.fr/abcm2ps-doc/select.xhtml).
When one or many tunes are displayed, a menu in the top/right corner
offers to go back to the tune list or to modify the ABC source.
- `snd-1.js`
This script may be used with `abcweb-1.js` or `abcweb1-1.js`
to play the rendered ABC music.
### 5. MEI support
As an experimental feature, an extended core `mei2svg-1.js` may be generated.
This one may handle both the ABC and
[MEI](https://music-encoding.org/ "Music Encoding Initiative")
notations.
|
| ︙ | ︙ |
Deleted abc2svg.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to abc2svg.ttf.
cannot compute difference between binary files
Deleted abcjs24.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted abcjs52.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted abcjs60.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to abcnode.
1 2 3 4 5 6 7 8 9 10 11 12 | :;# abc2svg with raw nodeJS # search where are the abc2svg scripts p=$0 if [ `dirname $p` = . ]; then p=`which $p` fi if [ -L $p ]; then p=`realpath $p` fi p=`dirname $p` | < < < < < < < < < < < < < | < | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
:;# abc2svg with raw nodeJS
# search where are the abc2svg scripts
p=$0
if [ `dirname $p` = . ]; then
p=`which $p`
fi
if [ -L $p ]; then
p=`realpath $p`
fi
p=`dirname $p`
node - "$@" <<EOF
var path='${p}/',
abc2svg = {}
// interpreter specific functions
abc2svg.print = function(str) {
process.stdout.write(str + '\n')
}
abc2svg.printErr = function(str) {
process.stderr.write(str + '\n')
|
| ︙ | ︙ | |||
63 64 65 66 67 68 69 |
if (onerror)
onerror()
else
abc2svg.printErr('Cannot read file ' + fn)
}
}
| < < < < > > > | > > | > > > < < | 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
if (onerror)
onerror()
else
abc2svg.printErr('Cannot read file ' + fn)
}
}
// main
var args = process.argv,
i = '${ABCPATH}'
if (i)
abc2svg.path = i.split(':')
abc2svg.loadjs("abc2svg-1.js")
abc2svg.loadjs("cmdline.js")
global.Abc = Abc
global.abc2svg = abc2svg
global.user = user; // (for modules/page.js)
args.shift() // (remove 'node')
args.shift() // (remove the '-')
abc_cmd("abcnode", args, "nodeJS")
EOF
|
Changes to abctopdf.
| ︙ | ︙ | |||
37 38 39 40 41 42 43 | if [ $bdir != '.' ]; then bdir="$bdir/" else bdir='' fi fi # (sorted from fastest to slowest in ARM machines) | | | | | > < | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | if [ $bdir != '.' ]; then bdir="$bdir/" else bdir='' fi fi # (sorted from fastest to slowest in ARM machines) for c in qjs jsc js78 js60 js52 js24 d8 node end; do if [ $c = 'end' ]; then echo "$0: could not find a javascript interpreter - abort" exit 1 fi if command -v $c >/dev/null 2>&1; then case $c in (qjs) c=abcqjs;; (jsc) c=abcjsc;; (js24) c=abcmjs;; (js52) c=abcmjs;; (js60) c=abcmjs;; (js78) c=abcmjs;; (d8) c=abcv8;; (node) c=abcnode;; esac if command -v $c >/dev/null 2>&1; then abcscr=$c break fi if command -v $bdir$c >/dev/null 2>&1; then |
| ︙ | ︙ |
Changes to build.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
:;# simple build of abc2svg as a shell script
MAJOR=1
# use jsmin if available
if command -v jsmin >/dev/null 2>&1; then
# binary program
gen() {
cat "$@" | jsmin
}
elif command -v qjs >/dev/null 2>&1; then
# script using QuickJS
if [ ! -f jsmin-min.js ] || [ jsmin-min.js -ot jsmin.js ]; then
qjs --std jsmin.js < jsmin.js > jsmin-min.js
fi
gen() {
cat "$@" | qjs --std jsmin-min.js
}
else
# no minify
gen() {
cat "$@"
}
fi
out=abc2svg-$MAJOR.js
| > | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
:;# simple build of abc2svg as a shell script
MAJOR=1
# use jsmin if available
if command -v jsmin >/dev/null 2>&1; then
# binary program
gen() {
cat "$@" | jsmin
echo ""
}
elif command -v qjs >/dev/null 2>&1; then
# script using QuickJS
if [ ! -f jsmin-min.js ] || [ jsmin-min.js -ot jsmin.js ]; then
qjs --std jsmin.js < jsmin.js > jsmin-min.js
fi
gen() {
cat "$@" | qjs --std jsmin-min.js
}
else
# no minify
gen() {
cat "$@"
}
fi
out=abc2svg-$MAJOR.js
VERSION='??????'
DATE=`date -Idate`
cp core/license $out
gen core/abc2svg.js core/deco.js core/draw.js\
font.js core/format.js core/front.js core/music.js core/parse.js core/subs.js\
core/svg.js core/tune.js core/lyrics.js core/gchord.js core/tail.js\
core/modules.js >> $out
echo "abc2svg.version=\"$VERSION\";abc2svg.vdate=\"$DATE\"" >> $out
|
| ︙ | ︙ | |||
64 65 66 67 68 69 70 71 72 73 74 | gen modules/perc.js > perc-$MAJOR.js gen modules/wps.js modules/psvg.js > psvg-$MAJOR.js gen modules/roman.js > roman-$MAJOR.js gen modules/soloffs.js > soloffs-$MAJOR.js gen modules/sth.js > sth-$MAJOR.js gen modules/strtab.js > strtab-$MAJOR.js gen modules/temper.js > temper-$MAJOR.js cp editor/edit.css edit-$MAJOR.css gen util/abcdoc.js > abcdoc-$MAJOR.js | > < < < < < < < < < | | < < | 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | gen modules/perc.js > perc-$MAJOR.js gen modules/wps.js modules/psvg.js > psvg-$MAJOR.js gen modules/roman.js > roman-$MAJOR.js gen modules/soloffs.js > soloffs-$MAJOR.js gen modules/sth.js > sth-$MAJOR.js gen modules/strtab.js > strtab-$MAJOR.js gen modules/temper.js > temper-$MAJOR.js gen modules/tropt.js > tropt-$MAJOR.js cp editor/edit.css edit-$MAJOR.css gen util/abcdoc.js > abcdoc-$MAJOR.js gen util/abcweb.js > abcweb-$MAJOR.js gen util/abcweb1.js > abcweb1-$MAJOR.js gen util/play.js util/sndgen.js util/sndaud.js util/sf2-parser.js\ util/sndmid.js util/follow.js util/chord.js > snd-$MAJOR.js sed "s+@MAJOR@+$MAJOR+" editor/edit.xhtml > edit-$MAJOR.xhtml sed "s+@MAJOR@+$MAJOR+" editor/abckbd.js > abckbd-$MAJOR.js sed "s+@MAJOR@+$MAJOR+" editor/abckbd2.js > abckbd2-$MAJOR.js sed "s+@MAJOR@+$MAJOR+" editor/edit.js > edit-$MAJOR.js |
Changes to build.ninja.
1 2 3 4 5 6 7 | # rules for ninja (ninja-build) or samurai # minifying with 'jsmin' or 'uglifyjs' may be disabled by running # NOMIN=1 ninja -v MAJOR=1 | < < < < | | < < < | < > < > > > > > | > | > > | > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# rules for ninja (ninja-build) or samurai
# minifying with 'jsmin' or 'uglifyjs' may be disabled by running
# NOMIN=1 ninja -v
MAJOR=1
rule cp
command = cp $in $out
rule cpm
command = sed "s+@MAJOR@+$MAJOR+" $in > $out
rule font
command = fontforge -c 'open("font/abc2svg.sfd").generate("abc2svg.ttf")';$
fontforge -c 'open("font/abc2svg.sfd").generate("abc2svg.woff")';$
echo '// abc2svg music font' > font.js;$
echo "var musicfont = 'url(\"data:application/octet-stream;base64,\\" >> font.js;$
base64 abc2svg.ttf | sed 's/$$/\\/' >> font.js;$
echo "\") format(\"truetype\")'" >> font.js
rule jsc
command = if [ -e .fslckout ] && command -v fossil >/dev/null 2>&1; then $
v=`fossil describe`;$
d=`date -Idate`;$
v="abc2svg.version=\"$$v\";abc2svg.vdate=\"$$d\"";$
else $
v=`grep abc2svg.version $out`;$
fi;$
cp core/license $out;$
if [ "x$$NOMIN" = "x" ]; then $
if command -v jsmin >/dev/null 2>&1; then $
cat $in | jsmin >> $out;$
echo "" >> $out;$
else $
if command -v qjs >/dev/null 2>&1; then $
cat $in | ./jsmin >> $out;$
else $
cat $in | uglifyjs >> $out;$
fi;$
fi;$
else $
cat $in >> $out;$
fi;$
echo $$v >> $out
rule jscu
command = cp core/license $out;$
if [ "x$$NOMIN" = "x" ]; then $
if command -v jsmin >/dev/null 2>&1; then $
cat $in | jsmin >> $out;$
echo "" >> $out;$
else $
if command -v qjs >/dev/null 2>&1; then $
cat $in | ./jsmin >> $out;$
else $
cat $in | uglifyjs >> $out;$
fi;$
fi;$
else $
cat $in >> $out;$
fi
rule edit
command = if [ "x$$NOMIN" = "x" ]; then $
|
| ︙ | ︙ | |||
85 86 87 88 89 90 91 | build font: font | font/abc2svg.sfd build sf: sf | Scc1t2/ build abc2svg-$MAJOR.js: jsc core/abc2svg.js core/deco.js core/draw.js $ font.js core/format.js core/front.js core/music.js core/parse.js core/subs.js $ core/svg.js core/tune.js core/lyrics.js core/gchord.js core/tail.js $ | | > | 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | build font: font | font/abc2svg.sfd build sf: sf | Scc1t2/ build abc2svg-$MAJOR.js: jsc core/abc2svg.js core/deco.js core/draw.js $ font.js core/format.js core/front.js core/music.js core/parse.js core/subs.js $ core/svg.js core/tune.js core/lyrics.js core/gchord.js core/tail.js $ core/modules.js #| package.json build mei2svg-$MAJOR.js: jsc core/abc2svg.js core/deco.js core/draw.js $ font.js core/format.js core/front.js core/music.js core/parse.js core/subs.js $ core/svg.js core/tune.js core/lyrics.js core/gchord.js core/mei.js core/tail.js $ core/modules.js | package.json build ambitus-$MAJOR.js: jscu modules/ambitus.js build break-$MAJOR.js: jscu modules/break.js |
| ︙ | ︙ | |||
118 119 120 121 122 123 124 125 126 127 128 | build perc-$MAJOR.js: jscu modules/perc.js build psvg-$MAJOR.js: jscu modules/wps.js modules/psvg.js build roman-$MAJOR.js: jscu modules/roman.js build soloffs-$MAJOR.js: jscu modules/soloffs.js build sth-$MAJOR.js: jscu modules/sth.js build strtab-$MAJOR.js: jscu modules/strtab.js build temper-$MAJOR.js: jscu modules/temper.js build edit-$MAJOR.css: cp editor/edit.css build abcdoc-$MAJOR.js: jscu util/abcdoc.js | > < < < < < < < < | | < | | | | | | | | > > > | > > > > | > > > > > > > > > > > | < < < < < | 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
build perc-$MAJOR.js: jscu modules/perc.js
build psvg-$MAJOR.js: jscu modules/wps.js modules/psvg.js
build roman-$MAJOR.js: jscu modules/roman.js
build soloffs-$MAJOR.js: jscu modules/soloffs.js
build sth-$MAJOR.js: jscu modules/sth.js
build strtab-$MAJOR.js: jscu modules/strtab.js
build temper-$MAJOR.js: jscu modules/temper.js
build tropt-$MAJOR.js: jscu modules/tropt.js
build edit-$MAJOR.css: cp editor/edit.css
build abcdoc-$MAJOR.js: jscu util/abcdoc.js
build abcweb-$MAJOR.js: jscu util/abcweb.js
build abcweb1-$MAJOR.js: jscu util/abcweb1.js
build json-$MAJOR.js: jscu util/json.js
build snd-$MAJOR.js: jscu util/play.js util/sndgen.js util/sndaud.js $
util/sf2-parser.js util/sndmid.js util/follow.js util/chord.js
build edit-$MAJOR.xhtml: cpm editor/edit.xhtml
build abckbd-$MAJOR.js: edit editor/abckbd.js
build abckbd2-$MAJOR.js: edit editor/abckbd2.js
build edit-$MAJOR.js: edit editor/edit.js
build all: phony abc2svg-$MAJOR.js abcdoc-$MAJOR.js $
abcweb-$MAJOR.js abcweb1-$MAJOR.js $
snd-$MAJOR.js psvg-$MAJOR.js $
ambitus-$MAJOR.js break-$MAJOR.js capo-$MAJOR.js $
chordnames-$MAJOR.js clair-$MAJOR.js clip-$MAJOR.js $
combine-$MAJOR.js diag-$MAJOR.js equalbars-$MAJOR.js gamelan-$MAJOR.js $
grid-$MAJOR.js grid2-$MAJOR.js grid3-$MAJOR.js jianpu-$MAJOR.js $
jazzchord-$MAJOR.js mdnn-$MAJOR.js MIDI-$MAJOR.js $
nns-$MAJOR.js page-$MAJOR.js pedline-$MAJOR.js perc-$MAJOR.js psvg-$MAJOR.js $
roman-$MAJOR.js soloffs-$MAJOR.js sth-$MAJOR.js strtab-$MAJOR.js $
temper-$MAJOR.js tropt-$MAJOR.js edit-$MAJOR.css edit-$MAJOR.js edit-$MAJOR.xhtml $
abckbd-$MAJOR.js abckbd2-$MAJOR.js
# not mei2svg-$MAJOR.js
default all
# fossil new release
rule version
command = v=`fossil changes|wc -l`;$
if [ $$v -ne 0 ]; then $
echo "!! There are changes !!";$
exit 1;$
fi;$
v=`fossil describe`;$
if [ "$$out"="patch" ]; then $
v=`echo $$v|awk -F. -v OFS=. '{$$3 += 1; print}'`;$
else $
v=`echo $$v|awk -F. -v OFS=. '{$$2 += 1; $$3=0; print}'`;$
fi;$
fossil commit --allow-empty -m "New release $$v" -tag $$v;$
n=`tail -1 abc2svg-1.js|wc -c`;$
truncate -s -$$n abc2svg-1.js;$
d=`date -Idate`;$
echo "abc2svg.version=\"$$v\";abc2svg.vdate=\"$$d\"" >> abc2svg-1.js;$
r="abc2svg-$$v";$
ln -s . $$r;$
sed "s#^#$$r/#" dist_bin | pax -wj -x tar -f abc2svg.tar.bz2;$
rm -f abc2svg.zip;$
sed "s#^#$$r/#" dist_bin | zip -r abc2svg.zip -@;$
rm $$r;$
echo "Don't forget to upload abc2svg.tar.bz2 and abc2svg.zip"
build minor: version
build patch: version
|
Changes to core/abc2svg.js.
1 2 | // abc2svg - abc2svg.js // | | | 1 2 3 4 5 6 7 8 9 10 | // abc2svg - abc2svg.js // // Copyright (C) 2014-2022 Jean-Francois Moine // // This file is part of abc2svg-core. // // abc2svg-core is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
abc2svg.C = {
BLEN: 1536,
// symbol types
BAR: 0,
CLEF: 1,
CUSTOS: 2,
GRACE: 4,
KEY: 5,
METER: 6,
MREST: 7,
NOTE: 8,
PART: 9,
REST: 10,
| > | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
abc2svg.C = {
BLEN: 1536,
// symbol types
BAR: 0,
CLEF: 1,
CUSTOS: 2,
SM: 3, // sequence marker (transient)
GRACE: 4,
KEY: 5,
METER: 6,
MREST: 7,
NOTE: 8,
PART: 9,
REST: 10,
|
| ︙ | ︙ | |||
59 60 61 62 63 64 65 |
SL_ALI_MSK: 0x70, // align
SL_ALIGN: 0x10,
SL_CENTER: 0x20,
SL_CLOSE: 0x40
};
// !! tied to the symbol types in abc2svg.js !!
| | | 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
SL_ALI_MSK: 0x70, // align
SL_ALIGN: 0x10,
SL_CENTER: 0x20,
SL_CLOSE: 0x40
};
// !! tied to the symbol types in abc2svg.js !!
abc2svg.sym_name = ['bar', 'clef', 'custos', 'smark', 'grace',
'key', 'meter', 'Zrest', 'note', 'part',
'rest', 'yspace', 'staves', 'Break', 'tempo',
'', 'block', 'remark']
// key table - index = number of accidentals + 7
abc2svg.keys = [
new Int8Array([-1,-1,-1,-1,-1,-1,-1 ]), // 7 flat signs
|
| ︙ | ︙ | |||
96 97 98 99 100 101 102 | // C D [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, // E F G 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, // A B 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6 ]) abc2svg.b40_a = new Int8Array( // base-40 to accidental | | | | | | | | | 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | // C D [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, // E F G 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, // A B 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6 ]) abc2svg.b40_a = new Int8Array( // base-40 to accidental // C D [-2, -1, 0, 1, 2, -3, -2, -1, 0, 1, 2, -3, // E F G -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -3, -2, -1, 0, 1, 2, -3, // A B -2, -1, 0, 1, 2, -3, -2, -1, 0, 1, 2 ]) abc2svg.b40_m = new Int8Array( // base-40 to midi // C D [-2, -1, 0, 1, 2, 0, 0, 1, 2, 3, 4, 0, // E F G 2, 3, 4, 5, 6, 3, 4, 5, 6, 7, 0, 5, 6, 7, 8, 9, 0, // A B 7, 8, 9, 10, 11, 0, 9, 10, 11, 12, 13 ]) abc2svg.b40k = new Int8Array( // base-40 interval to possible transposition // C D [36, 1, 2, 3, 8, 2, 2, 7, 8,13,14, 2, // 37 // E F G 8,13,14,19,20,13,14,19,20,25, 2,19,24,25,30,31, 2, // 20 // A B 25,30,31,36,37, 2,31,36,37, 2, 3 ]) // 2 abc2svg.b40sf = new Int8Array( // base-40 interval to key signature // C D [-2,-7, 0, 7, 2, 88, 0,-5, 2,-3, 4, 88, // E F G 2,-3, 4,-1, 6,-3, 4,-1, 6, 1,88,-1,-6, 1,-4, 3,88, // A B |
| ︙ | ︙ | |||
174 175 176 177 178 179 180 | "aug7": "+7", "7+5": "+7", "7#5": "+7", "sus": "sus4", "7sus": "7sus4" } // ch_alias | < < < < < < < < < < < < < < < < < | 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
"aug7": "+7",
"7+5": "+7",
"7#5": "+7",
"sus": "sus4",
"7sus": "7sus4"
} // ch_alias
// font weight
// reference:
// https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight
abc2svg.ft_w = {
thin: 100,
extralight: 200,
light: 300,
|
| ︙ | ︙ |
Changes to core/deco.js.
| ︙ | ︙ | |||
71 72 73 74 75 76 77 | gmark: "3 grm 6 5 5", wedge: "0 wedge 8 3 3", // (staccatissimo or spiccato) longphrase: "3 lphr 0 1 1", mediumphrase: "3 mphr 0 1 1", shortphrase: "3 sphr 0 1 1", turnx: "3 turnx 5,5 6 6", invertedturn: "3 turn 5,5 6 6", | < | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | gmark: "3 grm 6 5 5", wedge: "0 wedge 8 3 3", // (staccatissimo or spiccato) longphrase: "3 lphr 0 1 1", mediumphrase: "3 mphr 0 1 1", shortphrase: "3 sphr 0 1 1", turnx: "3 turnx 5,5 6 6", invertedturn: "3 turn 5,5 6 6", "0": "3 fng 5,5 3 3 0", "1": "3 fng 5,5 3 3 1", "2": "3 fng 5,5 3 3 2", "3": "3 fng 5,5 3 3 3", "4": "3 fng 5,5 3 3 4", "5": "3 fng 5,5 3 3 5", plus: "3 dplus 7 3 3", |
| ︙ | ︙ | |||
112 113 114 115 116 117 118 | dacoda: "5 dacs 16 20 20 Da Coda", "D.C.": "5 dcap 16 10 10", "D.S.": "5 dsgn 16 10 10", "D.C.alcoda": "5 dacs 16 38 38 D.C. al Coda", "D.S.alcoda": "5 dacs 16 38 38 D.S. al Coda", "D.C.alfine": "5 dacs 16 38 38 D.C. al Fine", "D.S.alfine": "5 dacs 16 38 38 D.S. al Fine", | | | | | | | | 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
dacoda: "5 dacs 16 20 20 Da Coda",
"D.C.": "5 dcap 16 10 10",
"D.S.": "5 dsgn 16 10 10",
"D.C.alcoda": "5 dacs 16 38 38 D.C. al Coda",
"D.S.alcoda": "5 dacs 16 38 38 D.S. al Coda",
"D.C.alfine": "5 dacs 16 38 38 D.C. al Fine",
"D.S.alfine": "5 dacs 16 38 38 D.S. al Fine",
fermata: "3 hld 12 7 7",
fine: "5 dacs 16 10 10 Fine",
invertedfermata: "4 hld 12 7 7",
segno: "5 sgno 22 8 8",
f: "6 f 18 4 4",
ff: "6 ff 18 6 6",
fff: "6 fff 18 9 9",
ffff: "6 ffff 18 12 12",
mf: "6 mf 18 9 9",
mp: "6 mp 18 10 10",
p: "6 p 18 5 5",
pp: "6 pp 18 9 9",
ppp: "6 ppp 18 13 13",
pppp: "6 pppp 18 17 17",
pralltriller: "3 umrd 4,4 5 5",
sfz: "6 sfz 18 8 8",
ped: "7 ped 18 6 10",
"ped-up": "7 pedoff 12 4 4",
"ped(": "7 lped 20 5 5",
"ped)": "7 lped 20 5 5",
"crescendo(": "6 cresc 18 0 0",
"crescendo)": "6 cresc 18 0 0",
"<(": "6 cresc 18 0 0",
"<)": "6 cresc 18 0 0",
"diminuendo(": "6 dim 18 0 0",
"diminuendo)": "6 dim 18 0 0",
">(": "6 dim 18 0 0",
|
| ︙ | ︙ | |||
262 263 264 265 266 267 268 |
function up3(s, pos) {
switch (pos & 0x07) {
case C.SL_ABOVE:
return 1 // true
case C.SL_BELOW:
return 0 // false
}
| | | | > | 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 |
function up3(s, pos) {
switch (pos & 0x07) {
case C.SL_ABOVE:
return 1 // true
case C.SL_BELOW:
return 0 // false
}
// if (s.multi)
// return s.multi > 0
// return 1 // true
return !s.second
} // up3()
// - of the dynamic and volume marks
function up6(s, pos) {
switch (pos & 0x07) {
case C.SL_ABOVE:
return true
|
| ︙ | ︙ | |||
435 436 437 438 439 440 441 | else if (dd.ty == '_') up = 0 else if (s.multi) up = s.multi > 0 else up = s.stem < 0 y = up ? s.ymx : s.ymn | | | | > > > > > > > > > | 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 |
else if (dd.ty == '_')
up = 0
else if (s.multi)
up = s.multi > 0
else
up = s.stem < 0
y = up ? s.ymx : s.ymn
if (y > 0 && y < 24) {
y = (((y + 9) / 6) | 0) * 6 - 6 // between lines
}
if (up) {
y += dd.hd
s.ymx = y + dd.h
} else if (dd.name[0] == 'w') { // wedge (no descent)
de.inv = true
y -= dd.h
s.ymn = y
} else {
y -= dd.h
s.ymn = y - dd.hd
}
de.y = y
if (s.type == C.NOTE)
de.x += s.notes[s.stem >= 0 ? 0 : s.nhd].shhd
if (dd.name[0] == 'd') { // if dot (staccato)
if (!(s.beam_st && s.beam_end)) { // if in a beam sequence
if (up) {
if (s.stem > 0)
de.x += 3.5 // stem_xoff
} else {
if (s.stem < 0)
de.x -= 3.5
}
} else {
if (up && s.stem > 0) {
y = s.y + (y - s.y) * .6
if (y >= 27) {
de.y = y // put the dot a bit lower
s.ymx = de.y + dd.h
}
}
}
}
}
/* 6: dynamic marks */
function d_pf(de) {
var dd2, x2, x, up,
s = de.s,
|
| ︙ | ︙ | |||
505 506 507 508 509 510 511 | if (x2 > x) x = x2 } } } de.x = x; | | | 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 | if (x2 > x) x = x2 } } } de.x = x; de.y = y_get(s.st, up, x - dd.wl, de.val) if (!up) de.y -= dd.h else de.y += dd.hd /* (y_set is done later in draw_deco_staff) */ } |
| ︙ | ︙ | |||
721 722 723 724 725 726 727 | || dd.glyph == "accent" || dd.glyph == "roll") de.inv = 1 s.ymn = y - dd.hd } } | < < | 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 | || dd.glyph == "accent" || dd.glyph == "roll") de.inv = 1 s.ymn = y - dd.hd } } if (y >= stafft) y_set(s.st, 1, x - dd.wl, w, y + dd.h) else if (y <= staffb) y_set(s.st, 0, x - dd.wl, w, y - dd.hd) de.x = x; de.y = y } // add a decoration /* syntax: |
| ︙ | ︙ | |||
897 898 899 900 901 902 903 |
if (dd)
return dd
if ("<>^_@".indexOf(nm[0]) >= 0 // if position
&& !/^([>^]|[<>]\d?[()])$/.test(nm)) {
ty = nm[0]
if (ty == '@') {
p = nm.match(/@([-\d]+),([-\d]+)/)
| | < < < | > > | 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 |
if (dd)
return dd
if ("<>^_@".indexOf(nm[0]) >= 0 // if position
&& !/^([>^]|[<>]\d?[()])$/.test(nm)) {
ty = nm[0]
if (ty == '@') {
p = nm.match(/@([-\d]+),([-\d]+)/)
if (p)
ty = p[0]
else
ty = '' // accept decorations starting with '@'
}
dd = deco_def(nm, nm.replace(ty, ''))
} else {
dd = deco_def(nm)
}
if (!dd)
return
|
| ︙ | ︙ | |||
1469 1470 1471 1472 1473 1474 1475 |
ix: a_de.length,
defl: {},
x: x,
y: y,
pos: pos
// dy: 0
}
| | | 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 |
ix: a_de.length,
defl: {},
x: x,
y: y,
pos: pos
// dy: 0
}
if (dd.name.indexOf("inverted") >= 0)
de.inv = 1
if (s.type == C.BAR && !dd.ty)
de.x -= s.wl / 2 - 2
a_de.push(de)
if (dd.dd_en) {
de.ldst = true
} else if (dd.dd_st) {
|
| ︙ | ︙ | |||
1549 1550 1551 1552 1553 1554 1555 |
create_dh(s, m)
}
}
} // create_all()
// link the long decorations
function ll_deco() {
| | | 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 |
create_dh(s, m)
}
}
} // create_all()
// link the long decorations
function ll_deco() {
var i, j, de, de2, de3, dd, dd2, v, s, st,
n_de = a_de.length
// add ending decorations
for (i = 0; i < n_de; i++) {
de = a_de[i]
if (!de.ldst) // not the start of long decoration
continue
|
| ︙ | ︙ | |||
1599 1600 1601 1602 1603 1604 1605 | if (de.m != undefined) de2.m = de.m; a_de.push(de2) } de2.start = de; de2.defl.nost = de.defl.nost | | | | > > | | < > | | > > > | 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 |
if (de.m != undefined)
de2.m = de.m;
a_de.push(de2)
}
de2.start = de;
de2.defl.nost = de.defl.nost
// handle same decoration ending at a same time
j = i
while (--j >= 0) {
de3 = a_de[j]
if (!de3.start)
continue
if (de3.s.time < s.time)
break
if (de3.dd.name == de2.dd.name) {
de2.prev = de3
break
}
}
}
// add starting decorations
for (i = 0; i < n_de; i++) {
de2 = a_de[i]
if (!de2.lden // not the end of long decoration
|| de2.start) // start already found
|
| ︙ | ︙ | |||
1699 1700 1701 1702 1703 1704 1705 |
nd = a_de.length
/* draw the repeat brackets */
function draw_repbra(p_voice) {
var s, s1, x, y, y2, i, p, w, wh, first_repeat;
// search the max y offset of the line
| | | 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 |
nd = a_de.length
/* draw the repeat brackets */
function draw_repbra(p_voice) {
var s, s1, x, y, y2, i, p, w, wh, first_repeat;
// search the max y offset of the line
y = staff_tb[p_voice.st].topbar + 15 // 10 (vert bar) + 5 (room)
for (s = p_voice.sym; s; s = s.next) {
if (s.type != C.BAR)
continue
if (!s.rbstart || s.norepbra)
continue
/*fixme: line cut on repeat!*/
if (!s.next)
|
| ︙ | ︙ | |||
1726 1727 1728 1729 1730 1731 1732 |
}
y2 = y_get(p_voice.st, true, s1.x, s.x - s1.x) + 2
if (y < y2)
y = y2
// have room for the vertical lines and the repeat numbers
if (s1.rbstart == 2) {
| | | | 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 |
}
y2 = y_get(p_voice.st, true, s1.x, s.x - s1.x) + 2
if (y < y2)
y = y2
// have room for the vertical lines and the repeat numbers
if (s1.rbstart == 2) {
y2 = y_get(p_voice.st, true, s1.x, 3) + 10
if (y < y2)
y = y2
}
if (s.rbstop == 2) {
y2 = y_get(p_voice.st, true, s.x - 3, 3) + 10
if (y < y2)
y = y2
}
if (s1.text) {
wh = strwh(s1.text);
y2 = y_get(p_voice.st, true, s1.x + 4, wh[0]) +
wh[1]
|
| ︙ | ︙ | |||
1788 1789 1790 1791 1792 1793 1794 |
w = 12
else if (s.bar_type[0] != ':')
// || s.bar_type == "]")
w = 0 /* explicit repeat end */
else
w = 8
} else {
| | | | | | | 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 |
w = 12
else if (s.bar_type[0] != ':')
// || s.bar_type == "]")
w = 0 /* explicit repeat end */
else
w = 8
} else {
w = (s.rbstop && !s.rbstart) ? 0 : 8
}
w = (s.x - x - w) // / staff_tb[p_voice.st].staffscale;
if (!s.next // 2nd ending at end of line
&& !s.rbstop
&& !p_voice.bar_start) { // continue on next line
p_voice.bar_start = _bar(s)
p_voice.bar_start.bar_type = ""
p_voice.bar_start.rbstart = 1
}
if (s1.text)
xy_str(x + 4, y2 - gene.curfont.size,
s1.text);
xypath(x, y2);
if (s1.rbstart == 2)
output += 'm0 10v-10';
output+= 'h' + w.toFixed(1)
if (s.rbstop == 2)
output += 'v10';
output += '"/>\n';
y_set(s1.st, true, x, w, y + 2)
if (s.rbstart)
s = s.prev.prev
}
} // draw_repbra()
/* create the decorations tied to the staves */
for (i = 0; i <= nstaff; i++)
minmax[i] = {
ymin: 0,
|
| ︙ | ︙ | |||
1877 1878 1879 1880 1881 1882 1883 |
}
draw_all_chsy() // draw all chord symbols
/* draw the repeat brackets */
for (v = 0; v < voice_tb.length; v++) {
p_voice = voice_tb[v]
| | | 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 |
}
draw_all_chsy() // draw all chord symbols
/* draw the repeat brackets */
for (v = 0; v < voice_tb.length; v++) {
p_voice = voice_tb[v]
if (p_voice.second || !p_voice.sym || p_voice.ignore)
continue
draw_repbra(p_voice)
}
}
/* -- draw the measure bar numbers -- */
/* (scaled delayed output) */
|
| ︙ | ︙ | |||
1915 1916 1917 1918 1919 1920 1921 |
bar_num = gene.nbar
if (bar_num > 1) {
if (cfmt.measurenb == 0) {
any_nb = true;
y = y_get(st, true, 0, 20)
if (y < staff_tb[st].topbar + 14)
y = staff_tb[st].topbar + 14;
| | | 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 |
bar_num = gene.nbar
if (bar_num > 1) {
if (cfmt.measurenb == 0) {
any_nb = true;
y = y_get(st, true, 0, 20)
if (y < staff_tb[st].topbar + 14)
y = staff_tb[st].topbar + 14;
xy_str(0, y - gene.curfont.size * .2, bar_num.toString())
y_set(st, true, 0, 20, y + gene.curfont.size + 2)
} else if (bar_num % cfmt.measurenb == 0) {
for ( ; ; s = s.ts_next) {
switch (s.type) {
case C.CLEF:
case C.KEY:
case C.METER:
|
| ︙ | ︙ | |||
1937 1938 1939 1940 1941 1942 1943 |
if (s.type != C.BAR || !s.bar_num) {
any_nb = true;
w = w0
if (bar_num >= 10)
w *= bar_num >= 100 ? 3 : 2
if (gene.curfont.pad)
w += gene.curfont.pad * 2
| | | | | | 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 |
if (s.type != C.BAR || !s.bar_num) {
any_nb = true;
w = w0
if (bar_num >= 10)
w *= bar_num >= 100 ? 3 : 2
if (gene.curfont.pad)
w += gene.curfont.pad * 2
x = s.x - s.wl - w
y = y_get(st, true, x, w) + 5
if (y < staff_tb[st].topbar + 6)
y = staff_tb[st].topbar + 6;
y += gene.curfont.pad
xy_str(x, y - gene.curfont.size * .2, bar_num.toString())
y += gene.curfont.size + gene.curfont.pad
y_set(st, true, x, w, y);
// s.ymx = y
}
}
}
|
| ︙ | ︙ | |||
1995 1996 1997 1998 1999 2000 2001 |
y = s.next.ys - gene.curfont.size
} else {
if (y < s.next.y)
y = s.next.y
}
}
y += 2 + gene.curfont.pad
| | | 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 |
y = s.next.ys - gene.curfont.size
} else {
if (y < s.next.y)
y = s.next.y
}
}
y += 2 + gene.curfont.pad
xy_str(x, y - gene.curfont.size * .2, bar_num.toString())
y += gene.curfont.size + gene.curfont.pad
y_set(st, true, x, w, y);
// s.ymx = y
}
gene.nbar = bar_num
if (font_size)
|
| ︙ | ︙ | |||
2061 2062 2063 2064 2065 2066 2067 | s.ymn = (dosh & 1) ? h : y; s.ymx = s.ymn + 14; anno_start(s) } writempo(s, s.x - 16, (dosh & 1) ? h : y); anno_stop(s); dosh >>= 1 | < < | 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 |
s.ymn = (dosh & 1) ? h : y;
s.ymx = s.ymn + 14;
anno_start(s)
}
writempo(s, s.x - 16, (dosh & 1) ? h : y);
anno_stop(s);
dosh >>= 1
}
}
/* then, put the parts */
/*fixme: should reduce vertical space if parts don't overlap tempo...*/
ymin = staff_tb[st].topbar + 6
for (s = tsfirst; s; s = s.ts_next) {
|
| ︙ | ︙ | |||
2106 2107 2108 2109 2110 2111 2112 | s2.v = s.v s2.st = s2.wl = 0 s2.wr = strwh(s2.text)[0] s2.ymn = -ht s2.ymx = s2.ymn + h anno_start(s2) } | | | 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 | s2.v = s.v s2.st = s2.wl = 0 s2.wr = strwh(s2.text)[0] s2.ymn = -ht s2.ymx = s2.ymn + h anno_start(s2) } xy_str(s2.x, 2 - ht + gene.curfont.size * .22, s2.text) anno_stop(s2) } } return dy /= staff_tb[0].staffscale } |
Changes to core/draw.js.
1 2 | // abc2svg - draw.js - draw functions // | | | 1 2 3 4 5 6 7 8 9 10 | // abc2svg - draw.js - draw functions // // Copyright (C) 2014-2023 Jean-Francois Moine // // This file is part of abc2svg-core. // // abc2svg-core is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
25 26 27 28 29 30 31 | STEM_CH_MIN = 14, /* min stem height for chords under beams */ STEM_CH_MIN2 = 10, /* ... for notes with two beams */ STEM_CH_MIN3 = 9, /* ... for notes with three beams */ STEM_CH_MIN4 = 9, /* ... for notes with four beams */ BEAM_DEPTH = 3.2, /* width of a beam stroke */ BEAM_OFFSET = .25, /* pos of flat beam relative to staff line */ BEAM_SHIFT = 5, /* shift of second and third beams */ | | | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
STEM_CH_MIN = 14, /* min stem height for chords under beams */
STEM_CH_MIN2 = 10, /* ... for notes with two beams */
STEM_CH_MIN3 = 9, /* ... for notes with three beams */
STEM_CH_MIN4 = 9, /* ... for notes with four beams */
BEAM_DEPTH = 3.2, /* width of a beam stroke */
BEAM_OFFSET = .25, /* pos of flat beam relative to staff line */
BEAM_SHIFT = 5, /* shift of second and third beams */
BEAM_STUB = 7, /* length of stub for flag under beam */
SLUR_SLOPE = .5, /* max slope of a slur */
GSTEM = 15, /* grace note stem length */
GSTEM_XOFF = 2.3 /* x offset for grace note stem */
var cache,
anno_a = [] // symbols with annotations
|
| ︙ | ︙ | |||
241 242 243 244 245 246 247 |
/* have room for the symbols in the staff */
max_stem_err = 0; /* check stem lengths */
s = s1
if (two_dir) { /* 2 directions */
/*fixme: more to do*/
ys = ((s1.grace ? 3.5 : BEAM_SHIFT) * (nflags - 1) +
BEAM_DEPTH) * .5
| > > | | 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
/* have room for the symbols in the staff */
max_stem_err = 0; /* check stem lengths */
s = s1
if (two_dir) { /* 2 directions */
/*fixme: more to do*/
ys = ((s1.grace ? 3.5 : BEAM_SHIFT) * (nflags - 1) +
BEAM_DEPTH) * .5
if (s1.nflags == s2.nflags)
;
else if (s1.stem != s2.stem && s1.nflags < s2.nflags)
b += ys * s2.stem
else
b += ys * s1.stem
} else if (!s1.grace) { /* normal notes */
var beam_h = BEAM_DEPTH + BEAM_SHIFT * (nflags - 1)
//--fixme: added for abc2svg
while (s.ts_prev
|
| ︙ | ︙ | |||
339 340 341 342 343 344 345 346 347 348 349 350 351 352 |
/* have room for the gracenotes, bars and clefs */
/*fixme: test*/
if (!two_staves && !two_dir)
for (s = s1.next; ; s = s.next) {
switch (s.type) {
case C.REST: /* cannot move rests in multi-voices */
g = s.ts_next
if (!g || g.st != st
|| (g.type != C.NOTE && g.type != C.REST))
break
//fixme:too much vertical shift if some space above the note
//fixme:this does not fix rest under beam in second voice (ts_prev)
/*fall thru*/
| > > | 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 |
/* have room for the gracenotes, bars and clefs */
/*fixme: test*/
if (!two_staves && !two_dir)
for (s = s1.next; ; s = s.next) {
switch (s.type) {
case C.REST: /* cannot move rests in multi-voices */
if (!s.multi)
break
g = s.ts_next
if (!g || g.st != st
|| (g.type != C.NOTE && g.type != C.REST))
break
//fixme:too much vertical shift if some space above the note
//fixme:this does not fix rest under beam in second voice (ts_prev)
/*fall thru*/
|
| ︙ | ︙ | |||
452 453 454 455 456 457 458 |
bm.nflags = nflags
return true
}
/* -- draw the beams for one word -- */
/* (the staves are defined) */
function draw_beams(bm) {
| | > > > > > | | > | | 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 |
bm.nflags = nflags
return true
}
/* -- draw the beams for one word -- */
/* (the staves are defined) */
function draw_beams(bm) {
var s, i, beam_dir, shift, bshift, bstub, bh, da, bd,
k, k1, k2, x1,
s1 = bm.s1,
s2 = bm.s2
/* -- draw a single beam -- */
function draw_beam(x1, x2, dy, h, bm,
n) { /* beam number (1..n) */
var y1, dy2,
s = bm.s1,
nflags = s.nflags
if (s.ntrem)
nflags -= s.ntrem
if (s.trem2 && n > nflags) {
if (s.dur >= C.BLEN / 2) {
x1 = s.x + 6;
x2 = bm.s2.x - 6
} else if (s.dur < C.BLEN / 4) {
var dx = x2 - x1
if (dx < 16) {
x1 += dx / 4
x2 -= dx / 4
} else {
x1 += 5
x2 -= 6
}
}
}
y1 = bm.a * x1 + bm.b - dy;
x2 -= x1;
x2 /= stv_g.scale;
dy2 = bm.a * x2 * stv_g.scale
xypath(x1, y1, true);
output += 'l' + x2.toFixed(1) + ' ' + (-dy2).toFixed(1) +
'v' + h.toFixed(1) +
'l' + (-x2).toFixed(1) + ' ' + dy2.toFixed(1) +
'z"/>\n'
} // draw_beam()
|
| ︙ | ︙ | |||
501 502 503 504 505 506 507 508 509 510 511 512 513 514 |
bh = BEAM_DEPTH
} else {
bshift = 3.5;
bstub = 3.2;
shift = .29;
bh = 1.8
}
/*fixme: quick hack for stubs at end of beam and different stem directions*/
beam_dir = s1.stem
if (s1.stem != s2.stem
&& s1.nflags < s2.nflags)
beam_dir = s2.stem
if (beam_dir < 0)
| > | 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 |
bh = BEAM_DEPTH
} else {
bshift = 3.5;
bstub = 3.2;
shift = .29;
bh = 1.8
}
bh /= stv_g.scale
/*fixme: quick hack for stubs at end of beam and different stem directions*/
beam_dir = s1.stem
if (s1.stem != s2.stem
&& s1.nflags < s2.nflags)
beam_dir = s2.stem
if (beam_dir < 0)
|
| ︙ | ︙ | |||
580 581 582 583 584 585 586 587 588 589 590 591 592 593 |
break
s = k
}
k2 = s
while (k2.type != C.NOTE)
k2 = k2.prev;
x1 = k1.xs
if (k1 == k2) {
if (k1 == s1) {
x1 += bstub
} else if (k1 == s2) {
x1 -= bstub
} else if (k1.beam_br1
|| (k1.beam_br2
| > | 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 |
break
s = k
}
k2 = s
while (k2.type != C.NOTE)
k2 = k2.prev;
x1 = k1.xs
bd = beam_dir
if (k1 == k2) {
if (k1 == s1) {
x1 += bstub
} else if (k1 == s2) {
x1 -= bstub
} else if (k1.beam_br1
|| (k1.beam_br2
|
| ︙ | ︙ | |||
608 609 610 611 612 613 614 | || (k1.nflags == k.nflags && k1.dots < k.dots)) x1 += bstub else x1 -= bstub } } | > > > > | > | | 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 |
|| (k1.nflags == k.nflags
&& k1.dots < k.dots))
x1 += bstub
else
x1 -= bstub
}
}
if (k1.stem != beam_dir) {
bd = k1.stem
k1.ys = bm.a * k1.xs + bm.b
- staff_tb[k1.st].y - bh
}
}
draw_beam(x1, k2.xs,
shift * bd,
bh, bm, i)
if (s == s2)
break
}
}
if (s1.tmp)
unlksym(s1)
|
| ︙ | ︙ | |||
862 863 864 865 866 867 868 |
flat2 = new Int8Array([-12, 9, -12, 9, -12, 9])
Abc.prototype.draw_keysig = function(x, s) {
var old_sf = s.k_old_sf,
st = s.st,
staffb = staff_tb[st].y,
i, shift, p_seq,
| | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 |
flat2 = new Int8Array([-12, 9, -12, 9, -12, 9])
Abc.prototype.draw_keysig = function(x, s) {
var old_sf = s.k_old_sf,
st = s.st,
staffb = staff_tb[st].y,
i, shift, p_seq,
clef_ix = s.k_y_clef,
a_acc = s.k_a_acc // accidental list [pit, acc]
// set the accidentals when K: with modified accidentals
function set_k_acc(a_acc, sf) {
var i, j, n, nacc, p_acc,
accs = [],
pits = []
if (sf > 0) {
for (nacc = 0; nacc < sf; nacc++) {
accs[nacc] = 1 // sharp
pits[nacc] = [26, 23, 27, 24, 21, 25, 22][nacc]
}
} else {
for (nacc = 0; nacc < -sf; nacc++) {
accs[nacc] = -1 // flat
pits[nacc] = [22, 25, 21, 24, 20, 23, 26][nacc]
}
}
n = a_acc.length
for (i = 0; i < n; i++) {
p_acc = a_acc[i]
for (j = 0; j < nacc; j++) {
if (pits[j] == p_acc.pit) {
accs[j] = p_acc.acc
break
}
}
if (j == nacc) {
accs[j] = p_acc.acc
pits[j] = p_acc.pit
nacc++
}
}
for (i = 0; i < nacc; i++) {
p_acc = a_acc[i]
if (!p_acc)
p_acc = a_acc[i] = {}
p_acc.acc = accs[i]
p_acc.pit = pits[i]
}
} // set_k_acc()
// ---- draw_keysig ---
if (clef_ix & 1)
clef_ix += 7;
clef_ix /= 2
while (clef_ix < 0)
clef_ix += 7;
clef_ix %= 7
/* normal accidentals */
if (a_acc && !s.exp) // if added accidentals
set_k_acc(a_acc, s.k_sf) // merge them into the key
if (!a_acc) {
/* put neutrals if 'accidental cancel' */
if (s.fmt.cancelkey || s.k_sf == 0) {
/* when flats to sharps, or sharps to flats, */
if (s.k_sf == 0
|| old_sf * s.k_sf < 0) {
|
| ︙ | ︙ | |||
920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 |
x += 2
for (; i < old_sf; i++) {
xygl(x, staffb + shift, "acc3");
shift += p_seq[i];
x += 5.5
}
}
}
/* new flats */
if (s.k_sf < 0) {
shift = flat_cl[clef_ix];
p_seq = shift < 18 ? flat1 : flat2
for (i = 0; i > s.k_sf; i--) {
xygl(x, staffb + shift, "acc-1");
shift += p_seq[-i];
x += 5.5
}
if (s.fmt.cancelkey && i > old_sf) {
x += 2
for (; i > old_sf; i--) {
xygl(x, staffb + shift, "acc3");
shift += p_seq[-i];
x += 5.5
}
}
}
| > > > > | | | | | 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 |
x += 2
for (; i < old_sf; i++) {
xygl(x, staffb + shift, "acc3");
shift += p_seq[i];
x += 5.5
}
}
if (s.k_bagpipe == 'p') { // K:Hp - add the g natural
xygl(x, staffb + 27, "acc3")
x += 5.5
}
}
/* new flats */
if (s.k_sf < 0) {
shift = flat_cl[clef_ix];
p_seq = shift < 18 ? flat1 : flat2
for (i = 0; i > s.k_sf; i--) {
xygl(x, staffb + shift, "acc-1");
shift += p_seq[-i];
x += 5.5
}
if (s.fmt.cancelkey && i > old_sf) {
x += 2
for (; i > old_sf; i--) {
xygl(x, staffb + shift, "acc3");
shift += p_seq[-i];
x += 5.5
}
}
}
} else if (a_acc.length) {
/* explicit accidentals */
var acc,
last_acc = a_acc[0].acc,
last_shift = 100,
s2 = {
st: st,
nhd: 0,
notes: [{}]
}
for (i = 0; i < a_acc.length; i++) {
acc = a_acc[i];
shift = (s.k_y_clef // clef shift
+ acc.pit - 18) * 3
while (shift < -3) // let the accidentals inside the staff
shift += 21
while (shift > 27)
shift -= 21
if (i != 0
|
| ︙ | ︙ | |||
1092 1093 1094 1095 1096 1097 1098 |
set_color();
anno_a.push(s)
}
// -- draw a multi-measure rest --
// (the staves are defined)
function draw_mrest(s) {
| | > > > > > > > > | | | 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 |
set_color();
anno_a.push(s)
}
// -- draw a multi-measure rest --
// (the staves are defined)
function draw_mrest(s) {
var x1, x2, prev,
p_st = staff_tb[s.st],
y = p_st.y + (p_st.topbar + p_st.botbar) / 2,
p = s.nmes.toString()
if (!s.next) {
error(1, s, "Lack of bar after multi-measure rest")
return
}
set_scale(s)
prev = s // search the start of the previous time sequence
while (!prev.seqst)
prev = prev.ts_prev
prev = prev.ts_prev
while (!prev.seqst)
prev = prev.ts_prev
x1 = prev.x + 20
x2 = s.next.x - 20
s.x = (x1 + x2) / 2
anno_start(s)
out_XYAB('<path d="mX Y', x1 + .6, y - 2.7)
output += 'v2.7h-1.4v-10.8h1.4v2.7h'
+ ((x2 - x1 - 2.8) / stv_g.scale).toFixed(1)
+ 'v-2.7h1.4v10.8h-1.4v-2.7z"/>\n'
out_XYAB('<text x ="X" y="Y" text-anchor="middle">A</text>\n',
s.x, y + 22, m_gl(p))
anno_a.push(s)
} // draw_mrest()
function grace_slur(s) {
|
| ︙ | ︙ | |||
1669 1670 1671 1672 1673 1674 1675 | } // draw a slur between two chords / notes /* (the staves are not yet defined) */ /* (delayed output) */ /* (not a pretty routine, this) */ function draw_slur(path, // list of symbols under the slur | < | > | 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 |
}
// draw a slur between two chords / notes
/* (the staves are not yet defined) */
/* (delayed output) */
/* (not a pretty routine, this) */
function draw_slur(path, // list of symbols under the slur
sl) { // slur variables: type, end symbol, note
var i,
k, g, x1, y1, x2, y2, height, addy,
a, y, z, h, dx, dy,
ty = sl.ty,
dir = (ty & 0x07) == C.SL_ABOVE ? 1 : -1,
n = path.length,
i1 = 0,
i2 = n - 1,
not1 = sl.nts, // if the slur start on a note
k1 = path[0],
k2 = path[i2]
/*fixme: if two staves, may have upper or lower slur*/
var nn = 1,
upstaff = k1.st,
|
| ︙ | ︙ | |||
1762 1763 1764 1765 1766 1767 1768 |
} else {
y1 = k1.y - 8
}
}
}
}
| | | | 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 |
} else {
y1 = k1.y - 8
}
}
}
}
if (sl.nte) { // slur ending on a note
y2 = 3 * (sl.nte.pit - 18) + 2 * dir
x2 -= 3
} else { // end on a chord
y2 = dir > 0 ? k2.ymx + 2 : k2.ymn - 2
if (k2.type == C.NOTE) {
if (dir > 0) {
if (k2.stem > 0) {
x2 += 1
|
| ︙ | ︙ | |||
1984 1985 1986 1987 1988 1989 1990 |
y = a * k.x + addy
if (k.ymx < y)
k.ymx = y
else if (k.ymn > y)
k.ymn = y
if (i == i2 - 1) {
dx = x2
| | | 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 |
y = a * k.x + addy
if (k.ymx < y)
k.ymx = y
else if (k.ymn > y)
k.ymn = y
if (i == i2 - 1) {
dx = x2
if (sl.nte)
dx -= 5;
if (i)
y -= height / 3
} else {
dx = path[i + 1].x
}
if (i != 0)
|
| ︙ | ︙ | |||
2006 2007 2008 2009 2010 2011 2012 |
/* -- draw the slurs between 2 symbols --*/
function draw_slurs(s, last) {
var gr1, i, m, note, sls, nsls
// draw a slur knowing the start and stop elements
function draw_sls(s, // start symbol
| | < | | < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > < < | | 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 |
/* -- draw the slurs between 2 symbols --*/
function draw_slurs(s, last) {
var gr1, i, m, note, sls, nsls
// draw a slur knowing the start and stop elements
function draw_sls(s, // start symbol
sl) { // slur variables
var k, v, i, dir, s3,
path = [],
s2 = sl.se // slur end
if (last && s2.time > last.time)
return // will be drawn next time
// handle slurs without start or end
switch (sl.loc) {
case 'i': // no start
s3 = s.ts_prev
for (s = s3; s; s = s.ts_prev) {
if (s.dur) {
if (s.v == s2.v) {
s3 = s
break
}
if (s.st == s2.st) {
s3 = s
continue
} else if (!s3) {
s3 = s
}
} else if (!s3) {
s3 = s
}
}
s = s3
break
case 'o': // no end
for (s3 = s; s3.ts_next; s3 = s3.ts_next)
;
s2 = s3
for (; s3; s3 = s3.ts_prev) {
if (s3.v == s.v) {
s2 = s3
break
}
if (s3.st == s.st)
s2 = s3
if (s3.ts_prev.time != s2.time)
break
}
break
}
// if the slur continues on the next music line,
// stop it at the end of the current line
if (tsnext && s2.time >= tsnext.time) {
if (s2.grace && s2.time == tsnext.time) {
for (s3 = tsnext; s3 && s3.time == s2.time; s3 = s3.ts_next) {
if (s3.type == C.GRACE)
//fixme: check if s2 in the grace notes
break
}
if (s3.type == C.GRACE)
s3 = null
}
if (!s2.grace || s2.time == tsnext.time || !s3) {
s.p_v.sls.push(sl); // continuation on next line
s2 = s.p_v.s_next.prev // one voice
while (s2.next)
s2 = s2.next; // search the ending bar
sl = Object.create(sl); // new slur
}
}
// set the slur position
switch (sl.ty & 0x07) {
case C.SL_ABOVE: dir = 1; break
case C.SL_BELOW: dir = -1; break
default:
|
| ︙ | ︙ | |||
2073 2074 2075 2076 2077 2078 2079 |
s = s.next
else
s = s.ts_next
}
if (!s2.grace) { // if end on a normal note
while (s) {
| | > | 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 |
s = s.next
else
s = s.ts_next
}
if (!s2.grace) { // if end on a normal note
while (s) {
if (s.v == v
&& !s.invis)
path.push(s)
if (s == s2)
break
s = s.ts_next
}
} else if (s.grace) { // if start/end in the same sequence
while (1) {
|
| ︙ | ︙ | |||
2110 2111 2112 2113 2114 2115 2116 |
s = s.next
}
}
// if some nested slurs/tuplets, draw them
for (i = 1; i < path.length - 1; i++) {
s = path[i]
| | | | 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 |
s = s.next
}
}
// if some nested slurs/tuplets, draw them
for (i = 1; i < path.length - 1; i++) {
s = path[i]
if (s.sls)
draw_slurs(s, last)
if (s.tp)
draw_tuplet(s)
}
draw_slur(path, sl)
return 1 // slur drawn, remove it
} // draw_sls()
// code of draw_slurs()
while (1) {
if (!s || s == last) {
if (!gr1 // if end of grace notes
|
| ︙ | ︙ | |||
2144 2145 2146 2147 2148 2149 2150 |
for (i = 0; i < sls.length; i++) {
if (!draw_sls(s, sls[i]))
nsls.push(sls[i])
}
if (nsls.length)
s.sls = nsls
}
| < < < < < < < < < < < < < < < < | > > | | | 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 |
for (i = 0; i < sls.length; i++) {
if (!draw_sls(s, sls[i]))
nsls.push(sls[i])
}
if (nsls.length)
s.sls = nsls
}
s = s.next
}
}
/* -- draw a tuplet -- */
/* (the staves are not yet defined) */
/* (delayed output) */
/* See http://moinejf.free.fr/abcm2ps-doc/tuplets.html
* for the value of 'tp.f' */
function draw_tuplet(s1) {
var s2, s3, g, upstaff, nb_only,
x1, x2, y1, y2, xm, ym, a, s0, yy, yx, dy, a, dir, r,
tp = s1.tp.shift() // tuplet parameters
if (!s1.tp.length)
delete s1.tp // last tuplet
// treat the slurs and the nested tuplets
upstaff = s1.st
set_dscale(s1.st)
for (s2 = s1; s2; s2 = s2.next) {
switch (s2.type) {
case C.GRACE:
if (!s2.sl1)
continue
for (g = s2.extra; g; g = g.next) {
if (g.sls)
draw_slurs(g)
}
// fall thru
default:
continue
case C.NOTE:
case C.REST:
break
}
if (s2.sls)
draw_slurs(s2)
if (s2.st < upstaff)
upstaff = s2.st
if (s2.tp)
draw_tuplet(s2)
if (s2.tpe)
break
|
| ︙ | ︙ | |||
2218 2219 2220 2221 2222 2223 2224 |
error(1, s1, "No end of tuplet in this music line")
return
}
dir = tp.f[3] // 'where'
if (!dir) { // if auto
s3 = s1
| | | | | 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 |
error(1, s1, "No end of tuplet in this music line")
return
}
dir = tp.f[3] // 'where'
if (!dir) { // if auto
s3 = s1
while (s3 && !s3.stem) // (may have tuplets of rests!)
s3 = s3.next
dir = (s3 && s3.stem < 0) ? C.SL_BELOW : C.SL_ABOVE
}
if (s1 == s2 // tuplet with 1 note (!)
|| tp.f[1] == 2) { // what == nothing
nb_only = true
} else if (tp.f[1] == 1) { /* 'what' == slur */
nb_only = true;
draw_slur([s1, s2], {ty: dir})
} else {
/* search if a bracket is needed */
if (tp.f[0] != 2 // if 'when' != always
&& s1.type == C.NOTE && s2.type == C.NOTE) {
nb_only = true
for (s3 = s1; ; s3 = s3.next) {
|
| ︙ | ︙ | |||
2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 |
a = s0
} else {
if (a > 0)
a = 0
else if (a < s0)
a = s0
}
if (a * a < .1 * .1)
a = 0
/* shift up bracket if needed */
dy = 0
for (s3 = s1; ; s3 = s3.next) {
if (!s3.dur /* not a note or a rest */
| > | 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 |
a = s0
} else {
if (a > 0)
a = 0
else if (a < s0)
a = s0
}
a = s1.fmt.beamslope * a / (s1.fmt.beamslope + Math.abs(a))
if (a * a < .1 * .1)
a = 0
/* shift up bracket if needed */
dy = 0
for (s3 = s1; ; s3 = s3.next) {
if (!s3.dur /* not a note or a rest */
|
| ︙ | ︙ | |||
2427 2428 2429 2430 2431 2432 2433 |
/* shift the slurs / decorations */
ym += 6
for (s3 = s1; ; s3 = s3.next) {
if (s3.st == upstaff) {
yy = ym + (s3.x - xm) * a
if (s3.ymx < yy)
s3.ymx = yy
| < | | 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 |
/* shift the slurs / decorations */
ym += 6
for (s3 = s1; ; s3 = s3.next) {
if (s3.st == upstaff) {
yy = ym + (s3.x - xm) * a
if (s3.ymx < yy)
s3.ymx = yy
y_set(upstaff, true, s3.x - 3, 6, yy)
}
if (s3 == s2)
break
}
// below
} else { /* lower voice of the staff: the bracket is below the staff */
|
| ︙ | ︙ | |||
2506 2507 2508 2509 2510 2511 2512 |
/* shift the slurs / decorations */
ym -= 2
for (s3 = s1; ; s3 = s3.next) {
if (s3.st == upstaff) {
yy = ym + (s3.x - xm) * a
if (s3.ymn > yy)
s3.ymn = yy;
| < < | | 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 |
/* shift the slurs / decorations */
ym -= 2
for (s3 = s1; ; s3 = s3.next) {
if (s3.st == upstaff) {
yy = ym + (s3.x - xm) * a
if (s3.ymn > yy)
s3.ymn = yy;
y_set(upstaff, false, s3.x - 3, 6, yy)
}
if (s3 == s2)
break
}
} /* lower voice */
if (tp.f[2] == 1) { /* if 'which' == none */
|
| ︙ | ︙ | |||
2700 2701 2702 2703 2704 2705 2706 | /* -- draw the symbols near the notes -- */ /* (the staves are not yet defined) */ /* order: * - scaled * - beams * - decorations near the notes | < | | 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 |
/* -- draw the symbols near the notes -- */
/* (the staves are not yet defined) */
/* order:
* - scaled
* - beams
* - decorations near the notes
* - decorations tied to the notes
* - tuplets and slurs
* - not scaled
* - measure numbers
* - lyrics
* - staff decorations
* - chord symbols
* - repeat brackets
* The buffer output is delayed until the definition of the staff system
*/
function draw_sym_near() {
var p_voice, p_st, s, v, st, y, g, w, i, st, dx, top, bot, ymn,
output_sav = output;
// set the staff offsets of a beam
function set_yab(s1, s2) {
var y,
k = realwidth / YSTEP,
i = (s1.x / k) | 0,
|
| ︙ | ︙ | |||
2768 2769 2770 2771 2772 2773 2774 |
var bm = {},
first_note = true;
p_voice = voice_tb[v]
for (s = p_voice.sym; s; s = s.next) {
switch (s.type) {
case C.GRACE:
| < < < | | 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 |
var bm = {},
first_note = true;
p_voice = voice_tb[v]
for (s = p_voice.sym; s; s = s.next) {
switch (s.type) {
case C.GRACE:
for (g = s.extra; g; g = g.next) {
if (g.beam_st && !g.beam_end) {
self.calculate_beam(bm, g)
if (bm.s2)
set_yab(g, bm.s2)
}
}
if (!s.p_v.ckey.k_bagpipe // no slur when bagpipe
&& s.fmt.graceslurs
&& !s.gr_shift // tied to previous note
&& !s.sl1 // explicit slur
&& !s.ti1 // some tie
&& s.next
&& s.next.type == C.NOTE)
grace_slur(s)
break
}
}
|
| ︙ | ︙ | |||
2868 2869 2870 2871 2872 2873 2874 |
}
dx += s.notes[0].shhd;
y_set(s.st, false, s.x + dx, w, s.ymn)
}
/* have room for the accidentals */
if (s.notes[s.nhd].acc) {
| | | | | < | | < < | < < | | 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 |
}
dx += s.notes[0].shhd;
y_set(s.st, false, s.x + dx, w, s.ymn)
}
/* have room for the accidentals */
if (s.notes[s.nhd].acc) {
y = 3 * (s.notes[s.nhd].pit - 18)
+ (s.notes[s.nhd].acc == -1 // flat
? 11 : 10)
y_set(s.st, true, s.x - 10, 10, y)
}
if (s.notes[0].acc) {
y = 3 * (s.notes[0].pit - 18)
- (s.notes[0].acc == -1 // flat
? 5 : 10)
y_set(s.st, false, s.x - 10, 10, y)
}
}
draw_deco_note()
for (v = 0; v < voice_tb.length; v++) {
p_voice = voice_tb[v];
|
| ︙ | ︙ | |||
2948 2949 2950 2951 2952 2953 2954 |
set_dscale(-1);
output = output_sav
}
/* -- draw the name/subname of the voices -- */
function draw_vname(indent, stl) {
| | < | < < < < < < < < < < < < < < | < < | > | 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 |
set_dscale(-1);
output = output_sav
}
/* -- draw the name/subname of the voices -- */
function draw_vname(indent, stl) {
var p_voice, n, st, v, a_p, p, y, h, h2,
staff_d = []
for (st = stl.length; st >= 0; st--) {
if (stl[st])
break
}
if (st < 0)
return
for (v = 0; v < voice_tb.length; v++) {
p_voice = voice_tb[v]
if (!cur_sy.voices[v])
continue
st = cur_sy.voices[v].st
if (!stl[st])
continue
if (!gene.vnt)
continue
p = gene.vnt == 2 ? p_voice.nm : p_voice.snm
if (!p)
continue
delete p_voice.new_name
if (!staff_d[st])
staff_d[st] = p
else
staff_d[st] += "\n" + p
}
if (!staff_d.length)
return
|
| ︙ | ︙ | |||
3058 3059 3060 3061 3062 3063 3064 | y = val } // } /* draw the parts and tempo indications if any */ y += draw_partempo(st, y) | < < < < < > | > > > | 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 |
y = val
}
// }
/* draw the parts and tempo indications if any */
y += draw_partempo(st, y)
/* set the vertical offset of the 1st staff */
y *= p_staff.staffscale;
staffsep = fmt.staffsep * .5 +
p_staff.topbar * p_staff.staffscale
if (y < staffsep)
y = staffsep
if (y < p_staff.ann_top) // absolute annotation
y = p_staff.ann_top;
p_staff.y = -y;
/* set the offset of the other staves */
for (prev_staff = 0; prev_staff < st; prev_staff++)
staff_tb[prev_staff].y = -y
if (!gene.st_print[st]) // no staff
return y
var sy_staff_prev = sy.staves[prev_staff]
for (st++; st <= nstaff; st++) {
if (!gene.st_print[st])
continue
p_staff = staff_tb[st]
staffsep = sy_staff_prev.sep || cfmt.sysstaffsep;
maxsep = sy_staff_prev.maxsep || cfmt.maxsysstaffsep;
|
| ︙ | ︙ | |||
3110 3111 3112 3113 3114 3115 3116 | dy = staffsep; maxsep += p_staff.topbar * p_staff.staffscale if (dy > maxsep) dy = maxsep; y += dy; p_staff.y = -y; | > | | 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 |
dy = staffsep;
maxsep += p_staff.topbar * p_staff.staffscale
if (dy > maxsep)
dy = maxsep;
y += dy;
p_staff.y = -y;
while (!gene.st_print[++prev_staff])
staff_tb[prev_staff].y = -y
while (1) {
sy_staff_prev = sy.staves[prev_staff]
if (sy_staff_prev)
break
sy = sy.next
}
}
|
| ︙ | ︙ | |||
3163 3164 3165 3166 3167 3168 3169 |
// return the height of the whole staff system
return y + dy
}
/* -- draw the staff systems and the measure bars -- */
function draw_systems(indent) {
var s, s2, st, x, x2, res, sy,
| < | 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 |
// return the height of the whole staff system
return y + dy
}
/* -- draw the staff systems and the measure bars -- */
function draw_systems(indent) {
var s, s2, st, x, x2, res, sy,
xstaff = [],
stl = [], // all staves in the line
bar_bot = [],
bar_height = [],
ba = [], // bars [symbol, bottom, height]
sb = "",
thb = ""
|
| ︙ | ︙ | |||
3196 3197 3198 3199 3200 3201 3202 |
dy = (cur_sy.staves[st].flags & STOP_BAR) ?
0 : bar_bot[st]
}
} // bar_set()
/* -- draw a staff -- */
function draw_staff(st, x1, x2) {
| | | > | < | | | | | | | | 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 |
dy = (cur_sy.staves[st].flags & STOP_BAR) ?
0 : bar_bot[st]
}
} // bar_set()
/* -- draw a staff -- */
function draw_staff(st, x1, x2) {
var w, i, dy, ty,
y = 0,
ln = "",
stafflines = staff_tb[st].stafflines,
l = stafflines.length,
il = 6 * staff_tb[st].staffscale // interline
if (!/[\[|]/.test(stafflines))
return // no line
w = x2 - x1;
set_sscale(-1)
// check if default staff
if (cache && cache.st_l == stafflines
&& cache.st_w == (w | 0)) {
xygl(x1, staff_tb[st].y, 'stdef' + cfmt.fullsvg)
return
}
for (i = 0; i < l; i++, y -= il) {
if (stafflines[i] == '.')
continue
dy = 0
for (; i < l; i++, y -= il, dy -= il) {
switch (stafflines[i]) {
case '.':
case '-':
continue
case ty:
ln += 'm-' + w.toFixed(1) +
' ' + dy +
'h' + w.toFixed(1);
dy = 0
continue
}
if (ty != undefined)
ln += '"/>\n';
ty = stafflines[i]
ln += '<path class="' +
(ty == '[' ? 'slthW' : 'slW') +
'" d="m0 ' + y + 'h' + w.toFixed(1);
dy = 0
}
ln += '"/>'
}
y = staff_tb[st].y
if (!cache
&& w > get_lwidth() - 10) {
cache = {
st_l: stafflines,
st_w: w | 0
}
i = 'stdef' + cfmt.fullsvg;
if (ln.indexOf('<path', 1) < 0)
glyphs[i] = ln.replace('path', 'path id="' + i + '"')
else
glyphs[i] = '<g id="' + i + '">\n' + ln + '\n</g>';
xygl(x1, y, i)
|
| ︙ | ︙ | |||
3425 3426 3427 3428 3429 3430 3431 |
}
} // hl_rest()
// ---- draw_systems() ----
/* draw the staff, skipping the staff breaks */
for (st = 0; st <= nstaff; st++) {
| | | < < < < < < < < < < < < < < < < < < < < < < < < < < > > > | > > | > | | < | < | | 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 |
}
} // hl_rest()
// ---- draw_systems() ----
/* draw the staff, skipping the staff breaks */
for (st = 0; st <= nstaff; st++) {
stl[st] = gene.st_print[st] || cur_sy.st_print[st] // staff in the line
xstaff[st] = !stl[st] ? -1 : 0;
}
bar_set();
draw_lstaff(0)
for (s = tsfirst; s; s = s.ts_next) {
switch (s.type) {
case C.STAVES:
sy = s.sy
for (st = 0; st <= nstaff; st++) {
x = xstaff[st]
if (x < 0) { // no staff yet
if (sy.st_print[st]) {
if (s.ts_prev.bar_type)
xstaff[st] = s.ts_prev.x
else if (s.ts_next.bar_type)
xstaff[st] = s.x
else
xstaff[st] = s.ts_prev.x
+ s.ts_prev.wr
stl[st] = true
}
continue
}
if (sy.st_print[st] // if not staff stop
&& cur_sy.staves[st]
&& sy.staves[st].stafflines ==
cur_sy.staves[st].stafflines)
continue
if (s.ts_prev.bar_type) {
x2 = s.ts_prev.x
} else {
x2 = (s.ts_prev.x + s.x) / 2
xstaff[st] = -1
}
draw_staff(st, x, x2)
xstaff[st] = sy.st_print[st] ? x2 : -1
}
cur_sy = sy;
bar_set()
continue
case C.BAR: // display the bars after the staves
if (s.invis || !s.bar_type
|| !cur_sy.st_print[s.st])
|
| ︙ | ︙ | |||
3561 3562 3563 3564 3565 3566 3567 |
// s.invis = true
// break
}
}
// draw the end of the staves
for (st = 0; st <= nstaff; st++) {
| < < | 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 |
// s.invis = true
// break
}
}
// draw the end of the staves
for (st = 0; st <= nstaff; st++) {
x = xstaff[st]
if (x < 0 || x >= realwidth)
continue
draw_staff(st, x, realwidth)
}
// the ledger lines
|
| ︙ | ︙ | |||
3618 3619 3620 3621 3622 3623 3624 | draw_note(s, !bm.s2); anno_a.push(s) } if (s == bm.s2) bm.s2 = null break case C.REST: | | | 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 | draw_note(s, !bm.s2); anno_a.push(s) } if (s == bm.s2) bm.s2 = null break case C.REST: if (!gene.st_print[st]) break draw_rest(s); break case C.BAR: break /* drawn in draw_systems */ case C.CLEF: if (s.time >= staff_tb[st].clef.time) |
| ︙ | ︙ |
Changes to core/format.js.
1 2 | // abc2svg - format.js - formatting functions // | | | 1 2 3 4 5 6 7 8 9 10 | // abc2svg - format.js - formatting functions // // Copyright (C) 2014-2022 Jean-Francois Moine // // This file is part of abc2svg-core. // // abc2svg-core is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
87 88 89 90 91 92 93 94 95 96 97 |
musicspace: 6,
// notespacingfactor: "1.3, 38",
partsfont: {name: txt_ff, size: 15},
parskipfac: .4,
partsspace: 8,
// pageheight: 29.7 * CM,
pagewidth: 21 * CM,
printmargin: 0,
rightmargin: 1.4 * CM,
rbmax: 4,
rbmin: 2,
| > | | 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
musicspace: 6,
// notespacingfactor: "1.3, 38",
partsfont: {name: txt_ff, size: 15},
parskipfac: .4,
partsspace: 8,
// pageheight: 29.7 * CM,
pagewidth: 21 * CM,
"propagate-accidentals": "o", // octave
printmargin: 0,
rightmargin: 1.4 * CM,
rbmax: 4,
rbmin: 2,
repeatfont: {name: txt_ff, size: 9},
scale: 1,
slurheight: 1.0,
spatab: // spacing table (see "notespacingfactor" and set_space())
new Float32Array([ // default = "1.3, 38"
10.2, 13.3, 17.3, 22.48, 29.2,
38,
49.4, 64.2, 83.5, 108.5]),
|
| ︙ | ︙ | |||
126 127 128 129 130 131 132 |
tupletfont: {name: txt_ff, style: "italic", size: 12},
vocalfont: {name: txt_ff, weight: "bold", size: 13},
vocalspace: 10,
voicefont: {name: txt_ff, weight: "bold", size: 13},
// voicescale: 1,
writefields: "CMOPQsTWw",
wordsfont: {name: txt_ff, size: 16},
| | > | 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
tupletfont: {name: txt_ff, style: "italic", size: 12},
vocalfont: {name: txt_ff, weight: "bold", size: 13},
vocalspace: 10,
voicefont: {name: txt_ff, weight: "bold", size: 13},
// voicescale: 1,
writefields: "CMOPQsTWw",
wordsfont: {name: txt_ff, size: 16},
wordsspace: 5,
"writeout-accidentals": "n"
}
// parameters that are used in the symbols
var sfmt = {
bardef: true,
barsperstaff: true,
beamslope: true,
|
| ︙ | ︙ | |||
181 182 183 184 185 186 187 |
return
}
font_scale_tb[a[0]] = scale
}
// set the width factor of a font
function set_font_fac(font) {
| | | 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
return
}
font_scale_tb[a[0]] = scale
}
// set the width factor of a font
function set_font_fac(font) {
var scale = font_scale_tb[font.fname || font.name]
if (!scale)
scale = 1.1;
font.swfac = font.size * scale
}
// %%xxxfont fontname|* [encoding] [size|*]
|
| ︙ | ︙ | |||
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
font = {
pad: 0
}
} else {
font = {
name: font.name,
size: font.size,
box: font.box,
pad: font.pad || 0
}
}
cfmt[xxxfont] = font;
// fill the values
a = p.match(/\s+(no)?box(\s|$)/)
if (a) { // if box
if (a[1]) {
font.box = false // nobox
font.pad = 0
} else {
font.box = true
| > > | | 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
font = {
pad: 0
}
} else {
font = {
name: font.name,
size: font.size,
weight: font.weight,
style: font.style,
box: font.box,
pad: font.pad || 0
}
}
cfmt[xxxfont] = font;
// fill the values
a = p.match(/\s+(no)?box(\s|$)/)
if (a) { // if box
if (a[1]) {
font.box = false // nobox
font.pad = 0
} else {
font.box = true
font.pad = 2.5
}
p = p.replace(a[0], a[2])
}
a = p.match(/\s+padding=([\d.]+)(\s|$)/)
if (a) { // if padding
font.pad = a[1] ? +a[1] : 0
p = p.replace(a[0], a[2])
|
| ︙ | ︙ | |||
267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
a = p.match(/\s+([0-9.]+|\*)$/)
if (a) {
if (a[1] != "*")
font.size = +a[1]
p = p.replace(a[0], "")
}
// accept url(...) as the font name
if (p[0] == 'u' && p.slice(0, 4) == "url(") {
n = p.indexOf(')', 1)
if (n < 0) {
syntax(1, "No end of url in font family")
return
}
| > > | 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 |
a = p.match(/\s+([0-9.]+|\*)$/)
if (a) {
if (a[1] != "*")
font.size = +a[1]
p = p.replace(a[0], "")
}
font.fname = p // full name for scale factor
// accept url(...) as the font name
if (p[0] == 'u' && p.slice(0, 4) == "url(") {
n = p.indexOf(')', 1)
if (n < 0) {
syntax(1, "No end of url in font family")
return
}
|
| ︙ | ︙ | |||
296 297 298 299 300 301 302 303 304 305 306 307 308 309 |
}
// extract the font attributes
a = p.match(/[- ]?[nN]ormal/)
if (a) {
font.normal = true
p = p.replace(a[0], '')
}
// font weight
a = p.match(abc2svg.ft_re)
if (a) {
font.weight = abc2svg.ft_w[a[0].replace(/[ -]/, '')
.toLowerCase()]
| > > > > | 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 |
}
// extract the font attributes
a = p.match(/[- ]?[nN]ormal/)
if (a) {
font.normal = true
p = p.replace(a[0], '')
if (font.weight)
font.weight = null
if (font.style)
font.style = null
}
// font weight
a = p.match(abc2svg.ft_re)
if (a) {
font.weight = abc2svg.ft_w[a[0].replace(/[ -]/, '')
.toLowerCase()]
|
| ︙ | ︙ | |||
335 336 337 338 339 340 341 342 343 344 345 |
default:
//hack: the font "Figurato" is used for figured bass
if (p.indexOf("Fig") > 0)
font.figb = true
break
}
}
if (font.size)
set_font_fac(font)
else
font.swfac = 0
| > > < < | | 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 |
default:
//hack: the font "Figurato" is used for figured bass
if (p.indexOf("Fig") > 0)
font.figb = true
break
}
}
font.name = p
if (font.size)
set_font_fac(font)
else
font.swfac = 0
}
// get a length with a unit - return the number of pixels
function get_unit(param) {
var v = param.toLowerCase().match(/(-?[\d.]+)(.*)/)
if (!v)
return NaN
v[1] = +v[1]
switch (v[2]) {
case "cm":
return v[1] * CM
|
| ︙ | ︙ | |||
445 446 447 448 449 450 451 |
}
}
}
// set a voice specific parameter
function set_v_param(k, v) {
k = [k + '=', v]
| > > | | 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 |
}
}
}
// set a voice specific parameter
function set_v_param(k, v) {
k = [k + '=', v]
if (parse.state < 3)
memo_kv_parm(curvoice ? curvoice.id : '*', k)
else if (curvoice)
set_kv_parm(k)
else
memo_kv_parm('*', k)
}
function set_page() {
if (!img.chg)
|
| ︙ | ︙ | |||
508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 | break } cfmt[cmd] = v break case "abc-version": case "bgcolor": case "fgcolor": case "titleformat": cfmt[cmd] = param break case "beamslope": case "breaklimit": // float values case "lineskipfac": case "maxshrink": case "pagescale": | > > | 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 | break } cfmt[cmd] = v break case "abc-version": case "bgcolor": case "fgcolor": case "propagate-accidentals": case "titleformat": case "writeout-accidentals": cfmt[cmd] = param break case "beamslope": case "breaklimit": // float values case "lineskipfac": case "maxshrink": case "pagescale": |
| ︙ | ︙ | |||
558 559 560 561 562 563 564 | case "flatbeams": case "graceslurs": case "graceword": case "hyphencont": case "keywarn": case "linewarn": case "quiet": | < | 572 573 574 575 576 577 578 579 580 581 582 583 584 585 | case "flatbeams": case "graceslurs": case "graceword": case "hyphencont": case "keywarn": case "linewarn": case "quiet": case "squarebreve": case "splittune": case "straightflags": case "stretchstaff": case "timewarn": case "titlecaps": case "titleleft": |
| ︙ | ︙ | |||
671 672 673 674 675 676 677 | } if (parse.ufmt) cfmt[cmd] = new Float32Array(3) for (i = 0; i < 3; i++) cfmt[cmd][i] = +v[i] break case "tuplets": | | | | | > > > > > | | 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 |
}
if (parse.ufmt)
cfmt[cmd] = new Float32Array(3)
for (i = 0; i < 3; i++)
cfmt[cmd][i] = +v[i]
break
case "tuplets":
v = param.split(/\s+/)
f = v[3]
if (f) // if 'where'
f = posval[f] // translate the keyword
if (f)
v[3] = f
if (curvoice)
curvoice.tup = v
else
cfmt[cmd] = v
break
case "infoname":
set_infoname(param)
break
case "notespacingfactor":
v = param.match(/([.\d]+)[,\s]*(\d+)?/)
if (v) {
|
| ︙ | ︙ | |||
723 724 725 726 727 728 729 730 731 732 733 734 735 736 |
cfmt.sound = "play" // without clef
break
case "pos":
cmd = param.match(/(\w*)\s+(.*)/)
if (!cmd || !cmd[2]) {
syntax(1, "Error in %%pos")
break
}
set_pos(cmd[1], cmd[2])
break
case "sounding-score":
if (cfmt.sound != "play")
cfmt.sound = "sounding"
break
| > > > > > > > > > > > > > > > > > > > > | 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 |
cfmt.sound = "play" // without clef
break
case "pos":
cmd = param.match(/(\w*)\s+(.*)/)
if (!cmd || !cmd[2]) {
syntax(1, "Error in %%pos")
break
}
if (cmd[1].slice(0, 3) == 'tup' // special case for %%pos tuplet
&& curvoice) { // inside tune
if (!curvoice.tup)
curvoice.tup = cfmt.tuplets
else
curvoice.tup = Object.create(curvoice.tup)
v = posval[cmd[2]]
switch (v) {
case C.SL_ABOVE:
curvoice.tup[3] = 1
break
case C.SL_BELOW:
curvoice.tup[3] = 2
break
case C.SL_HIDDEN:
curvoice.tup[2] = 1
break
}
break
}
set_pos(cmd[1], cmd[2])
break
case "sounding-score":
if (cfmt.sound != "play")
cfmt.sound = "sounding"
break
|
| ︙ | ︙ | |||
752 753 754 755 756 757 758 759 760 761 762 763 | cfmt.rightmargin = v; img.chg = true break case "textoption": cfmt[cmd] = get_textopt(param) break case "dynalign": case "stretchlast": case "titletrim": v = +param if (isNaN(v)) v = get_bool(param) ? 0 : 1 | > | | 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 |
cfmt.rightmargin = v;
img.chg = true
break
case "textoption":
cfmt[cmd] = get_textopt(param)
break
case "dynalign":
case "singleline":
case "stretchlast":
case "titletrim":
v = +param
if (isNaN(v))
v = get_bool(param) ? 0 : 1
if (cmd[1] == 't') { // stretchlast
if (v < 0 || v > 1) {
syntax(1, errs.bad_val, '%%' + cmd)
break
}
}
cfmt[cmd] = v
break
|
| ︙ | ︙ | |||
847 848 849 850 851 852 853 |
if (font.src)
add_fstyle("@font-face{\n\
font-family:" + font.name + ";\n\
src:" + font.src + "}")
if (font == cfmt.musicfont) // add more music font style
add_fstyle(".f" + font.fid
+ (cfmt.fullsvg || "")
| | | | 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 |
if (font.src)
add_fstyle("@font-face{\n\
font-family:" + font.name + ";\n\
src:" + font.src + "}")
if (font == cfmt.musicfont) // add more music font style
add_fstyle(".f" + font.fid
+ (cfmt.fullsvg || "")
+ ' text,tspan{white-space:pre}')
}
}
// get the font of the 'xxxfont' parameter
function get_font(fn) {
var font, font2, fid, st
fn += "font"
font = cfmt[fn]
if (!font) {
syntax(1, "Unknown font $1", fn)
return gene.curfont
}
if (!font.name || !font.size) { // if incomplete user font
font2 = Object.create(gene.deffont)
if (font.name)
font2.name = font.name
|
| ︙ | ︙ |
Changes to core/front.js.
1 2 | // abc2svg - front.js - ABC parsing front-end // | | | 1 2 3 4 5 6 7 8 9 10 | // abc2svg - front.js - ABC parsing front-end // // Copyright (C) 2014-2022 Jean-Francois Moine // // This file is part of abc2svg-core. // // abc2svg-core is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
269 270 271 272 273 274 275 |
if (flag && src.indexOf('\\') >= 0)
return cnv_escape(src, flag)
return src
} // uncomment()
function end_tune() {
generate()
| < < < < < < | | 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 |
if (flag && src.indexOf('\\') >= 0)
return cnv_escape(src, flag)
return src
} // uncomment()
function end_tune() {
generate()
cfmt = sav.cfmt;
info = sav.info;
char_tb = sav.char_tb;
glovar = sav.glovar;
maps = sav.maps;
mac = sav.mac;
maci = sav.maci;
parse.tune_v_opts = null;
parse.scores = null;
parse.ufmt = false
delete parse.ctrl
init_tune()
img.chg = true;
set_page();
} // end_tune()
// get %%voice
function do_voice(select, in_tune) {
|
| ︙ | ︙ | |||
422 423 424 425 426 427 428 429 430 431 432 433 434 435 |
eol++
if (eol == bol) { // empty line
if (parse.state == 1) {
parse.istart = bol;
syntax(1, "Empty line in tune header - ignored")
} else if (parse.state >= 2) {
end_tune()
if (parse.select) { // skip to next tune
eol = file.indexOf('\nX:', parse.eol)
if (eol < 0)
eol = eof
parse.eol = eol
}
}
| > | 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 |
eol++
if (eol == bol) { // empty line
if (parse.state == 1) {
parse.istart = bol;
syntax(1, "Empty line in tune header - ignored")
} else if (parse.state >= 2) {
end_tune()
parse.state = 0
if (parse.select) { // skip to next tune
eol = file.indexOf('\nX:', parse.eol)
if (eol < 0)
eol = eof
parse.eol = eol
}
}
|
| ︙ | ︙ | |||
488 489 490 491 492 493 494 495 496 497 498 499 500 501 |
syntax(1, "No $1 after %%$2",
end.slice(1), a[1]);
parse.eol = eof
continue
}
self.do_begin_end(b, uncomment(a[2]),
file.slice(eol + 1, i)
.replace(/^%%/gm,''))
parse.eol = file.indexOf('\n', i + 6)
if (parse.eol < 0)
parse.eol = eof
continue
}
switch (a[1]) {
| > | 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 |
syntax(1, "No $1 after %%$2",
end.slice(1), a[1]);
parse.eol = eof
continue
}
self.do_begin_end(b, uncomment(a[2]),
file.slice(eol + 1, i)
.replace(/\n%[^%].*$/gm,'')
.replace(/^%%/gm,''))
parse.eol = file.indexOf('\n', i + 6)
if (parse.eol < 0)
parse.eol = eof
continue
}
switch (a[1]) {
|
| ︙ | ︙ |
Changes to core/gchord.js.
| ︙ | ︙ | |||
17 18 19 20 21 22 23 |
// You should have received a copy of the GNU Lesser General Public License
// along with abc2svg-core. If not, see <http://www.gnu.org/licenses/>.
// -- parse a chord symbol / annotation --
// the result is added in the global variable a_gch
// 'type' may be a single '"' or a string '"xxx"' created by U:
function parse_gchord(type) {
| | | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
// You should have received a copy of the GNU Lesser General Public License
// along with abc2svg-core. If not, see <http://www.gnu.org/licenses/>.
// -- parse a chord symbol / annotation --
// the result is added in the global variable a_gch
// 'type' may be a single '"' or a string '"xxx"' created by U:
function parse_gchord(type) {
var c, text, gch, x_abs, y_abs,
i, j, istart, iend,
ann_font = get_font("annotation"),
h_ann = ann_font.size,
line = parse.line
function get_float() {
var txt = ''
|
| ︙ | ︙ | |||
46 47 48 49 50 51 52 |
i = ++line.index // search the ending double quote
while (1) {
j = line.buffer.indexOf('"', i)
if (j < 0) {
syntax(1, "No end of chord symbol/annotation")
return
}
| | > | 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
i = ++line.index // search the ending double quote
while (1) {
j = line.buffer.indexOf('"', i)
if (j < 0) {
syntax(1, "No end of chord symbol/annotation")
return
}
if (line.buffer[j - 1] != '\\'
|| line.buffer[j - 2] == '\\') // (string ending with \\")
break
i = j + 1
}
text = cnv_escape(line.buffer.slice(line.index, j))
line.index = j
iend = parse.bol + line.index + 1
}
|
| ︙ | ︙ | |||
83 84 85 86 87 88 89 |
y_abs = 0
} else {
y_abs = get_float()
if (c != ' ')
i--
}
gch.x = x_abs;
| < | 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
y_abs = 0
} else {
y_abs = get_float()
if (c != ' ')
i--
}
gch.x = x_abs;
gch.y = y_abs
break
case '^':
gch.pos = C.SL_ABOVE
// fall thru
case '_':
if (c == '_')
|
| ︙ | ︙ | |||
126 127 128 129 130 131 132 |
while (1) {
c = text[i]
if (!c)
break
switch (c) {
case '\\':
c = text[++i]
| | > > | 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
while (1) {
c = text[i]
if (!c)
break
switch (c) {
case '\\':
c = text[++i]
if (c == 'n')
break
gch.text += '\\'
if (!c)
break
default:
gch.text += c;
i++
continue
case '&': /* skip "&xxx;" */
while (1) {
gch.text += c;
|
| ︙ | ︙ | |||
170 171 172 173 174 175 176 | } } // transpose a chord symbol var note_names = "CDEFGAB", acc_name = ["bb", "b", "", "#", "##"] | | > | < < < < < < < < < < < > | > > > > > > > > < < < | 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
}
}
// transpose a chord symbol
var note_names = "CDEFGAB",
acc_name = ["bb", "b", "", "#", "##"]
function gch_tr1(p) {
var i, o, n, a, ip, b40,
tr = curvoice.tr_sco,
csa = p.split('/')
for (i = 0; i < csa.length; i++) { // main and optional bass
p = csa[i];
o = p.search(/[A-G]/)
if (o < 0)
continue // strange chord symbol!
ip = o + 1
a = 0
while (p[ip] == '#' || p[ip] == '\u266f') {
a++;
ip++
}
while (p[ip] == 'b' || p[ip] == '\u266d') {
a--;
ip++
}
n = note_names.indexOf(p[o]) + 16
b40 = (abc2svg.pab40(n, a) + tr + 200) % 40
b40 = abc2svg.b40k[b40]
csa[i] = p.slice(0, o) +
note_names[abc2svg.b40_p[b40]] +
acc_name[abc2svg.b40_a[b40] + 2] +
p.slice(ip)
}
return csa.join('/')
} // gch_tr1
// parser: add the parsed list of chord symbols and annotations
// to the symbol (note, rest or bar)
// and transpose the chord symbols
function csan_add(s) {
var i, gch
// there cannot be chord symbols on measure bars
if (s.type == C.BAR) {
for (i = 0; i < a_gch.length; i++) {
if (a_gch[i].type == 'g') {
error(1, s,
"There cannot be chord symbols on measure bars")
a_gch.splice(i)
}
}
}
if (curvoice.tr_sco) {
for (i = 0; i < a_gch.length; i++) {
gch = a_gch[i]
if (gch.type == 'g')
gch.text = gch_tr1(gch.text)
}
}
if (s.a_gch)
s.a_gch = s.a_gch.concat(a_gch)
else
s.a_gch = a_gch
a_gch = null
} // csan_add
// generator: build the chord symbols / annotations
// (possible hook)
Abc.prototype.gch_build = function(s) {
/* split the chord symbols / annotations
|
| ︙ | ︙ | |||
269 270 271 272 273 274 275 |
return "𝄫"
});
} else {
if (gch.type == '@'
&& !user.anno_start && !user.anno_stop) {
set_font(gch.font)
gch.text = str2svg(gch.text)
| < < | 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 |
return "𝄫"
});
} else {
if (gch.type == '@'
&& !user.anno_start && !user.anno_stop) {
set_font(gch.font)
gch.text = str2svg(gch.text)
continue /* no width */
}
}
/* set the offsets and widths */
set_font(gch.font);
gch.text = str2svg(gch.text)
wh = gch.text.wh
switch (gch.type) {
case '@':
break
case '^': /* above */
case '_': /* below */
xspc = wh[0] * GCHPRE
if (xspc > 8)
|
| ︙ | ︙ | |||
336 337 338 339 340 341 342 |
if (s.invis && s.play) // play sequence: no chord nor annotation
return
var y2,
an = s.a_gch[i],
h = an.text.wh[1],
pad = an.font.pad,
w = an.text.wh[0] + pad * 2,
| | | < < < < < < < | < | < < | | | > > > > > > > > | 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 |
if (s.invis && s.play) // play sequence: no chord nor annotation
return
var y2,
an = s.a_gch[i],
h = an.text.wh[1],
pad = an.font.pad,
w = an.text.wh[0] + pad * 2,
dy = h * .22 // descent
if (an.font.figb) {
h *= 2.4
dy += an.font.size * 1.3
}
switch (an.type) {
case '_': // below
y -= h + pad
break
case '^': // above
y += pad
break
case '<': // left
case '>': // right
if (an.type == '<') {
/*fixme: what symbol space?*/
if (s.notes[0].acc)
x -= s.notes[0].shac
x -= pad
} else {
if (s.xmx)
x += s.xmx
if (s.dots)
x += 1.5 + 3.5 * s.dots
x += pad
}
y += (s.type == C.NOTE ?
(((s.notes[s.nhd].pit + s.notes[0].pit) >> 1) -
18) * 3 :
12) // fixed offset on rests and bars
- h / 2
break
default: // chord symbol
if (y >= 0)
y += pad
else
y -= h + pad
break
case '@': // absolute
y += (s.type == C.NOTE ?
(((s.notes[s.nhd].pit + s.notes[0].pit) >> 1) -
18) * 3 :
12) // fixed offset on rests and bars
- h / 2
if (y > 0) {
y2 = y + h + pad + 2
if (y2 > staff_tb[s.st].ann_top)
staff_tb[s.st].ann_top = y2
} else {
y2 = y - 2
if (y2 < staff_tb[s.st].ann_bot)
staff_tb[s.st].ann_bot = y2
}
break
}
if (an.type != '@') {
if (y > 24)
y_set(s.st, 1, x, w, y + h + pad + 2)
else if (y < 0)
y_set(s.st, 0, x, w, y - pad)
}
use_font(an.font)
set_font(an.font)
set_dscale(s.st)
if (user.anno_start)
user.anno_start("annot", an.istart, an.iend,
x - 2, y + h + 2, w + 4, h + 4, s)
xy_str(x, y + dy, an.text)
|
| ︙ | ︙ | |||
438 439 440 441 442 443 444 |
if (!an)
continue
if (an.pos == C.SL_ABOVE) {
x = s.x + an.x
w = an.text.wh[0]
if (w && x + w > realwidth)
x = realwidth - w // let the text in the page
| | | 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 |
if (!an)
continue
if (an.pos == C.SL_ABOVE) {
x = s.x + an.x
w = an.text.wh[0]
if (w && x + w > realwidth)
x = realwidth - w // let the text in the page
y = y_get(s.st, 1, x, w) + 2 // y / staff
if (an.type == 'g' && y < minmax[s.st].yup)
y = minmax[s.st].yup
} else if (an.pos == C.SL_BELOW
|| an.pos == C.SL_HIDDEN) {
continue
} else {
x = s.x + an.x
|
| ︙ | ︙ | |||
467 468 469 470 471 472 473 | if (!an || an.pos != C.SL_BELOW) continue x = s.x + an.x w = an.text.wh[0] if (w && x + w > realwidth) // let the text inside the page x = realwidth - w | | | 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 | if (!an || an.pos != C.SL_BELOW) continue x = s.x + an.x w = an.text.wh[0] if (w && x + w > realwidth) // let the text inside the page x = realwidth - w y = y_get(s.st, 0, x, w) - 2 // y / staff if (an.type == 'g' && y > minmax[s.st].ydn) y = minmax[s.st].ydn self.draw_gchord(i, s, x, y) } } // set_an_yl() // get the number of chord symbols / annotations |
| ︙ | ︙ | |||
495 496 497 498 499 500 501 |
if (i > n_an)
n_an = i
while (--i >= 0) {
if (an[i].type == 'g') {
an = an[i]
w = an.text.wh[0]
if (an.pos == C.SL_ABOVE) {
| | | | 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 |
if (i > n_an)
n_an = i
while (--i >= 0) {
if (an[i].type == 'g') {
an = an[i]
w = an.text.wh[0]
if (an.pos == C.SL_ABOVE) {
y = y_get(s.st, true, s.x, w) + 2
if (y > minmax[s.st].yup)
minmax[s.st].yup = y
} else if (an.pos == C.SL_BELOW) {
y = y_get(s.st, false, s.x, w) - 2
if (y < minmax[s.st].ydn)
minmax[s.st].ydn = y
}
break
}
}
}
|
| ︙ | ︙ |
Changes to core/license.
1 2 | // abc2svg - ABC to SVG translator // @source: https://chiselapp.com/user/moinejf/repository/abc2svg | | | 1 2 3 | // abc2svg - ABC to SVG translator // @source: https://chiselapp.com/user/moinejf/repository/abc2svg // Copyright (C) 2014-2023 Jean-Francois Moine - LGPL3+ |
Changes to core/lyrics.js.
1 2 | // abc2svg - lyrics.js - lyrics // | | | 1 2 3 4 5 6 7 8 9 10 | // abc2svg - lyrics.js - lyrics // // Copyright (C) 2014-2022 Jean-Francois Moine // // This file is part of abc2svg-core. // // abc2svg-core is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
200 201 202 203 204 205 206 | case '*': case '|': i-- case ' ': case '\t': break case '~': | | | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | case '*': case '|': i-- case ' ': case '\t': break case '~': word += ' ' i++ continue case '-': ln = 1 // start of line break case '\\': if (!p[++i]) |
| ︙ | ︙ | |||
313 314 315 316 317 318 319 |
shift = s.wl
} else if ((p[0] >= '0' && p[0] <= '9' && p.length > 2)
|| p[1] == ':'
|| p[0] == '(' || p[0] == ')') {
if (p[0] == '(') {
sz = spw
} else {
| | | 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 |
shift = s.wl
} else if ((p[0] >= '0' && p[0] <= '9' && p.length > 2)
|| p[1] == ':'
|| p[0] == '(' || p[0] == ')') {
if (p[0] == '(') {
sz = spw
} else {
j = p.indexOf(' ')
set_font(ly.font)
if (j > 0)
sz = strwh(p.slice(0, j))[0]
else
sz = w * .2
}
w -= sz
|
| ︙ | ︙ | |||
382 383 384 385 386 387 388 |
}
} // ly_set()
/* -- draw the lyrics under (or above) notes -- */
/* (the staves are not yet defined) */
function draw_lyric_line(p_voice, j, y) {
var p, lastx, w, s, s2, ly, lyl, ln,
| | | 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 |
}
} // ly_set()
/* -- draw the lyrics under (or above) notes -- */
/* (the staves are not yet defined) */
function draw_lyric_line(p_voice, j, y) {
var p, lastx, w, s, s2, ly, lyl, ln,
hyflag, lflag, x0, shift
if (p_voice.hy_st & (1 << j)) {
hyflag = true;
p_voice.hy_st &= ~(1 << j)
}
for (s = p_voice.sym; /*s*/; s = s.next)
if (s.type != C.CLEF
|
| ︙ | ︙ | |||
412 413 414 415 416 417 418 | lflag = false; lastx = s.x + s.wr } } continue } if (ly.font != gene.curfont) /* font change */ | | | 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 |
lflag = false;
lastx = s.x + s.wr
}
}
continue
}
if (ly.font != gene.curfont) /* font change */
gene.curfont = ly.font
p = ly.t;
w = p.wh[0]
shift = ly.shift
if (hyflag) {
if (ly.ln == 2 && p == "_") { // '_'
p = "-"
} else if (ly.ln != 2) { // not '-'
|
| ︙ | ︙ | |||
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 |
continue
}
x0 = s.x - shift;
if (ly.ln) // '-' at end
hyflag = true
if (user.anno_start || user.anno_stop) {
s2 = {
st: s.st,
istart: ly.istart,
iend: ly.iend,
x: x0,
y: y,
ymn: y,
ymx: y + gene.curfont.size,
wl: 0,
wr: w
}
| > > > | 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 |
continue
}
x0 = s.x - shift;
if (ly.ln) // '-' at end
hyflag = true
if (user.anno_start || user.anno_stop) {
s2 = {
p_v: s.p_v,
st: s.st,
istart: ly.istart,
iend: ly.iend,
ts_prev: s,
ts_next: s.ts_next,
x: x0,
y: y,
ymn: y,
ymx: y + gene.curfont.size,
wl: 0,
wr: w
}
|
| ︙ | ︙ |
Changes to core/mei.js.
| ︙ | ︙ | |||
696 697 698 699 700 701 702 |
curr.beam = 2
break
}
sym_link(s)
}
}
if (id) {
| | > | 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 |
curr.beam = 2
break
}
sym_link(s)
}
}
if (id) {
note.s = s // chord
note.m = s.nhd // note index in the chord
do_delayed(id, curr.chord ? note : s)
}
note.dur = dur
if (acc_ty[tag.accid])
note.acc = acc_ty[tag.accid]
//fixme: may have notes of the chord on different staves
|
| ︙ | ︙ | |||
1015 1016 1017 1018 1019 1020 1021 |
case "below": ty = C.SL_BELOW; break
}
switch (tag.lform) {
case "dashed":
case "dotted": ty |= C.SL_DOTTED; break
}
| | < < < | | | > > > > < < | 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 |
case "below": ty = C.SL_BELOW; break
}
switch (tag.lform) {
case "dashed":
case "dotted": ty |= C.SL_DOTTED; break
}
sl = {
ty: ty,
ss: s1.s || s1,
se: s2.s || s2
}
if (s1.s)
sl.nts = s1
if (s2.s)
sl.nte = s2 // to note
if (!s1.sls)
s1.sls = []
s1.sls.push(sl)
//fixme: ko if grace note
}, // slur()
sourceDesc: function(tag) {
return true // skip
},
|
| ︙ | ︙ |
Changes to core/modules.js.
1 2 | // abc2svg - modules.js - module handling // | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
// abc2svg - modules.js - module handling
//
// Copyright (C) 2018-2022 Jean-Francois Moine
//
// This file is part of abc2svg-core.
//
// abc2svg-core is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// abc2svg-core is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with abc2svg-core. If not, see <http://www.gnu.org/licenses/>.
// empty function
if (!abc2svg.loadjs) {
abc2svg.loadjs = function(fn, onsuccess, onerror) {
if (onerror)
onerror(fn)
}
}
abc2svg.modules = {
ambitus: {},
begingrid: { fn: 'grid3' },
beginps: { fn: 'psvg' },
|
| ︙ | ︙ | |||
49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
pedline: {},
percmap: { fn: 'perc' },
roman: {},
soloffs: {},
sth: {},
strtab: {},
temperament: { fn: 'temper' },
nreq: 0,
hooks: [],
g_hooks: [],
// scan the file and find the required modules
// @file: ABC file
| > | 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
pedline: {},
percmap: { fn: 'perc' },
roman: {},
soloffs: {},
sth: {},
strtab: {},
temperament: { fn: 'temper' },
tropt: {},
nreq: 0,
hooks: [],
g_hooks: [],
// scan the file and find the required modules
// @file: ABC file
|
| ︙ | ︙ | |||
79 80 81 82 83 84 85 |
} // get_errmsg()
// call back functions for loadjs()
function load_end() {
if (--abc2svg.modules.nreq == 0)
abc2svg.modules.cbf()
}
| < < < < | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
} // get_errmsg()
// call back functions for loadjs()
function load_end() {
if (--abc2svg.modules.nreq == 0)
abc2svg.modules.cbf()
}
// test if some keyword in the file
var m, i, fn,
nreq_i = this.nreq,
ls = file.match(/(^|\n)(%%|I:).+?\b/g)
if (!ls)
|
| ︙ | ︙ | |||
109 110 111 112 113 114 115 | // load the module if (m.fn) fn = m.fn this.nreq++ abc2svg.loadjs(fn + "-1.js", load_end, | | > > > > | 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
// load the module
if (m.fn)
fn = m.fn
this.nreq++
abc2svg.loadjs(fn + "-1.js",
load_end,
function () {
abc2svg.modules.errmsg(
'Error loading the module ' + fn)
load_end()
})
}
return this.nreq == nreq_i
}
} // modules
|
Changes to core/music.js.
1 2 | // abc2svg - music.js - music generation // | | | 1 2 3 4 5 6 7 8 9 10 | // abc2svg - music.js - music generation // // Copyright (C) 2014-2023 Jean-Francois Moine // // This file is part of abc2svg-core. // // abc2svg-core is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
236 237 238 239 240 241 242 |
if (p1 > ps + 4) { // if interval greater than a sixth
if (dx1 > dx2)
dx2 = dx1 // align the accidentals
notes[i1].shac = notes[i2].shac = dx2
} else {
notes[i1].shac = dx1
| < | | 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
if (p1 > ps + 4) { // if interval greater than a sixth
if (dx1 > dx2)
dx2 = dx1 // align the accidentals
notes[i1].shac = notes[i2].shac = dx2
} else {
notes[i1].shac = dx1
dx1 += 7
notes[i2].shac = dx2 = dx1
}
dx2 += 7
// shift the remaining accidentals
for (i = i1; --i > i2; ) { // from top to bottom
acc = notes[i].acc
|
| ︙ | ︙ | |||
310 311 312 313 314 315 316 | continue } dx_head = dx_tb[s.head] // build a pseudo chord and shift the accidentals notes = [] | | > | > | 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 |
continue
}
dx_head = dx_tb[s.head]
// build a pseudo chord and shift the accidentals
notes = []
for ( ; s != s2; s = s.ts_next) {
if (!s.invis)
Array.prototype.push.apply(notes, s.notes)
}
notes.sort(abc2svg.pitcmp)
acc_shift(notes, dx_head)
}
}
// link a symbol before an other one
function lkvsym(s, next) { // voice linkage
|
| ︙ | ︙ | |||
690 691 692 693 694 695 696 |
}
switch (s.type) {
case C.NOTE:
case C.REST:
/* set the note widths */
| | | 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 |
}
switch (s.type) {
case C.NOTE:
case C.REST:
/* set the note widths */
s.wr = wlnote = s.invis ? 0 : hw_tb[s.head]
/* room for shifted heads and accidental signs */
if (s.xmx > 0)
s.wr += s.xmx + 4;
for (s2 = s.prev; s2; s2 = s2.prev) {
if (w_tb[s2.type])
break
|
| ︙ | ︙ | |||
801 802 803 804 805 806 807 | wlw = 14 } break case C.CLEF: /* extra space at start of line */ if (s2.second || s2.clef_small) break | < | | | | | > | > | 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 |
wlw = 14
}
break
case C.CLEF: /* extra space at start of line */
if (s2.second
|| s2.clef_small)
break
// fall thru
case C.KEY:
case C.METER:
wlw += 3
break
}
}
/* leave room for guitar chord */
if (s.a_gch)
wlw = gchord_width(s, wlnote, wlw)
// ignore the lyrics for now
/* if preceeded by a grace note sequence, adjust */
if (s.prev && s.prev.type == C.GRACE) {
s.prev.wl += wlnote - 4.5
s.wl = s.prev.wl
} else {
s.wl = wlw
}
return
case C.SPACE:
xx = s.width / 2;
s.wr = xx
if (s.a_gch)
xx = gchord_width(s, xx, xx)
if (s.a_dd)
|
| ︙ | ︙ | |||
864 865 866 867 868 869 870 | && s.next.type != C.METER) s.wr = 7 else s.wr = 5 // s.notes[0].shhd = (w - 5) * -.5 /* if preceeded by a grace note sequence, adjust */ | | < | | > > | 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 |
&& s.next.type != C.METER)
s.wr = 7
else
s.wr = 5
// s.notes[0].shhd = (w - 5) * -.5
/* if preceeded by a grace note sequence, adjust */
s2 = s.prev
if (s2 && s2.type == C.GRACE)
s.wl -= 6
for ( ; s2; s2 = s2.prev) {
if (w_tb[s2.type]) {
if (s2.type == C.STBRK)
s.wl -= 12
break
}
}
if (s.a_dd)
|
| ︙ | ︙ | |||
894 895 896 897 898 899 900 |
case C.CLEF:
// (there may be invisible clefs in empty staves)
if (s.invis) {
s.wl = s.wr = 1 // (!! not 0 !!)
return
}
s.wl = s.clef_small ? 11 : 12
| | < < | | < | > > | > > > > > > > > < > > > | 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 |
case C.CLEF:
// (there may be invisible clefs in empty staves)
if (s.invis) {
s.wl = s.wr = 1 // (!! not 0 !!)
return
}
s.wl = s.clef_small ? 11 : 12
s.wr = s.clef_small ? 8 : 13
if (s.prev && s.prev.type == C.STBRK) {
s.wl -= 6
delete s.next.clef_small
}
return
case C.KEY:
if (s.invis) { // if no accidental
s.wl = s.wr = 0 // no width
return
}
s.wl = 0
esp = 3
n1 = s.k_sf /* new key sig */
if (s.k_old_sf && (s.fmt.cancelkey || n1 == 0))
n2 = s.k_old_sf /* old key */
else
n2 = 0
if (n1 * n2 >= 0) { /* if no natural */
if (n1 < 0)
n1 = -n1
if (n2 < 0)
n2 = -n2
if (n2 > n1)
n1 = n2
} else {
n1 -= n2
if (n1 < 0)
n1 = -n1;
esp += 3 /* see extra space in draw_keysig() */
}
if (s.k_bagpipe == 'p') // K:Hp - add the g natural
n1++
if (s.k_a_acc) {
n2 = s.k_a_acc.length
if (s.exp)
n1 = n2 // no key signature
else
n1 += n2
if (n2)
last_acc = s.k_a_acc[0].acc
for (i = 1; i < n2; i++) {
acc = s.k_a_acc[i]
if (acc.pit > s.k_a_acc[i - 1].pit + 6
|| acc.pit < s.k_a_acc[i - 1].pit - 6)
n1-- // no clash
else if (acc.acc != last_acc)
esp += 3;
last_acc = acc.acc
}
}
if (!n1)
break // no width
s.wr = 5.5 * n1 + esp
if (s.prev && !s.prev.bar_type)
s.wl += 2
return
case C.METER:
s.x_meter = []
if (!s.a_meter.length)
break // no width
wlw = 0
for (i = 0; i < s.a_meter.length; i++) {
meter = s.a_meter[i]
switch (meter.top[0]) {
case 'C':
case 'c':
case 'o':
s.x_meter[i] = wlw + 6;
|
| ︙ | ︙ | |||
985 986 987 988 989 990 991 | break } } s.x_meter[i] = wlw + w / 2 wlw += w } } | | | | 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 | break } } s.x_meter[i] = wlw + w / 2 wlw += w } } s.wl = 1 s.wr = wlw + 7 return case C.MREST: s.wl = 6; s.wr = 66 return case C.GRACE: if (s.invis) |
| ︙ | ︙ | |||
1106 1107 1108 1109 1110 1111 1112 |
while (!s.dur) {
switch (s.type) {
case C.BAR:
// (hack to have quite the same note widths between measures)
if (!s.next)
space *= .9
| | | 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 |
while (!s.dur) {
switch (s.type) {
case C.BAR:
// (hack to have quite the same note widths between measures)
if (!s.next)
space *= .9
return space * .9 - 3
case C.CLEF:
return space - s.wl - s.wr
case C.BLOCK: // no space
case C.REMARK:
case C.STAVES:
case C.TEMPO:
s = s.ts_next
|
| ︙ | ︙ | |||
1225 1226 1227 1228 1229 1230 1231 |
prev: s,
fmt: s.fmt
}
} // _bar()
// create an invisible bar for end of music lines
function add_end_bar(s) {
| | > | | > | | > > > > | | < < < < < < < > | > > > > > > > | | | 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 |
prev: s,
fmt: s.fmt
}
} // _bar()
// create an invisible bar for end of music lines
function add_end_bar(s) {
var b = _bar(s),
sn = s.ts_next // start of next line
b.wl = 0
b.wr = 0
b.ts_prev = s
b.next = s.next
b.ts_next = s.ts_next
b.shrink = s.type == C.STBRK ? 0 : (s.wr + 3)
if (s.next) // (must not be the end of the voice)
s.next.prev = b
// if (s.ts_next)
s.ts_next.ts_prev = b
s.next = s.ts_next = b
b.space = sn.space * .9 - 3
return b
}
/* -- set the width and space of all symbols -- */
// this function is called once for the whole tune
// and once more for each new music line
function set_allsymwidth(first) {
var val, st, s_chs, stup, itup,
s = tsfirst,
s2 = s,
xa = 0,
xl = [],
wr = [],
maxx = xa,
tim = s.time
/* loop on all symbols */
while (1) {
itup = 0
do {
if ((s.a_gch || s.a_ly) && !s_chs)
s_chs = s;
self.set_width(s);
st = s.st
if (xl[st] == undefined)
xl[st] = 0
if (wr[st] == undefined)
wr[st] = 0;
val = xl[st] + wr[st] + s.wl
if (val > maxx)
maxx = val
if (s.dur && s.dur != s.notes[0].dur // if in tuplet
&& first) // (first time only)
itup = 1
s = s.ts_next
} while (s && !s.seqst);
// set the spaces of the time sequence
s2.shrink = maxx - xa
s2.space = s2.ts_prev ? set_space(s2, tim) : 0
// adjust the spacing when after a spacer (y)
if (s2.space == 0 && s2.ts_prev
&& s2.ts_prev.type == C.SPACE && s2.ts_prev.seqst)
s2.space = s2.ts_prev.space /= 2
if (itup) {
if (!stup)
stup = s2
} else if (stup && stup.v == s2.v) {
set_sp_tup(stup, s2)
stup = null
}
if (!s2.shrink) {
if (!s2.space && s2.type == C.CLEF
&& !s2.ts_prev.bar_type) {
delete s2.seqst; /* no space */
s2.time = tim
} else if (s2.dur) {
s2.shrink = 10 // cannot be null
}
}
tim = s2.time
if (!s)
break
// update the min left space per staff
for (st = 0; st < wr.length; st++)
wr[st] = 0;
xa = maxx
do {
st = s2.st;
xl[st] = xa
if (s2.wr > wr[st])
wr[st] = s2.wr
s2 = s2.ts_next
} while (!s2.seqst)
}
if (stup)
set_sp_tup(stup, s2)
// let the chord symbols at the same offset
// and adjust the spacing due to the lyrics
if (first && s_chs)
set_w_chs(s_chs)
}
// insert a rest, this one replacing a sequence or a measure
function to_rest(so) {
var s = clone(so)
s.prev.next = so.ts_prev = so.prev = s.ts_prev.ts_next = s
s.next = s.ts_next = so
so.seqst = false
so.invis = so.play = true
s.type = C.REST
// just keep nl and seqst
delete s.in_tuplet
delete s.tp
delete s.a_dd
delete s.a_gch
delete s.sls
//fixme: what if chord / slur in notes / ... ?
/*fixme: should set many parameters for set_width*/
// set_width(s)
return s
|
| ︙ | ︙ | |||
1594 1595 1596 1597 1598 1599 1600 |
/* -- define the beginning of a new music line -- */
function set_nl(s) { // s = start of line
var p_voice, done, tim, ptyp
// divide the left repeat (|:) or variant bars (|1)
// the new bars go in the next line
function bardiv(so) { // start of next line
| | | 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 |
/* -- define the beginning of a new music line -- */
function set_nl(s) { // s = start of line
var p_voice, done, tim, ptyp
// divide the left repeat (|:) or variant bars (|1)
// the new bars go in the next line
function bardiv(so) { // start of next line
var s, s1, s2, t1, t2, i
function new_type(s) {
var t = s.bar_type.match(/(:*)([^:]*)(:*)/)
// [1] = starting ':'s, [2] = middle, [3] = ending ':'s
if (!t[3]) { // if start of variant
// |1 -> | [1
|
| ︙ | ︙ | |||
1621 1622 1623 1624 1625 1626 1627 |
}
} // new_typ()
s = so // start of sequence
while (s.ts_prev
&& s.ts_prev.time == so.time) {
s = s.ts_prev
| | > > > > > > > | | < < > | > | | < | < < < | 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 |
}
} // new_typ()
s = so // start of sequence
while (s.ts_prev
&& s.ts_prev.time == so.time) {
s = s.ts_prev
if (s.bar_type) {
// if repeat variant, move the new line
if (s.bar_type[0] == '['
&& s.text
&& s.ts_next == so)
so = s
s1 = s // first previous bar
}
// if (s.type == C.GRACE)
// so = s // keep the grace notes in the next line
}
if (!s1)
return so
// search the insertion point in the new line
for (s = so; ; s = s.ts_next) {
switch (s.type) {
// default:
// if (w_tb[s.type])
// break
case C.KEY:
case C.METER:
case C.CLEF:
continue
}
break
}
while (s1 != so) {
if (s1.bar_type
&& s1.next
&& (s1.bar_type.slice(-1) == ':'
|| s1.text)
&& s1.bar_type != ':') {
new_type(s1) // return t1 and t2
s2 = clone(s1)
s1.bar_type = t1
delete s1.a_gch
if (t1 == '|')
delete s1.rbstop // (needed for play variant)
s2.bar_type = t2
lkvsym(s2, s1.next) // voice
while (1) {
if (s.type != C.BAR
//fixme: pb if inverted voices
|| s.v > s2.v)
break
s = s.ts_next
}
lktsym(s2, s) // time
if (s1.seqst)
s2.seqst = 1
if (s == so)
so = s2
if (s1.text) {
s2.invis = true
delete s1.text
delete s1.rbstart
}
|
| ︙ | ︙ | |||
1699 1700 1701 1702 1703 1704 1705 |
if (s.type != C.BAR)
add_end_bar(s)
} // set_eol()
// put the warning symbols
// the new symbols go in the previous line
function do_warn(s) { // start of next line
| | | 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 |
if (s.type != C.BAR)
add_end_bar(s)
} // set_eol()
// put the warning symbols
// the new symbols go in the previous line
function do_warn(s) { // start of next line
var s1, s2, s3, s4
// advance in the next line
for (s2 = s; s2; s2 = s2.ts_next) {
switch (s2.type) {
case C.KEY:
if (!s.fmt.keywarn
|| s2.invis)
|
| ︙ | ︙ | |||
1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 |
s1 = s.ts_prev
}
// fall thru
case C.CLEF:
if (!s2.prev) // start of voice
continue
if (s2.type == C.CLEF) {
for (s1 = s.ts_prev; s1; s1 = s1.ts_prev) {
switch (s1.type) {
case C.BAR:
case C.KEY:
case C.METER:
continue
}
break
}
}
| > > > > > | 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 |
s1 = s.ts_prev
}
// fall thru
case C.CLEF:
if (!s2.prev) // start of voice
continue
if (s2.type == C.CLEF) {
if (s2.invis) // if 'K: clef=none' after bar
break
for (s1 = s.ts_prev; s1; s1 = s1.ts_prev) {
switch (s1.type) {
case C.BAR:
if (s1.bar_type[0] == ':')
break
// fall thru
case C.KEY:
case C.METER:
continue
}
break
}
}
|
| ︙ | ︙ | |||
1750 1751 1752 1753 1754 1755 1756 1757 |
if (s1.v == s2.v)
break
}
lkvsym(s3, s1) // voice link
// care with spacing
if (s3.seqst) {
s3.shrink = s3.wl
| > > > | | | > > > | | 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 |
if (s1.v == s2.v)
break
}
lkvsym(s3, s1) // voice link
// care with spacing
if (s3.seqst) {
self.set_width(s3)
s3.shrink = s3.wl
s4 = s3.ts_prev
while (!s4.seqst)
s4 = s4.ts_prev
s3.shrink += s4.wr
s3.space = 0
s4 = s3.ts_next
while (!s4.seqst)
s4 = s4.ts_next
s4.shrink = s3.wr + s4.wl
}
delete s3.part
continue
}
if (w_tb[s2.type])
break // symbol with a width
}
|
| ︙ | ︙ | |||
1881 1882 1883 1884 1885 1886 1887 |
}
/* -- search where to cut the lines according to the staff width -- */
function set_lines( s, /* first symbol */
next, /* symbol of the next line / null */
lwidth, /* w - (clef & key sig) */
indent) { /* for start of tune */
| | | | | 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 |
}
/* -- search where to cut the lines according to the staff width -- */
function set_lines( s, /* first symbol */
next, /* symbol of the next line / null */
lwidth, /* w - (clef & key sig) */
indent) { /* for start of tune */
var first, s2, s3, s4, s5, x, xmin, xmid, xmax, wwidth, shrink, space,
nlines,
last = next ? next.ts_prev : null,
ws = get_width(s, next) // 2 widths: nice and shrunk
// take care of big key signatures at end of line
if (s.fmt.keywarn && next
&& next.type == C.KEY && !last.dur) {
ws[0] += next.wr
ws[1] += next.wr
}
// check if the symbols can enter in one line
if (ws[0] + indent < lwidth) {
if (next)
next = set_nl(next)
return next || last
}
/* loop on cutting the tune into music lines */
wwidth = ws[0] + indent
|
| ︙ | ︙ | |||
1926 1927 1928 1929 1930 1931 1932 |
s2 = s
if (s.x >= xmin)
break
}
s4 = s // keep first symbol with x greater than xmin
//fixme: can this occur?
if (s == next) {
| | | | | 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 |
s2 = s
if (s.x >= xmin)
break
}
s4 = s // keep first symbol with x greater than xmin
//fixme: can this occur?
if (s == next) {
if (s)
s = set_nl(s)
return s
}
/* try to cut on a measure bar */
s3 = null
for ( ; s != next; s = s.ts_next) {
x = s.x
if (!x)
|
| ︙ | ︙ | |||
1960 1961 1962 1963 1964 1965 1966 1967 |
if (!s3) {
s = s4 // restart after xmin
var beam = 0,
bar_time = s2.time
xmax -= 8; // (left width of the inserted bar in set_allsymwidth)
for ( ; s != next; s = s.ts_next) {
| > | < < < < < | < < | | | < < | | < > | > > > > | > > | > | | | 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 |
if (!s3) {
s = s4 // restart after xmin
var beam = 0,
bar_time = s2.time
xmax -= 8; // (left width of the inserted bar in set_allsymwidth)
s5 = s
for ( ; s != next; s = s.ts_next) {
if (s.seqst) {
x = s.x
if (x + s.wr >= xmax)
break
if (!beam && !s.in_tuplet
&& (xmid - s5.x > x - xmid
|| (s.time - bar_time)
% (C.BLEN / 4) == 0))
s3 = s
}
if (s.beam_st)
beam |= 1 << s.v
if (s.beam_end)
beam &= ~(1 << s.v)
s5 = s // start of new time sequence
}
if (s3) {
do { // cut on the previous sequence
s3 = s3.ts_prev
} while (!s3.seqst)
}
}
// cut anyhere
if (!s3) {
s3 = s = s4
for ( ; s != next; s = s.ts_next) {
x = s.x
if (!x)
continue
if (x + s.wr >= xmax)
break
if (s3 && x >= xmid) {
if (xmid - s3.x > x - xmid)
s3 = s
break
}
s3 = s
}
}
s = s3
|
| ︙ | ︙ | |||
2032 2033 2034 2035 2036 2037 2038 | wwidth -= s.x - first.x; indent = 0 } return s } /* -- cut the tune into music lines -- */ | | | < | | | | | | > > < < < | > | | < | < < < | | | 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 |
wwidth -= s.x - first.x;
indent = 0
}
return s
}
/* -- cut the tune into music lines -- */
function cut_tune(lwidth, lsh) {
var s2, i, mc,
pg_sav = { // save the page parameters
leftmargin: cfmt.leftmargin,
rightmargin: cfmt.rightmargin,
pagewidth: cfmt.pagewidth,
scale: cfmt.scale
},
indent = lsh[0] - lsh[1], // extra width of the first line
ckw = get_ck_width(), // width of the starting symbols
s = tsfirst
lwidth -= lsh[1] // width of the lines
if (cfmt.indent && cfmt.indent > lsh[0])
indent += cfmt.indent
// adjust the line width according to the starting symbols
lwidth -= ckw[0]
indent += ckw[1]
if (cfmt.custos && voice_tb.length == 1)
lwidth -= 12
/* if asked, count the measures and set the EOLNs */
i = s.fmt.barsperstaff
if (i) {
|
| ︙ | ︙ | |||
2079 2080 2081 2082 2083 2084 2085 |
i = s.fmt.barsperstaff
}
}
/* cut at explicit end of line, checking the line width */
s2 = s
for ( ; s; s = s.ts_next) {
| < | | | | | | | | > | | < > > | > > > > > > > | > > > > > | | | < | | | | | > > | 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 |
i = s.fmt.barsperstaff
}
}
/* cut at explicit end of line, checking the line width */
s2 = s
for ( ; s; s = s.ts_next) {
if (s.type == C.BLOCK) {
switch (s.subtype) {
case "leftmargin":
case "rightmargin":
case "pagescale":
case "pagewidth":
case "scale":
case "staffwidth":
if (!s.soln)
self.set_format(s.subtype, s.param)
break
case "mc_start":
mc = {
lm: cfmt.leftmargin,
rm: cfmt.rightmargin
}
break
case "mc_new":
case "mc_end":
cfmt.leftmargin = mc.lm
cfmt.rightmargin = mc.rm
img.chg = 1 //true
break
}
}
if (!s.ts_next) {
s = null
} else if (!s.soln) {
continue
} else {
s.soln = false
if (s.time == s2.time)
continue // empty music line!
while (!s.seqst)
s = s.ts_prev
}
set_page()
lwidth = get_lwidth() - lsh[1] - ckw[0]
s2 = set_lines(s2, s, lwidth, indent)
if (!s2)
break
s = s2.type == C.BLOCK
? s2.ts_prev // don't miss a parameter
: s
indent = 0
}
// restore the page parameters at start of line
cfmt.leftmargin = pg_sav.leftmargin
cfmt.rightmargin = pg_sav.rightmargin
cfmt.pagewidth = pg_sav.pagewidth
cfmt.scale = pg_sav.scale
img.chg = 1
set_page()
}
/* -- set the y values of some symbols -- */
function set_yval(s) {
//fixme: staff_tb is not yet defined
// var top = staff_tb[s.st].topbar
// var bot = staff_tb[s.st].botbar
|
| ︙ | ︙ | |||
2501 2502 2503 2504 2505 2506 2507 |
}
/* go backwards and search where to insert a clef change */
s3 = s
for (s2 = s.ts_prev; s2 != s_last_chg; s2 = s2.ts_prev) {
if (s2.st != st)
continue
| | < | 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 |
}
/* go backwards and search where to insert a clef change */
s3 = s
for (s2 = s.ts_prev; s2 != s_last_chg; s2 = s2.ts_prev) {
if (s2.st != st)
continue
if (s2.type == C.BAR) {
s3 = s2.bar_type[0] != ':' ? s2 : s2.next
break
}
if (s2.type != C.NOTE)
continue
/* have a 2nd choice on beam start */
|
| ︙ | ︙ | |||
2558 2559 2560 2561 2562 2563 2564 |
}
staff_tb[st] = {
output: "",
sc_out: ""
}
}
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 |
}
staff_tb[st] = {
output: "",
sc_out: ""
}
}
for (st = 0; st <= sy.nstaff; st++)
mid[st] = (sy.staves[st].stafflines.length - 1) * 3
for (s = tsfirst; s; s = s.ts_next) {
if (s.repeat_n)
set_repeat(s)
|
| ︙ | ︙ | |||
2646 2647 2648 2649 2650 2651 2652 |
new_line = new_type == 't' ? 2 : 4
} else {
new_type = s2.clef_type;
new_line = s2.clef_line
}
if (!staff_clef[st].clef) { // new staff
if (s2.clef_auto) {
| | | 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 |
new_line = new_type == 't' ? 2 : 4
} else {
new_type = s2.clef_type;
new_line = s2.clef_line
}
if (!staff_clef[st].clef) { // new staff
if (s2.clef_auto) {
if (s2.clef_type != 'a')
p_voice.clef =
clone(p_voice.clef);
p_voice.clef.clef_type = new_type;
p_voice.clef.clef_line = new_line
}
staff_tb[st].clef =
staff_clef[st].clef = p_voice.clef
|
| ︙ | ︙ | |||
2766 2767 2768 2769 2770 2771 2772 | } /* upper and lower space needed by rests */ var rest_sp = [ [18, 18], [12, 18], [12, 12], | | | 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 | } /* upper and lower space needed by rests */ var rest_sp = [ [18, 18], [12, 18], [12, 12], [6, 12], [6, 8], [10, 10], /* crotchet */ [6, 4], [10, 0], [10, 4], [10, 10] ] |
| ︙ | ︙ | |||
3248 3249 3250 3251 3252 3253 3254 |
p_v.last_sym = s;
lktsym(s, last_s)
}
/* -- init the symbols at start of a music line -- */
function init_music_line() {
| | | > > < < < < < < < < < < < < < | < < | 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 |
p_v.last_sym = s;
lktsym(s, last_s)
}
/* -- init the symbols at start of a music line -- */
function init_music_line() {
var p_voice, s, s1, s2, s3, last_s, v, st, shr, shrmx, shl,
shlp, p_st, top,
nv = voice_tb.length,
fmt = tsfirst.fmt
/* initialize the voices */
for (v = 0; v < nv; v++) {
if (!cur_sy.voices[v])
continue
p_voice = voice_tb[v];
p_voice.st = cur_sy.voices[v].st
p_voice.second = cur_sy.voices[v].second;
p_voice.last_sym = p_voice.sym;
// move the first clefs, key signatures and time signatures
// to the staves
for (s = p_voice.sym; s && s.time == tsfirst.time; s = s.next) {
switch (s.type) {
case C.CLEF:
case C.KEY:
case C.METER:
switch (s.type) {
case C.CLEF:
staff_tb[s.st].clef = s
|
| ︙ | ︙ | |||
3302 3303 3304 3305 3306 3307 3308 | break } unlksym(s) // fall thru case C.TEMPO: case C.BLOCK: case C.REMARK: | < > | 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 |
break
}
unlksym(s)
// fall thru
case C.TEMPO:
case C.BLOCK:
case C.REMARK:
continue
}
break
}
}
// generate the starting clefs, key signatures and time signatures
// add a clef at start of the main voices
last_s = tsfirst
for (v = 0; v < nv; v++) {
|
| ︙ | ︙ | |||
3343 3344 3345 3346 3347 3348 3349 |
s.ts_prev = null
if (!s.ts_prev) {
tsfirst = s;
} else {
s.ts_prev.ts_next = s
delete s.seqst
}
| | < | < | > > | 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 |
s.ts_prev = null
if (!s.ts_prev) {
tsfirst = s;
} else {
s.ts_prev.ts_next = s
delete s.seqst
}
if (last_s)
last_s.ts_prev = s
delete s.clef_small;
delete s.part
s.second = cur_sy.voices[v].second
// (fixme: needed for sample5 X:3 Fugue & staffnonote.xhtml)
if (!cur_sy.st_print[st])
s.invis = true
s.fmt = fmt
}
/* add keysig */
for (v = 0; v < nv; v++) {
if (!cur_sy.voices[v]
|| cur_sy.voices[v].second
|| !cur_sy.st_print[cur_sy.voices[v].st])
continue
p_voice = voice_tb[v]
s2 = p_voice.ckey
if (s2.k_sf || s2.k_a_acc) {
s = clone(s2)
new_sym(s, p_voice, last_s)
delete s.invis
delete s.part
s.k_old_sf = s2.k_sf // no key cancel
s.fmt = fmt
}
}
/* add time signature (meter) if needed */
if (insert_meter) {
for (v = 0; v < nv; v++) {
p_voice = voice_tb[v];
s2 = p_voice.meter
if (!cur_sy.voices[v]
|| cur_sy.voices[v].second
|| !cur_sy.st_print[cur_sy.voices[v].st])
// || !s2.a_meter.length)
continue
s = clone(s2)
new_sym(s, p_voice, last_s)
delete s.part
s.fmt = fmt
}
insert_meter = false // no meter any more
}
// add an invisible bar for the various continued elements
for (v = 0; v < nv; v++) {
|
| ︙ | ︙ | |||
3443 3444 3445 3446 3447 3448 3449 | } // compute the spacing of the added symbols self.set_pitch(last_s); s = tsfirst s.seqst = true | < < < < < < < < < < < < < < < < < < | > | < | | < < | < < < < | < < < | 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 |
}
// compute the spacing of the added symbols
self.set_pitch(last_s);
s = tsfirst
s.seqst = true
for (s = last_s; s.ts_next && !s.ts_next.seqst; s = s.ts_next)
;
s2 = s.ts_next
s.ts_next = null
set_allsymwidth()
s.ts_next = s2
} // init_music_line()
// check if the tune ends on a measure bar
function check_end_bar() {
var s2,
s = tsfirst
while (s.ts_next)
|
| ︙ | ︙ | |||
3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 |
// and sort the pitches in the chords
// and build the chord symbols / annotations
// this function is called only once per tune
function set_words(p_voice) {
var s, s2, nflags, lastnote, res,
start_flag = true,
pitch = 127 /* no note */
for (s = p_voice.sym; s; s = s.next) {
if (s.type == C.NOTE) {
pitch = s.notes[0].pit
break
}
}
| > > > > > > > > > > > > > > > > | 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 |
// and sort the pitches in the chords
// and build the chord symbols / annotations
// this function is called only once per tune
function set_words(p_voice) {
var s, s2, nflags, lastnote, res,
start_flag = true,
pitch = 127 /* no note */
// adjust the duration of the notes in a decoration !trem1..4!
function trem_adj(s) {
s.prev.trem2 = true
s.prev.head = ++s.head
if (--s.nflags > 0) {
s.nflags += s.ntrem
} else {
if (s.nflags <= -2) {
s.stemless = true
s.prev.stemless = true
}
s.nflags = s.ntrem
}
s.prev.nflags = s.nflags
} // trem_adj()
for (s = p_voice.sym; s; s = s.next) {
if (s.type == C.NOTE) {
pitch = s.notes[0].pit
break
}
}
|
| ︙ | ︙ | |||
3527 3528 3529 3530 3531 3532 3533 | start_flag = true if (!s.next && s.prev && !s.invis && s.prev.head == C.OVALBARS) s.prev.head = C.SQUARE break case C.GRACE: | | > > > > > > > > | 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 |
start_flag = true
if (!s.next && s.prev
&& !s.invis
&& s.prev.head == C.OVALBARS)
s.prev.head = C.SQUARE
break
case C.GRACE:
for (s2 = s.extra; s2; s2 = s2.next) {
s2.notes.sort(abc2svg.pitcmp)
res = identify_note(s2, s2.dur_orig)
s2.head = res[0]
s2.dots = res[1]
s2.nflags = res[2]
if (s2.trem2
&& (!s2.next || s2.next.trem2))
trem_adj(s2)
}
break
case C.NOTE:
case C.REST:
res = identify_note(s, s.dur_orig);
s.head = res[0];
s.dots = res[1];
s.nflags = res[2]
|
| ︙ | ︙ | |||
3550 3551 3552 3553 3554 3555 3556 |
s.nflags += s.ntrem
else
s.nflags = s.ntrem
}
if (s.next && s.next.trem2)
break
if (s.trem2) {
| < < < < < < < < < < | < < | | 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 |
s.nflags += s.ntrem
else
s.nflags = s.ntrem
}
if (s.next && s.next.trem2)
break
if (s.trem2) {
trem_adj(s)
break
}
nflags = s.nflags
if (s.ntrem)
nflags += s.ntrem
if (s.type == C.REST && s.beam_end
&& !s.beam_on) {
// s.beam_end = false;
start_flag = true
}
if (start_flag
|| nflags <= 0) {
if (lastnote) {
lastnote.beam_end = true;
lastnote = null
|
| ︙ | ︙ | |||
3707 3708 3709 3710 3711 3712 3713 | set_ottava(); // set the clefs and adjust the pitches of all symbol set_clefs(); self.set_pitch(null) } | > | | | > > > | < < | < | < < < < < | < < < | | | < | | < | | > > | > > > > > > > > | > > | | > > > > > > | > > | | | | | | | | | > > > > | > > > > | > > > | > > > > > > > > > > > > > > | | < | | | > | 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 |
set_ottava();
// set the clefs and adjust the pitches of all symbol
set_clefs();
self.set_pitch(null)
}
// get the left offsets of the first and other staff systems
// return [lsh1, lsho]
function get_lshift() {
var st, v, p_v, p1, po, fnt, w,
sy = cur_sy,
lsh1 = 0,
lsho = 0,
nv = voice_tb.length
// get the max width of a voice name/subname
function get_wx(p, wx) {
var w, j,
i = 0
p += '\n'
while (1) {
j = p.indexOf("\n", i)
if (j < 0)
break
w = strwh(p.slice(i, j))[0] + 12
if (w > wx)
wx = w
if (j < 0)
break
i = j + 1
}
return wx
} // get_wx()
for (v = 0; v < nv; v++) {
p_v = voice_tb[v]
p1 = p_v.nm
po = p_v.snm
if ((p1 || po) && !fnt) {
set_font("voice")
fnt = gene.deffont
}
if (p1) {
w = get_wx(p1, lsh1)
if (w > lsh1)
lsh1 = w
}
if (po) {
w = get_wx(po, lsho)
if (w > lsho)
lsho = w
}
}
// add the width of the braces/brackets
w = 0
while (sy) {
for (st = 0; st <= sy.nstaff; st++) {
if (sy.staves[st].flags
& (OPEN_BRACE2 | OPEN_BRACKET2)) {
w = 12
break
}
if (sy.staves[st].flags & (OPEN_BRACE | OPEN_BRACKET))
w = 6
}
if (w == 12)
break
sy = sy.next
}
lsh1 += w
lsho += w
return [lsh1, lsho]
} // get_lshift()
/* -- return the left indentation of the staves -- */
function set_indent(lsh) {
var st, v, w, p_voice, p, i, j, font,
vnt = 0,
nv = voice_tb.length
// name or subname?
for (v = 0; v < nv; v++) {
p_voice = voice_tb[v]
if (!cur_sy.voices[v]
|| !gene.st_print[p_voice.st])
continue
if (p_voice.new_name) {
vnt = 2 // full name
break
}
if (p_voice.snm)
vnt = 1 // subname
}
gene.vnt = vnt // voice name type for draw
return vnt == 2 ? lsh[0] : lsh[1]
}
/* -- decide on beams and on stem directions -- */
/* this routine is called only once per tune */
function set_beams(sym) {
var s, t, g, beam, s_opp, n, m, mid_p, pu, pd,
laststem = -1
for (s = sym; s; s = s.next) {
if (s.type != C.NOTE) {
if (s.type != C.GRACE)
continue
g = s.extra
if (g.stem == 2) { /* opposite gstem direction */
s_opp = s
continue
}
if (!s.stem)
s.stem = s.multi || 1
for (; g; g = g.next) {
g.stem = s.stem;
g.multi = s.multi
}
continue
}
if (!s.stem && s.multi)
s.stem = s.multi
if (!s.stem) { // if note alone on the staff
mid_p = s.mid / 3 + 18
/* notes in a beam have the same stem direction */
if (beam) {
s.stem = laststem
} else if (s.beam_st && !s.beam_end) { // beam start
beam = true;
|
| ︙ | ︙ | |||
4437 4438 4439 4440 4441 4442 4443 |
}
}
/* -- set the stem height -- */
/* this routine is called only once per tune */
// (possible hook)
Abc.prototype.set_stems = function() {
| | < < < < | | | 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 |
}
}
/* -- set the stem height -- */
/* this routine is called only once per tune */
// (possible hook)
Abc.prototype.set_stems = function() {
var s, s2, g, slen, scale,ymn, ymx, nflags, ymin, ymax
for (s = tsfirst; s; s = s.ts_next) {
if (s.type != C.NOTE) {
if (s.type != C.GRACE)
continue
ymin = ymax = s.mid
for (g = s.extra; g; g = g.next) {
slen = GSTEM
if (g.nflags > 1)
slen += 1.2 * (g.nflags - 1);
ymn = 3 * (g.notes[0].pit - 18);
ymx = 3 * (g.notes[g.nhd].pit - 18)
if (s.stem >= 0) {
g.y = ymn;
g.ys = ymx + slen;
ymx = Math.round(g.ys)
} else {
g.y = ymx;
g.ys = ymn - slen;
ymn = Math.round(g.ys)
}
ymx += 4
ymn -= 4
if (ymn < ymin)
ymin = ymn
else if (ymx > ymax)
ymax = ymx;
g.ymx = ymx;
g.ymn = ymn
}
|
| ︙ | ︙ | |||
4575 4576 4577 4578 4579 4580 4581 | if (s.notes[s.nhd].tie) ymx += 3; s.ymx = ymx + 4 } } } | < < < < < < < < < < < < < | | > > < < < < | | < | > > < < < < | | > > | < | 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 |
if (s.notes[s.nhd].tie)
ymx += 3;
s.ymx = ymx + 4
}
}
}
// generate a block symbol
var blocks = [] // array of delayed block symbols
// (possible hook)
Abc.prototype.block_gen = function(s) {
switch (s.subtype) {
case "leftmargin":
case "rightmargin":
case "pagescale":
case "pagewidth":
case "scale":
case "staffwidth":
self.set_format(s.subtype, s.param)
break
case "mc_start": // multicol start
multicol = {
posy: posy,
maxy: posy,
lm: cfmt.leftmargin,
rm: cfmt.rightmargin,
w: cfmt.pagewidth,
sc: cfmt.scale
}
break
case "mc_new": // multicol new
if (posy > multicol.maxy)
multicol.maxy = posy
cfmt.leftmargin = multicol.lm
cfmt.rightmargin = multicol.rm
cfmt.pagewidth = multicol.w
cfmt.scale = multicol.sc
posy = multicol.posy
img.chg = 1 //true
break
case "mc_end": // multicol end
if (posy < multicol.maxy)
posy = multicol.maxy
cfmt.leftmargin = multicol.lm
cfmt.rightmargin = multicol.rm
cfmt.pagewidth = multicol.w
cfmt.scale = multicol.sc
multicol = undefined
blk_flush()
img.chg = 1 //true
break
case "ml":
blk_flush()
user.img_out(s.text)
break
case "newpage":
if (!user.page_format)
|
| ︙ | ︙ | |||
4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 |
write_title(s.text, true)
break
case "vskip":
vskip(s.sk);
break
}
}
/* -- define the start and end of a piece of tune -- */
/* tsnext becomes the beginning of the next line */
function set_piece() {
var s, last, p_voice, st, v, nv, tmp,
non_empty = [],
non_empty_gl = [],
| > > > > > > > > > > > > > > | 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 |
write_title(s.text, true)
break
case "vskip":
vskip(s.sk);
break
}
}
// -- move some symbols of an empty staff to the next one --
function sym_staff_move(st) {
for (var s = tsfirst; s; s = s.ts_next) {
if (s.nl)
break
if (s.st == st
&& s.type != C.CLEF) {
s.st++
if (s.type != C.TEMPO)
s.invis = true
}
}
} // sym_staff_move()
/* -- define the start and end of a piece of tune -- */
/* tsnext becomes the beginning of the next line */
function set_piece() {
var s, last, p_voice, st, v, nv, tmp,
non_empty = [],
non_empty_gl = [],
|
| ︙ | ︙ | |||
4730 4731 4732 4733 4734 4735 4736 | // ledger lines // index = line number // values = [x symbol, x start, x stop] p_staff.hlu = [] // above the staff p_staff.hld = [] // under the staff | < < < < | 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 |
// ledger lines
// index = line number
// values = [x symbol, x start, x stop]
p_staff.hlu = [] // above the staff
p_staff.hld = [] // under the staff
l = p_staff.stafflines.length;
p_staff.topbar = 6 * (l - 1)
for (i = 0; i < l - 1; i++) {
switch (p_staff.stafflines[i]) {
case '.':
case '-':
|
| ︙ | ︙ | |||
4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 |
p_staff.topbar += 6
} else { // no line: big bar
p_staff.botbar -= 12;
p_staff.topbar += 12
continue // no helper line
}
}
// define the helper lines
p_staff.hll = 17 + i * 2 // pitch of lowest note
// without helper line
// ('D' when standard staff)
p_staff.hlmap = new Int8Array(new Array((l - i + 1) * 2))
for (j = 1; i < l; i++, j += 2) {
| > > | 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 |
p_staff.topbar += 6
} else { // no line: big bar
p_staff.botbar -= 12;
p_staff.topbar += 12
continue // no helper line
}
}
if (!non_empty_gl[st])
continue
// define the helper lines
p_staff.hll = 17 + i * 2 // pitch of lowest note
// without helper line
// ('D' when standard staff)
p_staff.hlmap = new Int8Array(new Array((l - i + 1) * 2))
for (j = 1; i < l; i++, j += 2) {
|
| ︙ | ︙ | |||
4871 4872 4873 4874 4875 4876 4877 | /* set the last empty staves */ set_brace() sy.st_print = new Uint8Array(non_empty); /* define the offsets of the measure bars */ set_top_bot() | | < | | | 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 |
/* set the last empty staves */
set_brace()
sy.st_print = new Uint8Array(non_empty);
/* define the offsets of the measure bars */
set_top_bot()
// move the symbols of the empty staves to the next staff
for (st = 0; st < nstaff; st++) {
if (!non_empty_gl[st])
sym_staff_move(st)
}
// set a null height if the last staff is empty
if (!non_empty_gl[nstaff])
staff_tb[nstaff].topbar = 0
/* initialize the music line */
init_music_line();
// keep the array of the staves to be printed
gene.st_print = new Uint8Array(non_empty_gl)
|
| ︙ | ︙ | |||
5101 5102 5103 5104 5105 5106 5107 |
}
tsfirst = null /* no more notes */
}
/* -- generate the music -- */
// (possible hook)
Abc.prototype.output_music = function() {
| | | | | > > > > > | | > > > > > > > | < < > > < | 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 |
}
tsfirst = null /* no more notes */
}
/* -- generate the music -- */
// (possible hook)
Abc.prototype.output_music = function() {
var v, lwidth, indent, lsh, line_height, ts1st, tslast, p_v,
nv = voice_tb.length
set_global()
if (nv > 1) // if many voices
self.set_stem_dir() // set the stems direction in 'multi'
for (v = 0; v < nv; v++)
set_beams(voice_tb[v].sym); /* decide on beams */
self.set_stems() // set the stem lengths
gen_init() // output the blocks and define the page layout
if (!tsfirst)
return
set_acc_shft() // set the horizontal offset of accidentals
if (nv > 1) { // if many voices
set_rest_offset(); /* set the vertical offset of rests */
set_overlap(); /* shift the notes on voice overlap */
}
set_allsymwidth(1) // set the width of all symbols
lsh = get_lshift()
/* if single line, adjust the page width */
if (cfmt.singleline) {
v = get_ck_width();
lwidth = lsh[0] + v[0] + v[1] + get_width(tsfirst, null)[0]
v = cfmt.singleline == 2 // if as wide as the page width
? get_lwidth() : lwidth
if (v > lwidth)
lwidth = v
else
img.width = lwidth * cfmt.scale + img.lm + img.rm + 2
} else {
/* else, split the tune into music lines */
lwidth = get_lwidth();
cut_tune(lwidth, lsh)
}
// save symbol pointers for play
ts1st = tsfirst
v = nv
while (--v >= 0)
voice_tb[v].osym = voice_tb[v].sym
spf_last = 0 // last spacing factor
while (1) { /* loop per music line */
set_piece();
indent = set_indent(lsh)
if (!line_height
&& cfmt.indent
&& indent < cfmt.indent)
indent = cfmt.indent
self.set_sym_glue(lwidth - indent)
if (realwidth) {
if (indent)
posx += indent;
draw_sym_near(); // delayed output
line_height = set_staff();
draw_systems(indent);
draw_all_sym();
delayed_update();
//fixme: KO if at start of tune (the header is generated)
if (output) // if some music
vskip(line_height)
if (indent)
posx -= indent;
}
blk_flush()
while (blocks.length)
self.block_gen(blocks.shift())
if (tslast)
tslast.ts_next.ts_prev = tslast
if (!tsnext)
break
tsnext.ts_prev.ts_next = // (restore for play)
tsfirst = tsnext
// next line
gen_init()
if (!tsfirst)
break
tslast = tsfirst.ts_prev
tsfirst.ts_prev = null;
set_sym_line();
lwidth = get_lwidth() // the image size may have changed
}
// restore for play
tsfirst = ts1st
v = nv
while (--v >= 0) {
p_v = voice_tb[v]
if (p_v.sym && p_v.s_prev)
p_v.sym.prev = p_v.s_prev
p_v.sym = p_v.osym
}
}
|
Changes to core/parse.js.
1 2 | // abc2svg - parse.js - ABC parse // | | | 1 2 3 4 5 6 7 8 9 10 | // abc2svg - parse.js - ABC parse // // Copyright (C) 2014-2023 Jean-Francois Moine // // This file is part of abc2svg-core. // // abc2svg-core is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
return
}
pit[i] = abc2svg.pab40(note.pit, note.acc)
}
}
return pit[1] - pit[0]
}
// set the linebreak character
function set_linebreak(param) {
var i, item
for (i = 0; i < 128; i++) {
if (char_tb[i] == "\n")
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
return
}
pit[i] = abc2svg.pab40(note.pit, note.acc)
}
}
return pit[1] - pit[0]
}
// transpose a note for the score
// Return the transposed real accidental
function nt_trans(nt,
a) { // real accidental
var ak, an, d, b40, n
if (typeof a == "object") { // if microtonal accidental
n = a[0] // numerator
d = a[1] // denominator
a = n > 0 ? 1 : -1 // base accidental for transpose
}
b40 = abc2svg.pab40(nt.pit, a)
+ curvoice.tr_sco // base-40 transposition
nt.pit = abc2svg.b40p(b40) // new pitch
an = abc2svg.b40a(b40) // new accidental
if (!d) { // if not a microtonal accidental
if (an == -3) // if triple sharp/flat
return an
a = an
if (nt.acc) { // if old accidental
if (!a)
a = 3 // required natural
} else {
if (!curvoice.ckey.k_none) // if normal key
a = 0 // no accidental
}
nt.acc = a
return an
}
// set the microtonal accidental after transposition
switch (a) {
case -2:
if (n > 0)
n -= d * 2
else
n -= d
break
case -1:
if (n > 0)
n -= d
break
case 0:
case 3:
if (n > 0)
n -= d
else
n += d
break
case 1:
if (n < 0)
n += d
break
case 2:
if (n < 0)
n += d * 2
else
n += d
break
}
nt.acc = [n, d]
return an
} // nt_trans()
// set the linebreak character
function set_linebreak(param) {
var i, item
for (i = 0; i < 128; i++) {
if (char_tb[i] == "\n")
|
| ︙ | ︙ | |||
275 276 277 278 279 280 281 |
sym_link(s)
return s
}
// set the voice parameters
// (possible hook)
Abc.prototype.set_vp = function(a) {
| | > | 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 |
sym_link(s)
return s
}
// set the voice parameters
// (possible hook)
Abc.prototype.set_vp = function(a) {
var s, item, pos, val, clefpit,
tr_p = 0
while (1) {
item = a.shift()
if (!item)
break
if (item.slice(-1) == '='
&& !a.length) {
|
| ︙ | ︙ | |||
331 332 333 334 335 336 337 |
// (instrument=M == instrument=M/M)
item = a.shift()
val = item.indexOf('/')
if (val < 0) {
val = get_interval('c' + item)
if (val == undefined)
break
| | > | > | | | 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 |
// (instrument=M == instrument=M/M)
item = a.shift()
val = item.indexOf('/')
if (val < 0) {
val = get_interval('c' + item)
if (val == undefined)
break
curvoice.sound = val
tr_p |= 2
val = 0
} else {
val = get_interval('c' + item.slice(val + 1))
if (val == undefined)
break
curvoice.sound = val
tr_p |= 2
val = get_interval(item.replace('/', ''))
if (val == undefined)
break
}
curvoice.score = cfmt.sound ? curvoice.sound : val
tr_p |= 1
break
case "map=": // %%voicemap
curvoice.map = a.shift()
break
case "name=":
case "nm=":
curvoice.nm = a.shift()
|
| ︙ | ︙ | |||
396 397 398 399 400 401 402 |
// score=MN
// (score=M == score=Mc)
item = a.shift()
if (cfmt.sound)
break
val = get_interval(item, true)
if (val != undefined) {
| | | | | | | | | 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 |
// score=MN
// (score=M == score=Mc)
item = a.shift()
if (cfmt.sound)
break
val = get_interval(item, true)
if (val != undefined) {
curvoice.score = val
tr_p |= 1
}
break
case "shift=":
if (cfmt.nedo) {
syntax(1, errs.notransp)
break
}
val = get_interval(a.shift())
if (val != undefined) {
curvoice.shift = val
tr_p = 3
}
break
case "sound=":
if (cfmt.nedo) {
syntax(1, errs.notransp)
break
}
// concert-score display: apply sound=
// sounding-score display: apply sound= only if M != c/C
// sound: apply sound=
val = get_interval(a.shift())
if (val == undefined)
break
curvoice.sound = val
if (cfmt.sound)
curvoice.score = val
tr_p |= 2
break
case "subname=":
case "sname=":
case "snm=":
curvoice.snm = a.shift()
if (curvoice.snm[0] == '"')
curvoice.snm = curvoice.snm.slice(1, -1);
|
| ︙ | ︙ | |||
466 467 468 469 470 471 472 |
syntax(1, errs.notransp)
break
}
val = get_transp(a.shift())
if (val == undefined) {
syntax(1, errs.bad_transp)
} else {
| | | | | 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 |
syntax(1, errs.notransp)
break
}
val = get_transp(a.shift())
if (val == undefined) {
syntax(1, errs.bad_transp)
} else {
curvoice.sound = val
if (cfmt.sound)
curvoice.score = val
tr_p = 2
}
break
default:
switch (item.slice(0, 4)) {
case "treb":
case "bass":
case "alto":
|
| ︙ | ︙ | |||
506 507 508 509 510 511 512 |
s = new_clef(s)
if (s) {
if (clefpit)
s.clefpit = clefpit
get_clef(s)
}
}
| > > | > > > | > > > > > > > > > > > | | | | | 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 |
s = new_clef(s)
if (s) {
if (clefpit)
s.clefpit = clefpit
get_clef(s)
}
}
// if transposition
if (tr_p) {
curvoice.tr_p = tr_p // keep this key signature
tr_p = (curvoice.score | 0)
+ (curvoice.shift | 0)
+ (cfmt.transp | 0)
if (tr_p)
curvoice.tr_sco = tr_p // b40 interval
else if (curvoice.tr_sco)
curvoice.tr_sco = 0
tr_p = (curvoice.sound | 0) + (curvoice.shift | 0)
if (tr_p)
curvoice.tr_snd = abc2svg.b40m(tr_p + 122) - 36
// semi-tone interval
else if (curvoice.tr_snd)
curvoice.tr_snd = 0
}
} // set_vp()
// set the K: / V: parameters
function set_kv_parm(a) { // array of items
if (!curvoice.init) { // add the global parameters if not done yet
curvoice.init = true
if (info.V) {
if (info.V[curvoice.id])
a = info.V[curvoice.id].concat(a)
if (info.V['*'])
a = info.V['*'].concat(a)
}
}
if (a.length)
self.set_vp(a)
} // set_kv_parm()
// memorize the K:/V: parameters
|
| ︙ | ︙ | |||
541 542 543 544 545 546 547 |
else
info.V[vid] = a
}
// K: key signature
// return the key and the voice/clef parameters
function new_key(param) {
| | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 |
else
info.V[vid] = a
}
// K: key signature
// return the key and the voice/clef parameters
function new_key(param) {
var i, key_end, c, tmp, note,
sf = "FCGDAEB".indexOf(param[0]) - 1,
mode = 0,
s = {
type: C.KEY,
dur: 0
}
set_ref(s);
// tonic
i = 1
if (sf < -1) {
switch (param[0]) {
case 'H': // bagpipe
|
| ︙ | ︙ | |||
695 696 697 698 699 700 701 |
param = param.replace(/\w+\s*/, '')
// [exp] accidentals
if (param.indexOf("exp ") == 0) {
param = param.replace(/\w+\s*/, '')
if (!param)
syntax(1, "No accidental after 'exp'");
| | | < < | > > > > > > > > > > | < < < < < | 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 |
param = param.replace(/\w+\s*/, '')
// [exp] accidentals
if (param.indexOf("exp ") == 0) {
param = param.replace(/\w+\s*/, '')
if (!param)
syntax(1, "No accidental after 'exp'");
s.exp = 1 //true
}
c = param[0]
if (c == '^' || c == '_' || c == '=') {
s.k_a_acc = [];
tmp = new scanBuf;
tmp.buffer = param
do {
note = parse_acc_pit(tmp)
if (!note)
break
s.k_a_acc.push(note);
c = param[tmp.index]
while (c == ' ')
c = param[++tmp.index]
} while (c == '^' || c == '_' || c == '=');
param = param.slice(tmp.index)
} else if (s.exp && param.indexOf("none") == 0) {
sf = 0
param = param.replace(/\w+\s*/, '')
}
}
if (sf < -7 || sf > 7) {
syntax(1, "Key with double sharps/flats")
if (sf > 7)
sf -= 12
else
sf += 12
}
s.k_sf = sf;
// set the map of the notes with accidentals
s.k_map = s.k_bagpipe && !sf
? abc2svg.keys[9] // implicit F# and C#
: abc2svg.keys[sf + 7]
if (s.k_a_acc) {
s.k_map = new Int8Array(s.k_map)
i = s.k_a_acc.length
while (--i >= 0) {
note = s.k_a_acc[i]
s.k_map[(note.pit + 19) % 7] = note.acc
}
}
s.k_mode = mode
// key note as base-40
s.k_b40 = [1,24,7,30,13,36,19, 2 ,25,8,31,14,37,20,3][sf + 7]
return [s, info_split(param)]
|
| ︙ | ︙ | |||
887 888 889 890 891 892 893 894 895 896 897 898 899 900 |
if (p[i] == '=') {
val = p.substring(++i).match(/^(\d+)\/(\d+)$/)
if (!val) {
syntax(1, "Bad duration '$1' in M:", p.substring(i))
return
}
wmeasure = C.BLEN * val[1] / val[2]
}
s.wmeasure = wmeasure
if (cfmt.writefields.indexOf('M') < 0)
s.a_meter = []
if (parse.state != 3) {
| > > > > | 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 |
if (p[i] == '=') {
val = p.substring(++i).match(/^(\d+)\/(\d+)$/)
if (!val) {
syntax(1, "Bad duration '$1' in M:", p.substring(i))
return
}
wmeasure = C.BLEN * val[1] / val[2]
}
if (!wmeasure) {
syntax(1, errs.bad_val, 'M:')
return
}
s.wmeasure = wmeasure
if (cfmt.writefields.indexOf('M') < 0)
s.a_meter = []
if (parse.state != 3) {
|
| ︙ | ︙ | |||
1009 1010 1011 1012 1013 1014 1015 |
if (!s.tempo || isNaN(s.tempo)) {
syntax(1, "Bad tempo value")
return
}
}
}
| | > > | < < < > > > > > > > > > > | > | | > | > > > > > > | 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 |
if (!s.tempo || isNaN(s.tempo)) {
syntax(1, "Bad tempo value")
return
}
}
}
if (parse.state < 2 // if in tune header
|| (!curvoice.time && !glovar.tempo)) {
info.Q = txt
glovar.tempo = s
return
}
var tim = curvoice.time
if (!glovar.tempo)
syntax(0, "No previous tempo")
if (!parse.ctrl)
parse.ctrl = {}
if (!parse.ctrl[tim])
parse.ctrl[tim] = {}
parse.ctrl[tim].tempo = s
s.v = par_sy.top_voice
s.p_v = voice_tb[s.v]
s.fmt = cfmt
s.st = s.p_v.st
s.time = tim
}
// treat the information fields which may embedded
function do_info(info_type, text) {
var s, d1, d2, a, vid, tim, v, p_v
// skip this line if the current voice is ignored
// but keep the time related definitions
if (curvoice && curvoice.ignore) {
switch (info_type) {
default:
return
case 'P':
case 'Q':
case 'V':
break
}
}
switch (info_type) {
// info fields in any state
case 'I':
self.do_pscom(text)
break
|
| ︙ | ︙ | |||
1079 1080 1081 1082 1083 1084 1085 |
case 'P':
if (!parse.state)
break
if (parse.state == 1) {
info.P = text
break
}
| | | | < | | > > > > > > > > | 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 |
case 'P':
if (!parse.state)
break
if (parse.state == 1) {
info.P = text
break
}
// memorize the part in the control
tim = curvoice.time
s = {
text: text,
time: tim
}
set_ref(s)
if (cfmt.writefields.indexOf(info_type) < 0)
s.invis = true
if (!parse.ctrl)
parse.ctrl = {}
if (!parse.ctrl[tim])
parse.ctrl[tim] = {}
parse.ctrl[tim].part = s
s.v = par_sy.top_voice
s.p_v = voice_tb[s.v]
s.fmt = cfmt
s.st = s.p_v.st
break
case 'Q':
if (!parse.state)
break
new_tempo(text)
break
case 'V':
|
| ︙ | ︙ | |||
1317 1318 1319 1320 1321 1322 1323 |
delete s.text
}
curvoice.tie_s_rep = null // no tie anymore on new variant
}
// handle the accidentals (ties and repeat)
if (s.text) {
| < | | 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 |
delete s.text
}
curvoice.tie_s_rep = null // no tie anymore on new variant
}
// handle the accidentals (ties and repeat)
if (s.text) {
s.rbstart = s.rbstop = 2
if (s.text[0] == '1') {
curvoice.tie_s_rep = curvoice.tie_s
if (curvoice.acc_tie)
curvoice.acc_tie_rep = curvoice.acc_tie.slice()
else if (curvoice.acc_tie_rep)
curvoice.acc_tie_rep = null
} else {
|
| ︙ | ︙ | |||
1400 1401 1402 1403 1404 1405 1406 |
}
}
}
/* set some flags */
switch (bar_type) {
case "[":
| < | 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 |
}
}
}
/* set some flags */
switch (bar_type) {
case "[":
case "[]":
case "[|]":
s.invis = true;
bar_type = s.rbstart ? "[" : "[]"
break
case ":|:":
case ":||:":
|
| ︙ | ︙ | |||
1601 1602 1603 1604 1605 1606 1607 |
return a_vf
}
// split an info string
function info_split(text) {
if (!text)
return []
| | | 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 |
return a_vf
}
// split an info string
function info_split(text) {
if (!text)
return []
var a = text.match(/[^\s"=]+=?|"[^"]*"/g) // "
if (!a) {
//fixme: bad error text
syntax(1, "Unterminated string")
return []
}
return a
}
|
| ︙ | ︙ | |||
1626 1627 1628 1629 1630 1631 1632 | if (!res[0]) return [1, 1]; num = res[1] || 1; den = res[3] || 1 if (!res[3]) den *= 1 << res[2].length; line.index = reg_dur.lastIndex | | | 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 |
if (!res[0])
return [1, 1];
num = res[1] || 1;
den = res[3] || 1
if (!res[3])
den *= 1 << res[2].length;
line.index = reg_dur.lastIndex
return [+num, +den]
}
// parse the note accidental and pitch
function parse_acc_pit(line) {
var note, acc, pit, d, nd,
c = line.char()
|
| ︙ | ︙ | |||
1784 1785 1786 1787 1788 1789 1790 | line.index++ return ty + C.SL_BELOW } return ty + C.SL_AUTO } // on end of slur, create the slur | | | < < < | > > | | | | | | | < < < < < | | | < < < < | | | < < < < < < | | | | | | | < | > > | | | > > > > > > > > > | 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 |
line.index++
return ty + C.SL_BELOW
}
return ty + C.SL_AUTO
}
// on end of slur, create the slur
function slur_add(s, nt) { // nt = note if slur ending on note
var i, s2, sl
// go back and find the last start of slur
for (i = curvoice.sls.length; --i >= 0; ) {
sl = curvoice.sls[i]
// the slur must not start and stop on a same symbol
if (sl.ss == s)
continue
curvoice.sls.splice(i, 1)
sl.se = s // ending symbol
if (nt)
sl.nte = nt
s2 = sl.ss // start of slur
if (!s2.sls)
s2.sls = []
s2.sls.push(sl)
// set a flag if the slur starts on a grace note
if (sl.grace)
sl.grace.sl1 = true
return
}
// the lack of a starting slur may be due to a repeat
for (s2 = s.prev; s2; s2 = s2.prev) {
if (s2.type == C.BAR
&& s2.bar_type[0] == ':'
&& s2.text) {
if (!s2.sls)
s2.sls = [];
s2.sls.push({
//fixme: should go back to the bar "|1" and find the slur type...
ty: C.SL_AUTO,
ss: s2,
se: s
})
if (nt)
s2.sls[s2.sls.length - 1].nte = nt
return
}
}
// syntax(1, "End of slur without start")
if (!s.sls)
s.sls = [];
s.sls.push({
ty: C.SL_AUTO,
se: s,
loc: 'i' // no slur start
})
if (nt)
s.sls[s.sls.length - 1].nte = nt
}
// convert a diatonic pitch and accidental to a MIDI pitch with cents
function pit2mid(pit, acc) {
var p = [0, 2, 4, 5, 7, 9, 11][pit % 7], // chromatic pitch
o = ((pit / 7) | 0) * 12, // octave
p0, p1, s, b40
|
| ︙ | ︙ | |||
1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 |
if (!not1.tie_ty)
continue
if (not1.midi == mid
&& (!se
|| !not1.tie_e)) { // (if unison)
not2.tie_s = not1
not2.s = s
if (se) {
not1.tie_e = not2
not1.s = tie_s
}
nt++
break
}
| > | 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 |
if (!not1.tie_ty)
continue
if (not1.midi == mid
&& (!se
|| !not1.tie_e)) { // (if unison)
not2.tie_s = not1
not2.s = s
delete not2.acc // (if transposing)
if (se) {
not1.tie_e = not2
not1.s = tie_s
}
nt++
break
}
|
| ︙ | ︙ | |||
1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 |
s.ti2 = true
} // do_ties()
// (possible hook)
Abc.prototype.new_note = function(grace, sls) {
var note, s, in_chord, c, dcn, type, tie_s, acc_tie,
i, n, s2, nd, res, num, dur, apit, div, ty,
sl1 = [],
line = parse.line,
a_dcn_sav = a_dcn // save parsed decoration names
a_dcn = []
parse.stemless = false;
s = {
| > | 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 |
s.ti2 = true
} // do_ties()
// (possible hook)
Abc.prototype.new_note = function(grace, sls) {
var note, s, in_chord, c, dcn, type, tie_s, acc_tie,
i, n, s2, nd, res, num, dur, apit, div, ty,
dpit = 0,
sl1 = [],
line = parse.line,
a_dcn_sav = a_dcn // save parsed decoration names
a_dcn = []
parse.stemless = false;
s = {
|
| ︙ | ︙ | |||
1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 |
switch (c) {
case 'X':
s.invis = true
case 'Z':
s.type = C.MREST;
c = line.next_char()
s.nmes = (c > '0' && c <= '9') ? line.get_int() : 1;
s.dur = curvoice.wmeasure * s.nmes
// ignore if in second voice
if (curvoice.second) {
delete curvoice.eoln // ignore the end of line
curvoice.time += s.dur
return //null
| > > > > | 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 |
switch (c) {
case 'X':
s.invis = true
case 'Z':
s.type = C.MREST;
c = line.next_char()
s.nmes = (c > '0' && c <= '9') ? line.get_int() : 1;
if (curvoice.wmeasure == 1) {
error(1, s, "multi-measure rest, but no measure!")
return
}
s.dur = curvoice.wmeasure * s.nmes
// ignore if in second voice
if (curvoice.second) {
delete curvoice.eoln // ignore the end of line
curvoice.time += s.dur
return //null
|
| ︙ | ︙ | |||
2100 2101 2102 2103 2104 2105 2106 | s.grace ? C.BLEN / 4 : curvoice.ulen < 0 ? C.BLEN : curvoice.ulen) if (!note) return //null | < > < < | > | | | < < > > > > > > > > > > > | > > > > > > > > > > > | | | > > > > > > > > > > > > > > > > > > > > < < | > > < | > > < | < | > | > | 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 |
s.grace ? C.BLEN / 4 :
curvoice.ulen < 0 ?
C.BLEN :
curvoice.ulen)
if (!note)
return //null
if (curvoice.octave)
note.pit += curvoice.octave * 7
// get the real accidental
apit = note.pit + 19 // pitch from C-1
i = note.acc
if (!i) {
if (cfmt["propagate-accidentals"][0] == 'p')
i = curvoice.acc[apit % 7]
else
i = curvoice.acc[apit]
if (!i)
i = curvoice.ckey.k_map[apit % 7] || 0
}
if (i) {
if (cfmt["propagate-accidentals"][0] == 'p')
curvoice.acc[apit % 7] = i
else if (cfmt["propagate-accidentals"][0] != 'n')
curvoice.acc[apit] = i
}
if (acc_tie && acc_tie[apit])
i = acc_tie[apit] // tied note
// map
if (curvoice.map
&& maps[curvoice.map])
set_map(note, i)
// set the MIDI pitch
if (!note.midi) // if not map play
note.midi = pit2mid(apit, i)
// transpose
if (curvoice.tr_sco) {
i = nt_trans(note, i)
if (i == -3) { // if triple sharp/flat
error(1, s, "triple sharp/flat")
i = note.acc > 0 ? 1 : -1
note.pit += i
note.acc = i
}
dpit = note.pit + 19 - apit
}
if (curvoice.tr_snd)
note.midi += curvoice.tr_snd
//fixme: does not work if transposition
if (i) {
switch (cfmt["writeout-accidentals"][1]) {
case 'd': // added
s2 = curvoice.ckey
if (!s2.k_a_acc)
break
for (n = 0; n < s2.k_a_acc.length; n++) {
if ((s2.k_a_acc[n].pit - note.pit)
% 7 == 0) {
note.acc = i
break
}
}
break
case 'l': // all
note.acc = i
break
}
}
// starting slurs
if (sl1.length) {
while (1) {
i = sl1.shift()
if (!i)
break
curvoice.sls.push({
ty: i,
ss: s,
nts: note // starting note
})
}
}
if (a_dcn.length) {
s.time = curvoice.time // (needed for !tie)!
dh_cnv(s, note)
}
s.notes.push(note)
if (!in_chord)
break
// in chord: get the ending slurs and the ties
c = line.char()
while (1) {
switch (c) {
case ')':
slur_add(s, note)
c = line.next_char()
continue
case '-':
note.tie_ty = parse_vpos()
note.s = s
curvoice.tie_s = s
s.ti1 = true
if (curvoice.acc[apit]
|| (acc_tie
&& acc_tie[apit])) {
if (!curvoice.acc_tie)
curvoice.acc_tie = []
i = curvoice.acc[apit]
if (acc_tie && acc_tie[apit])
i = acc_tie[apit]
curvoice.acc_tie[apit] = i
}
c = line.char()
continue
case '.':
c = line.next_char()
switch (c) {
case '-':
|
| ︙ | ︙ | |||
2208 2209 2210 2211 2212 2213 2214 |
// handle the starting slurs
if (sls.length) {
while (1) {
i = sls.shift()
if (!i)
break
| < < | > > > | 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 |
// handle the starting slurs
if (sls.length) {
while (1) {
i = sls.shift()
if (!i)
break
curvoice.sls.push({
ty: i,
ss: s
// no starting note
})
if (grace)
curvoice.sls[curvoice.sls.length - 1].grace =
grace
}
}
// the duration of the chord is the duration of the 1st note
s.dur_orig = s.notes[0].dur;
s.dur = s.notes[0].dur * curvoice.dur_fact
break
}
if (s.grace && s.type != C.NOTE) {
syntax(1, errs.bad_grace)
return //null
}
if (s.notes) { // if note or rest
|
| ︙ | ︙ | |||
2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 |
s.notes[i].s = s
}
curvoice.tie_s = grace || s
curvoice.tie_s.ti1 = true
for (i = 0; i <= s.nhd; i++) {
note = s.notes[i]
apit = note.pit + 19 // pitch from C-1
if (curvoice.acc[apit]
|| (acc_tie
&& acc_tie[apit])) {
if (!curvoice.acc_tie)
curvoice.acc_tie = []
| > < | > | > | 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 |
s.notes[i].s = s
}
curvoice.tie_s = grace || s
curvoice.tie_s.ti1 = true
for (i = 0; i <= s.nhd; i++) {
note = s.notes[i]
apit = note.pit + 19 // pitch from C-1
- dpit // (if transposition)
if (curvoice.acc[apit]
|| (acc_tie
&& acc_tie[apit])) {
if (!curvoice.acc_tie)
curvoice.acc_tie = []
n = curvoice.acc[apit]
if (acc_tie && acc_tie[apit])
n = acc_tie[apit]
curvoice.acc_tie[apit] = n
}
}
c = line.char()
continue
}
break
}
|
| ︙ | ︙ | |||
2353 2354 2355 2356 2357 2358 2359 |
s.stemless = true
s.iend = parse.bol + line.index
return s
}
// adjust the duration of the elements in a tuplet
function tp_adj(s, fact) {
| > | > > | > > | > | 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 |
s.stemless = true
s.iend = parse.bol + line.index
return s
}
// adjust the duration of the elements in a tuplet
function tp_adj(s, fact) {
var d,
tim = s.time,
to = curvoice.time - tim, // previous delta time
tt = to * fact // new delta time
curvoice.time = tim + tt
while (1) {
//fixme: tuplets in grace notes?
s.in_tuplet = true
if (!s.grace) {
s.time = tim
if (s.dur) {
d = Math.round(s.dur * tt / to) // new duration
to -= s.dur // old remaining time
s.dur = d
tt -= s.dur // new remaining time
tim += s.dur
}
}
if (!s.next) {
if (s.tpe)
s.tpe++
else
|
| ︙ | ︙ | |||
2387 2388 2389 2390 2391 2392 2393 2394 |
line = parse.line,
i = line.index, // in case no deco end
dcn = ""
while (1) {
c = line.next_char()
if (!c) {
syntax(1, "No end of decoration")
| > < | 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 |
line = parse.line,
i = line.index, // in case no deco end
dcn = ""
while (1) {
c = line.next_char()
if (!c) {
line.index = i
syntax(1, "No end of decoration")
return
}
if (c == '!')
break
dcn += c
}
if (ottava[dcn] != undefined) {
|
| ︙ | ︙ | |||
2577 2578 2579 2580 2581 2582 2583 |
var c, idx, type, k, s, dcn, i, n, text, note
while (1) {
c = line.char()
if (!c)
break
| < < < < < < < < < < < < < | 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 |
var c, idx, type, k, s, dcn, i, n, text, note
while (1) {
c = line.char()
if (!c)
break
// check if start of a macro
if (!in_mac && maci[c]) {
n = undefined
for (k in mac) {
if (!mac.hasOwnProperty(k)
|| k[0] != c)
continue
|
| ︙ | ︙ | |||
2658 2659 2660 2661 2662 2663 2664 |
if (c > '0' && c <= '9') { // tuplet
if (grace) {
syntax(1, errs.bad_grace)
break
}
var pplet = line.get_int(),
qplet = qplet_tb[pplet],
| | < > | 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 |
if (c > '0' && c <= '9') { // tuplet
if (grace) {
syntax(1, errs.bad_grace)
break
}
var pplet = line.get_int(),
qplet = qplet_tb[pplet],
rplet = pplet
c = line.char()
if (c == ':') {
c = line.next_char()
if (c > '0' && c <= '9') {
qplet = line.get_int();
c = line.char()
}
if (c == ':') {
|
| ︙ | ︙ | |||
2683 2684 2685 2686 2687 2688 2689 | } } if (qplet == 0 || qplet == undefined) qplet = (curvoice.wmeasure % 9) == 0 ? 3 : 2; if (tpn < 0) tpn = tp.length // new tuplet | < < < < < < < < < < < < < < < | | 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 |
}
}
if (qplet == 0 || qplet == undefined)
qplet = (curvoice.wmeasure % 9) == 0 ?
3 : 2;
if (tpn < 0)
tpn = tp.length // new tuplet
tp.push({
p: pplet,
q: qplet,
r: rplet,
ro: rplet,
f: curvoice.tup || cfmt.tuplets
})
continue
}
if (c == '&') { // voice overlay start
if (grace) {
syntax(1, errs.bad_grace)
break
|
| ︙ | ︙ | |||
2745 2746 2747 2748 2749 2750 2751 |
break
}
}
if (!s) {
syntax(1, errs.bad_char, c)
break
}
| < | | 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 |
break
}
}
if (!s) {
syntax(1, errs.bad_char, c)
break
}
slur_add(s)
break
case '!': // start of decoration
if (type.length > 1) // decoration letter
a_dcn.push(type.slice(1, -1))
else
get_deco() // (line -> a_dcn)
break
|
| ︙ | ︙ | |||
2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 |
if (grace) {
syntax(1, errs.bar_grace)
break
}
new_bar()
continue
case '}':
s = curvoice.last_note
if (!grace || !s) {
syntax(1, errs.bad_char, c)
break
}
if (a_dcn.length)
syntax(1, "Decoration ignored");
| > > > > | 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 |
if (grace) {
syntax(1, errs.bar_grace)
break
}
new_bar()
continue
case '}':
if (curvoice.ignore) {
grace = null
break
}
s = curvoice.last_note
if (!grace || !s) {
syntax(1, errs.bad_char, c)
break
}
if (a_dcn.length)
syntax(1, "Decoration ignored");
|
| ︙ | ︙ | |||
2948 2949 2950 2951 2952 2953 2954 |
if (tp.length) {
parse.tp = tp
parse.tps = tps
parse.tpn = tpn
}
if (sls.length)
syntax(1, "Start of slur without note")
| < < < < | 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 |
if (tp.length) {
parse.tp = tp
parse.tps = tps
parse.tpn = tpn
}
if (sls.length)
syntax(1, "Start of slur without note")
if (grace) {
syntax(1, "No end of grace note sequence");
curvoice.last_sym = grace.prev;
curvoice.last_note = last_note_sav
if (grace.prev)
grace.prev.next = null
}
if (!no_eol && !cfmt.barsperstaff && !vover
&& char_tb['\n'.charCodeAt(0)] == '\n')
curvoice.eoln = true
if (curvoice.eoln && cfmt.breakoneoln && curvoice.last_note)
curvoice.last_note.beam_end = true
}
|
Changes to core/subs.js.
1 2 | // abc2svg - subs.js - text output // | | | 1 2 3 4 5 6 7 8 9 10 | // abc2svg - subs.js - text output // // Copyright (C) 2014-2022 Jean-Francois Moine // // This file is part of abc2svg-core. // // abc2svg-core is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
102 103 104 105 106 107 108 |
}
// return the character width with the current font
function cwidf(c) {
return cwid(c) * gene.curfont.swfac
}
// estimate the width and height of a string ..
| > > > | | | > > > > > > > | | | | | > | | < < | 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
}
// return the character width with the current font
function cwidf(c) {
return cwid(c) * gene.curfont.swfac
}
// estimate the width and height of a string ..
var strwh
(function() {
if (typeof document != "undefined") {
// .. by the browser
// create a text element if not done yet
var el = abc2svg.eltxt
// change the function
strwh = function(str) {
if (str.wh)
return str.wh
if (!el) {
el = document.createElement('text')
el.style.position = 'absolute'
el.style.top = '-1000px'
el.style.padding = '0'
document.body.appendChild(el)
abc2svg.eltxt = el // reused after new Abc()
}
var c,
font = gene.curfont,
h = font.size,
w = 0,
n = str.length,
i0 = 0,
i = 0
|
| ︙ | ︙ | |||
144 145 146 147 148 149 150 |
case '&': return "&"
}
return c // &xxx;
})
while (1) {
i = str.indexOf('$', i)
| | < | | | | | | | | | > > | | | | | > < < < | | | 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
case '&': return "&"
}
return c // &xxx;
})
while (1) {
i = str.indexOf('$', i)
if (i >= 0) {
c = str[i + 1]
if (c == '0') {
font = gene.deffont
} else if (c >= '1' && c <= '9') {
font = get_font("u" + c)
} else {
i++
continue
}
}
el.innerHTML = str.slice(i0, i >= 0 ? i : undefined)
w += el.clientWidth
//fixme: bad width if space(s) at end of string
if (el.clientHeight > h)
h = el.clientHeight
if (i < 0)
break
el.style.font = style_font(font).slice(5);
i += 2;
i0 = i
}
return [w, h]
}
} else {
// .. by internal tables
strwh = function(str) {
var font = gene.curfont,
swfac = font.swfac,
h = font.size,
w = 0,
i, j, c,
n = str.length
|
| ︙ | ︙ | |||
212 213 214 215 216 217 218 | c = 'a' // XML character reference } break } w += cwid(c) * swfac } return [w, h] | | > > | | | > > > | | 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
c = 'a' // XML character reference
}
break
}
w += cwid(c) * swfac
}
return [w, h]
}
}
})()
// convert a string to a SVG text, handling the font changes
// The string size is memorized into the String.
function str2svg(str) {
// check if the string is already converted
if (typeof str == "object")
return str
var n_font, wh,
o_font = gene.deffont,
c_font = gene.curfont,
o = ""
// start a '<tspan>' element
function tspan(nf, of) {
var cl
if (nf.class
&& nf.name == of.name
&& nf.size == of.size
&& nf.weight == of.weight
&& nf.style == of.style)
cl = nf.class // change only the class
else
cl = font_class(nf)
return '<tspan\n\tclass="' + cl + '">'
} // tspan()
if (c_font != o_font)
o = tspan(c_font, o_font)
o += str.replace(/<|>|&[^&\s]*?;|&|\$./g, function(c){
switch (c) {
case '<': return "<"
case '>': return ">"
case '&': return "&"
default:
if (c[0] != '$')
break
|
| ︙ | ︙ | |||
309 310 311 312 313 314 315 |
str, // string or object String with attribute 'wh'
action, // default: align left
w, // needed for justify
wh) { // optional [width, height]
if (!wh)
wh = str.wh || strwh(str)
| | | | | | 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 |
str, // string or object String with attribute 'wh'
action, // default: align left
w, // needed for justify
wh) { // optional [width, height]
if (!wh)
wh = str.wh || strwh(str)
output += '<text class="' + font_class(gene.deffont)
if (action != 'j' && str.length > 5
&& gene.deffont.wadj)
output += '" lengthAdjust="' + gene.deffont.wadj +
'" textLength="' + wh[0].toFixed(1);
output += '" x="';
out_sxsy(x, '" y="', y)
switch (action) {
case 'c':
x -= wh[0] / 2;
output += '" text-anchor="middle">'
break
case 'j':
output += '" textLength="' + w.toFixed(1) + '">'
|
| ︙ | ︙ | |||
450 451 452 453 454 455 456 |
if (i == text.length)
break
} else {
if (i < 0)
str = text.slice(j)
else
str = text.slice(j, i)
| > | | | > | < | | 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 |
if (i == text.length)
break
} else {
if (i < 0)
str = text.slice(j)
else
str = text.slice(j, i)
ww = strwh(str)
vskip(ww[1] * cfmt.lineskipfac
+ font.pad * 2)
xy_str(x, font.pad + ww[1] * .2, str, action)
if (i < 0)
break
}
j = i + 1
}
vskip(parskip);
blk_flush()
break
case 'f':
case 'j':
j = 0
while (1) {
i = text.indexOf('\n\n', j)
if (i < 0)
words = text.slice(j)
else
words = text.slice(j, i);
words = words.split(/\s+/);
w = k = wh = 0
for (j = 0; j < words.length; j++) {
ww = strwh(words[j] + ' ') //
w += ww[0]
if (w >= strlw) {
vskip(wh * cfmt.lineskipfac)
xy_str(0, ww[1] * .2,
words.slice(k, j).join(' '),
action, strlw)
k = j;
w = ww[0]
wh = 0
}
if (ww[1] > wh)
wh = ww[1]
}
if (w != 0) { // last line
vskip(wh * cfmt.lineskipfac)
xy_str(0, ww[1] * .2, words.slice(k).join(' '))
}
vskip(parskip);
blk_flush()
if (i < 0)
break
while (text[i + 2] == '\n') {
vskip(lineskip);
|
| ︙ | ︙ | |||
539 540 541 542 543 544 545 546 | break } k = i while (p[i] == ' ') i++ } if (k != 0) | > | | | 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 |
break
}
k = i
while (p[i] == ' ')
i++
}
var y = gene.curfont.size * .22 // descent
if (k != 0)
xy_str(x, y, p.slice(0, k), 'r')
if (i < p.length)
xy_str(x + 5, y, p.slice(i), 'l')
} // put_wline()
set_font("words")
vskip(cfmt.wordsspace)
svg_flush()
// estimate the width of the lines
|
| ︙ | ︙ | |||
681 682 683 684 685 686 687 |
P: "parts",
Q: "tempo",
R: "info",
T: "title",
X: "title"
}
function write_headform(lwidth) {
| | | 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 |
P: "parts",
Q: "tempo",
R: "info",
T: "title",
X: "title"
}
function write_headform(lwidth) {
var c, font, font_name, align, x, y, sz, w,
info_val = {},
info_font = Object.create(info_font_init),
info_sz = {
A: cfmt.infospace,
C: cfmt.composerspace,
O: cfmt.composerspace,
R: cfmt.infospace
|
| ︙ | ︙ |
Changes to core/svg.js.
| ︙ | ︙ | |||
21 22 23 24 25 26 27 |
style = '\
\n.stroke{stroke:currentColor;fill:none}\
\n.bW{stroke:currentColor;fill:none;stroke-width:1}\
\n.bthW{stroke:currentColor;fill:none;stroke-width:3}\
\n.slW{stroke:currentColor;fill:none;stroke-width:.7}\
\n.slthW{stroke:currentColor;fill:none;stroke-width:1.5}\
\n.sW{stroke:currentColor;fill:none;stroke-width:.7}\
| | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
style = '\
\n.stroke{stroke:currentColor;fill:none}\
\n.bW{stroke:currentColor;fill:none;stroke-width:1}\
\n.bthW{stroke:currentColor;fill:none;stroke-width:3}\
\n.slW{stroke:currentColor;fill:none;stroke-width:.7}\
\n.slthW{stroke:currentColor;fill:none;stroke-width:1.5}\
\n.sW{stroke:currentColor;fill:none;stroke-width:.7}\
\n.box{outline:1px solid black;outline-offset:1px}',
font_style = '',
posx = cfmt.leftmargin / cfmt.scale, // default x offset of the images
posy = 0, // y offset in the block
img = { // image
width: cfmt.pagewidth, // width
lm: cfmt.leftmargin, // left and right margins
rm: cfmt.rightmargin
|
| ︙ | ︙ | |||
304 305 306 307 308 309 310 |
output += 'transform="translate(0,' +
(posy - stv_g.dy).toFixed(1) +
') scale(' + stv_g.scale.toFixed(2) + ')"'
}
if (stv_g.color) {
if (stv_g.scale != 1)
output += ' ';
| | < | 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 |
output += 'transform="translate(0,' +
(posy - stv_g.dy).toFixed(1) +
') scale(' + stv_g.scale.toFixed(2) + ')"'
}
if (stv_g.color) {
if (stv_g.scale != 1)
output += ' ';
output += 'color="' + stv_g.color + '"'
}
output += ">\n";
stv_g.started = true
}
/* set the color */
function set_color(color) {
|
| ︙ | ︙ | |||
367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
stv_g.v = s.v;
set_g()
}
// -- set the staff output buffer and scale when delayed output
function set_dscale(st, no_scale) {
if (output) {
if (stv_g.st < 0) {
staff_tb[0].output += output
} else if (stv_g.scale == 1) {
staff_tb[stv_g.st].output += output
} else {
staff_tb[stv_g.st].sc_out += output
}
| > > > > > | 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 |
stv_g.v = s.v;
set_g()
}
// -- set the staff output buffer and scale when delayed output
function set_dscale(st, no_scale) {
if (output) {
if (stv_g.started) { // close the previous sequence
stv_g.started = false
glout()
output += "</g>\n"
}
if (stv_g.st < 0) {
staff_tb[0].output += output
} else if (stv_g.scale == 1) {
staff_tb[stv_g.st].output += output
} else {
staff_tb[stv_g.st].sc_out += output
}
|
| ︙ | ︙ | |||
728 729 730 731 732 733 734 |
n = ((w - 15) / d) | 0
else
n = 0;
x += (w - d * n - 5) / 2;
out_XYAB('<path class="stroke" stroke-width="1.2"\n\
stroke-dasharray="5,A"\n\
d="mX YhB"/>\n',
| | | 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 |
n = ((w - 15) / d) | 0
else
n = 0;
x += (w - d * n - 5) / 2;
out_XYAB('<path class="stroke" stroke-width="1.2"\n\
stroke-dasharray="5,A"\n\
d="mX YhB"/>\n',
x, y + 4, // set the line a bit upper
Math.round((d - 5) / stv_g.scale), d * n + 5)
}
// stem [and flags]
function out_stem(x, y, h, grace,
nflags, straight) { // optional
//fixme: dx KO with half note or longa
var dx = grace ? GSTEM_XOFF : 3.5,
|
| ︙ | ︙ | |||
847 848 849 850 851 852 853 |
// tuplet bracket with number - the staves are not defined
function out_tubrn(x, y, dx, dy, up, str) {
var dxx,
sw = str.length * 10,
h = up ? -3 : 3;
set_font("tuplet")
| | | 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 |
// tuplet bracket with number - the staves are not defined
function out_tubrn(x, y, dx, dy, up, str) {
var dxx,
sw = str.length * 10,
h = up ? -3 : 3;
set_font("tuplet")
xy_str(x + dx / 2, y + dy / 2 - gene.curfont.size * .1,
str, 'c')
dx /= stv_g.scale
if (!up)
y += 6;
output += '<path class="stroke" d="m';
out_sxsy(x, ' ', y);
dxx = dx - sw + 1
|
| ︙ | ︙ | |||
872 873 874 875 876 877 878 |
out_sxsy(x, ' ', y - h);
output += 'l' + dx.toFixed(1) + ' ' + (-dy).toFixed(1) + '"/>\n'
}
// underscore line
function out_wln(x, y, w) {
out_XYAB('<path class="stroke" stroke-width="0.8" d="mX YhF"/>\n',
| | | 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 |
out_sxsy(x, ' ', y - h);
output += 'l' + dx.toFixed(1) + ' ' + (-dy).toFixed(1) + '"/>\n'
}
// underscore line
function out_wln(x, y, w) {
out_XYAB('<path class="stroke" stroke-width="0.8" d="mX YhF"/>\n',
x, y + 1, w)
}
// decorations with string
var deco_str_style = {
crdc: {
dx: 0,
dy: 5,
|
| ︙ | ︙ | |||
1069 1070 1071 1072 1073 1074 1075 |
if (deco_val_tb[name])
deco_val_tb[name](x, y, val, defl)
else
error(1, null, "No function for decoration '$1'", name)
}
function out_glisq(x2, y2, de) {
| > | > > > > > > | | > > | | > | > > > > > > | | > > | | < < | 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 |
if (deco_val_tb[name])
deco_val_tb[name](x, y, val, defl)
else
error(1, null, "No function for decoration '$1'", name)
}
function out_glisq(x2, y2, de) {
var ar, a, len,
de1 = de.start,
x1 = de1.x,
y1 = de1.y + staff_tb[de1.st].y,
dx = x2 - x1,
dy = self.sh(y1 - y2)
if (!stv_g.g)
dx /= stv_g.scale
ar = Math.atan2(dy, dx)
a = ar / Math.PI * 180
len = (dx - (de1.s.dots ? 13 + de1.s.xmx : 8)
- 8 - (de.s.notes[0].shac || 0))
/ Math.cos(ar)
g_open(x1, y1, a);
x1 = de1.s.dots ? 13 + de1.s.xmx : 8;
len = len / 6 | 0
if (len < 1)
len = 1
while (--len >= 0) {
xygl(x1, 0, "ltr");
x1 += 6
}
g_close()
}
function out_gliss(x2, y2, de) {
var ar, a, len,
de1 = de.start,
x1 = de1.x,
y1 = de1.y + staff_tb[de1.st].y,
dx = x2 - x1,
dy = self.sh(y1 - y2)
if (!stv_g.g)
dx /= stv_g.scale
ar = Math.atan2(dy, dx)
a = ar / Math.PI * 180
len = (dx - (de1.s.dots ? 13 + de1.s.xmx : 8)
- 8 - (de.s.notes[0].shac || 0))
/ Math.cos(ar)
g_open(x1, y1, a);
xypath(de1.s.dots ? 13 + de1.s.xmx : 8, 0)
output += 'h' + len.toFixed(1) + '" stroke-width="1"/>\n';
g_close()
}
var deco_l_tb = {
glisq: out_glisq,
gliss: out_gliss
|
| ︙ | ︙ | |||
1233 1234 1235 1236 1237 1238 1239 | bh = gene.curfont.size + 4 } //fixme: xy_str() cannot be used because <tspan> in s.tempo_str //fixme: then there cannot be font changes by "$n" in the Q: texts output += '<text class="' + font_class(gene.curfont) + '" x="' | | | | 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 |
bh = gene.curfont.size + 4
}
//fixme: xy_str() cannot be used because <tspan> in s.tempo_str
//fixme: then there cannot be font changes by "$n" in the Q: texts
output += '<text class="' + font_class(gene.curfont) +
'" x="'
out_sxsy(x, '" y="', y + gene.curfont.size * .22)
output += '">' + s.tempo_str + '</text>\n'
if (bh) {
gene.curfont.box = true
output += '<rect class="stroke" x="'
out_sxsy(x - 2, '" y="', y + bh - 1)
output += '" width="' + (s.tempo_wh[0] + 4).toFixed(1) +
'" height="' + bh.toFixed(1) +
'"/>\n'
}
// don't display anymore
s.invis = true
} // writempo()
|
| ︙ | ︙ | |||
1262 1263 1264 1265 1266 1267 1268 |
function svg_flush() {
if (multicol || !output || !user.img_out || posy == 0)
return
var i, font,
head = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1"\n\
xmlns:xlink="http://www.w3.org/1999/xlink"\n\
| | < < < < < < < < < | | > > > > > > > > > > > | 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 |
function svg_flush() {
if (multicol || !output || !user.img_out || posy == 0)
return
var i, font,
head = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1"\n\
xmlns:xlink="http://www.w3.org/1999/xlink"\n\
fill="currentColor" stroke-width=".7"',
g = ''
glout()
font = get_font("music")
head += ' class="' + font_class(font) +
' tune' + tunes.length + '"\n' // tune index for play
posy *= cfmt.scale
if (user.imagesize) {
head += user.imagesize +
' viewBox="0 0 ' + img.width.toFixed(0) + ' ' +
posy.toFixed(0) + '">\n'
} else {
head += ' viewBox="0 0 ' + img.width.toFixed(0) + ' ' +
posy.toFixed(0) +
'" width="' + img.width.toFixed(0) +
'px" height="' + posy.toFixed(0) + 'px">\n'
}
head += fulldefs
if (style || font_style) {
head += '<style>' + font_style
if (cfmt.fgcolor || cfmt.bgcolor) {
head += '\n.f' + font.fid + (cfmt.fullsvg || '')
+ '{'
+ (cfmt.fgcolor ? ('color:' + cfmt.fgcolor + ';')
: '')
+ (cfmt.bgcolor ? ('background-color:' + cfmt.bgcolor)
: '')
+ '}'
}
head += style + '\n</style>\n'
}
if (defs)
head += '<defs>' + defs + '\n</defs>\n'
// if %%pagescale != 1, do a global scale
// (with a container: transform scale in <svg> does not work
// the same in all browsers)
|
| ︙ | ︙ | |||
1324 1325 1326 1327 1328 1329 1330 | '<div class="nobrk newpage">') blkdiv = -1 // block started } user.img_out(head + output + g + "</svg>"); output = "" font_style = '' | | | 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 |
'<div class="nobrk newpage">')
blkdiv = -1 // block started
}
user.img_out(head + output + g + "</svg>");
output = ""
font_style = ''
if (cfmt.fullsvg) {
defined_glyph = {}
for (i = 0; i < font_tb.length; i++)
font_tb[i].used = false
} else {
style = '';
fulldefs = ''
}
|
| ︙ | ︙ |
Changes to core/tail.js.
1 2 | // abc2svg - tail.js // | | | 1 2 3 4 5 6 7 8 9 10 | // abc2svg - tail.js // // Copyright (C) 2014-2022 Jean-Francois Moine // // This file is part of abc2svg-core. // // abc2svg-core is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
52 53 54 55 56 57 58 |
Abc.prototype.get_multi = function() { return multicol };
Abc.prototype.get_newpage = function() {
if (block.newpage) {
block.newpage = false;
return true
}
};
| | | 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
Abc.prototype.get_multi = function() { return multicol };
Abc.prototype.get_newpage = function() {
if (block.newpage) {
block.newpage = false;
return true
}
};
Abc.prototype.get_posy = function() { return posy }
Abc.prototype.get_staff_tb = function() { return staff_tb };
Abc.prototype.get_top_v = function() { return par_sy.top_voice };
Abc.prototype.get_tsfirst = function() { return tsfirst };
Abc.prototype.get_unit = get_unit;
Abc.prototype.get_voice_tb = function() { return voice_tb };
Abc.prototype.glout = glout
Abc.prototype.info = function() { return info };
|
| ︙ | ︙ | |||
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
Abc.prototype.psxygl = empty_function;
Abc.prototype.set_cur_sy = function(sy) { cur_sy = sy };
Abc.prototype.set_dscale = set_dscale;
Abc.prototype.set_font = set_font;
Abc.prototype.set_a_gch = function(s, a) { a_gch = a; csan_add(s) }
Abc.prototype.set_hl = set_hl
Abc.prototype.set_pagef = function() { blkdiv = 1 }
Abc.prototype.set_scale = set_scale;
Abc.prototype.set_tsfirst = function(s) { tsfirst = s };
Abc.prototype.set_v_param = set_v_param;
Abc.prototype.strwh = strwh;
Abc.prototype.stv_g = function() { return stv_g };
Abc.prototype.svg_flush = svg_flush;
Abc.prototype.syntax = syntax;
Abc.prototype.tunes = tunes
| > > | 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
Abc.prototype.psxygl = empty_function;
Abc.prototype.set_cur_sy = function(sy) { cur_sy = sy };
Abc.prototype.set_dscale = set_dscale;
Abc.prototype.set_font = set_font;
Abc.prototype.set_a_gch = function(s, a) { a_gch = a; csan_add(s) }
Abc.prototype.set_hl = set_hl
Abc.prototype.set_pagef = function() { blkdiv = 1 }
Abc.prototype.set_realwidth = function(v) { realwidth = v }
Abc.prototype.set_scale = set_scale;
Abc.prototype.set_sscale = set_sscale
Abc.prototype.set_tsfirst = function(s) { tsfirst = s };
Abc.prototype.set_v_param = set_v_param;
Abc.prototype.strwh = strwh;
Abc.prototype.stv_g = function() { return stv_g };
Abc.prototype.svg_flush = svg_flush;
Abc.prototype.syntax = syntax;
Abc.prototype.tunes = tunes
|
| ︙ | ︙ |
Changes to core/tune.js.
1 2 | // abc2svg - tune.js - tune generation // | | | 1 2 3 4 5 6 7 8 9 10 | // abc2svg - tune.js - tune generation // // Copyright (C) 2014-2023 Jean-Francois Moine // // This file is part of abc2svg-core. // // abc2svg-core is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
52 53 54 55 56 57 58 59 60 61 62 63 |
for (opt in parse.tune_v_opts) {
if (parse.tune_v_opts.hasOwnProperty(opt))
vfilt(parse.tune_v_opts[opt], opt)
}
}
/* -- link a ABC symbol into the current voice -- */
function sym_link(s) {
var tim = curvoice.time
if (!s.fname)
set_ref(s)
| > > | > < < < < < < | 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
for (opt in parse.tune_v_opts) {
if (parse.tune_v_opts.hasOwnProperty(opt))
vfilt(parse.tune_v_opts[opt], opt)
}
}
/* -- link a ABC symbol into the current voice -- */
// if a voice is ignored (not in %%staves) don't link the symbol
// but update the time for P: and Q:
function sym_link(s) {
var tim = curvoice.time
if (!s.fname)
set_ref(s)
if (!curvoice.ignore) {
s.prev = curvoice.last_sym
if (curvoice.last_sym)
curvoice.last_sym.next = s
else
curvoice.sym = s
}
curvoice.last_sym = s
s.v = curvoice.v;
s.p_v = curvoice;
s.st = curvoice.cst;
s.time = tim
if (s.dur && !s.grace)
curvoice.time += s.dur;
parse.ufmt = true
s.fmt = cfmt // global parameters
s.pos = curvoice.pos
if (curvoice.second)
s.second = true
if (curvoice.floating)
s.floating = true
if (curvoice.eoln) {
s.soln = true
curvoice.eoln = false
}
}
/* -- add a new symbol in a voice -- */
function sym_add(p_voice, type) {
var s = {
type:type,
dur:0
|
| ︙ | ︙ | |||
118 119 120 121 122 123 124 | /* -- sort all symbols by time and vertical sequence -- */ // weight of the symbols !! depends on the symbol type !! var w_tb = new Uint8Array([ 5, // bar 1, // clef 8, // custos | | | | | 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | /* -- sort all symbols by time and vertical sequence -- */ // weight of the symbols !! depends on the symbol type !! var w_tb = new Uint8Array([ 5, // bar 1, // clef 8, // custos 6, // sm (sequence marker, after bar) 0, // grace (must be null) 2, // key 3, // meter 9, // mrest 9, // note 0, // part 9, // rest 4, // space (before bar) 0, // staves 7, // stbrk 0, // tempo 0, // (free) 0, // block 0 // remark ]) |
| ︙ | ︙ | |||
158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
sy: sy,
next: p_voice.sym,
seqst: true
}
if (!p_voice.sym)
return
prev.fmt = fmt = p_voice.sym.fmt // starting format
// set the first symbol of each voice
for (v = 0; v < nv; v++) {
s = voice_tb[v].sym
vtb[v] = s
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
sy: sy,
next: p_voice.sym,
seqst: true
}
if (!p_voice.sym)
return
// check if different bars at the same time
function b_chk() {
var ir, bt, s, s2, v
ir = 0
bt = ""
while (1) {
v = vn[ir++]
if (v == undefined)
break
s = vtb[v]
if (!s || !s.bar_type || s.invis)
continue
if (!bt) {
bt = s.bar_type
continue
}
if (s.bar_type != bt)
break
}
if (!v)
return // no problem
if (bt == "::" || bt == ":|") {
ir = 0
while (1) {
v = vn[ir++]
if (v == undefined)
break
s = vtb[v]
if (!s || s.invis
|| s.bar_type != "::")
continue
s2 = clone(s)
s.bar_type = ":|"
s2.bar_type = "|:"
s2.next = s.next
s2.prev = s
s.next = s2
}
} else {
error(2, s, "Different bars $1 and $2",
bt, s.bar_type)
}
} // b_chk()
prev.fmt = fmt = p_voice.sym.fmt // starting format
// set the first symbol of each voice
for (v = 0; v < nv; v++) {
s = voice_tb[v].sym
vtb[v] = s
|
| ︙ | ︙ | |||
195 196 197 198 199 200 201 202 203 204 205 206 207 |
else
p_voice.last_sym = s
s.prev.next = s
s.fmt = fmt
glovar.tempo = null
vtb[v] = s
}
// loop on the symbols of all voices
while (1) {
if (new_sy) {
sy = new_sy;
new_sy = null;
| > > > > > > > > > > > > > > > > > > | > > > > > > | > | > > > > | 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 |
else
p_voice.last_sym = s
s.prev.next = s
s.fmt = fmt
glovar.tempo = null
vtb[v] = s
}
// if only one voice, quickly create the time links
if (nv == 1) {
s = tsfirst
s.ts_next = s.next
while (1) {
s = s.next
if (!s)
return
s.ts_prev = s.prev
s.ts_next = s.next
if (s.time != s.prev.time
|| w_tb[s.prev.type]
|| s.type == C.GRACE && s.prev.type == C.GRACE)
s.seqst = 1 //true
}
// not reached
}
// loop on the symbols of all voices
while (1) {
if (new_sy) {
sy = new_sy;
new_sy = null;
vn.length = 0
for (v = 0; v < nv; v++) {
if (!sy.voices[v])
continue
vn[sy.voices[v].range] = v
}
}
/* search the min time and symbol weight */
wmin = time = 10000000 // big int
ir = 0
while (1) {
v = vn[ir++]
if (v == undefined)
break
s = vtb[v]
if (!s || s.time > time)
continue
w = w_tb[s.type]
if (s.type == C.GRACE && s.next && s.next.type == C.GRACE)
w--
if (s.time < time) {
time = s.time;
wmin = w
} else if (w < wmin) {
wmin = w
}
}
if (wmin > 127)
break // done
// check the type of the measure bars
if (wmin == 5) // weight of bars
b_chk()
/* link the vertical sequence */
ir = 0
while (1) {
v = vn[ir++]
if (v == undefined)
break
s = vtb[v]
if (!s)
continue
w = w_tb[s.type]
if (s.type == C.GRACE && s.next && s.next.type == C.GRACE)
w--
if (s.time != time
|| w != wmin)
continue
if (s.type == C.STAVES)
new_sy = s.sy
if (fl) {
fl = 0;
s.seqst = true
}
|
| ︙ | ︙ | |||
318 319 320 321 322 323 324 |
p_voice = voice_tb[v]
if (!sys_chg) { // if not %%score
delete p_voice.eoln
while (1) { // set the end of slurs
sl = p_voice.sls.shift()
if (!sl)
break
| | | < < < < > | < < < < < < | | | | | > > > > > | > > > > | > > > > > | > > > > > > > > > | 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 |
p_voice = voice_tb[v]
if (!sys_chg) { // if not %%score
delete p_voice.eoln
while (1) { // set the end of slurs
sl = p_voice.sls.shift()
if (!sl)
break
s = sl.ss
// error(1, s, "Lack of ending slur(s)")
if (!s.sls)
s.sls = []
sl.loc = 'o' // no slur end
s.sls.push(sl)
}
} // not %%score
for (s = p_voice.sym; s; s = s.next) {
if (s.time >= staves_found)
break
}
for ( ; s; s = s.next) {
// if the symbol has a sequence weight smaller than the bar one
// and if there a time skip,
// add an invisible bar before it
if (w_tb[s.type] < 5
&& s.type != C.STAVES
&& s.type != C.CLEF
&& s.time // not at start of tune
&& (!s.prev || s.time > s.prev.time + s.prev.dur)) {
s2 = {
type: C.BAR,
bar_type: "[]",
v: s.v,
p_v: s.p_v,
st: s.st,
time: s.time,
dur:0,
next: s,
prev: s.prev,
fmt: s.fmt,
invis: 1
}
if (s.prev)
s.prev.next = s2
else
voice_tb[s.v].sym = s2
s.prev = s2
}
switch (s.type) {
case C.GRACE:
if (!cfmt.graceword)
continue
for (s2 = s.next; s2; s2 = s2.next) {
switch (s2.type) {
case C.SPACE:
continue
case C.NOTE:
|
| ︙ | ︙ | |||
409 410 411 412 413 414 415 |
par_sy.next = sy_new;
par_sy = sy_new
}
/* -- set the bar numbers -- */
// (possible hook)
Abc.prototype.set_bar_num = function() {
| | > > > > > > > > > > > > > > > > > > | 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 |
par_sy.next = sy_new;
par_sy = sy_new
}
/* -- set the bar numbers -- */
// (possible hook)
Abc.prototype.set_bar_num = function() {
var s, s2, rep_tim, k, n, nu, txt,
tim = 0, // time of the previous bar
bar_num = gene.nbar,
bar_tim = 0, // time of previous repeat variant
ptim = 0, // time of previous bar
wmeasure = voice_tb[cur_sy.top_voice].meter.wmeasure
// check the measure duration
function check_meas() {
var s3
if (tim > ptim + wmeasure
&& s.prev.type != C.MREST)
return 1 //true
// the measure is too short,
// check if there is a bar a bit further
for (s3 = s.next; s3 && s3.time == s.time; s3 = s3.next)
;
for ( ; s3 && !s3.bar_type; s3 = s3.next)
;
return s3 && (s3.time - bar_tim) % wmeasure
}
// don't count a bar at start of tune
for (s = tsfirst; ; s = s.ts_next) {
if (!s)
return
switch (s.type) {
case C.METER:
|
| ︙ | ︙ | |||
448 449 450 451 452 453 454 |
}
break
}
}
// set the measure number on the top bars
for ( ; s; s = s.ts_next) {
| < < > > | | > > > > > > > > > > > > > | | > | | | > | | | < | | 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 |
}
break
}
}
// set the measure number on the top bars
for ( ; s; s = s.ts_next) {
switch (s.type) {
case C.METER:
if (s.time == bar_tim)
break // already seen
if (wmeasure != 1) // if not M:none
bar_num += (s.time - bar_tim) / wmeasure
bar_tim = s.time
wmeasure = s.wmeasure
break
case C.BAR:
if (s.time <= tim)
break // already seen
tim = s.time
nu = 1 //true // no num update
txt = ""
for (s2 = s; s2; s2 = s2.next) {
if (s2.time > tim || s2.dur)
break
if (!s2.bar_type)
continue
if (s2.bar_type != '[')
nu = 0 //false // do update
if (s2.text)
txt = s2.text
}
if (s.bar_num) {
bar_num = s.bar_num // (%%setbarnb)
ptim = bar_tim = tim
continue
}
if (wmeasure == 1) { // if M:none
if (s.bar_dotted)
continue
if (txt) {
if (!cfmt.contbarnb) {
if (txt[0] == '1')
rep_tim = bar_num
else
bar_num = rep_tim
}
}
if (!nu)
s.bar_num = ++bar_num
continue
}
n = bar_num + (tim - bar_tim) / wmeasure
k = n - (n | 0)
if (cfmt.checkbars
&& k
&& check_meas())
error(0, s, "Bad measure duration")
if (tim > ptim + wmeasure) { // if more than one measure
n |= 0
k = 0
bar_tim = tim // re-synchronize
bar_num = n
}
if (txt) {
if (txt[0] == '1') {
if (cfmt.contbarnb)
rep_tim = bar_tim + k * wmeasure
else
rep_tim = tim
if (!nu)
s.bar_num = n
} else {
if (cfmt.contbarnb)
bar_tim = rep_tim
else
bar_tim += tim - rep_tim
n = bar_num + (tim - bar_tim) / wmeasure
if (n == (n | 0))
s.bar_num = n
}
} else {
n |= 0
s.bar_num = n
}
if (!k)
ptim = tim
break
}
}
|
| ︙ | ︙ | |||
648 649 650 651 652 653 654 | } map[2] = a[i] break } } } | | | < < < < < < < < < < < < < < < < < < | < < < | < < | | < < < > | < < < < < < < | < < < < < < < < < < | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < | > | < | < < | < < | < < | | < < < | < < | < < | < < < | < | < < < < < < < < | < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < | | | | < | < < < < | | | < < < < < | < < < < < < | | < < < | < < | < | < | < | | 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 |
}
map[2] = a[i]
break
}
}
}
// set the transposition in the first key signature or in a new key
function set_transp() {
var s
if (curvoice.ckey.k_bagpipe || curvoice.ckey.k_drum)
return
if (cfmt.transp && curvoice.shift) // if %%transpose and shift=
syntax(0, "Mix of old and new transposition syntaxes");
if (is_voice_sig()) { // if no symbol yet
curvoice.okey.fmt = cfmt
curvoice.key = s = clone(curvoice.okey)
} else {
s = clone(curvoice.ckey)
s.k_old_sf = s.k_sf
sym_link(s)
}
delete s.invis // needed if K:C/none at start of tune
key_transp(s)
curvoice.ckey = clone(s)
if (curvoice.key.k_none)
s.k_sf = 0
}
// set the control values (P: and Q:)
function set_ctrl() {
var s, tim, e
for (tim in parse.ctrl) {
// if (!parse.ctrl.hasOwnProperty(tim))
// continue
e = parse.ctrl[tim]
s = tsfirst
while (s.next && s.next.time < tim)
s = s.next
while (s && s.time < tim)
s = s.ts_next
if (!s) {
//fixme: insert at the end
} else {
// put the P: and/or Q: on a note or rest
while (s.time == tim && s.ts_next
&& !s.dur)
s = s.ts_next
if (e.part) {
// if (s.time != tim) {
// // fixme: insert a part (?)
// }
s.part = e.part
}
if (e.tempo) {
lkvsym(e.tempo, s)
lktsym(e.tempo, s)
}
}
}
} // set_ctrl()
// get a abcm2ps/abcMIDI compatible transposition value as a base-40 interval
// The value may be
// - [+|-]<number of semitones>[s|f]
// - <note1>[<note2>] % <note2> default is 'c'
function get_transp(param) {
if (param[0] == '0')
|
| ︙ | ︙ | |||
889 890 891 892 893 894 895 |
} // get_transp()
/* -- process a pseudo-comment (%% or I:) -- */
// (possible hook)
Abc.prototype.do_pscom = function(text) {
var h1, val, s, cmd, param, n, k, b
| | | 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 |
} // get_transp()
/* -- process a pseudo-comment (%% or I:) -- */
// (possible hook)
Abc.prototype.do_pscom = function(text) {
var h1, val, s, cmd, param, n, k, b
cmd = text.match(/[^\s]+/)
if (!cmd)
return
cmd = cmd[0];
// ignore the command if the voice is ignored,
// but not if %%score/%%staves!
if (curvoice && curvoice.ignore) {
|
| ︙ | ︙ | |||
953 954 955 956 957 958 959 |
if (parse.state >= 2) {
curvoice = voice_tb[0]
s = new_block("mc_" + param)
break
}
switch (param) {
case "start":
| | | < < | < < < < < | < > > < < < < < < < | > > | 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 |
if (parse.state >= 2) {
curvoice = voice_tb[0]
s = new_block("mc_" + param)
break
}
switch (param) {
case "start":
self.block_gen({
subtype: "mc_start"
})
break
case "new":
if (!multicol) {
syntax(1, "%%multicol new without start")
break
}
self.block_gen({
subtype: "mc_new"
})
break
case "end":
if (!multicol) {
syntax(1, "%%multicol end without start")
break
}
self.block_gen({
subtype: "mc_end"
})
break
default:
syntax(1, "Unknown keyword '$1' in %%multicol", param)
break
}
return
case "ottava":
|
| ︙ | ︙ | |||
1177 1178 1179 1180 1181 1182 1183 | case 0: cfmt.transp = 0 // fall thru case 1: cfmt.transp = (cfmt.transp || 0) + val return } | < < < < < < < < < < < < < < | | 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 | case 0: cfmt.transp = 0 // fall thru case 1: cfmt.transp = (cfmt.transp || 0) + val return } curvoice.tr_sco = val set_transp() return case "tune": //fixme: to do return case "user": set_user(param) |
| ︙ | ︙ | |||
1317 1318 1319 1320 1321 1322 1323 | } write_text(text, action) break } } /* -- generate a piece of tune -- */ | | > > > > > > | < < > > > > > > > > > > > > | | < < < < < < < < < < < < < < < < < | | < < < > > | > | | | | | < | < < < | | < < < < < < < < < < < < < < < | | < < | < < < < < | | | < | < < | | | | < | < < > | 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 |
}
write_text(text, action)
break
}
}
/* -- generate a piece of tune -- */
function generate() {
var s, v, p_voice;
if (a_dcn.length) {
syntax(1, "Decoration without symbol")
a_dcn = []
}
if (parse.tp) {
syntax(1, "No end of tuplet")
s = parse.tps
if (s)
delete s.tp
delete parse.tp
}
if (vover) {
syntax(1, "No end of voice overlay");
get_vover(vover.bar ? '|' : ')')
}
voice_adj();
sort_all() /* define the time / vertical sequences */
if (tsfirst) {
if (user.anno_start)
anno_start = a_start
if (user.anno_stop)
anno_stop = a_stop
self.set_bar_num()
if (info.P)
tsfirst.parts = info.P // for play
if (parse.ctrl)
set_ctrl() // set control values
// give the parser result to the application
if (user.get_abcmodel)
user.get_abcmodel(tsfirst, voice_tb, abc2svg.sym_name, info)
if (user.img_out) // if SVG generation
self.output_music()
} // (tsfirst)
// finish the generation
set_page() // the page layout may have changed
if (info.W)
put_words(info.W)
put_history()
parse.state = 0 // file header
blk_flush() // (force end of block)
if (tsfirst) { // if non void, keep tune data for upper layers
tunes.push([tsfirst, voice_tb, info, cfmt])
tsfirst = null
}
}
// transpose a key
function key_transp(s) {
if (s.k_none) // no key
return
var n, a_acc,
b40 = (s.k_b40 + 200 + curvoice.tr_sco) % 40,
d = abc2svg.b40k[b40] - b40
if (d) {
if (curvoice.tr_sco > 0)
curvoice.tr_sco -= d
else
curvoice.tr_sco += d
b40 += d
}
s.k_b40 = b40
s.k_sf = abc2svg.b40sf[b40]
// transpose the accidental list
if (!s.k_a_acc)
return
a_acc = []
for (n = 0; n < s.k_a_acc.length; n++) {
b40 = abc2svg.pab40(s.k_a_acc[n].pit, s.k_a_acc[n].acc)
+ curvoice.tr_sco
a_acc[n] = {
pit: abc2svg.b40p(b40),
acc: abc2svg.b40a(b40) || 3
}
}
s.k_a_acc = a_acc
}
/* -- get staves definition (%%staves / %%score) -- */
function get_staves(cmd, parm) {
var s, p_voice, p_voice2, i, flags, v, vid, a_vf,
st, range,
nv = voice_tb.length,
|
| ︙ | ︙ | |||
1700 1701 1702 1703 1704 1705 1706 |
voice_tb.push(p_voice)
return p_voice
} // clone_voice()
/* -- get a voice overlay -- */
function get_vover(type) {
| | < > > > > > > > > > > > > > > > > > > > > > > > > > | | 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 |
voice_tb.push(p_voice)
return p_voice
} // clone_voice()
/* -- get a voice overlay -- */
function get_vover(type) {
var p_voice2, p_voice3, range, s, time, v, v2, v3, s2
/* treat the end of overlay */
if (type == '|'
|| type == ')') {
if (!curvoice.last_note) {
syntax(1, errs.nonote_vo)
if (vover) {
curvoice = vover.p_voice
vover = null
}
return
}
curvoice.last_note.beam_end = true
if (!vover) {
syntax(1, "Erroneous end of voice overlay")
return
}
if (curvoice.time != vover.p_voice.time) {
if (!curvoice.ignore)
syntax(1, "Wrong duration in voice overlay");
if (curvoice.time > vover.p_voice.time)
vover.p_voice.time = curvoice.time
}
curvoice.acc = [] // no accidental anymore
// if the last symbols are spaces, move them to the main voice
p_voice2 = vover.p_voice // main voice
s = curvoice.last_sym
if (s.type == C.SPACE && p_voice2.last_sym.type != C.SPACE) {
s.p_v = p_voice2
s.v = s.p_v.v
while (s.prev.type == C.SPACE) {
s = s.prev
s.p_v = p_voice2
s.v = s.p_v.v
}
s2 = s.prev
s2.next = null
s.prev = p_voice2.last_sym
s.prev.next = s
p_voice2.last_sym = curvoice.last_sym
curvoice.last_sym = s2
}
curvoice = p_voice2
vover = null
return
}
/* treat the full overlay start */
if (type == '(') {
if (vover) {
|
| ︙ | ︙ | |||
1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 |
curvoice.last_note.beam_end = true;
p_voice2 = curvoice.voice_down
if (!p_voice2) {
p_voice2 = clone_voice(curvoice.id + 'o');
curvoice.voice_down = p_voice2;
p_voice2.time = 0;
p_voice2.second = true;
v2 = p_voice2.v;
par_sy.voices[v2] = {
st: curvoice.st,
second: true
}
range = par_sy.voices[curvoice.v].range
for (v = 0; v < par_sy.voices.length; v++) {
if (par_sy.voices[v]
&& par_sy.voices[v].range > range)
par_sy.voices[v].range++
}
par_sy.voices[v2].range = range + 1
}
p_voice2.ulen = curvoice.ulen
p_voice2.dur_fact = curvoice.dur_fact
p_voice2.acc = [] // no accidental
if (!vover) { /* first '&' in a measure */
time = p_voice2.time
for (s = curvoice.last_sym; /*s*/; s = s.prev) {
if (s.type == C.BAR
|| s.time <= time) /* (if start of tune) */
break
}
vover = {
bar: (s && s.bar_type) ? s.bar_type : '|',
p_voice: curvoice,
| > > > > > > | < < < < < < < < < < < < | | | | > | > | | | > | 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 |
curvoice.last_note.beam_end = true;
p_voice2 = curvoice.voice_down
if (!p_voice2) {
p_voice2 = clone_voice(curvoice.id + 'o');
curvoice.voice_down = p_voice2;
p_voice2.time = 0;
p_voice2.second = true;
p_voice2.last_note = null
v2 = p_voice2.v;
if (par_sy.voices[curvoice.v]) { // if voice in the staff system
par_sy.voices[v2] = {
st: curvoice.st,
second: true
}
range = par_sy.voices[curvoice.v].range
for (v = 0; v < par_sy.voices.length; v++) {
if (par_sy.voices[v]
&& par_sy.voices[v].range > range)
par_sy.voices[v].range++
}
par_sy.voices[v2].range = range + 1
}
}
p_voice2.ulen = curvoice.ulen
p_voice2.dur_fact = curvoice.dur_fact
p_voice2.acc = [] // no accidental
if (!vover) { /* first '&' in a measure */
time = p_voice2.time
if (curvoice.ignore)
s = null
else
for (s = curvoice.last_sym; /*s*/; s = s.prev) {
if (s.type == C.BAR
|| s.time <= time) /* (if start of tune) */
break
}
vover = {
bar: (s && s.bar_type) ? s.bar_type : '|',
p_voice: curvoice,
time: s ? s.time : curvoice.time
}
} else {
if (curvoice != vover.p_voice
&& curvoice.time != vover.p_voice.time) {
syntax(1, "Wrong duration in voice overlay")
if (curvoice.time > vover.p_voice.time)
vover.p_voice.time = curvoice.time
}
}
p_voice2.time = vover.time;
curvoice = p_voice2
}
// check if a clef, key or time signature may go at start of the current voice
function is_voice_sig() {
var s
if (curvoice.time)
return false
if (!curvoice.last_sym)
return true
for (s = curvoice.last_sym; s; s = s.prev)
if (w_tb[s.type])
return false
return true
}
// treat a clef found in the tune body
function get_clef(s) {
if (!curvoice.time // (force a clef when new voice)
&& is_voice_sig()) {
curvoice.clef = s
s.fmt = cfmt
return
}
// clef change
sym_link(s);
s.clef_small = true
// move the clef before a (not right repeat) bar
var s2 = s.prev
if (!s.invis // if not 'K: clef=none'
&& s2 && s2.type == C.BAR
&& s2.bar_type[0] != ':') {
s.next = s2
s.prev = s2.prev
if (s.prev)
s.prev.next = s
s2.prev = s
s2.next = null
curvoice.last_sym = s2
if (s.soln) {
delete s.soln
curvoice.eoln = true
}
}
}
// treat K: (kp = key signature + parameters)
function get_key(parm) {
var v, p_voice, transp, sndtran, tr_p, nt,
// [s_key, a] = new_key(parm) // KO with nodejs
a = new_key(parm),
s_key = a[0],
s = s_key
a = a[1]
if (parse.state == 1) { // in tune header (first K:)
if (s_key.k_sf == undefined && !s_key.k_a_acc) { // empty K:
s_key.k_sf = 0;
s_key.k_none = true
|
| ︙ | ︙ | |||
1878 1879 1880 1881 1882 1883 1884 |
if (!glovar.ulen)
glovar.ulen = C.BLEN / 8;
if (a.length) {
memo_kv_parm('*', a)
a = ''
}
goto_tune()
| < < | | | | < | < < | < < < < < < | | < | | < < | > < < < < | > | | | < | 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 |
if (!glovar.ulen)
glovar.ulen = C.BLEN / 8;
if (a.length) {
memo_kv_parm('*', a)
a = ''
}
goto_tune()
} else {
set_kv_parm(a)
}
tr_p = curvoice.tr_p // transposition change 1=sco, 2=snd
curvoice.tr_p = 0
if (s.k_sf == undefined) { // if no key
if (!s.k_a_acc // if no accidental list
&& !(tr_p & 1)) // and no score transposition
return // not a key signature
s_key.k_sf = curvoice.okey.k_sf // set the same key
s_key.k_b40 = curvoice.okey.k_b40
}
if (curvoice.tr_sco) // if transpose score
key_transp(s)
curvoice.okey = clone(s_key)
s_key.k_old_sf = curvoice.ckey.k_sf // memorize the key changes
if ((!s_key.k_a_acc || !s_key.k_a_acc.length)
&& !s_key.k_sf && !s_key.k_old_sf)
s_key.invis = true // don't display the key signature
if (!s_key.k_b40)
s_key.k_b40 = curvoice.ckey.k_b40
curvoice.ckey = s_key
if (is_voice_sig()) {
s_key.fmt = cfmt
curvoice.key = clone(s_key)
if (s_key.k_none)
curvoice.key.k_sf = 0
} else {
sym_link(s_key) // (don't move the key)
|
| ︙ | ︙ | |||
1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 |
if (!p_voice.time) { // if no symbol yet
p_voice.id = id
delete p_voice.init // reload the global attributes
if (cfmt.transp // != undefined
&& parse.state >= 2) {
p_v_sav = curvoice;
curvoice = p_voice;
set_transp();
curvoice = p_v_sav
}
return p_voice // default voice
}
}
for (v = 0; v < n; v++) {
| > | 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 |
if (!p_voice.time) { // if no symbol yet
p_voice.id = id
delete p_voice.init // reload the global attributes
if (cfmt.transp // != undefined
&& parse.state >= 2) {
p_v_sav = curvoice;
curvoice = p_voice;
curvoice.tr_sco = cfmt.transp
set_transp();
curvoice = p_v_sav
}
return p_voice // default voice
}
}
for (v = 0; v < n; v++) {
|
| ︙ | ︙ | |||
2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 |
bol: parse.iend
}
if (parse.file[curvoice.clone.bol - 1] != ']')
curvoice.clone.bol++ // start of new line
}
set_kv_parm(a)
v = curvoice.v
if (curvoice.new) { // if new voice
delete curvoice.new
if (staves_found < 0) { // if no %%score/%%staves
curvoice.st = curvoice.cst = ++nstaff;
par_sy.nstaff = nstaff;
par_sy.voices[v] = {
st: nstaff,
range: v
}
par_sy.staves[nstaff] = {
stafflines: curvoice.stafflines || "|||||",
staffscale: 1
}
}
}
if (!curvoice.filtered
&& par_sy.voices[v]
&& (parse.voice_opts
|| parse.tune_v_opts)) {
| > > > > > > > | 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 |
bol: parse.iend
}
if (parse.file[curvoice.clone.bol - 1] != ']')
curvoice.clone.bol++ // start of new line
}
set_kv_parm(a)
if (curvoice.tr_p) {
curvoice.tr_p = 0
set_transp()
}
v = curvoice.v
if (curvoice.new) { // if new voice
delete curvoice.new
if (staves_found < 0) { // if no %%score/%%staves
curvoice.st = curvoice.cst = ++nstaff;
par_sy.nstaff = nstaff;
par_sy.voices[v] = {
st: nstaff,
range: v
}
par_sy.staves[nstaff] = {
stafflines: curvoice.stafflines || "|||||",
staffscale: 1
}
} else if (!par_sy.voices[v]) {
curvoice.ignore = 1 // voice not declared in %%staves
return
}
}
if (!curvoice.filtered
&& par_sy.voices[v]
&& (parse.voice_opts
|| parse.tune_v_opts)) {
|
| ︙ | ︙ | |||
2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 |
write_heading();
if (glovar.new_nbar) {
gene.nbar = glovar.new_nbar // measure numbering
glovar.new_nbar = 0
} else {
gene.nbar = 1
}
// if no voice yet, create the default voice
if (!voice_tb.length) {
get_voice("1");
curvoice.clef.istart = curvoice.key.istart;
curvoice.clef.iend = curvoice.key.iend;
// nstaff = 0;
| > > | 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 |
write_heading();
if (glovar.new_nbar) {
gene.nbar = glovar.new_nbar // measure numbering
glovar.new_nbar = 0
} else {
gene.nbar = 1
}
parse.state = 3 // in tune body
// if no voice yet, create the default voice
if (!voice_tb.length) {
get_voice("1");
curvoice.clef.istart = curvoice.key.istart;
curvoice.clef.iend = curvoice.key.iend;
// nstaff = 0;
|
| ︙ | ︙ |
Added dist_bin.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | COPYING COPYING.LESSER MIDI-1.js Scc1t2/ abc2svg-1.js abc2svg.ttf abc2svg.woff abcdoc-1.js abcjsc abcmjs abcnode abcqjs abctopdf abcweb1-1.js abcweb-1.js ambitus-1.js break-1.js capo-1.js chordnames-1.js clair-1.js clip-1.js cmdline.js combine-1.js diag-1.js edit-1.css edit-1.js edit-1.xhtml edit-de.js edit-en.js edit-fr.js edit-it.js edit-pt_BR.js equalbars-1.js err-de.js err-en.js err-fr.js err-it.js err-pt_BR.js gamelan-1.js grid2-1.js grid-1.js grid3-1.js jazzchord-1.js jianpu-1.js mdnn-1.js nns-1.js page-1.js pedline-1.js perc-1.js psvg-1.js roman-1.js snd-1.js soloffs-1.js sth-1.js strtab-1.js temper-1.js tropt-1.js toabc.js tohtml.js tomei.js tonotes.js toparam.js |
Changes to editor/edit.css.
| ︙ | ︙ | |||
96 97 98 99 100 101 102 103 104 |
#dleft, #ctxMenu, .popup { display: none }
body {
margin:0; padding:0; border:0;
background-color: white;
}
#dright { margin:0; padding:0; border:0 }
.newpage { page-break-before: always }
.nobrk { page-break-inside: avoid }
}
| > | 96 97 98 99 100 101 102 103 104 105 |
#dleft, #ctxMenu, .popup { display: none }
body {
margin:0; padding:0; border:0;
background-color: white;
}
#dright { margin:0; padding:0; border:0 }
.newpage { page-break-before: always }
.newpage:first-of-type { page-break-before: avoid }
.nobrk { page-break-inside: avoid }
}
|
Changes to editor/edit.js.
| ︙ | ︙ | |||
290 291 292 293 294 295 296 |
// select a source ABC element on error
function gotoabc(l, c) {
var s = elt_ref.source
selsrc(0)
if (l >= 0)
c = soffs(l, Number(c))
| > > | | 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 |
// select a source ABC element on error
function gotoabc(l, c) {
var s = elt_ref.source
selsrc(0)
if (l >= 0)
c = soffs(l, Number(c))
s.blur() // unfocus
s.setSelectionRange(c, c) // just set the cursor (no range)
s.focus() // should scroll the textarea
s.setSelectionRange(c, syms[c] ? syms[c].iend : c + 1)
}
// click in the target
function selsvg(evt) {
var v,
cl = evt.target.getAttribute('class')
|
| ︙ | ︙ | |||
319 320 321 322 323 324 325 | play.stop = -1; play.abcplay.stop() return } // highlight the clicked element or clear the selection start s = elt_ref.source; | > | < < < | < < > > | 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 |
play.stop = -1;
play.abcplay.stop()
return
}
// highlight the clicked element or clear the selection start
s = elt_ref.source;
s.blur();
v = cl && cl.substr(0, 4) == 'abcr' ? Number(cl.slice(6, -1)) : 0
s.setSelectionRange(v, v) // just a cursor
s.focus()
if (v)
s.setSelectionRange(v, syms[v].iend)
}
// set/clear a selection
function setsel(idx, v) {
var i, elts, s,
old_v = selx[idx];
|
| ︙ | ︙ | |||
353 354 355 356 357 358 359 |
elts[i].style.fillOpacity = 0.4
}
selx[idx] = v
}
function do_scroll(elt) {
| | > > | | < < > > | | | < | | | | | | > > > > > | 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 |
elts[i].style.fillOpacity = 0.4
}
selx[idx] = v
}
function do_scroll(elt) {
var x = 0,
y = 0,
b = elt.getBoundingClientRect(), // box of the rectangle
d = elt_ref.target.parentElement, // <div> 'dright'
r = elt.parentNode.getBoundingClientRect() // box of the svg container
if (b.x < d.offsetLeft // x offset of the rectangle
|| b.x + b.width > d.offsetLeft + d.clientWidth * .7)
x = b.x - d.offsetLeft - d.clientWidth * .3
if (r.y < d.offsetTop // y offset of the svg container
|| r.y + r.height > d.offsetTop + d.clientHeight * .7)
y = r.y - d.offsetTop - d.clientHeight * .3
if (x || y)
// d.scrollBy(x, y)
d.scrollBy({
top: y,
left: x,
behavior: (x < 0 || y) ? 'instant' : 'smooth'
// 'smooth', 'instant' or 'auto' (default)
})
}
// source text selection callback
function seltxt(evt) {
var s, elts,
e = 0,
elt = elt_ref.source,
|
| ︙ | ︙ | |||
514 515 516 517 518 519 520 521 522 523 524 525 526 527 |
// start playing
// -1: All (removed)
// 0: Tune
// 1: Selection
// 2: Loop
// 3: Continue
function play_tune(what) {
var i, si, ei, elt,
C = abc2svg.C,
tunes = abc.tunes
if (play.playing) {
if (!play.stop) {
play.stop = -1;
| > > | 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 |
// start playing
// -1: All (removed)
// 0: Tune
// 1: Selection
// 2: Loop
// 3: Continue
function play_tune(what) {
if (!abc)
return // no generation yet
var i, si, ei, elt,
C = abc2svg.C,
tunes = abc.tunes
if (play.playing) {
if (!play.stop) {
play.stop = -1;
|
| ︙ | ︙ | |||
809 810 811 812 813 814 815 |
// display the play menu
// This function is called on non left click
function show_menu(evt) {
var x, y,
elt = evt.target,
cl = elt.getAttribute('class')
| < < < > | > > > > > > > < | > | < < | 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 |
// display the play menu
// This function is called on non left click
function show_menu(evt) {
var x, y,
elt = evt.target,
cl = elt.getAttribute('class')
// if right click on an element, select it
if (cl && cl.substr(0, 4) == 'abcr') {
setsel(1, Number(cl.slice(6, -1)))
evt.preventDefault()
return
}
// if the play menu is already active
// display the default context menu
ctxMenu = document.getElementById("ctxMenu");
if (ctxMenu.style.display == "block")
return
// otherwise, display the play menu
evt.preventDefault()
play.click = { // keep the click references for 'play tune'
svg: elt,
Y: evt.pageY
}
ctxMenu.style.display = "block";
x = evt.pageX - elt_ref.target.parentNode.offsetLeft
+ elt_ref.target.parentNode.scrollLeft;
y = evt.pageY + elt_ref.target.parentNode.scrollTop;
ctxMenu.style.left = (x - 30) + "px";
ctxMenu.style.top = (y - 10) + "px"
} // showmenu
e = elt_ref.target
// e.onauxclick = show_menu // right or middle buttons (KO in Safari)
e.ondblclick = show_menu // double click
e.oncontextmenu = show_menu
}
set_pref() // set the preferences from local storage
}
// drag and drop
function drag_enter(evt) {
evt.stopImmediatePropagation();
|
| ︙ | ︙ |
Changes to editor/edit.xhtml.
1 2 3 4 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
| > < < | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link href="edit-@MAJOR@.css" rel="stylesheet" type="text/css"/>
<script src="edit-@MAJOR@.js" type="text/javascript" async="true"></script>
<script src="abc2svg-@MAJOR@.js" type="text/javascript" async="true"></script>
<script src="pref.js" type="text/javascript" async="true"></script>
<title>ABC edit with abc2svg</title>
</head>
<body ontouchstart="" bgcolor="#faf0e6" spellcheck="false">
<!-- left -->
<div id="dleft">
<!-- menu bar -->
<ul id="nav">
<li class="dropbutton"><label id="f">File</label>
|
| ︙ | ︙ | |||
141 142 143 144 145 146 147 |
</ul>
</div>
<!-- about popup window -->
<div id="about" class="popup" style="width: 350px">
<div class="close" onclick="popshow('about')">x</div>
<p id="abc2svg">abc2svg</p>
| | | 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
</ul>
</div>
<!-- about popup window -->
<div id="about" class="popup" style="width: 350px">
<div class="close" onclick="popshow('about')">x</div>
<p id="abc2svg">abc2svg</p>
<p>Copyright © 2016-2022 <a
href="http://moinejf.free.fr">Jean-François Moine</a></p>
</div>
<!-- javascript must be enabled -->
<noscript>
<div id="okjs" class="popup" style="width:50%;background:#ff8080;visibility:visible">
Please enable Javascript.
</div>
</noscript>
</body>
</html>
|
Changes to err-de.js.
| ︙ | ︙ | |||
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
"Error loading the module $1": "Error loading the module $1",
"Incorrect 1st value in %%repeat": "erster Wert fehlerhaft in %%repeat",
"Incorrect 2nd value in %%repeat": "zweiter Wert fehlerhaft in %%repeat",
"Invalid 'r' in tuplet": "'r' fehlerhaft in Tuplet",
"Invalid decoration '$1'": "fehlerhafte Dekoration '$1'",
"Invalid note duration $1": "Fehlerhafte Notendekoration '$1'",
"K:P is deprecated": "K:P is deprecated",
"Lack of ']'": "']' fehlt",
"Lack of bar after multi-measure rest":
"Lack of bar after multi-measure rest",
"Lack of ending slur(s)": "Lack of ending slur(s)",
"Lack of starting [, ! or \" in U: / %%user":
"[, ! or \" fehlt in U: / %%user",
"Line split problem - adjust maxshrink and/or breaklimit":
"Probleme beim Aufteilen der Zeile - justiere maxshrink und/oder breaklimit",
"Line too much shrunk $1 $2 $3": "Zeile zu stark geschrumpft $1 $2 $3",
"Line underfull ($1pt of $2pt)": "Zeile nicht voll genug ($1pt of $2pt)",
"Microtone transposition not coded":
"Microtone transposition not coded",
"Misplaced '$1' in %%score": "'$1' fehlerhaft platziert in %%score",
"Misplaced dot": "fehlerhaft platzierter Punkt",
"Mix of old and new transposition syntaxes":
"Mix von alter und neuer Transponierungs-syntax",
"No $1 after %%$2": "kein $1 nach %%$2",
"No </defs> in %%beginsvg sequence": "kein </defs> in %%beginsvg squenz",
"No </style> in %%beginsvg sequence": "kein </style> in %%beginsvg sequenz",
"No accidental after 'exp'": "kein Vorzeichen nach 'exp'",
"No end of decoration": "kein Ende der Dekoration",
"No end of grace note sequence": "kein Ende der Vorschlagnoten",
"No end of chord symbol/annotation": "kein Ende des Akkordsymbols",
| > > > | 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
"Error loading the module $1": "Error loading the module $1",
"Incorrect 1st value in %%repeat": "erster Wert fehlerhaft in %%repeat",
"Incorrect 2nd value in %%repeat": "zweiter Wert fehlerhaft in %%repeat",
"Invalid 'r' in tuplet": "'r' fehlerhaft in Tuplet",
"Invalid decoration '$1'": "fehlerhafte Dekoration '$1'",
"Invalid note duration $1": "Fehlerhafte Notendekoration '$1'",
"K:P is deprecated": "K:P is deprecated",
"Key with double sharps/flats": "Key with double sharps/flats",
"Lack of ']'": "']' fehlt",
"Lack of bar after multi-measure rest":
"Lack of bar after multi-measure rest",
"Lack of ending slur(s)": "Lack of ending slur(s)",
"Lack of starting [, ! or \" in U: / %%user":
"[, ! or \" fehlt in U: / %%user",
"Line split problem - adjust maxshrink and/or breaklimit":
"Probleme beim Aufteilen der Zeile - justiere maxshrink und/oder breaklimit",
"Line too much shrunk $1 $2 $3": "Zeile zu stark geschrumpft $1 $2 $3",
"Line underfull ($1pt of $2pt)": "Zeile nicht voll genug ($1pt of $2pt)",
"Microtone transposition not coded":
"Microtone transposition not coded",
"Misplaced '$1' in %%score": "'$1' fehlerhaft platziert in %%score",
"Misplaced dot": "fehlerhaft platzierter Punkt",
"Mix of old and new transposition syntaxes":
"Mix von alter und neuer Transponierungs-syntax",
"multi-measure rest, but no measure!":
"multi-measure rest, but no measure!",
"No $1 after %%$2": "kein $1 nach %%$2",
"No </defs> in %%beginsvg sequence": "kein </defs> in %%beginsvg squenz",
"No </style> in %%beginsvg sequence": "kein </style> in %%beginsvg sequenz",
"No accidental after 'exp'": "kein Vorzeichen nach 'exp'",
"No end of decoration": "kein Ende der Dekoration",
"No end of grace note sequence": "kein Ende der Vorschlagnoten",
"No end of chord symbol/annotation": "kein Ende des Akkordsymbols",
|
| ︙ | ︙ | |||
143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
"s: without music": "s: ohne Musik",
"Too many elements in symbol line": "zu viele elemente in einer Symbolzeile",
"Too many include levels": "Verschachtelung für include zu tief",
"There cannot be chord symbols on measure bars":
"There cannot be chord symbols on measure bars",
"Too many ties": "zu viele Haltebogen",
"Too many words in lyric line": "zu viele Worte in Liedtextzeile",
"Unknown bagpipe-like key": "unbekante Dudelsackartige Tonart",
"Unknown clef '$1'": "unbekannter Schlüssel '$1'",
"Unknown decoration '$1'": "unbekannte Dekoration '$1'",
"Unknown font $1": "unbekannte Schriftart '$1'",
"Unknown glyph: '$1'": "Unbekanntes Schriftsybol '$1'",
"Unknown keyword '$1' in %%multicol": "unbekanntes Schlüsselwort '$1' in %%multicol",
"Unsecure code": "Unsicherer Code",
| > | 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
"s: without music": "s: ohne Musik",
"Too many elements in symbol line": "zu viele elemente in einer Symbolzeile",
"Too many include levels": "Verschachtelung für include zu tief",
"There cannot be chord symbols on measure bars":
"There cannot be chord symbols on measure bars",
"Too many ties": "zu viele Haltebogen",
"Too many words in lyric line": "zu viele Worte in Liedtextzeile",
"triple sharp/flat": "triple sharp/flat",
"Unknown bagpipe-like key": "unbekante Dudelsackartige Tonart",
"Unknown clef '$1'": "unbekannter Schlüssel '$1'",
"Unknown decoration '$1'": "unbekannte Dekoration '$1'",
"Unknown font $1": "unbekannte Schriftart '$1'",
"Unknown glyph: '$1'": "Unbekanntes Schriftsybol '$1'",
"Unknown keyword '$1' in %%multicol": "unbekanntes Schlüsselwort '$1' in %%multicol",
"Unsecure code": "Unsicherer Code",
|
| ︙ | ︙ |
Changes to err-fr.js.
| ︙ | ︙ | |||
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | "Error loading the module $1": "Erreur de chargement du module $1", "Incorrect 1st value in %%repeat": "Première valeur incorrecte dans %%repeat", "Incorrect 2nd value in %%repeat": "Deuxième valeur incorrecte dans %%repeat", "Invalid 'r' in tuplet": "'r' invalide dans le tuplet", "Invalid decoration '$1'": "Décoration '$1' invalide", "Invalid note duration $1": "Durée de note $1 invalide", "K:P is deprecated": "K:P est déprécié", "Lack of ']'": "']' manquant", "Lack of bar after multi-measure rest": "Manque de barre de mesure après silence multiple", "Lack of ending slur(s)": "Pas de fin de liaison(s)", 'Lack of starting [, ! or " in U: / %%user': 'U: / %%user ne commence pas par [, ! ou "', "Line split problem - adjust maxshrink and/or breaklimit": "Problème de découpe en lignes - ajuster maxshrink et/ou breaklimit", "Line too much shrunk $1 $2 $3": "Ligne trop compressée $1 $2 $3", "Line underfull ($1pt of $2pt)": "Trop d'espacement ($1pt of $2pt)", "Microtone transposition not coded": "Transposition de microtonalité pas codée", "Misplaced '$1' in %%score": "'$1' mal placé dans %%score", "Misplaced dot": "Point mal placé", "Mix of old and new transposition syntaxes": "Mélange des syntaxes de transposition ancienne et nouvelle", "No $1 after %%$2": "Pas de $1 après %%$2", "No </defs> in %%beginsvg sequence": "Pas de </defs> dans séquence %%beginsvg", "No </style> in %%beginsvg sequence": "Pas de </style> dans séquence %%beginsvg", "No accidental after 'exp'": "Pas d'altération après 'exp'", "No end of decoration": "Pas de fin de décoration", | > > > | 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | "Error loading the module $1": "Erreur de chargement du module $1", "Incorrect 1st value in %%repeat": "Première valeur incorrecte dans %%repeat", "Incorrect 2nd value in %%repeat": "Deuxième valeur incorrecte dans %%repeat", "Invalid 'r' in tuplet": "'r' invalide dans le tuplet", "Invalid decoration '$1'": "Décoration '$1' invalide", "Invalid note duration $1": "Durée de note $1 invalide", "K:P is deprecated": "K:P est déprécié", "Key with double sharps/flats": "Armature avec doubles dièses/bémols", "Lack of ']'": "']' manquant", "Lack of bar after multi-measure rest": "Manque de barre de mesure après silence multiple", "Lack of ending slur(s)": "Pas de fin de liaison(s)", 'Lack of starting [, ! or " in U: / %%user': 'U: / %%user ne commence pas par [, ! ou "', "Line split problem - adjust maxshrink and/or breaklimit": "Problème de découpe en lignes - ajuster maxshrink et/ou breaklimit", "Line too much shrunk $1 $2 $3": "Ligne trop compressée $1 $2 $3", "Line underfull ($1pt of $2pt)": "Trop d'espacement ($1pt of $2pt)", "Microtone transposition not coded": "Transposition de microtonalité pas codée", "Misplaced '$1' in %%score": "'$1' mal placé dans %%score", "Misplaced dot": "Point mal placé", "Mix of old and new transposition syntaxes": "Mélange des syntaxes de transposition ancienne et nouvelle", "multi-measure rest, but no measure!": "silence multi-mesure, mais pas de mesure!", "No $1 after %%$2": "Pas de $1 après %%$2", "No </defs> in %%beginsvg sequence": "Pas de </defs> dans séquence %%beginsvg", "No </style> in %%beginsvg sequence": "Pas de </style> dans séquence %%beginsvg", "No accidental after 'exp'": "Pas d'altération après 'exp'", "No end of decoration": "Pas de fin de décoration", |
| ︙ | ︙ | |||
155 156 157 158 159 160 161 162 163 164 165 166 167 168 | "s: without music": "s: sans musique", "There cannot be chord symbols on measure bars": "On ne peut pas mettre d'indication d'accord sur une barre de mesure", "Too many elements in symbol line": "Trop d'éléments dans ligne s:", "Too many include levels": "Trop de niveaux d'inclusion de fichier", "Too many ties": "Trop de liaisons de prolongation", "Too many words in lyric line": "Trop de mots dans la ligne de paroles", "Unknown bagpipe-like key": "Armature de cornemuse inconnue", "Unknown clef '$1'": "Clé '$1' inconnue", "Unknown decoration '$1'": "Décoration '$1' inconnue", "Unknown font $1": "Police $1 inconnue", "Unknown glyph: '$1'": "Glyph '$1' inconnu", "Unknown keyword '$1' in %%multicol": "Mot clé '$1' inconnu dans %%multicol", "Unsecure code": "Code dangereux", | > | 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | "s: without music": "s: sans musique", "There cannot be chord symbols on measure bars": "On ne peut pas mettre d'indication d'accord sur une barre de mesure", "Too many elements in symbol line": "Trop d'éléments dans ligne s:", "Too many include levels": "Trop de niveaux d'inclusion de fichier", "Too many ties": "Trop de liaisons de prolongation", "Too many words in lyric line": "Trop de mots dans la ligne de paroles", "triple sharp/flat": "triple dièse/bémol", "Unknown bagpipe-like key": "Armature de cornemuse inconnue", "Unknown clef '$1'": "Clé '$1' inconnue", "Unknown decoration '$1'": "Décoration '$1' inconnue", "Unknown font $1": "Police $1 inconnue", "Unknown glyph: '$1'": "Glyph '$1' inconnu", "Unknown keyword '$1' in %%multicol": "Mot clé '$1' inconnu dans %%multicol", "Unsecure code": "Code dangereux", |
| ︙ | ︙ |
Changes to err-it.js.
| ︙ | ︙ | |||
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | "Error loading the module $1": "Error loading the module $1", "Incorrect 1st value in %%repeat": "Primo valore in %%repeat errato", "Incorrect 2nd value in %%repeat": "Secondo valore in %%repeat errato", "Invalid 'r' in tuplet": "'r' non valido in gruppo irregolare", "Invalid decoration '$1'": "Decorazione '$1' non valida", "Invalid note duration $1": "Durée de note $1 non valida", "K:P is deprecated": "K:P is deprecated", "Lack of ']'": "']' mancante", "Lack of bar after multi-measure rest": "Lack of bar after multi-measure rest", "Lack of ending slur(s)": "Lack of ending slur(s)", 'Lack of starting [, ! or " in U: / %%user': 'U: / %%user non inizia con [, ! o "', "Line split problem - adjust maxshrink and/or breaklimit": "Problema di linea divisa - modificare maxshrink e/o breaklimit", "Line too much shrunk $1 $2 $3": "Linea troppo compressa $1 $2 $3", "Line underfull ($1pt of $2pt)": "Linea troppo vuota ($1pt di $2pt)", "Microtone transposition not coded": "Microtone transposition not coded", "Misplaced '$1' in %%score": "'$1' in posizione errata in %%score", "Misplaced dot": "Punto in posizione errata", "Mix of old and new transposition syntaxes": "Sintassi di trasposizione vecchia e nuova allo stesso tempo", "No $1 after %%$2": "Manca $1 dopo %%$2", "No </defs> in %%beginsvg sequence": "Manca </defs> nella sequenza %%beginsvg", "No </style> in %%beginsvg sequence": "manca </style> nella sequenza %%beginsvg", "No accidental after 'exp'": "Manca l'alterazione dopo 'exp'", "No end of chord symbol/annotation": "Accordo di accompagnamento non terminato", | > > > | 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | "Error loading the module $1": "Error loading the module $1", "Incorrect 1st value in %%repeat": "Primo valore in %%repeat errato", "Incorrect 2nd value in %%repeat": "Secondo valore in %%repeat errato", "Invalid 'r' in tuplet": "'r' non valido in gruppo irregolare", "Invalid decoration '$1'": "Decorazione '$1' non valida", "Invalid note duration $1": "Durée de note $1 non valida", "K:P is deprecated": "K:P is deprecated", "Key with double sharps/flats": "Key with double sharps/flats", "Lack of ']'": "']' mancante", "Lack of bar after multi-measure rest": "Lack of bar after multi-measure rest", "Lack of ending slur(s)": "Lack of ending slur(s)", 'Lack of starting [, ! or " in U: / %%user': 'U: / %%user non inizia con [, ! o "', "Line split problem - adjust maxshrink and/or breaklimit": "Problema di linea divisa - modificare maxshrink e/o breaklimit", "Line too much shrunk $1 $2 $3": "Linea troppo compressa $1 $2 $3", "Line underfull ($1pt of $2pt)": "Linea troppo vuota ($1pt di $2pt)", "Microtone transposition not coded": "Microtone transposition not coded", "Misplaced '$1' in %%score": "'$1' in posizione errata in %%score", "Misplaced dot": "Punto in posizione errata", "Mix of old and new transposition syntaxes": "Sintassi di trasposizione vecchia e nuova allo stesso tempo", "multi-measure rest, but no measure!": "multi-measure rest, but no measure!", "No $1 after %%$2": "Manca $1 dopo %%$2", "No </defs> in %%beginsvg sequence": "Manca </defs> nella sequenza %%beginsvg", "No </style> in %%beginsvg sequence": "manca </style> nella sequenza %%beginsvg", "No accidental after 'exp'": "Manca l'alterazione dopo 'exp'", "No end of chord symbol/annotation": "Accordo di accompagnamento non terminato", |
| ︙ | ︙ | |||
154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
"s: without music": "s: senza musica",
"There cannot be chord symbols on measure bars":
"There cannot be chord symbols on measure bars",
"Too many elements in symbol line": "Troppi elementi nella linea s:",
"Too many include levels": "Troppi livelli di inclusione di file",
"Too many ties": "Troppi simboli di legato",
"Too many words in lyric line": "Troppe parole per la linea di musica",
"Unknown bagpipe-like key": "Chiave per cornamusa sconosciuta",
"Unknown clef '$1'": "Chiave '$1' sconosciuta",
"Unknown decoration '$1'": "Decorazione '$1' sconosciuta",
"Unknown font $1": "Font $1 sconosciuto",
"Unknown glyph: '$1'": "Glifo '$1' sconosciuto",
"Unknown keyword '$1' in %%multicol": "Keyword '$1' sconosciuta in %%multicol",
"Unsecure code": "Codice pericoloso",
| > | 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
"s: without music": "s: senza musica",
"There cannot be chord symbols on measure bars":
"There cannot be chord symbols on measure bars",
"Too many elements in symbol line": "Troppi elementi nella linea s:",
"Too many include levels": "Troppi livelli di inclusione di file",
"Too many ties": "Troppi simboli di legato",
"Too many words in lyric line": "Troppe parole per la linea di musica",
"triple sharp/flat": "triple sharp/flat",
"Unknown bagpipe-like key": "Chiave per cornamusa sconosciuta",
"Unknown clef '$1'": "Chiave '$1' sconosciuta",
"Unknown decoration '$1'": "Decorazione '$1' sconosciuta",
"Unknown font $1": "Font $1 sconosciuto",
"Unknown glyph: '$1'": "Glifo '$1' sconosciuto",
"Unknown keyword '$1' in %%multicol": "Keyword '$1' sconosciuta in %%multicol",
"Unsecure code": "Codice pericoloso",
|
| ︙ | ︙ |
Changes to err-pt_BR.js.
1 2 3 4 | //JS abc2svg - Brazilian Portuguese translation of the error codes: // Tradução dos códigos de erro para português brasileiro // Adicione este arquivo na linha de comando para obter as // mensagens de erro em português do Brasil. | | | 1 2 3 4 5 6 7 8 9 10 11 12 |
//JS abc2svg - Brazilian Portuguese translation of the error codes:
// Tradução dos códigos de erro para português brasileiro
// Adicione este arquivo na linha de comando para obter as
// mensagens de erro em português do Brasil.
// (Hudson Lacerda - 11/dez/2016 - 23/set/2021 - 02/nov/2022)
user.textrans = {
"+: lyric without music": "+: palavras sem música",
"+: symbol line without music": "+: linha de símbolos sem música",
"+: without previous info field": "+: continuação sem campo anterior",
"'{' in grace note": "'{' em notinha ornamental",
"'}', ')' or ']' missing in %%score":
|
| ︙ | ︙ | |||
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | "Error loading the module $1": "Error loading the module $1", "Incorrect 1st value in %%repeat": "Primeiro valor incorreto em %%repeat", "Incorrect 2nd value in %%repeat": "Segundo valor incorreto em %%repeat", "Invalid 'r' in tuplet": "'r' inválido em quiáltera", "Invalid decoration '$1'": "Decoração '$1' inválida", "Invalid note duration $1": "Duração de nota $1 inválida", "K:P is deprecated": "K:P é obsoleto", "Lack of ']'": "']' faltando", "Lack of bar after multi-measure rest": "Falta barra de compasso após pausa de múltiplos compassos", "Lack of ending slur(s)": "Falta fim de ligadura(s)", 'Lack of starting [, ! or " in U: / %%user': 'U: / %%user não começou com [, ! ou "', "Line split problem - adjust maxshrink and/or breaklimit": "Problema de quebra de linha - ajuste maxshrink e/ou breaklimit", "Line too much shrunk $1 $2 $3": "Linha muito encolhida $1 $2 $3", "Line underfull ($1pt of $2pt)": "Linha muito espaçada ($1pt de $2pt)", "Microtone transposition not coded": "A transposição de microtons não está codificada", "Misplaced '$1' in %%score": "'$1' deslocado em %%score", "Misplaced dot": "Ponto fora de lugar", "Mix of old and new transposition syntaxes": "Mistura de sintaxes de transposição antiga e nova", "No $1 after %%$2": "Falta $1 após %%$2", "No </defs> in %%beginsvg sequence": "Falta </defs> em bloco %%beginsvg", "No </style> in %%beginsvg sequence": "Falta </style> em bloco %%beginsvg", "No accidental after 'exp'": "Falta acidente após 'exp'", "No end of decoration": "Decoração sem término", | > > > | 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | "Error loading the module $1": "Error loading the module $1", "Incorrect 1st value in %%repeat": "Primeiro valor incorreto em %%repeat", "Incorrect 2nd value in %%repeat": "Segundo valor incorreto em %%repeat", "Invalid 'r' in tuplet": "'r' inválido em quiáltera", "Invalid decoration '$1'": "Decoração '$1' inválida", "Invalid note duration $1": "Duração de nota $1 inválida", "K:P is deprecated": "K:P é obsoleto", "Key with double sharps/flats": "Tonalidade com sustenidos/bemóis duplos", "Lack of ']'": "']' faltando", "Lack of bar after multi-measure rest": "Falta barra de compasso após pausa de múltiplos compassos", "Lack of ending slur(s)": "Falta fim de ligadura(s)", 'Lack of starting [, ! or " in U: / %%user': 'U: / %%user não começou com [, ! ou "', "Line split problem - adjust maxshrink and/or breaklimit": "Problema de quebra de linha - ajuste maxshrink e/ou breaklimit", "Line too much shrunk $1 $2 $3": "Linha muito encolhida $1 $2 $3", "Line underfull ($1pt of $2pt)": "Linha muito espaçada ($1pt de $2pt)", "Microtone transposition not coded": "A transposição de microtons não está codificada", "Misplaced '$1' in %%score": "'$1' deslocado em %%score", "Misplaced dot": "Ponto fora de lugar", "Mix of old and new transposition syntaxes": "Mistura de sintaxes de transposição antiga e nova", "multi-measure rest, but no measure!": "Pausa de múltiplos compassos, porém o compasso não foi definido!", "No $1 after %%$2": "Falta $1 após %%$2", "No </defs> in %%beginsvg sequence": "Falta </defs> em bloco %%beginsvg", "No </style> in %%beginsvg sequence": "Falta </style> em bloco %%beginsvg", "No accidental after 'exp'": "Falta acidente após 'exp'", "No end of decoration": "Decoração sem término", |
| ︙ | ︙ | |||
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | "s: without music": "s: sem música", "There cannot be chord symbols on measure bars": "Não pode haver cifra de acorde em barra de compasso", "Too many elements in symbol line": "Excesso de elementos na linha de símbolos", "Too many include levels": "Excessivos níveis de inclusão de arquivos", "Too many ties": "Excesso de ligaduras de prolongamento", "Too many words in lyric line": "Excesso de palavras", "Unknown bagpipe-like key": "Armadura desconhecida para gaita de foles", "Unknown clef '$1'": "Clave '$1' desconhecida", "Unknown decoration '$1'": "Decoração '$1' desconhecida", "Unknown font $1": "Fonte $1 desconhecida", "Unknown glyph: '$1'": "Glifo '$1' desconhecido", "Unknown keyword '$1' in %%multicol": "Palavra-chave '$1' desconhecida em %%multicol", "Unsecure code": "Código inseguro", "Unterminated string": "Cadeia de caracteres não terminada", "Unterminated string in Q:": "Cadeia de caracteres não terminada em Q:", "Variant ending on a left repeat bar": | > | | | | 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | "s: without music": "s: sem música", "There cannot be chord symbols on measure bars": "Não pode haver cifra de acorde em barra de compasso", "Too many elements in symbol line": "Excesso de elementos na linha de símbolos", "Too many include levels": "Excessivos níveis de inclusão de arquivos", "Too many ties": "Excesso de ligaduras de prolongamento", "Too many words in lyric line": "Excesso de palavras", "triple sharp/flat": "sustenido/bemol triplo", "Unknown bagpipe-like key": "Armadura desconhecida para gaita de foles", "Unknown clef '$1'": "Clave '$1' desconhecida", "Unknown decoration '$1'": "Decoração '$1' desconhecida", "Unknown font $1": "Fonte $1 desconhecida", "Unknown glyph: '$1'": "Glifo '$1' desconhecido", "Unknown keyword '$1' in %%multicol": "Palavra-chave '$1' desconhecida em %%multicol", "Unsecure code": "Código inseguro", "Unterminated string": "Cadeia de caracteres não terminada", "Unterminated string in Q:": "Cadeia de caracteres não terminada em Q:", "Variant ending on a left repeat bar": "Variante de repetição em início de ritornello", "Voice overlay already started": "Divisão de vozes já foi iniciada", "w: without music": "w: sem música", "Wrong duration in voice overlay": "Duração incorreta na divisão de vozes" } |
Changes to font/abc2svg.sfd.
| ︙ | ︙ | |||
15 16 17 18 19 20 21 | Layer: 0 1 "Back" 1 Layer: 1 0 "Fore" 0 XUID: [1021 296 1430826605 13506888] OS2Version: 0 OS2_WeightWidthSlopeOnly: 0 OS2_UseTypoMetrics: 0 CreationTime: 1433498007 | | | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | Layer: 0 1 "Back" 1 Layer: 1 0 "Fore" 0 XUID: [1021 296 1430826605 13506888] OS2Version: 0 OS2_WeightWidthSlopeOnly: 0 OS2_UseTypoMetrics: 0 CreationTime: 1433498007 ModificationTime: 1654926804 PfmFamily: 17 TTFWeight: 400 TTFWidth: 5 LineGap: 92 VLineGap: 92 Panose: 2 0 5 3 0 0 0 0 0 0 OS2TypoAscent: 0 |
| ︙ | ︙ | |||
46 47 48 49 50 51 52 | Encoding: Custom Compacted: 1 UnicodeInterp: none NameList: Adobe Glyph List DisplaySize: -96 AntiAlias: 1 FitToEm: 1 | | | 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | Encoding: Custom Compacted: 1 UnicodeInterp: none NameList: Adobe Glyph List DisplaySize: -96 AntiAlias: 1 FitToEm: 1 WinInfo: 0 8 2 BeginPrivate: 0 EndPrivate TeXData: 1 0 0 346030 173015 115343 0 1048576 115343 783286 444596 497025 792723 393216 433062 380633 303038 157286 324010 404750 52429 2506097 1059062 262144 BeginChars: 143 143 StartChar: .nodef Encoding: 0 0 0 |
| ︙ | ︙ | |||
339 340 341 342 343 344 345 | 203 2 167 51 167 91 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE048 Encoding: 10 57416 10 | | | | | | > | > > > | > | > | < | | | < | | | < | < | | | > > | | | | | | < < < < | | | 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 | 203 2 167 51 167 91 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE048 Encoding: 10 57416 10 Width: 954 Flags: HMW LayerCount: 2 Fore SplineSet 452 866 m 1 504 866 l 1 504 695 l 1 653 680 772 545 784 374 c 1 956 374 l 1 956 322 l 1 784 322 l 1 772 153 653 16 504 1 c 1 504 -170 l 1 452 -170 l 1 452 1 l 1 303 16 184 153 172 322 c 1 -0 322 l 1 -0 374 l 1 172 374 l 1 184 548 303 680 452 695 c 1 452 866 l 1 452 322 m 1 304 322 l 1 309 136 373 69 452 58 c 1 452 322 l 1 504 322 m 1 504 58 l 1 583 69 647 134 652 322 c 1 504 322 l 1 504 374 m 1 652 374 l 1 647 563 583 627 504 638 c 1 504 374 l 1 452 374 m 1 452 640 l 1 373 629 309 565 304 374 c 1 452 374 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE050 Encoding: 11 57424 11 Width: 779 |
| ︙ | ︙ | |||
765 766 767 768 769 770 771 | Encoding: 19 57470 19 Width: 360 Flags: HMW LayerCount: 2 Fore SplineSet 212 -1 m 0 | | | | > | | | > | | | | | | | | | | | | | > > | | | | | > > | > > | | | | < > | | > > | < | | 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 | Encoding: 19 57470 19 Width: 360 Flags: HMW LayerCount: 2 Fore SplineSet 212 -1 m 0 171 -1 150 17 150 54 c 0 150 75 159 87 174 87 c 0 191 87 201 77 201 60 c 0 201 53 196 47 192 42 c 0 188 37 183 32 183 25 c 0 183 16 193 11 212 11 c 0 243 11 279 66 279 112 c 0 279 132 271 140 249 140 c 0 238 140 229 134 219 128 c 0 209 122 200 115 189 115 c 0 180 115 178 118 178 130 c 0 178 140 198 196 216 236 c 24 220 243 225 247 231 247 c 0 266 248 284 248 339 248 c 0 358 248 359 248 359 241 c 0 359 231 352 223 337 218 c 0 309 208 308 208 239 193 c 0 226 190 224 189 222 174 c 0 219 161 222 158 233 161 c 0 241 163 250 164 259 164 c 0 301 164 326 139 326 96 c 0 326 43 274 -1 212 -1 c 0 9 0 m 0 -3 0 -3 18 9 18 c 0 12 18 14 18 18 18 c 0 32 18 40 22 43 30 c 0 44 31 44 33 45 34 c 0 58 65 58 65 81 126 c 0 82 129 83 131 84 134 c 0 90 150 88 155 78 155 c 0 70 155 67 153 61 146 c 0 52 136 45 134 36 138 c 0 28 143 28 146 41 162 c 0 51 174 59 186 66 195 c 0 111 253 116 259 120 259 c 0 121 259 121 259 122 259 c 0 123 259 124 259 125 259 c 0 133 259 139 255 145 252 c 0 151 249 157 246 165 246 c 0 168 246 171 247 175 248 c 0 190 253 196 249 192 238 c 0 144 121 120 62 111 36 c 0 109 31 109 28 109 26 c 0 109 20 114 18 130 18 c 0 137 18 142 13 142 8 c 0 142 3 138 0 130 0 c 0 115 0 103 0 91 -0 c 0 79 -0 67 0 52 -0 c 0 38 0 25 0 9 0 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE080 Encoding: 20 57472 20 Width: 430 |
| ︙ | ︙ | |||
2499 2500 2501 2502 2503 2504 2505 | Width: 400 Flags: HMW LayerCount: 2 Fore SplineSet 152 35 m 2 357 483 l 2 | | | | | | | | | | | | | | | | | > | 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 | Width: 400 Flags: HMW LayerCount: 2 Fore SplineSet 152 35 m 2 357 483 l 2 364 495 370 501 378 501 c 0 381 501 384 501 387 499 c 0 395 495 398 490 398 484 c 0 398 479 396 473 393 466 c 2 189 17 l 2 184 7 178 -0 169 -0 c 0 166 -0 163 1 159 3 c 0 152 7 148 14 148 21 c 0 148 25 149 30 152 35 c 2 9 35 m 2 214 483 l 2 221 495 227 501 235 501 c 0 238 501 241 501 244 499 c 0 252 495 255 490 255 484 c 0 255 479 253 473 250 466 c 2 46 17 l 2 41 7 35 -0 26 -0 c 0 23 -0 20 1 16 3 c 0 9 7 5 14 5 21 c 0 5 25 6 30 9 35 c 2 EndSplineSet Validated: 1 EndChar StartChar: uniE4E1 Encoding: 83 58593 83 Width: 130 Flags: HMW LayerCount: 2 |
| ︙ | ︙ | |||
3076 3077 3078 3079 3080 3081 3082 | Encoding: 101 58665 101 Width: 703 Flags: HMW LayerCount: 2 Fore SplineSet 522 40 m 0 | | | | | | | | | | | | | | | | | | | | 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 | Encoding: 101 58665 101 Width: 703 Flags: HMW LayerCount: 2 Fore SplineSet 522 40 m 0 524 39 526 39 529 39 c 0 553 39 592 80 611 128 c 0 619 148 624 175 624 198 c 0 624 219 620 236 609 240 c 0 607 241 605 241 603 241 c 0 578 241 536 199 521 162 c 0 511 136 506 109 506 87 c 0 506 62 512 44 522 40 c 0 197 40 m 0 199 39 201 39 204 39 c 0 228 39 267 80 286 128 c 0 294 148 299 175 299 198 c 0 299 219 295 236 284 240 c 0 282 241 280 241 278 241 c 0 253 241 211 199 196 162 c 0 186 136 181 109 181 87 c 0 181 62 187 44 197 40 c 0 200 0 m 0 183 0 173 6 153 32 c 1 108 -90 l 1 160 -90 l 2 175 -90 175 -120 160 -120 c 2 -65 -120 l 2 -79 -120 -80 -90 -65 -90 c 2 10 -90 l 1 114 195 l 2 115 198 120 213 120 225 c 0 120 233 118 240 109 240 c 0 83 240 72 207 28 135 c 0 21 124 -6 139 1 151 c 0 56 249 69 280 125 280 c 0 170 280 193 271 203 235 c 1 244 278 263 280 305 280 c 0 331 280 358 264 371 230 c 1 395 267 413 280 450 280 c 0 |
| ︙ | ︙ | |||
3131 3132 3133 3134 3135 3136 3137 | 1083 -90 l 1 1135 -90 l 2 1150 -90 1150 -120 1135 -120 c 2 910 -120 l 2 896 -120 895 -90 910 -90 c 2 985 -90 l 1 1089 195 l 2 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 | 1083 -90 l 1 1135 -90 l 2 1150 -90 1150 -120 1135 -120 c 2 910 -120 l 2 896 -120 895 -90 910 -90 c 2 985 -90 l 1 1089 195 l 2 1090 198 1095 213 1095 225 c 0 1095 233 1093 240 1084 240 c 0 1064 240 1053 221 1030 181 c 0 1030 180 l 0 1030 87 949 0 850 0 c 0 833 0 823 6 803 32 c 1 758 -90 l 1 810 -90 l 2 825 -90 825 -120 810 -120 c 2 585 -120 l 2 571 -120 570 -90 585 -90 c 2 660 -90 l 1 764 195 l 2 765 198 770 213 770 225 c 0 770 233 768 240 759 240 c 0 739 240 728 221 705 181 c 0 705 180 l 0 705 87 624 0 525 0 c 0 508 0 498 6 478 32 c 1 433 -90 l 1 485 -90 l 2 500 -90 500 -120 485 -120 c 2 260 -120 l 2 246 -120 245 -90 260 -90 c 2 335 -90 l 1 439 195 l 2 440 198 445 213 445 225 c 0 445 233 443 240 434 240 c 0 414 240 403 221 380 181 c 0 380 180 l 0 380 87 299 0 200 0 c 0 1172 40 m 0 1174 39 1176 39 1179 39 c 0 1203 39 1242 80 1261 128 c 0 1269 148 1274 175 1274 198 c 0 1274 219 1270 236 1259 240 c 0 1257 241 1255 241 1253 241 c 0 1228 241 1186 199 1171 162 c 0 1161 136 1156 109 1156 87 c 0 1156 62 1162 44 1172 40 c 0 847 40 m 0 849 39 851 39 854 39 c 0 878 39 917 80 936 128 c 0 944 148 949 175 949 198 c 0 949 219 945 236 934 240 c 0 932 241 930 241 928 241 c 0 903 241 861 199 846 162 c 0 836 136 831 109 831 87 c 0 831 62 837 44 847 40 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE52A Encoding: 102 58666 102 Width: 563 Flags: W HStem: -120 30<-74.2249 10 108 169.668 250.775 335 433 494.668 575.775 660 758 819.668> 0 39<191.01 237.957 516.01 562.957 841.01 887.957> 240 40<80.1149 147.5 239.21 318 404.386 472.5 564.21 643 729.386 797.5 889.21 973> VStem: 120 61<87 225> 299 81<108.679 217.246> 445 61<87 225> 624 81<108.679 217.246> 770 61<87 225> 949 81<108.469 239.676> LayerCount: 2 Fore SplineSet 850 0 m 0 833 0 823 6 803 32 c 1 758 -90 l 1 810 -90 l 2 825 -90 825 -120 810 -120 c 2 585 -120 l 2 571 -120 570 -90 585 -90 c 2 660 -90 l 1 764 195 l 2 765 198 770 213 770 225 c 0 770 233 768 240 759 240 c 0 739 240 728 221 705 181 c 0 705 180 l 0 705 87 624 0 525 0 c 0 508 0 498 6 478 32 c 1 433 -90 l 1 485 -90 l 2 500 -90 500 -120 485 -120 c 2 260 -120 l 2 246 -120 245 -90 260 -90 c 2 335 -90 l 1 439 195 l 2 440 198 445 213 445 225 c 0 445 233 443 240 434 240 c 0 414 240 403 221 380 181 c 0 380 180 l 0 380 87 299 0 200 0 c 0 183 0 173 6 153 32 c 1 108 -90 l 1 160 -90 l 2 175 -90 175 -120 160 -120 c 2 -65 -120 l 2 -79 -120 -80 -90 -65 -90 c 2 10 -90 l 1 114 195 l 2 115 198 120 213 120 225 c 0 120 233 118 240 109 240 c 0 83 240 72 207 28 135 c 0 21 124 -6 139 1 151 c 0 56 249 69 280 125 280 c 0 170 280 193 271 203 235 c 1 244 278 263 280 305 280 c 0 331 280 358 264 371 230 c 1 395 267 413 280 450 280 c 0 495 280 518 271 528 235 c 1 569 278 588 280 630 280 c 0 656 280 683 264 696 230 c 1 720 267 738 280 775 280 c 0 820 280 843 271 853 235 c 1 894 278 913 280 955 280 c 0 991 280 1030 248 1030 180 c 0 1030 87 949 0 850 0 c 0 847 40 m 0 849 39 851 39 854 39 c 0 878 39 917 80 936 128 c 0 944 148 949 175 949 198 c 0 949 219 945 236 934 240 c 0 932 241 930 241 928 241 c 0 903 241 861 199 846 162 c 0 836 136 831 109 831 87 c 0 831 62 837 44 847 40 c 0 522 40 m 0 524 39 526 39 529 39 c 0 553 39 592 80 611 128 c 0 619 148 624 175 624 198 c 0 624 219 620 236 609 240 c 0 607 241 605 241 603 241 c 0 578 241 536 199 521 162 c 0 511 136 506 109 506 87 c 0 506 62 512 44 522 40 c 0 197 40 m 0 199 39 201 39 204 39 c 0 228 39 267 80 286 128 c 0 294 148 299 175 299 198 c 0 299 219 295 236 284 240 c 0 282 241 280 241 278 241 c 0 253 241 211 199 196 162 c 0 186 136 181 109 181 87 c 0 181 62 187 44 197 40 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE52B Encoding: 103 58667 103 Width: 703 Flags: HMW LayerCount: 2 Fore SplineSet 200 0 m 0 183 0 173 6 153 32 c 1 108 -90 l 1 160 -90 l 2 175 -90 175 -120 160 -120 c 2 -65 -120 l 2 -79 -120 -80 -90 -65 -90 c 2 10 -90 l 1 114 195 l 2 115 198 120 213 120 225 c 0 120 233 118 240 109 240 c 0 83 240 72 207 28 135 c 0 21 124 -6 139 1 151 c 0 56 249 69 280 125 280 c 0 170 280 193 271 203 235 c 1 244 278 263 280 305 280 c 0 331 280 358 264 371 230 c 1 395 267 413 280 450 280 c 0 495 280 518 271 528 235 c 1 569 278 588 280 630 280 c 0 666 280 705 248 705 180 c 0 705 87 624 0 525 0 c 0 508 0 498 6 478 32 c 1 433 -90 l 1 485 -90 l 2 500 -90 500 -120 485 -120 c 2 260 -120 l 2 246 -120 245 -90 260 -90 c 2 335 -90 l 1 439 195 l 2 440 198 445 213 445 225 c 0 445 233 443 240 434 240 c 0 414 240 403 221 380 181 c 0 380 180 l 0 380 87 299 0 200 0 c 0 197 40 m 0 199 39 201 39 204 39 c 0 228 39 267 80 286 128 c 0 294 148 299 175 299 198 c 0 299 219 295 236 284 240 c 0 282 241 280 241 278 241 c 0 253 241 211 199 196 162 c 0 186 136 181 109 181 87 c 0 181 62 187 44 197 40 c 0 522 40 m 0 524 39 526 39 529 39 c 0 553 39 592 80 611 128 c 0 619 148 624 175 624 198 c 0 624 219 620 236 609 240 c 0 607 241 605 241 603 241 c 0 578 241 536 199 521 162 c 0 511 136 506 109 506 87 c 0 506 62 512 44 522 40 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE52C Encoding: 104 58668 104 Width: 811 |
| ︙ | ︙ | |||
3361 3362 3363 3364 3365 3366 3367 | 539 -90 l 1 591 -90 l 2 606 -90 606 -120 591 -120 c 2 366 -120 l 2 352 -120 351 -90 366 -90 c 2 441 -90 l 1 545 195 l 2 | | | | | | | | | | | | | | | | | | | | | | | | | 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 | 539 -90 l 1 591 -90 l 2 606 -90 606 -120 591 -120 c 2 366 -120 l 2 352 -120 351 -90 366 -90 c 2 441 -90 l 1 545 195 l 2 546 198 551 213 551 225 c 0 551 233 549 240 540 240 c 0 514 240 491 175 454 100 c 0 423 37 388 -10 323 -10 c 0 296 -10 277 5 277 31 c 0 277 39 278 47 282 57 c 2 334 193 l 2 335 195 335 197 335 199 c 0 335 209 325 213 314 213 c 0 300 213 284 206 279 193 c 2 214 22 l 2 211 14 207 0 191 -1 c 2 153 0 l 2 134 -2 132 12 136 22 c 2 203 193 l 2 204 195 204 197 204 199 c 0 204 208 195 213 183 213 c 0 170 213 153 206 148 193 c 2 80 21 l 2 76 11 74 1 57 0 c 2 4 0 l 2 -6 0 0 18 4 26 c 2 70 193 l 2 77 211 69 221 60 221 c 0 42 221 35 210 -11 138 c 0 -18 127 -39 139 -33 151 c 0 3 216 36 280 86 280 c 0 128 280 145 266 152 240 c 1 170 260 194 280 224 280 c 0 254 280 273 263 278 240 c 1 292 259 322 280 349 280 c 0 382 280 410 254 410 219 c 0 410 211 408 202 405 193 c 2 358 68 l 2 355 60 354 54 354 48 c 0 354 40 357 34 362 34 c 0 364 34 365 35 367 36 c 0 389 48 418 94 429 119 c 0 628 40 m 0 630 39 632 39 635 39 c 0 659 39 698 80 717 128 c 0 725 148 730 175 730 198 c 0 730 219 726 236 715 240 c 0 713 241 711 241 709 241 c 0 684 241 642 199 627 162 c 0 617 136 612 109 612 87 c 0 612 62 618 44 628 40 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE52D Encoding: 105 58669 105 Width: 351 |
| ︙ | ︙ | |||
3432 3433 3434 3435 3436 3437 3438 | 42 221 35 210 -11 138 c 0 -18 127 -39 139 -33 151 c 0 3 216 36 280 86 280 c 0 128 280 145 266 152 240 c 1 170 260 194 280 224 280 c 0 254 280 273 263 278 240 c 1 292 259 322 280 349 280 c 0 | | | | | | | | | | | | | | | | | | | 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 | 42 221 35 210 -11 138 c 0 -18 127 -39 139 -33 151 c 0 3 216 36 280 86 280 c 0 128 280 145 266 152 240 c 1 170 260 194 280 224 280 c 0 254 280 273 263 278 240 c 1 292 259 322 280 349 280 c 0 382 280 410 254 410 219 c 0 410 211 408 202 405 193 c 0 358 68 l 0 355 60 354 54 354 48 c 0 354 40 357 34 362 34 c 0 364 34 365 35 367 36 c 0 389 48 404 72 419 93 c 0 427 104 449 93 440 78 c 0 411 27 388 -10 323 -10 c 0 296 -10 277 5 277 31 c 0 277 39 278 47 282 57 c 0 334 193 l 0 335 195 335 197 335 199 c 0 335 209 325 213 314 213 c 0 300 213 284 206 279 193 c 0 214 22 l 0 211 14 207 0 191 -1 c 1 153 0 l 16 134 -2 132 12 136 22 c 0 203 193 l 0 204 195 204 197 204 199 c 0 204 208 195 213 183 213 c 0 170 213 153 206 148 193 c 0 80 21 l 0 393 -160 m 0 353 -160 313 -135 313 -90 c 0 313 -55 330 -30 355 -30 c 0 380 -30 396 -45 396 -65 c 0 396 -75 389 -83 378 -90 c 0 368 -97 368 -100 368 -110 c 0 368 -120 378 -124 393 -124 c 0 456 -124 459 -35 526 230 c 1 507 230 508 230 473 230 c 0 460 230 454 241 454 251 c 0 454 261 460 270 471 270 c 0 502 270 504 270 536 270 c 1 564 374 647 440 713 440 c 0 753 440 793 415 793 370 c 0 793 335 776 310 751 310 c 0 726 310 710 325 710 345 c 0 710 355 717 363 728 370 c 0 739 377 738 380 738 390 c 0 738 400 728 404 713 404 c 0 671 404 661 332 648 270 c 1 675 270 672 270 702 270 c 0 715 270 722 260 722 250 c 0 722 240 715 230 702 230 c 0 676 230 672 230 639 230 c 1 596 -26 523 -160 393 -160 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE52F |
| ︙ | ︙ | |||
3503 3504 3505 3506 3507 3508 3509 | -130 -55 -113 -30 -88 -30 c 0 -63 -30 -47 -45 -47 -65 c 0 -47 -75 -54 -83 -65 -90 c 0 -75 -97 -75 -100 -75 -110 c 0 -75 -120 -65 -124 -50 -124 c 0 13 -124 16 -35 83 230 c 1 64 230 65 230 30 230 c 0 | | | | | | 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 | -130 -55 -113 -30 -88 -30 c 0 -63 -30 -47 -45 -47 -65 c 0 -47 -75 -54 -83 -65 -90 c 0 -75 -97 -75 -100 -75 -110 c 0 -75 -120 -65 -124 -50 -124 c 0 13 -124 16 -35 83 230 c 1 64 230 65 230 30 230 c 0 17 230 11 241 11 251 c 0 11 261 17 270 28 270 c 0 59 270 61 270 93 270 c 1 121 374 204 440 270 440 c 0 310 440 350 415 350 370 c 0 350 335 333 310 308 310 c 0 283 310 267 325 267 345 c 0 267 355 274 363 285 370 c 0 296 377 295 380 295 390 c 0 295 400 285 404 270 404 c 0 228 404 218 333 205 271 c 1 360 270 l 1 388 374 471 440 537 440 c 0 577 440 617 415 617 370 c 0 617 335 600 310 575 310 c 0 550 310 534 325 534 345 c 0 534 355 541 363 552 370 c 0 563 377 562 380 562 390 c 0 562 400 552 404 537 404 c 0 495 404 485 332 472 270 c 1 499 270 496 270 526 270 c 0 539 270 546 260 546 250 c 0 546 240 539 230 526 230 c 0 500 230 496 230 463 230 c 1 420 -26 347 -160 217 -160 c 0 177 -160 137 -135 137 -90 c 0 137 -55 154 -30 179 -30 c 0 204 -30 220 -45 220 -65 c 0 220 -75 213 -83 202 -90 c 0 192 -97 192 -100 192 -110 c 0 |
| ︙ | ︙ | |||
3566 3567 3568 3569 3570 3571 3572 | 884 335 867 310 842 310 c 0 817 310 801 325 801 345 c 0 801 355 808 363 819 370 c 0 830 377 829 380 829 390 c 0 829 400 819 404 804 404 c 0 762 404 752 332 739 270 c 1 766 270 763 270 793 270 c 0 | | | | 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 | 884 335 867 310 842 310 c 0 817 310 801 325 801 345 c 0 801 355 808 363 819 370 c 0 830 377 829 380 829 390 c 0 829 400 819 404 804 404 c 0 762 404 752 332 739 270 c 1 766 270 763 270 793 270 c 0 806 270 812 260 812 250 c 0 812 240 806 230 793 230 c 0 767 230 763 230 730 230 c 1 687 -26 614 -160 484 -160 c 0 444 -160 404 -135 404 -90 c 0 404 -55 421 -30 446 -30 c 0 471 -30 487 -45 487 -65 c 0 487 -75 480 -83 469 -90 c 0 459 -97 459 -100 459 -110 c 0 |
| ︙ | ︙ | |||
3596 3597 3598 3599 3600 3601 3602 | -130 -55 -113 -30 -88 -30 c 0 -63 -30 -47 -45 -47 -65 c 0 -47 -75 -54 -83 -65 -90 c 0 -75 -97 -75 -100 -75 -110 c 0 -75 -120 -65 -124 -50 -124 c 0 13 -124 16 -35 83 230 c 1 64 230 65 230 30 230 c 0 | | | | 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 | -130 -55 -113 -30 -88 -30 c 0 -63 -30 -47 -45 -47 -65 c 0 -47 -75 -54 -83 -65 -90 c 0 -75 -97 -75 -100 -75 -110 c 0 -75 -120 -65 -124 -50 -124 c 0 13 -124 16 -35 83 230 c 1 64 230 65 230 30 230 c 0 17 230 11 241 11 251 c 0 11 261 17 270 28 270 c 0 59 270 61 270 93 270 c 1 121 374 204 440 270 440 c 0 310 440 350 415 350 370 c 0 350 335 333 310 308 310 c 0 283 310 267 325 267 345 c 0 267 355 274 363 285 370 c 0 296 377 295 380 295 390 c 0 |
| ︙ | ︙ | |||
3638 3639 3640 3641 3642 3643 3644 | 1152 335 1135 310 1110 310 c 0 1085 310 1069 325 1069 345 c 0 1069 355 1076 363 1087 370 c 0 1098 377 1097 380 1097 390 c 0 1097 400 1087 404 1072 404 c 0 1030 404 1020 332 1007 270 c 1 1034 270 1031 270 1061 270 c 0 | | | | 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 | 1152 335 1135 310 1110 310 c 0 1085 310 1069 325 1069 345 c 0 1069 355 1076 363 1087 370 c 0 1098 377 1097 380 1097 390 c 0 1097 400 1087 404 1072 404 c 0 1030 404 1020 332 1007 270 c 1 1034 270 1031 270 1061 270 c 0 1074 270 1080 260 1080 250 c 0 1080 240 1074 230 1061 230 c 0 1035 230 1031 230 998 230 c 1 955 -26 882 -160 752 -160 c 0 712 -160 672 -135 672 -90 c 0 672 -55 689 -30 714 -30 c 0 739 -30 755 -45 755 -65 c 0 755 -75 748 -83 737 -90 c 0 727 -97 727 -100 727 -110 c 0 |
| ︙ | ︙ | |||
3677 3678 3679 3680 3681 3682 3683 | -130 -55 -113 -30 -88 -30 c 0 -63 -30 -47 -45 -47 -65 c 0 -47 -75 -54 -83 -65 -90 c 0 -75 -97 -75 -100 -75 -110 c 0 -75 -120 -65 -124 -50 -124 c 0 13 -124 16 -35 83 230 c 1 64 230 65 230 30 230 c 0 | | | | 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 | -130 -55 -113 -30 -88 -30 c 0 -63 -30 -47 -45 -47 -65 c 0 -47 -75 -54 -83 -65 -90 c 0 -75 -97 -75 -100 -75 -110 c 0 -75 -120 -65 -124 -50 -124 c 0 13 -124 16 -35 83 230 c 1 64 230 65 230 30 230 c 0 17 230 11 241 11 251 c 0 11 261 17 270 28 270 c 0 59 270 61 270 93 270 c 1 121 374 204 440 270 440 c 0 310 440 350 415 350 370 c 0 350 335 333 310 308 310 c 0 283 310 267 325 267 345 c 0 267 355 274 363 285 370 c 0 296 377 295 380 295 390 c 0 |
| ︙ | ︙ | |||
3720 3721 3722 3723 3724 3725 3726 | 60 34 69 30 85 30 c 0 113 30 140 45 140 70 c 0 140 100 120 107 94 124 c 0 61 145 30 167 30 200 c 0 30 247 70 280 130 280 c 0 175 280 218 253 218 220 c 0 218 199 202 180 180 180 c 0 | | | | | | | | | | | | | | | | | | | 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 | 60 34 69 30 85 30 c 0 113 30 140 45 140 70 c 0 140 100 120 107 94 124 c 0 61 145 30 167 30 200 c 0 30 247 70 280 130 280 c 0 175 280 218 253 218 220 c 0 218 199 202 180 180 180 c 0 164 180 145 195 145 214 c 0 145 219 147 224 150 230 c 1 142 240 133 250 120 250 c 0 101 250 80 239 80 220 c 0 80 193 127 175 150 160 c 0 184 137 200 120 200 90 c 0 200 26 156 0 80 0 c 0xd8 494 3 m 0 482 -6 470 16 481 26 c 0 655 217 l 0 647 221 637 222 625 222 c 0 614 222 601 221 585 221 c 0 574 221 554 173 541 162 c 0 527 150 511 153 524 187 c 0 543 238 542 251 548 267 c 1 581 265 605 264 623 264 c 0 679 264 680 272 702 272 c 0 708 272 714 271 724 270 c 0 739 268 737 254 728 245 c 0 574 82 l 0 571 78 570 75 570 72 c 0 570 55 620 71 651 44 c 0 660 36 672 52 668 64 c 0 661 84 629 65 629 100 c 0 629 115 645 130 661 130 c 0 681 130 699 117 699 75 c 0 699 36 667 3 624 3 c 0 622 3 620 3 618 3 c 0 575 6 554 18 533 18 c 0 521 18 509 14 494 3 c 0 182 -160 m 0 142 -160 102 -135 102 -90 c 0 102 -55 119 -30 144 -30 c 0 169 -30 185 -45 185 -65 c 0 185 -75 178 -83 167 -90 c 0 157 -97 165 -100 165 -110 c 0 165 -120 167 -124 182 -124 c 0 245 -124 248 -35 315 230 c 1 296 230 297 230 262 230 c 0 249 230 243 241 243 251 c 0 243 261 249 270 260 270 c 0 291 270 293 270 325 270 c 1 353 374 436 440 502 440 c 0 542 440 582 415 582 370 c 0 582 335 565 310 540 310 c 0 515 310 499 325 499 345 c 0 499 355 506 363 517 370 c 0 528 377 527 380 527 390 c 0 527 400 517 404 502 404 c 0 460 404 450 332 437 270 c 1 464 270 461 270 491 270 c 0 504 270 510 260 510 250 c 0 510 240 504 230 491 230 c 0 465 230 461 230 428 230 c 1 385 -26 312 -160 182 -160 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE566 |
| ︙ | ︙ | |||
4159 4160 4161 4162 4163 4164 4165 | EndChar StartChar: uniE650 Encoding: 124 58960 124 Width: 1037 Flags: W HStem: -2 60<361.035 435.033 953.253 1010.82> 0 49<543.265 652.027> 286 36<514.943 580.797> 359 66<58.4784 125.129> 402 58<367.211 444.917> 607 32<177.106 261> | | | | | 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 | EndChar StartChar: uniE650 Encoding: 124 58960 124 Width: 1037 Flags: W HStem: -2 60<361.035 435.033 953.253 1010.82> 0 49<543.265 652.027> 286 36<514.943 580.797> 359 66<58.4784 125.129> 402 58<367.211 444.917> 607 32<177.106 261> VStem: 0 57<406 505.924> 148 26<463.933 475.584> 200 67<410.241 442> 275 84<205.648 329> 425 56<126.64 255.856> 452 64<466.983 558.522> 585 40<194.878 284.873> 675 60<72.5613 225.441> 887 59<79.8865 267.532> 952 60<-0.820206 56.8202> LayerCount: 2 Fore SplineSet 152 90 m 0x67ef 221 120 275 165 275 209 c 0 275 216 273 224 270 231 c 0 252 273 185 332 185 389 c 0 185 407 200 441 200 442 c 2 261 607 l 1 114 601 57 505 57 460 c 0x6fef 57 436 69 425 89 425 c 0 110 425 128 443 148 485 c 1 174 472 l 1 |
| ︙ | ︙ | |||
4188 4189 4190 4191 4192 4193 4194 | 437 460 452 482 452 510 c 0x2fdf 452 530 431 601 303 608 c 1 276 542 l 2 275 538 267 498 267 479 c 0 267 390 359 361 359 297 c 0 359 211 296 140 296 140 c 1 334 114 366 63 394 63 c 0 | | | | 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 | 437 460 452 482 452 510 c 0x2fdf 452 530 431 601 303 608 c 1 276 542 l 2 275 538 267 498 267 479 c 0 267 390 359 361 359 297 c 0 359 211 296 140 296 140 c 1 334 114 366 63 394 63 c 0 399 63 403 63 407 63 c 0 418 63 427 66 458 93 c 1 438 125 425 152 425 186 c 27 425 226 431 247 453 276 c 0 479 311 522 322 563 322 c 0 599 322 625 289 625 247 c 3 625 233 625 214 615 195 c 0 591 148 551 110 526 90 c 1 550 61 566 49 604 49 c 0x6fef |
| ︙ | ︙ |
Changes to modules/MIDI.js.
1 2 | // MIDI.js - module to handle the %%MIDI parameters // | | | 1 2 3 4 5 6 7 8 9 10 | // MIDI.js - module to handle the %%MIDI parameters // // Copyright (C) 2019-2023 Jean-Francois Moine // // This file is part of abc2svg. // // abc2svg is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
130 131 132 133 134 135 136 |
// // M:9/8 fzcfzcfzc
// break
case "gchordon": // %%MIDI gchordon
case "gchordoff": // %%MIDI gchordoff
if (!cfmt.chord)
cfmt.chord = {}
if (abc.parse.state >= 2
| | | | | | | < < < < < < | 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
// // M:9/8 fzcfzcfzc
// break
case "gchordon": // %%MIDI gchordon
case "gchordoff": // %%MIDI gchordoff
if (!cfmt.chord)
cfmt.chord = {}
if (abc.parse.state >= 2
&& curvoice) {
s = abc.new_block("midigch")
s.play = s.invis = 1 //true
s.on = a[1][7] == 'n'
} else {
cfmt.chord.gchon = a[1][7] == 'n'
}
break
case "channel":
v = parseInt(a[2])
if (isNaN(v) || v <= 0 || v > 16) {
abc.syntax(1, abc.errs.bad_val, "%%MIDI channel")
break
}
v-- // channel range 1..16 => 0..15
if (abc.parse.state == 3) {
s = abc.new_block("midiprog")
s.play = s.invis = 1 //true
curvoice.chn = s.chn = v
} else {
abc.set_v_param("channel", v)
}
break
case "drummap":
//fixme: should have a 'MIDIdrum' per voice?
v = Number(a[3])
if (isNaN(v)) {
abc.syntax(1, abc.errs.bad_val, "%%MIDI drummap")
break
|
| ︙ | ︙ | |||
192 193 194 195 196 197 198 |
v = parseInt(v)
if (isNaN(v) || v < 0 || v > 127) {
abc.syntax(1, abc.errs.bad_val, "%%MIDI program")
break
}
if (abc.parse.state == 3) {
s = abc.new_block("midiprog");
| | > | | 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 |
v = parseInt(v)
if (isNaN(v) || v < 0 || v > 127) {
abc.syntax(1, abc.errs.bad_val, "%%MIDI program")
break
}
if (abc.parse.state == 3) {
s = abc.new_block("midiprog");
s.play = s.invis = 1 //true
s.instr = v
s.chn = curvoice.chn
} else {
abc.set_v_param("instr", v)
}
break
case "control":
n = parseInt(a[2])
if (isNaN(n) || n < 0 || n > 127) {
abc.syntax(1, "Bad controller number in %%MIDI")
break
}
v = parseInt(a[3])
if (isNaN(v) || v < 0 || v > 127) {
abc.syntax(1, "Bad controller value in %%MIDI")
break
}
if (abc.parse.state == 3) {
s = abc.new_block("midictl");
s.play = s.invis = 1 //true
s.ctrl = n;
s.val = v
} else {
abc.set_v_param("midictl", a[2] + ' ' + a[3])
}
break
case "temperamentequal":
|
| ︙ | ︙ | |||
292 293 294 295 296 297 298 |
break
}
}, // do_midi()
// set the MIDI parameters in the current voice
set_vp: function(of, a) {
| | > | > > | > > | > > > > > > | 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 |
break
}
}, // do_midi()
// set the MIDI parameters in the current voice
set_vp: function(of, a) {
var i, item, s,
abc = this,
curvoice = abc.get_curvoice()
for (i = 0; i < a.length; i++) {
switch (a[i]) {
case "channel=": // %%MIDI channel
s = abc.new_block("midiprog")
s.play = s.invis = 1 //true
s.chn = curvoice.chn = a[++i]
break
case "instr=": // %%MIDI program
s = abc.new_block("midiprog")
s.play = s.invis = 1 //true
s.instr = a[++i]
if (curvoice.chn == undefined) {
curvoice.chn = curvoice.v < 9 ?
curvoice.v :
curvoice.v + 1
}
s.chn = curvoice.chn
break
case "midictl=": // %%MIDI control
if (!curvoice.midictl)
curvoice.midictl = []
item = a[++i].split(' ');
curvoice.midictl[item[0]] = Number(item[1])
break
|
| ︙ | ︙ |
Changes to modules/capo.js.
| ︙ | ︙ | |||
32 33 34 35 36 37 38 |
if (p_v.capo && a_gch) {
t = p_v.capo
i = 0
while (1) {
gch = a_gch[i++]
| | > > | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
if (p_v.capo && a_gch) {
t = p_v.capo
i = 0
while (1) {
gch = a_gch[i++]
if (!gch) {
of(s)
return
}
if (gch.type == 'g')
break
}
gch2 = Object.create(gch)
gch2.capo = false // (would be erased when setting gch)
gch2.text = abc.gch_tr1(gch2.text, -abc2svg.ifb40[t % 12])
if (!p_v.capo_first) { // if new voice
|
| ︙ | ︙ |
Changes to modules/combine.js.
1 2 | // combine.js - module to add a combine chord line // | | | 1 2 3 4 5 6 7 8 9 10 | // combine.js - module to add a combine chord line // // Copyright (C) 2018-2022 Jean-Francois Moine // // This file is part of abc2svg. // // abc2svg is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
23 24 25 26 27 28 29 |
// %%voicecombine n 'n' is the combine level
abc2svg.combine = {
// function called at start of the generation when multi-voices
comb_v: function() {
var C = abc2svg.C,
| > | > > > > > > > > > > > > > > > > | | < | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
// %%voicecombine n 'n' is the combine level
abc2svg.combine = {
// function called at start of the generation when multi-voices
comb_v: function() {
var C = abc2svg.C,
abc = this
// get the symbol of the note to combine
function get_cmb(s) {
var p,
s2 = s.ts_next,
i = s.p_v.id.indexOf('.') // '.' is the group separator
if (i >= 0) {
p = s.p_v.id.slice(0, i) // group
while (s2 && s2.time == s.time) {
if (s2.p_v.id.indexOf(p) == 0)
break
s2 = s2.ts_next
}
}
return s2
} // get_cmb()
// check if voice combine may occur
function may_combine(s) {
var nhd2,
s2 = get_cmb(s)
if (!s2 || (s2.type != C.NOTE && s2.type != C.REST))
return false
if (s2.st != s.st
|| s2.time != s.time
|| s2.dur != s.dur)
return false
if (s.combine <= 0
&& s2.type != s.type)
return false
// if (s2.a_dd) { //fixme: should check the double decorations
// return false
// }
|
| ︙ | ︙ | |||
64 65 66 67 68 69 70 |
&& s.notes[0].pit <= s2.notes[nhd2].pit + 1)
return false
return true
} // may_combine()
// combine two notes
function combine_notes(s, s2) {
| | > | | > | > > | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
&& s.notes[0].pit <= s2.notes[nhd2].pit + 1)
return false
return true
} // may_combine()
// combine two notes
function combine_notes(s, s2) {
var nhd, type, m, not
// put the notes of the 2nd voice into the 1st one
for (m = 0; m <= s2.nhd; m++) {
not = abc.clone(s2.notes[m])
not.noplay = true // and don't play it
s.notes.push(not)
}
s.nhd = nhd = s.notes.length - 1;
s.notes.sort(abc2svg.pitcmp) // sort the notes by pitch
if (s.combine >= 3) { // remove unison heads
//fixme: KO for playback
for (m = nhd; m > 0; m--) {
if (s.notes[m].pit == s.notes[m - 1].pit
&& s.notes[m].acc == s.notes[m - 1].acc)
s.notes.splice(m, 1)
}
s.nhd = nhd = s.notes.length - 1
}
|
| ︙ | ︙ | |||
94 95 96 97 98 99 100 101 |
s.notes[0].tie_ty = C.SL_BELOW | (type & C.SL_DOTTED);
type = s.notes[nhd].tie_ty
if ((type & 0x07) == C.SL_AUTO)
s.notes[nhd].tie_ty = C.SL_ABOVE | (type & C.SL_DOTTED)
} // combine_notes()
// combine 2 voices
function do_combine(s) {
| > | | | | < < | > > > > > > > > | > > > > > > | > > > > > > | | > | | | < < < | | | | 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
s.notes[0].tie_ty = C.SL_BELOW | (type & C.SL_DOTTED);
type = s.notes[nhd].tie_ty
if ((type & 0x07) == C.SL_AUTO)
s.notes[nhd].tie_ty = C.SL_ABOVE | (type & C.SL_DOTTED)
} // combine_notes()
// combine 2 voices
// return the remaining one
function do_combine(s) {
var s2, s3, type, i, n, sl
s2 = get_cmb(s)
// there may be more voices
if (!s.in_tuplet
&& s2.combine != undefined && s2.combine >= 0
&& may_combine(s2))
s2 = do_combine(s2)
if (s.type != s2.type) { // if note and rest
if (s2.type != C.REST) {
s2 = s;
s = s2.ts_next
}
} else if (s.type == C.REST) {
if (s.invis
&& !s2.invis)
delete s.invis
} else {
combine_notes(s, s2)
if (s2.ti1)
s.ti1 = true
if (s2.ti2)
s.ti2 = true
}
// if some slurs start on the second symbol
// move them to the combined symbol
// also, set a flag in the symbols of the ending slurs
if (s2.sls) {
if (s.sls)
Array.prototype.push.apply(s.sls, s2.sls)
else
s.sls = s2.sls
for (i = 0; i < s2.sls.length; i++) {
sl = s2.sls[i]
if (sl.se)
sl.se.slsr = s // reverse pointer
sl.ty = C.SL_BELOW
}
delete s2.sls
}
// if a combined slur is ending on the second symbol,
// update its starting symbol
s3 = s2.slsr // pointer to the starting symbol
if (s3) {
for (i = 0; i < s3.sls.length; i++) {
sl = s3.sls[i]
if (sl.se == s2)
sl.se = s
}
}
if (s2.a_gch)
s.a_gch = s2.a_gch
if (s2.a_dd) {
if (!s.a_dd)
s.a_dd = s2.a_dd
else
Array.prototype.push.apply(s.a_dd, s2.a_dd)
}
s2.play = s2.invis = true // don't display, but play
return s
} // do_combine()
// code of comb_v()
var s, s2, g, i, r
for (s = abc.get_tsfirst(); s; s = s.ts_next) {
switch (s.type) {
case C.REST:
if (s.combine == undefined || s.combine < 0)
continue
if (may_combine(s))
s = do_combine(s)
// continue // fall thru
default:
continue
case C.NOTE:
if (s.combine == undefined || s.combine <= 0)
continue
break
}
if (!s.beam_st)
continue
s2 = s
while (1) {
if (!may_combine(s2)) {
s2 = null
break
}
//fixme: may have rests in beam
if (s2.beam_end)
break
do {
s2 = s2.next
} while (s2.type != C.NOTE && s2.type != C.REST)
}
if (!s2)
continue
s2 = s
while (1) {
s2 = do_combine(s2)
//fixme: may have rests in beam
if (s2.beam_end)
break
do {
s2 = s2.next
} while (s2.type != C.NOTE && s2.type != C.REST)
}
|
| ︙ | ︙ |
Changes to modules/diag.js.
| ︙ | ︙ | |||
167 168 169 170 171 172 173 | + '" y="' + ((l[1] || 1) * 6 - 35) + '" class="frn">' + l[0] + '</text>\n' decos[nm] = "3 " + nm + " 40 " + (l[0] ? "30" : "10") + " 0" // fingers dc += '<text x="' + (n == 6 ? '-12,-8,-4,0,4,8' : '-8,-4,0,4') + '" y="-36" class="fng">' | | | 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
+ '" y="' + ((l[1] || 1) * 6 - 35)
+ '" class="frn">' + l[0] + '</text>\n'
decos[nm] = "3 " + nm + " 40 " + (l[0] ? "30" : "10") + " 0"
// fingers
dc += '<text x="' + (n == 6 ? '-12,-8,-4,0,4,8'
: '-8,-4,0,4')
+ '" y="-36" class="fng">'
+ d[2].replace(/[y0]/g, ' ')
+ '</text>\n'
// dots
for (i = 0; i < n; i++) {
l = d[0][i]
if (l && l != 'x' && l != '0')
dc += '<use x="' + (i * 4 + x)
+ '" y="' + (l * 6 - 37)
|
| ︙ | ︙ |
Changes to modules/equalbars.js.
1 2 | // equalbars.js - module to set equal spaced measure bars // | | | 1 2 3 4 5 6 7 8 9 10 | // equalbars.js - module to set equal spaced measure bars // // Copyright (C) 2018-2022 Jean-Francois Moine // // This file is part of abc2svg. // // abc2svg is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
27 28 29 30 31 32 33 |
// new tune - clear the width of the start of the staff
output_music: function(of) {
this.equalbars_d = 0;
of()
},
// get the equalbars parameter
| | | < < | > > > > > > | | | | > > > > > > > > > > > > > > > > > > > > | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
// new tune - clear the width of the start of the staff
output_music: function(of) {
this.equalbars_d = 0;
of()
},
// get the equalbars parameter
set_fmt: function(of, cmd, parm) {
if (cmd != "equalbars") {
of(cmd, parm)
return
}
var fmt = this.cfmt()
fmt.equalbars = this.get_bool(parm)
fmt.stretchlast = 1
},
// adjust the symbol offsets of a music line
// only the bars of the first voice are treated
set_sym_glue: function(of, width) {
var C = abc2svg.C,
s, s2, w, i, n, x, g, t, t0,
bars = [],
tsfirst = this.get_tsfirst();
of(width) // compute the x offset of the symbols
if (!this.cfmt().equalbars)
return
// search the first note/rest/space
for (s2 = tsfirst; s2; s2 = s2.next) {
switch (s2.type) {
default:
continue
case C.GRACE:
case C.MREST:
case C.NOTE:
case C.REST:
case C.SPACE:
break
}
break
}
if (!s2)
return
// build an array of the bars
t0 = t = s2.time
for (s = s2; s.next; s = s.next) {
if (s.type == C.BAR && s.seqst) {
bars.push([s, s.time - t]);
t = s.time
}
}
// push the last bar if it is not the invisible bar after a key change
if (!s.invis || (s.prev && s.prev.type != C.KEY))
bars.push([s, s.time - t])
else
bars[bars.length - 1][0] = s // replace the last bar
t = s.time
if (s.dur)
t += s.dur;
n = bars.length
if (n <= 1)
return // one or no bar
// if small width, get the widest measure
if (s.x < width) {
w = 0
x = 0
for (i = 0; i < n; i++) {
s = bars[i][0]
if (s.x - x > w)
w = s.x - x
x = s.x
}
if (w * n < width)
width = w * n
this.set_realwidth(width)
}
// set the measure parameters
x = s2.type == C.GRACE ? s2.extra.x : s2.x;
if (this.equalbars_d < x)
this.equalbars_d = x // new offset of the first note/rest
d = this.equalbars_d
w = (width - d) / (t - t0) // width per time unit
// loop on the bars
for (i = 0; i < n; i++) {
do { // don't shift the 1st note
s2.x = d + s2.x - x // from the bar
s2 = s2.ts_next
} while (!s2.seqst)
s = bars[i][0]; // next bar
f = w * bars[i][1] / (s.x - x)
// and update the x offsets
for ( ; s2 != s; s2 = s2.ts_next) {
if (s2.type == C.GRACE) {
for (g = s2.extra; g; g = g.next)
|
| ︙ | ︙ |
Changes to modules/gamelan.js.
1 2 | // gamelan.js - module to output Gamelan (indonesian) music sheets // | | | 1 2 3 4 5 6 7 8 9 10 | // gamelan.js - module to output Gamelan (indonesian) music sheets // // Copyright (C) 2020-2023 Jean-Francois Moine // // This file is part of abc2svg. // // abc2svg is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
165 166 167 168 169 170 171 |
} // do_tie()
function set_sym(p_v) {
var s, s2, note, pit, nn, p, a, m, i,
sf = p_v.key.k_sf,
delta = abc2svg.gamelan.cgd2cde[sf + 7] - 2
| | | 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
} // do_tie()
function set_sym(p_v) {
var s, s2, note, pit, nn, p, a, m, i,
sf = p_v.key.k_sf,
delta = abc2svg.gamelan.cgd2cde[sf + 7] - 2
delete p_v.key.k_a_acc // no accidental
// no (visible) clef
p_v.clef.invis = true
// scan the voice
for (s = p_v.sym; s; s = s.next) {
s.st = p_v.st
|
| ︙ | ︙ | |||
354 355 356 357 358 359 360 |
continue
switch (s.type) {
case C.NOTE:
case C.REST:
x = s.x
y = staff_tb[s.st].y
draw_hd(s, x, y)
| > | > | > > | > > > > | > > > | | > | | | | < < < < < | | < < | 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 |
continue
switch (s.type) {
case C.NOTE:
case C.REST:
x = s.x
y = staff_tb[s.st].y
draw_hd(s, x, y)
break
}
}
// draw the (pseudo) beams
for (s = p_voice.sym; s; s = s.next) {
if (s.invis)
continue
switch (s.type) {
case C.NOTE:
case C.REST:
nl = s.nflags
if (nl <= 0)
continue
y = staff_tb[s.st].y
s2 = s
while (s.next && s.next.nflags > 0) {
s = s.next
if (s.nflags > nl)
nl = s.nflags
if (s.beam_end)
break
}
draw_dur(s2, y + 7, s, 1, nl)
break
}
}
}, // draw_symbols()
// set some parameters
set_fmt: function(of, cmd, param) {
|
| ︙ | ︙ | |||
434 435 436 437 438 439 440 |
var w, m, note,
C = abc2svg.C
switch (s.type) {
case C.CLEF:
case C.KEY:
case C.METER:
| | | 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 |
var w, m, note,
C = abc2svg.C
switch (s.type) {
case C.CLEF:
case C.KEY:
case C.METER:
s.wl = s.wr = .1 // (must not be null)
break
}
}, // set_width()
set_hooks: function(abc) {
abc.do_pscom = abc2svg.gamelan.do_pscom.bind(abc, abc.do_pscom)
abc.draw_symbols = abc2svg.gamelan.draw_symbols.bind(abc, abc.draw_symbols)
|
| ︙ | ︙ |
Changes to modules/grid.js.
1 2 | // abc2svg - grid.js - module to insert a chord grid before or after a tune // | | | 1 2 3 4 5 6 7 8 9 10 | // abc2svg - grid.js - module to insert a chord grid before or after a tune // // Copyright (C) 2018-2022 Jean-Francois Moine // // This file is part of abc2svg. // // abc2svg is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
43 44 45 46 47 48 49 |
var abc = this,
img, cls,
cfmt = abc.cfmt(),
grid = cfmt.grid
// generate the grid
function build_grid(s, font) {
| | | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
var abc = this,
img, cls,
cfmt = abc.cfmt(),
grid = cfmt.grid
// generate the grid
function build_grid(s, font) {
var i, k, l, nr, bar, w, hr, x0, x, y, yl, ps, d,
lc = '',
chords = s.chords,
bars = s.bars,
parts = s.parts || [],
wmx = s.wmx,
cells = [],
nc = grid.n
|
| ︙ | ︙ | |||
123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
}
}
} else {
abc.set_font('grid')
abc.xy_str(x, y, cell[0])
}
} // build_cell()
// ------- build_grid() -------
// set some chords in each cell
set_chords()
// build the content of the cells
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
}
}
} else {
abc.set_font('grid')
abc.xy_str(x, y, cell[0])
}
} // build_cell()
// draw the horizontal lines
function draw_hl() {
var i, i1, j, x,
y = -1
for (i = 0; i <= nr + 1; i++) {
j = 0
i1 = i > 0 ? i - 1 : 0
while (1) {
while (j <= nc && !d[i1][j])
j++
if (j > nc)
break
x = wmx * j
while (j <= nc && d[i1][j])
j++
if (i && i1 < nr) {
while (j <= nc && d[i1 + 1][j])
j++
}
abc.out_svg('M')
abc.out_sxsy(x0 + x, ' ', y)
abc.out_svg('h' + (wmx * j - x).toFixed(1)+ '\n')
}
y -= hr
}
} // draw_hl()
// draw the vertical lines
function draw_vl() {
var i, i1, j, y,
x = x0
for (i = 0; i <= nc; i++) {
j = 0
i1 = i > 0 ? i - 1 : 0
while (1) {
while (j <= nr && !d[j][i1])
j++
if (j > nr)
break
y = hr * j
while (j <= nr && d[j][i1])
j++
abc.out_svg('M')
abc.out_sxsy(x, ' ', -y - .5)
abc.out_svg('v' + (hr * j - y + 1).toFixed(1) + '\n')
}
x += wmx
}
} // draw_vl()
// ------- build_grid() -------
// set some chords in each cell
set_chords()
// build the content of the cells
|
| ︙ | ︙ | |||
176 177 178 179 180 181 182 | nc /= 2; w /= 2 } // generate the cells yl = -1 y = -1 + font.size * .6 | | > > > < < < < < | < < < < < < | < | 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
nc /= 2;
w /= 2
}
// generate the cells
yl = -1
y = -1 + font.size * .6
nr = -1
x0 = (x0 / cfmt.scale - w) / 2
d = []
for (i = 0; i < cells.length; i++) {
if (i == 0
|| (grid.repbrk
&& (bars[i].slice(-1) == ':' || bars[i][0] == ':'))
|| parts[i]
|| k >= nc) {
y -= hr // new row
yl -= hr
x = x0 + wmx / 2
k = 0
nr++
d[nr] = []
}
d[nr][k] = 1
k++
build_cell(cells[i], x, y, yl, hr)
x += wmx
}
// draw the lines
abc.out_svg('<path class="stroke" stroke-width="1" d="\n')
draw_hl()
draw_vl()
abc.out_svg('"/>\n')
// show the repeat signs and the parts
y = -1 + font.size * .7
x = x0
for (i = 0; i < bars.length; i++) {
bar = bars[i]
|
| ︙ | ︙ | |||
249 250 251 252 253 254 255 |
abc.out_svg('<text class="' + cls + '" x="')
abc.out_sxsy(x + 5, '" y="', y)
abc.out_svg('" style="font-weight:bold;font-size:' +
(font.size * 1.5).toFixed(1) + 'px">:</text>\n')
}
x += wmx
}
| | < < | 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
abc.out_svg('<text class="' + cls + '" x="')
abc.out_sxsy(x + 5, '" y="', y)
abc.out_svg('" style="font-weight:bold;font-size:' +
(font.size * 1.5).toFixed(1) + 'px">:</text>\n')
}
x += wmx
}
abc.vskip(hr * (nr + 1) + 6)
} // build_grid()
// ----- block_gen() -----
var p_voice, n, font, f2
img = abc.get_img()
// set the text style
font = abc.get_font('grid')
if (font.class)
font.class += ' mid'
else
font.class = 'mid'
cls = abc.font_class(font)
|
| ︙ | ︙ | |||
289 290 291 292 293 294 295 |
}, // block_gen()
set_stems: function(of) {
var C = abc2svg.C,
abc = this,
tsfirst = abc.get_tsfirst(),
voice_tb = abc.get_voice_tb(),
| | > > > > > > > > > > > > > > > > > > > > > > > > > | 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 |
}, // block_gen()
set_stems: function(of) {
var C = abc2svg.C,
abc = this,
tsfirst = abc.get_tsfirst(),
voice_tb = abc.get_voice_tb(),
cfmt = abc.cfmt(),
grid = cfmt.grid
// extract one of the chord symbols
// With chords as "[yyy];xxx"
// (!sel - default) returns "yyy" and (sel) returns "xxx"
function cs_filter(a_cs) {
var i, cs, t
for (i = 0; i < a_cs.length; i++) {
cs = a_cs[i]
if (cs.type != 'g')
continue
t = cs.text
if (cfmt.altchord) {
for (i++; i < a_cs.length; i++) {
cs = a_cs[i]
if (cs.type != 'g')
continue
t = cs.text
break
}
}
return t.replace(/\[|\]/g, '')
}
} // cs_filter()
function get_beat(s) {
var beat = C.BLEN / 4
if (!s.a_meter[0] || s.a_meter[0].top[0] == 'C'
|| !s.a_meter[0].bot)
return beat
|
| ︙ | ︙ | |||
333 334 335 336 337 338 339 |
if (s.part)
parts[chords.length] = s.part.text
switch (s.type) {
case C.NOTE:
case C.REST:
if (!s.a_gch || chord[beat_i])
break
| | < < < < < < < | > | | > > > | 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 |
if (s.part)
parts[chords.length] = s.part.text
switch (s.type) {
case C.NOTE:
case C.REST:
if (!s.a_gch || chord[beat_i])
break
bt = cs_filter(s.a_gch)
if (!bt)
break
w = abc.strwh(bt.replace(
/<[^>]+>/gm,''))
if (w[0] > wmx)
wmx = w[0]
bt = new String(bt)
bt.wh = w
chord[beat_i] = bt
break
case C.BAR:
i = s.bar_num // check if normal measure bar
bt = s.bar_type
while (s.ts_next && s.ts_next.time == s.time) {
if (s.ts_next.dur)
break
|
| ︙ | ︙ | |||
437 438 439 440 441 442 443 444 445 446 447 448 449 450 |
dur: 0,
time: 0,
p_v: p_v,
v: p_v.v,
st: p_v.st
}
build_chords(s) // build the array of the chords
// and insert it in the tune
if (!s.chords) { // if no chord
;
} else if (grid.nomusic) { // if just the grid
this.set_tsfirst(s)
| > > > | 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 |
dur: 0,
time: 0,
p_v: p_v,
v: p_v.v,
st: p_v.st
}
if (!cfmt.gridfont)
abc.param_set_font("gridfont", "serif 16")
abc.set_font('grid')
build_chords(s) // build the array of the chords
// and insert it in the tune
if (!s.chords) { // if no chord
;
} else if (grid.nomusic) { // if just the grid
this.set_tsfirst(s)
|
| ︙ | ︙ |
Changes to modules/grid2.js.
1 2 | // grid2.js - module to replace a voice in the music by a chord grid // | | | | > > > > > > > | > > | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
// grid2.js - module to replace a voice in the music by a chord grid
//
// Copyright (C) 2018-2023 Jean-Francois Moine
//
// This file is part of abc2svg.
//
// abc2svg is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// abc2svg is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with abc2svg. If not, see <http://www.gnu.org/licenses/>.
//
// This module is loaded when "%%grid2" appears in a ABC source.
//
// Parameters
// %%grid2 y
// This command may appear globally or in a voice.
abc2svg.grid2 = {
// function called before tune generation
do_grid: function() {
var s, v, p_v, ix, cs, c_a_cs, bt, gch,
voice_tb = this.get_voice_tb()
if (this.cfmt().grid2)
for (v = 0; v < voice_tb.length; v++)
if (voice_tb[v].grid2 == undefined)
voice_tb[v].grid2 = 1
for (v = 0; v < voice_tb.length; v++) {
p_v = voice_tb[v]
if (!p_v.grid2)
continue
curvoice = p_v
this.set_v_param("stafflines", "...") // no staff
p_v.clef.invis = true; // no clef
p_v.key.k_sf = 0 // no key signature
delete p_v.key.k_a_acc
p_v.staffnonote = 2 // draw the staff
for (s = p_v.sym; s; s = s.next) {
delete s.a_dd // no decoration
if (!s.dur) {
if (s.bar_type)
bt = s.time
continue
}
// set all notes
s.invis = true; // as invisible
delete s.sl1; // with no slur
delete s.ti1 // and no tie
delete s.ti2
for (ix = 0; ix <= s.nhd; ix++)
delete s.notes[ix].tie_ty
if (s.tf) // don't show the tuplets
s.tf[0] = 1
if (!s.a_gch) {
if (s.time == bt)
s.a_gch = [ this.clone(c_a_cs) ]
continue
}
for (ix = 0; ix < s.a_gch.length; ix++) {
gch = s.a_gch[ix]
if (gch.type == 'g') {
c_a_cs = gch
break
}
}
}
}
}, // do_grid()
|
| ︙ | ︙ | |||
89 90 91 92 93 94 95 |
output_music: function(of) {
abc2svg.grid2.do_grid.call(this);
of()
},
set_fmt: function(of, cmd, param) {
if (cmd == "grid2") {
| | > > | < | < > > | 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
output_music: function(of) {
abc2svg.grid2.do_grid.call(this);
of()
},
set_fmt: function(of, cmd, param) {
if (cmd == "grid2") {
var curvoice = this.get_curvoice(),
v = this.get_bool(param)
if (curvoice)
curvoice.grid2 = v
else
this.cfmt().grid2 = v
return
}
of(cmd, param)
},
set_hooks: function(abc) {
abc.draw_gchord = abc2svg.grid2.draw_gchord.bind(abc, abc.draw_gchord);
|
| ︙ | ︙ |
Changes to modules/grid3.js.
1 2 | // grid3.js - module to insert a manual chords // | | | 1 2 3 4 5 6 7 8 9 10 | // grid3.js - module to insert a manual chords // // Copyright (C) 2020-2022 Jean-Francois Moine // // This file is part of abc2svg. // // abc2svg is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
// generate the grid
block_gen: function(of, s) {
if (s.subtype != "grid3") {
of(s)
return
}
var abc = this,
cfmt = abc.cfmt(),
img = abc.get_img(),
txt = s.text,
font, font_cl, cls, w,
ln, i,
lines = [],
cl = [],
bars = [],
cells = [],
| > > > | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
// generate the grid
block_gen: function(of, s) {
if (s.subtype != "grid3") {
of(s)
return
}
this.blk_flush()
var abc = this,
cfmt = abc.cfmt(),
img = abc.get_img(),
posy = abc.get_posy(),
txt = s.text,
font, font_cl, cls, w,
ln, i,
lines = [],
cl = [],
bars = [],
cells = [],
|
| ︙ | ︙ | |||
114 115 116 117 118 119 120 | // build the content of the cells hr = font.size * 2.1 if (wc < hr * 1.4) wc = hr * 1.4 // cell width w = wc * nc // grid width // generate the cells | | | | > | > | | 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
// build the content of the cells
hr = font.size * 2.1
if (wc < hr * 1.4)
wc = hr * 1.4 // cell width
w = wc * nc // grid width
// generate the cells
yl = posy + 3
y = posy + 3 - font.size * .7
x0 = (img.width / cfmt.scale - w) / 2
while (1) {
cl = cells.shift()
if (!cl)
break
y += hr
yl += hr
x = x0 + wc / 2
while (1) {
cell = cl.shift()
if (!cell)
break
lc += build_cell(cell, x, y, yl, hr)
x += wc
}
}
// draw the lines
line = '<path class="stroke" d="\n'
y = posy + 3
for (i = 0; i <= nr; i++) {
line += 'M' + x0.toFixed(1) + ' ' + y.toFixed(1) +
'h' + w.toFixed(1)+ '\n'
y += hr
}
x = x0
y = posy + 3
for (i = 0; i <= nc; i++) {
line += 'M' + x.toFixed(1) + ' ' + y.toFixed(1) +
'v' + (hr * nr).toFixed(1) + '\n'
x += wc
}
line += '"/>\n'
// insert the cells
line += lc
// show the repeat signs
y = posy + 3 - font.size * .7
while (1) {
bl = bars.shift()
if (!bl)
break
x = x0
y += hr
while (1) {
|
| ︙ | ︙ | |||
250 251 252 253 254 255 256 |
wc = w
}
nr++
}
wc += abc.strwh(' ')[0]
// build the grid and insert it in the music
| < | 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
wc = w
}
nr++
}
wc += abc.strwh(' ')[0]
// build the grid and insert it in the music
build_grid()
abc.blk_flush()
}, // block_gen()
// handle %%begingrid
do_begin_end: function(of, type, opt, txt) {
var vt = this.get_voice_tb()
|
| ︙ | ︙ |
Changes to modules/jazzchord.js.
| ︙ | ︙ | |||
39 40 41 42 43 44 45 |
// "M": "Δ",
// "min": "–",
// "m": "–",
"^": "∆"
},
gch_build: function(of, s) {
| | > > > > > > > > > > > > > > > > > > > | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
// "M": "Δ",
// "min": "–",
// "m": "–",
"^": "∆"
},
gch_build: function(of, s) {
var gch, ix, r, t,
fmt = s.fmt
if (!fmt.jazzchord) {
of(s)
return
}
// jazzify a chord
function jzch(t) {
var r = '',
a = t.match(/(\[?[A-G])([#♯b♭]?)([^/]*)\/?(.*)\)?/)
// a[1]=note, a[2]=acc, a[3]=quality, a[4]=bass
if (!a)
return t
if (a[2])
r = "$7" + a[2]
if (a[3])
r += (a[2] ? "$0" : '') + "$8" + a[3]
if (a[4])
r += ((a[2] || a[3]) ? "$0" : '') + "$9/" + a[4]
if (!r)
return t
return a[1] + r + "$0"
} // jzch()
for (ix = 0; ix < s.a_gch.length; ix++) {
gch = s.a_gch[ix]
t = gch.text
if (gch.type != 'g'
|| t.indexOf('$') >= 0) // if some formatting already
continue
|
| ︙ | ︙ | |||
69 70 71 72 73 74 75 |
return fmt.jzrep[x]
})
}
if (fmt.jazzchord == 1) {
if (t[0] == '(')
t = t.slice(1, -1)
| | < < < | | | | < | | | | 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
return fmt.jzrep[x]
})
}
if (fmt.jazzchord == 1) {
if (t[0] == '(')
t = t.slice(1, -1)
t = t.split('(') // possible "ch1(ch2)"
r = jzch(t[0])
if (t.length > 1)
r += '(' + jzch(t[1])
} else {
r = t
}
if (gch.text[0] == '(')
gch.text = '(' + r + ')'
else
gch.text = r
}
of(s) // build the chord symbols
}, // gch_build()
set_fmt: function(of, cmd, parm) {
var i, k, s,
cfmt = this.cfmt()
|
| ︙ | ︙ |
Changes to modules/jianpu.js.
1 2 | // jianpu.js - module to output jiănpŭ (简谱) music sheets // | | | 1 2 3 4 5 6 7 8 9 10 | // jianpu.js - module to output jiănpŭ (简谱) music sheets // // Copyright (C) 2020-2023 Jean-Francois Moine // // This file is part of abc2svg. // // abc2svg is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
31 32 33 34 35 36 37 |
cgd2cde: new Int8Array([0, -4, -1, -5, -2, -6, -3,
0, -4, -1, -5, -2, -6, -3, 0]),
acc2: new Int8Array([-2, -1, 3, 1, 2]),
acc_tb: ["\ue264", "\ue260", , "\ue262", "\ue263", "\ue261"],
// don't calculate the beams
calc_beam: function(of, bm, s1) {
| | < < < < < < < < < < < < > | > > > > | > > > > > > > > > > > > > > > > > > > > | > > > > > > | > | > > > > > | > > > | > > > > > > | | | > > > > > > | | | > | | < | > > > | | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
cgd2cde: new Int8Array([0, -4, -1, -5, -2, -6, -3,
0, -4, -1, -5, -2, -6, -3, 0]),
acc2: new Int8Array([-2, -1, 3, 1, 2]),
acc_tb: ["\ue264", "\ue260", , "\ue262", "\ue263", "\ue261"],
// don't calculate the beams
calc_beam: function(of, bm, s1) {
if (!s1.p_v.jianpu)
return of(bm, s1)
// return 0
}, // calc_beam()
// adjust some symbols before the generation
output_music: function(of) {
var p_v, v,
C = abc2svg.C,
abc = this,
cur_sy = abc.get_cur_sy(),
voice_tb = abc.get_voice_tb()
// handle the overlay voices
function ov_def(v) {
var s1, tim,
s = p_v.sym
while (s) {
s1 = s.ts_prev
if (!s.invis
&& s.dur
&& s1.v != v
&& s1.st == s.st // overlay start
&& s1.time == s.time) {
while (1) { // go back to the previous bar
if (!s1.prev
|| s1.prev.bar_type)
break
s1 = s1.prev
}
//add deco '{' on s1
while (!s1.bar_type) {
s1.dy = 14
s1.notes[0].pit = 30
s1 = s1.next
}
// add deco '}' on s1
while (1) {
s.dy = -14
s.notes[0].pit = 20
if (!s.next
|| s.next.bar_type
|| s.next.time >= s1.time)
break
s = s.next
}
}
s = s.next
}
} // ov_def()
// output the key and time signatures
function set_head() {
var v, p_v, mt, s2, sk, s,
tsfirst = abc.get_tsfirst()
// search a jianpu voice
for (v = 0; v < voice_tb.length; v++) {
p_v = voice_tb[v]
if (p_v.jianpu)
break
}
if (v >= voice_tb.length)
return
mt = p_v.meter.a_meter[0]
sk = p_v.key
s2 = p_v.sym
s = {
type: C.BLOCK,
subtype: "text",
time: s2.time,
dur: 0,
v: 0,
p_v: p_v,
st: 0,
fmt: s2.fmt,
seqst: true,
text: (sk.k_mode + 1) + "=" +
(abc2svg.jianpu.k_tb[sk.k_sf + 7 +
abc2svg.jianpu.cde2fcg[sk.k_mode]]),
font: abc.get_font("text")
}
if (mt)
s.text += ' ' + (mt.bot ? (mt.top + '/' + mt.bot) : mt.top)
// insert the block after the first %%staves
s2 = tsfirst
s.next = s2.next
if (s.next)
s.next.prev = s
s.prev = s2
s2.next = s
s.ts_next = s2.ts_next
s.ts_next.ts_prev = s
s.ts_prev = s2
s2.ts_next = s
} // set head()
// expand a long note/rest
function slice(s) {
var n, s2, s3,
jn = s.type == C.REST ? 0 : 8 // '0' or '-'
if (s.dur >= C.BLEN)
n = 3
else if (s.dur == C.BLEN / 2)
n = 1
else
n = 2
s.notes[0].dur =
s.dur = s.dur_orig = C.BLEN / 4
delete s.fmr
while (--n >= 0) {
s2 = {
type: C.REST,
v: s.v,
p_v: s.p_v,
st: s.st,
dur: C.BLEN / 4,
dur_orig: C.BLEN / 4,
fmt: s.fmt,
stem: 0,
multi: 0,
nhd: 0,
notes: [{
dur: s.dur,
pit: s.notes[0].pit,
jn: jn
}],
xmx: 0,
noplay: true,
time: s.time + C.BLEN / 4,
prev: s,
next: s.next
}
|
| ︙ | ︙ | |||
157 158 159 160 161 162 163 164 |
break
}
}
s = s2
}
} // slice()
function set_sym(p_v) {
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | < | | | | | > > < | < < | < < < < | < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | > > | > > > > | | | | > | | | | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 |
break
}
}
s = s2
}
} // slice()
function set_note(s, sf) {
var i, m, note, p, pit, a, nn,
delta = abc2svg.jianpu.cgd2cde[sf + 7] - 2
s.stem = -1
s.stemless = true
if (s.sls) {
for (i = 0; i < s.sls.length; i++)
s.sls[i].ty = C.SL_ABOVE
}
for (m = 0; m <= s.nhd; m++) {
note = s.notes[m]
// note head
p = note.pit
pit = p + delta
note.jn = ((pit + 77) % 7) + 1 // note number
// set a fixed offset to the note for the decorations
note.pit = 25 // "e"
note.jo = (pit / 7) | 0 // octave number
// accidentals
a = note.acc
if (a) {
nn = abc2svg.jianpu.cde2fcg[(p + 5 + 16 * 7) % 7] - sf
if (a != 3)
nn += a * 7
nn = ((((nn + 1 + 21) / 7) | 0) + 2 - 3 + 32 * 5) % 5
note.acc = abc2svg.jianpu.acc2[nn]
}
// set the slurs and ties up
if (note.sls) {
for (i = 0; i < note.sls.length; i++)
note.sls[i].ty = C.SL_ABOVE
}
if (note.tie_ty)
note.tie_ty = C.SL_ABOVE
}
// change the long notes
if (s.dur >= C.BLEN / 2
&& !s.invis)
slice(s)
// replace the staccato dot
if (s.a_dd) {
for (i = 0; i < s.a_dd.length; i++) {
if (s.a_dd[i].glyph == "stc") {
abc.deco_put("gstc", s)
s.a_dd[i] = s.a_dd.pop()
}
}
}
} // set_note()
function set_sym(p_v) {
var s, g,
sf = p_v.key.k_sf
delete p_v.key.k_a_acc // no accidental
// no (visible) clef
s = p_v.clef
s.invis = true
s.clef_type = 't'
s.clef_line = 2
// scan the voice
for (s = p_v.sym; s; s = s.next) {
s.st = p_v.st
switch (s.type) {
case C.CLEF:
s.invis = true
s.clef_type = 't'
s.clef_line = 2
// continue
default:
continue
case C.KEY:
sf = s.k_sf
s.a_gch = [{
type: '@',
font: abc.get_font("annotation"),
wh: [10, 10],
x: -5,
y: 26,
text: (s.k_mode + 1) + "=" +
(abc2svg.jianpu.k_tb[sf + 7 +
abc2svg.jianpu.cde2fcg[s.k_mode]])
}]
continue
case C.REST:
if (s.notes[0].jn)
continue
s.notes[0].jn = 0
if (s.dur >= C.BLEN / 2
&& !s.invis)
slice(s)
continue
case C.NOTE: // change the notes
set_note(s, sf)
break
case C.GRACE:
for (g = s.extra; g; g = g.next)
set_note(g, sf)
break
}
}
} // set_sym()
// -- output_music --
set_head()
for (v = 0; v < voice_tb.length; v++) {
p_v = voice_tb[v]
if (p_v.jianpu) {
set_sym(p_v)
if (v > 0 && voice_tb[v - 1].st == p_v.st)
ov_def(v)
}
}
of()
}, // output_music()
draw_symbols: function(of, p_voice) {
var s, s2, nl, y,
C = abc2svg.C,
abc = this,
dot = "\ue1e7",
staff_tb = abc.get_staff_tb(),
out_svg = abc.out_svg,
out_sxsy = abc.out_sxsy,
xypath = abc.xypath
if (!p_voice.jianpu) {
of(p_voice)
return
}
// draw the duration lines under the notes
function draw_dur(s1, x, y, s2, n, nl) {
var s, s3,
sc = s1.grace ? .5 : 1
xypath(x - 3, y + 5)
out_svg('h' + ((s2.x - s1.x) / sc + 8).toFixed(1) + '"/>\n') // "
y -= 2.5
while (++n <= nl) {
s = s1
while (1) {
if (s.nflags && s.nflags >= n) {
s3 = s
while (s != s2) {
if (s.next.beam_br1
|| (s.next.beam_br2 && n > 2)
|| (s.next.nflags
&& s.next.nflags < n))
break
s = s.next
}
draw_dur(s3, s3.x, y, s, n, nl)
}
if (s == s2)
break
s = s.next
}
}
} // draw_dur()
|
| ︙ | ︙ | |||
356 357 358 359 360 361 362 | out_mus(x - 1, ym, dot) } } y += 20 } } // draw_hd() | > > > > | > > > > > > > > > > > > > > > > > > > > > > > | > > | | > | > | < > | | | > | | | > > > | | > | | | | < < < < < | > > | < < < < < < < < < | < | < > > > > > > > > > > > > > > > > > > > > > > > > > | | < > | 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 |
out_mus(x - 1, ym, dot)
}
}
y += 20
}
} // draw_hd()
function draw_note(s) {
var sc = 1,
x = s.x,
y = staff_tb[s.st].y
if (s.dy)
y += s.dy // voice overlay
if (s.grace) {
out_svg('<g transform="translate(')
out_sxsy(x, ',', y + 15) // (font height)
out_svg(') scale(.5)">\n')
abc.stv_g().g++ // in container
x = 0
y = 0
sc = .5
}
draw_hd(s, x, y)
if (s.nflags >= 0 && s.dots)
out_mus(x + 8 * sc, y + 13 * sc, dot)
if (s.grace) {
out_svg('</g>\n')
abc.stv_g().g--
}
} // draw_note()
// -- draw_symbols --
for (s = p_voice.sym; s; s = s.next) {
if (s.invis)
continue
switch (s.type) {
case C.METER:
abc.draw_meter(s)
break
case C.NOTE:
case C.REST:
draw_note(s)
break
case C.GRACE:
for (g = s.extra; g; g = g.next)
draw_note(g)
break
}
}
// draw the (pseudo) beams
for (s = p_voice.sym; s; s = s.next) {
if (s.invis)
continue
switch (s.type) {
case C.NOTE:
case C.REST:
nl = s.nflags
if (nl <= 0)
continue
y = staff_tb[s.st].y
s2 = s
while (s.next && s.next.nflags > 0) {
s = s.next
if (s.nflags > nl)
nl = s.nflags
if (s.beam_end)
break
}
if (s.dy)
y += s.dy
draw_dur(s2, s2.x, y, s, 1, nl)
break
}
}
}, // draw_symbols()
// set some parameters
set_fmt: function(of, cmd, param) {
if (cmd == "jianpu") {
this.set_v_param("jianpu", param)
return
}
of(cmd, param)
}, // set_fmt()
// adjust some values
set_pitch: function(of, last_s) {
of(last_s)
if (!last_s)
return // first time
var C = abc2svg.C
for (var s = this.get_tsfirst(); s; s = s.ts_next) {
if (!s.p_v.jianpu)
continue
switch (s.type) {
// draw the key signature only in the first voice
// and not at start of the staff
case C.KEY:
if (s.prev.type == C.CLEF
|| s.v != 0)
s.a_gch = null
break
// adjust the vertical spacing above the note heads
case C.NOTE:
s.ymx = 20 * s.nhd + 22
if (s.notes[s.nhd].jo > 2) {
s.ymx += 3
if (s.notes[s.nhd].jo > 3)
s.ymx += 2
}
s.ymn = 0 // bottom of line
break
}
}
}, // set_pitch()
set_vp: function(of, a) {
var i,
p_v = this.get_curvoice()
for (i = 0; i < a.length; i++) {
if (a[i] == "jianpu=") {
p_v.jianpu = this.get_bool(a[++i])
if (p_v.jianpu)
this.set_vp([
"staffsep=", "20",
"sysstaffsep=", "14",
"stafflines=", "...",
"tuplets=", "0 1 0 1"
// [auto, slur, number, above]
])
break
}
}
of(a)
}, // set_vp()
// set the width of some symbols
set_width: function(of, s) {
of(s)
if (!s.p_v // (if voice_tb[v].clef/key/meter)
|| !s.p_v.jianpu)
return
var w, m, note,
C = abc2svg.C
switch (s.type) {
case C.CLEF:
case C.KEY:
// case C.METER:
s.wl = s.wr = .1 // (must not be null)
break
case C.NOTE:
for (m = 0; m <= s.nhd; m++) {
note = s.notes[m]
if (note.acc && s.wl < 14) // room for the accidental
s.wl = 14
}
break
}
}, // set_width()
set_hooks: function(abc) {
abc.calculate_beam = abc2svg.jianpu.calc_beam.bind(abc, abc.calculate_beam)
abc.draw_symbols = abc2svg.jianpu.draw_symbols.bind(abc, abc.draw_symbols)
abc.output_music = abc2svg.jianpu.output_music.bind(abc, abc.output_music)
abc.set_format = abc2svg.jianpu.set_fmt.bind(abc, abc.set_format)
abc.set_pitch = abc2svg.jianpu.set_pitch.bind(abc, abc.set_pitch)
abc.set_vp = abc2svg.jianpu.set_vp.bind(abc, abc.set_vp)
abc.set_width = abc2svg.jianpu.set_width.bind(abc, abc.set_width)
// big staccato dot
abc.get_glyphs().gstc = '<circle id="gstc" cx="0" cy="-3" r="2"/>'
abc.get_decos().gstc = "0 gstc 5 1 1"
abc.add_style("\n.fj{font:15px sans-serif}")
|
| ︙ | ︙ |
Changes to modules/mdnn.js.
1 2 3 | // mdnn.js - module to output Modernised Diatonic Numerical Notation // (https://medium.com/@info_70544/the-case-for-numerical-music-notation-part-1-introduction-and-history-5f1543ca8a95) // | | | 1 2 3 4 5 6 7 8 9 10 11 | // mdnn.js - module to output Modernised Diatonic Numerical Notation // (https://medium.com/@info_70544/the-case-for-numerical-music-notation-part-1-introduction-and-history-5f1543ca8a95) // // Copyright (C) 2020-2023 Jean-Francois Moine // // This file is part of abc2svg. // // abc2svg is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
116 117 118 119 120 121 122 |
prev_oct = -10
if (!cfmt.mdnn) {
of()
return
}
| | | | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
prev_oct = -10
if (!cfmt.mdnn) {
of()
return
}
delete voice_tb[0].key.k_a_acc // no accidental
voice_tb[0].clef.invis = true // no (visible) clef
cur_sy.staves[0].stafflines = "..." // empty staff
// scan the first voice of the tune
for (s = voice_tb[0].sym; s; s = s.next) {
switch (s.type) {
case C.CLEF:
s.invis = true
continue
case C.KEY:
//fixme:nsk
// delete s.k_a_acc // don't display the accidentals
sf = s.k_sf
delta = abc2svg.mdnn.cgd2cde[sf + 7] - 2
nn = sf - s.k_old_sf // delta accidentals
//fixme:nsk
// if (!nn) {
// s.k_old_sf = s.k_sf = 0 // don't display the accidentals
// continue
|
| ︙ | ︙ | |||
265 266 267 268 269 270 271 |
return
var C = abc2svg.C,
s = this.get_tsfirst()
if (s && s.next && s.next.type == C.KEY)
//fixme:nsk
| | | 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
return
var C = abc2svg.C,
s = this.get_tsfirst()
if (s && s.next && s.next.type == C.KEY)
//fixme:nsk
delete s.next.k_a_acc
// s.next.a_gch = null
}, // set_pitch()
set_hooks: function(abc) {
abc.output_music = abc2svg.mdnn.output_music.bind(abc, abc.output_music)
abc.set_format = abc2svg.mdnn.set_fmt.bind(abc, abc.set_format)
abc.set_pitch = abc2svg.mdnn.set_pitch.bind(abc, abc.set_pitch)
|
| ︙ | ︙ |
Changes to modules/nns.js.
| ︙ | ︙ | |||
109 110 111 112 113 114 115 |
} // get_l()
function build_cell(c) {
var i, j, k,
u = '',
t = ''
| | | | 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
} // get_l()
function build_cell(c) {
var i, j, k,
u = '',
t = ''
row += ' '
if (c.length == 1) {
row += c[0] // one chord in the measure
return
}
i = 0
while (i < 4) {
t += c[i]
k = get_l(c[i])
j = k
while (--j >= 0)
u += ' '
if (i < 3 && !c[i + 1]) {
while (i < 3 && !c[i + 1])
i++
i++
if (i < 4 && c[i])
t += ' '
} else {
|
| ︙ | ︙ |
Changes to modules/page.js.
1 2 | // page.js - module to generate pages // | | | 1 2 3 4 5 6 7 8 9 10 | // page.js - module to generate pages // // Copyright (C) 2018-2022 Jean-Francois Moine // // This file is part of abc2svg. // // abc2svg is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
20 21 22 23 24 25 26 |
// This module is loaded when "%%pageheight" appears in a ABC source.
//
// Parameters
// %%pageheight <unit>
abc2svg.page = {
| < < < < < < < < < < < < < | > | | | < | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
// This module is loaded when "%%pageheight" appears in a ABC source.
//
// Parameters
// %%pageheight <unit>
abc2svg.page = {
// function called at end of generation
abc_end: function(of) {
var page = this.page
if (page && page.in_page)
abc2svg.page.close_page(page)
if (abc2svg.page.user_out) {
user.img_out = abc2svg.page.user_out
abc2svg.page.user_out = null
}
of()
}, // abc_end()
// generate a header or a footer in page.hf and return its height
gen_hf: function(page, ty) {
var a, i, j, k, x, y, y0, s, str,
font = page.abc.get_font(ty),
cfmt = page.abc.cfmt(),
fh = font.size * 1.1,
pos = [ '">',
'" text-anchor="middle">',
'" text-anchor="end">' ]
// replace <>& by XML character references
|
| ︙ | ︙ | |||
185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
function font_class(font) {
if (font.class)
return 'f' + font.fid + cfmt.fullsvg + ' ' + font.class
return 'f' + font.fid + cfmt.fullsvg
}
// gen_hf
if (str[0] == '-') { // not on 1st page
if (page.pn == 1)
return 0
str = str.slice(1)
}
| > > > > > | 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
function font_class(font) {
if (font.class)
return 'f' + font.fid + cfmt.fullsvg + ' ' + font.class
return 'f' + font.fid + cfmt.fullsvg
}
// gen_hf
if (!(page.pn & 1))
str = page[ty + '2'] || page[ty]
else
str = page[ty]
if (str[0] == '-') { // not on 1st page
if (page.pn == 1)
return 0
str = str.slice(1)
}
|
| ︙ | ︙ | |||
247 248 249 250 251 252 253 | if (page.first) page.first = false else sty += ";page-break-before:always" if (page.gutter) sty += ";margin-left:" + ((page.pn & 1) ? page.gutter : -page.gutter).toFixed(1) + "px" | | | | | 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 |
if (page.first)
page.first = false
else
sty += ";page-break-before:always"
if (page.gutter)
sty += ";margin-left:" +
((page.pn & 1) ? page.gutter : -page.gutter).toFixed(1) + "px"
abc2svg.page.user_out(sty + '">')
page.in_page = true
ht += page.topmargin
page.hmax = cfmt.pageheight - page.botmargin - ht
// define the header/footer
page.hf = ''
if (page.header) {
l = abc.get_font_style().length
h = abc2svg.page.gen_hf(page, "header")
sty = abc.get_font_style().slice(l) // new style(s)
if (cfmt.fullsvg || sty != page.hsty) {
page.hsty = sty
sty = '<style>' + sty + '\n</style>\n'
} else {
sty = ''
}
abc2svg.page.user_out(
'<svg xmlns="http://www.w3.org/2000/svg" version="1.1"\n\
xmlns:xlink="http://www.w3.org/1999/xlink"\n\
width="' + cfmt.pagewidth.toFixed(0) +
'px" height="' + (ht + h).toFixed(0) +
'px">\n' + sty +
'<g transform="translate(0,' +
page.topmargin.toFixed(1) + ')">' +
page.hf + '</g>\n</svg>')
page.hmax -= h;
page.hf = ''
} else {
abc2svg.page.user_out(
'<svg xmlns="http://www.w3.org/2000/svg" version="1.1"\n\
xmlns:xlink="http://www.w3.org/1999/xlink"\n\
width="' + cfmt.pagewidth.toFixed(0) +
'px" height="' + ht.toFixed(0) +
'px">\n</svg>')
}
if (page.footer) {
|
| ︙ | ︙ | |||
307 308 309 310 311 312 313 |
close_page: function(page) {
var h,
cfmt = page.abc.cfmt()
page.in_page = false
if (page.footer) {
h = page.hmax + page.fh - page.h
| | | | | 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 |
close_page: function(page) {
var h,
cfmt = page.abc.cfmt()
page.in_page = false
if (page.footer) {
h = page.hmax + page.fh - page.h
abc2svg.page.user_out(
'<svg xmlns="http://www.w3.org/2000/svg" version="1.1"\n\
xmlns:xlink="http://www.w3.org/1999/xlink"\n\
width="' + cfmt.pagewidth.toFixed(0) +
'px" height="' + h.toFixed(0) +
'px">\n' + page.ffsty +
'<g transform="translate(0,' +
(h - page.fh).toFixed(1) + ')">' +
page.hf + '</g>\n</svg>')
}
abc2svg.page.user_out('</div>')
page.h = 0
}, // close_page()
// handle the output flow of the abc2svg generator
img_in: function(p) {
var h, ht, nh,
page = this.page
// copy a block
function blkcpy(page) {
while (page.blk.length)
abc2svg.page.user_out(page.blk.shift())
page.blk = null // direct output
} // blkcpy()
// img_in()
switch (p.slice(0, 4)) {
case "<div": // block of new tune
if (p.indexOf('newpage') > 0
|
| ︙ | ︙ | |||
376 377 378 379 380 381 382 | break // error } // if no overflow yet, keep the block if (page.blk) page.blk.push(p) else | | | 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 | break // error } // if no overflow yet, keep the block if (page.blk) page.blk.push(p) else abc2svg.page.user_out(p) page.h += h break case "</di": // end of block if (page.blk) blkcpy(page) break // default: |
| ︙ | ︙ | |||
401 402 403 404 405 406 407 408 409 410 |
if (cmd == "pageheight") {
v = this.get_unit(parm)
if (isNaN(v)) {
this.syntax(1, this.errs.bad_val, '%%' + cmd)
return
}
cfmt.pageheight = v
// if first definition, install the hook
| > > > > | | < > > > > > > > > | 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 |
if (cmd == "pageheight") {
v = this.get_unit(parm)
if (isNaN(v)) {
this.syntax(1, this.errs.bad_val, '%%' + cmd)
return
}
if (!user.img_out || !abc2svg.abc_end)
v = 0
cfmt.pageheight = v
if (!v)
return
// if first definition, install the hook
if (!page || !abc2svg.page.user_out) {
this.page = page = {
abc: this,
topmargin: 38, // 1cm
botmargin: 38, // 1cm
// gutter: 0,
h: 0, // current page height
pn: 0, // page number
pna: 0, // absolute page number
first: true // no skip to next page
}
// don't let the backend handle the header/footer
if (cfmt.header) {
page.header = cfmt.header;
cfmt.header = null
}
if (cfmt.footer) {
page.footer = cfmt.footer;
cfmt.footer = null
}
if (cfmt.header2) {
page.header2 = cfmt.header2
cfmt.header2 = null
}
if (cfmt.footer2) {
page.footer2 = cfmt.footer2
cfmt.footer2 = null
}
// get the previously defined page parameters
if (cfmt.botmargin != undefined) {
v = this.get_unit(cfmt.botmargin)
if (!isNaN(v))
page.botmargin = v
}
|
| ︙ | ︙ | |||
449 450 451 452 453 454 455 456 | } if (cfmt.oneperpage) page.oneperpage = this.get_bool(cfmt.oneperpage) if (!cfmt.dateformat) cfmt.dateformat = "%b %e, %Y %H:%M" // set the hooks user.img_out = abc2svg.page.img_in.bind(this); | > > < > > | 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 |
}
if (cfmt.oneperpage)
page.oneperpage = this.get_bool(cfmt.oneperpage)
if (!cfmt.dateformat)
cfmt.dateformat = "%b %e, %Y %H:%M"
// set the hooks
if (!abc2svg.page.user_out)
abc2svg.page.user_out = user.img_out
user.img_out = abc2svg.page.img_in.bind(this);
abc2svg.abc_end = abc2svg.page.abc_end.bind(this,
abc2svg.abc_end)
}
return
}
if (page) {
switch (cmd) {
case "header":
case "footer":
case "header2":
case "footer2":
page[cmd] = parm
return
case "newpage":
if (!parm)
break
v = Number(parm)
if (isNaN(v)) {
|
| ︙ | ︙ |
Changes to modules/pedline.js.
1 2 | // pedline.js - module to draw pedal lines instead of 'Ped .. *' // | | | 1 2 3 4 5 6 7 8 9 10 | // pedline.js - module to draw pedal lines instead of 'Ped .. *' // // Copyright (C) 2020-2022 Jean-Francois Moine // // This file is part of abc2svg. // // abc2svg is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
41 42 43 44 45 46 47 | // \ de.prev // \ de.prev.start // |_____/\____| de.defl.nost = true de.prev.defl.noen = true de.x = de.prev.s.x - 5 de.val = de.s.x - de.x - 5 | < | | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
// \ de.prev
// \ de.prev.start
// |_____/\____|
de.defl.nost = true
de.prev.defl.noen = true
de.x = de.prev.s.x - 5
de.val = de.s.x - de.x - 5
de.prev.val = de.x - de.prev.x
} else {
de.x -= 3
de.val += 10
}
}
}
of()
|
| ︙ | ︙ |
Changes to modules/perc.js.
1 2 | // perc.js - module to handle %%percmap // | | | 1 2 3 4 5 6 7 8 9 10 | // perc.js - module to handle %%percmap // // Copyright (C) 2018-2023 Jean-Francois Moine // // This file is part of abc2svg. // // abc2svg is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
205 206 207 208 209 210 211 |
" print=" + p +
(a[3] ? (" heads=" + a[3]) : ''))
this.set_v_param("perc", "MIDIdrum")
}, // do_perc()
// set the MIDI parameters in the current voice
set_perc: function(a) {
| | | | | | 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
" print=" + p +
(a[3] ? (" heads=" + a[3]) : ''))
this.set_v_param("perc", "MIDIdrum")
}, // do_perc()
// set the MIDI parameters in the current voice
set_perc: function(a) {
var i, item, s,
curvoice = this.get_curvoice()
for (i = 0; i < a.length; i++) {
switch (a[i]) {
case "perc=": // %%percmap
if (!curvoice.map)
curvoice.map = {}
curvoice.map = a[i + 1];
s = this.new_block("midiprog")
s.play = s.invis = 1 //true
curvoice.chn = s.chn = 9 // channel 10
break
}
}
}, // set_perc()
do_pscom: function(of, text) {
if (text.slice(0, 8) == "percmap ")
|
| ︙ | ︙ |
Changes to modules/psvg.js.
| ︙ | ︙ | |||
469 470 471 472 473 474 475 |
} else if (g != 2) {
if (!g)
defg1()
svgbuf += '<text x="' + (x + gcur.xoffs).toFixed(1) + '" y="' +
(gcur.yoffs - y).toFixed(1) + '">';
g = 2
}
| | < | 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 |
} else if (g != 2) {
if (!g)
defg1()
svgbuf += '<text x="' + (x + gcur.xoffs).toFixed(1) + '" y="' +
(gcur.yoffs - y).toFixed(1) + '">';
g = 2
}
svgbuf += s.replace(/<|>|&/g, function(c){
switch (c) {
case '<': return "<"
case '>': return ">"
case '&': return "&"
}
})
if (span)
svgbuf += "</tspan>";
gcur.cx = x + strw(s)
}
|
| ︙ | ︙ |
Changes to modules/sth.js.
| ︙ | ︙ | |||
30 31 32 33 34 35 36 |
// function called after beam calculation
recal_beam: function(bm, s) {
var staff_tb = this.get_staff_tb(),
y = staff_tb[s.st].y,
s2 = bm.s2,
y2 = staff_tb[s2.st].y
| | | | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
// function called after beam calculation
recal_beam: function(bm, s) {
var staff_tb = this.get_staff_tb(),
y = staff_tb[s.st].y,
s2 = bm.s2,
y2 = staff_tb[s2.st].y
if (s.sth != undefined)
s.ys = s.sth
if (s2.sth != undefined)
s2.ys = s2.sth;
bm.a = (s.ys + y - s2.ys - y2) / (s.xs - s2.xs);
bm.b = s.ys - s.xs * bm.a + y
while (1) {
s.ys = bm.a * s.xs + bm.b - y
if (s.stem > 0)
s.ymx = s.ys + 2.5
|
| ︙ | ︙ |
Changes to modules/strtab.js.
| ︙ | ︙ | |||
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
// Syntax:
// %%strtab <string list> [diafret]
// <string list> is the list of the strings as ABC notes
// diafret indicates the instrument has diatonic frets
// The fret may be forced by a decoration format
// "!" digit "s!"
// where 'digit' is the string range in the string list (last string is '1')
//
// This module accepts Willem Vree's tablature syntax:
// https://wim.vree.org/svgParse/abc2xml.html#tab
abc2svg.strtab = {
// draw the tablature
draw_symbols: function(of, p_v) {
| > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < < < < < | > > | > | | < | < < | < < < | < > | > > > > > > > > > > > > > > > > > > > > > > > < < < < < < < < < < < < < < | | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
// Syntax:
// %%strtab <string list> [diafret]
// <string list> is the list of the strings as ABC notes
// diafret indicates the instrument has diatonic frets
// The fret may be forced by a decoration format
// "!" digit "s!"
// where 'digit' is the string range in the string list (last string is '1')
//
// The command %%minfret permits to force upper frets.
// Syntax:
// %%minfret [ <string number> : <fret number> ]*
// Each command replaces the previous value.
//
// This module accepts Willem Vree's tablature syntax:
// https://wim.vree.org/svgParse/abc2xml.html#tab
abc2svg.strtab = {
// draw the tablature
draw_symbols: function(of, p_v) {
var s, m, not, stb, x, y, g,
C = abc2svg.C,
abc = this
// draw the note heads
function draw_heads(stb, s) {
var m, not, x, y
for (m = 0; m <= s.nhd; m++) {
not = s.notes[m]
if (not.nb < 0)
continue
x = s.x - 3
if (not.nb >= 10)
x -= 3
y = 3 * (not.pit - 18)
abc.out_svg('<text class="bg' + abc.bgn +
'" x="')
abc.out_sxsy(x, '" y="', stb + y - 2.5)
abc.out_svg('">' + not.nb + '</text>\n')
}
} // draw_heads()
// draw the stems, flags and beams
function draw_stems(stb, s) {
if (!s.tabst)
return // don't draw any stem
var s1, s2, nfl, l,
y = stb + 3 * (s.notes[0].pit - 19) // -18) - 3
* s.p_v.staffscale,
h = (11 + 3 * (s.notes[0].pit - 18)) * s.p_v.staffscale
abc.out_svg('<path class="sW" d="M')
abc.out_sxsy(s.x, ' ', y)
abc.out_svg('v' + h.toFixed(1) +'"/>\n')
// draw the flag(s)
if (s.nflags <= 0
|| !s.beam_end) // inside beam
return
y -= h
if (s.beam_st) { // no beam
abc.out_svg('<text class="f'
+ abc.get_font('music').fid
+ '" transform="translate(')
abc.out_sxsy(s.x, ',', y)
abc.out_svg(') scale('
+ (s.grace ? '.5,.5' : '.7,.7') + ')">'
+ String.fromCharCode(0xe23f + 2 * s.nflags)
+ '</text>\n')
return
}
// draw the beam(s)
s2 = s
nfl = s.nflags
while (1) {
if (s.nflags > nfl)
nfl = s.nflags
if (s.beam_st)
break
s = s.prev
}
s1 = s
l = (s2.x - s1.x).toFixed(1)
abc.out_svg('<path d="M')
abc.out_sxsy(s1.x, ' ', y)
abc.out_svg('h' + l
+ 'v-3h-' + l
+ 'v3"/>\n')
if (nfl == 1)
return
//fixme: do more levels
y += 5
while (1) {
while (s.nflags < 2) {
s = s.next
if (s == s2)
break
}
if (s == s2)
break
s1 = s
while (s.next.nflags >= 2) {
s = s.next
if (s == s2)
break
}
l = (s.x - s1.x).toFixed(1)
abc.out_svg('<path d="M')
abc.out_sxsy(s1.x, ' ', y)
abc.out_svg('h' + l
+ 'v-3h-' + l
+ 'v3"/>\n')
if (s == s2)
break
s = s.next
if (s == s2)
break
}
} // draw_stems()
if (!p_v.tab) {
of(p_v)
return
}
// define the 'bgx' filter if not done yet
m = abc.cfmt().bgcolor || "white"
if (abc.bgt != m) {
if (!abc.bgn)
abc.bgn = 1
else
abc.bgn++
abc.bgt = m
abc.defs_add('\
<filter x="-0.1" y="0.1" width="1.2" height=".8" id="bg' + abc.bgn + '">\n\
<feFlood flood-color="' + m + '"/>\n\
<feComposite in="SourceGraphic" operator="over"/>\n\
</filter>')
abc.add_style('\n.bg' + abc.bgn + '{filter:url(#bg' + abc.bgn + ')}')
}
// adjust the symbol before generation
for (s = p_v.sym; s; s = s.next) {
switch (s.type) {
case C.KEY:
case C.METER:
case C.REST:
s.invis = true
break
}
}
of(p_v)
abc.glout() // output the stems
stb = abc.get_staff_tb()[p_v.st].y
// draw the stems and beams
abc.set_sscale(-1) // no scale
for (s = p_v.sym; s; s = s.next) {
switch (s.type) {
case C.GRACE:
for (g = s.extra; g; g = g.next)
draw_stems(stb, g)
break
case C.NOTE:
draw_stems(stb, s)
break
}
}
// draw the note heads
abc.set_scale(p_v.sym) // (for draw_all_ties)
abc.out_svg('<g class="bn">\n')
for (s = p_v.sym; s; s = s.next) {
switch (s.type) {
case C.GRACE:
for (g = s.extra; g; g = g.next)
draw_heads(stb, g)
break
case C.NOTE:
draw_heads(stb, s)
break
}
}
abc.out_svg('</g>\n')
}, // draw_symbols()
// set a format parameter
set_fmt: function(of, cmd, parm) {
if (cmd == "strtab") {
if (!parm)
return
var p_v = this.get_curvoice()
if (!p_v) {
this.parse.tab = parm
return
}
this.set_v_param("clef", "tab")
if (parm.indexOf("diafret") >= 0) {
this.set_v_param("diafret", true)
parm = parm.replace(/\s*diafret\s*/, "")
}
this.set_v_param("strings", parm)
return
}
if (cmd == "minfret") {
this.set_v_param("minfret", parm)
return
}
of(cmd, parm)
}, // set_fmt()
// change the notes when the global generation settings are done
set_stems: function(of) {
var p_v, i, m, nt, n, bi, bn, strss, g,
C = abc2svg.C,
abc = this,
s = abc.get_tsfirst(), // first symbol
strs = [], // notes per staff - index = staff
lstr = [] // lowest string per staff - index staff
// set a string (pitch) and a fret number
|
| ︙ | ︙ | |||
150 151 152 153 154 155 156 |
nt.pit = i * 2 + 18
} else {
nt.nb = -1
nt.pit = 18
}
nt.acc = 0
nt.invis = true
| > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < < | < | < < | < < | | | < | < < < | < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < | < | < < < < < < | | < < < | | 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 |
nt.pit = i * 2 + 18
} else {
nt.nb = -1
nt.pit = 18
}
nt.acc = 0
nt.invis = true
if (!s.grace)
strss[i] = s.time + s.dur
if (s.dur <= C.BLEN / 2 && !s.stemless) {
if (!lstr[st])
lstr[st] = [ 10 ]
if (lstr[st][0] > i) {
lstr[st][0] = i
lstr[st][1] = s
}
s.stemless = true
}
} // set_pit()
function set_notes(p_v, s) {
var i, bi, bn, nt, m, n, ns
s.stem = -1 // down stems
// handle the fret numbers as chord decoration
if (!s.nhd && s.a_dd) {
i = s.a_dd.length
while (--i >= 0) {
bi = strnum(s.a_dd[i].name)
if (bi >= 0) {
nt = s.notes[0]
set_pit(p_v, s, nt, bi)
break
}
}
}
delete s.a_dd
if (s.sls) { // set the slurs above the staff
for (i = 0; i < s.sls.length; i++) {
s.sls[i].ty &= ~0x07
s.sls[i].ty |= C.SL_ABOVE
}
}
ls: for (m = 0; m <= s.nhd; m++) {
nt = s.notes[m]
if (nt.sls) { // if start of slur
for (i = 0; i < nt.sls.length; i++) {
nt.sls[i].ty &= ~0x07
nt.sls[i].ty |= C.SL_ABOVE
}
}
if (nt.nb != undefined)
continue
if (nt.a_dd) {
i = nt.a_dd.length
while (--i >= 0) {
bi = strnum(nt.a_dd[i].name)
if (bi >= 0) {
set_pit(p_v, s, nt, bi)
delete nt.a_dd
continue ls
}
}
delete nt.a_dd
}
// search the best string
bn = 100
bi = -1
ns = i = p_v.tab.length
while (--i >= 0) {
if (strss[i] && strss[i] > s.time)
continue
n = (p_v.diafret ?
nt.pit : nt.midi) -
p_v.tab[i]
if (n >= 0 && n < bn
&& (!p_v.minfret
|| !p_v.minfret[ns - i]
|| n >= p_v.minfret[ns - i])) {
bi = i
bn = n
}
}
set_pit(p_v, s, nt, bi)
}
s.y = 3 * (nt.pit - 18)
s.ymn = 0 // don't get space below the tablature
} // set_notes()
// get the string number from the decoration
// format is either !<n>s! or !<n>!
function strnum(n) {
n = n.match(/^([1-9])s?$/)
return n ? p_v.tab.length - n[1] : -1
} // strnum()
// change the notes of the strings when a capo
p_v = abc.get_voice_tb()
for (n = 0; n < p_v.length; n++) {
if (!p_v[n].tab)
continue
m = p_v[n].capo
if (m) {
for (i = 0; i < p_v[n].tab.length; i++)
p_v[n].tab[i] += m
}
}
of() // do the normal work
// loop on the notes of the voices with a tablature
for ( ; s; s = s.ts_next) {
// let a stem on the lowest string
if (s.seqst || (s.ts_prev && s.ts_prev.type == C.GRACE)) {
for (i = 0; i < lstr.length; i++) {
if (lstr[i]) {
lstr[i][1].tabst = 1
lstr[i] = null
}
}
}
p_v = s.p_v
if (!p_v.tab)
continue
strss = strs[s.st]
if (!strss)
strss = strs[s.st] = []
switch (s.type) {
case C.KEY:
case C.REST:
case C.TIME:
s.invis = true
default:
delete s.a_dd
continue
case C.GRACE:
if (p_v.pos.gst == C.SL_HIDDEN)
s.sappo = 0
for (g = s.extra; g; g = g.next) {
if (p_v.pos.gst == C.SL_HIDDEN)
g.stemless = true
set_notes(p_v, g)
}
break
case C.NOTE:
set_notes(p_v, s)
break
}
}
}, // set_stems()
// get the parameters of the current voice
set_vp: function(of, a) {
var i, e, g, tab, strs, ok,
p_v = this.get_curvoice()
// convert a list of ABC notes into a list of MIDI pitches
function abc2tab(p) {
var i, c, a,
t = []
if (p_v.diafret) {
for (i = 0; i < p.length; i++) {
c = p[i]
c = "CDEFGABcdefgab".indexOf(c)
if (c < 0)
|
| ︙ | ︙ | |||
297 298 299 300 301 302 303 304 305 306 |
}
}
t.push(c)
}
} else {
for (i = 0; i < p.length; i++) {
c = p[i]
c = "CCDDEFFGGAABccddeffggaab".indexOf(c)
if (c < 0)
return // null
| > > > > > > > > > > | | 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 |
}
}
t.push(c)
}
} else {
for (i = 0; i < p.length; i++) {
c = p[i]
switch (c) {
case '^':
case '_':
a = c == '^' ? 1 : -1
c = p[++i]
break
default:
a = 0
break
}
c = "CCDDEFFGGAABccddeffggaab".indexOf(c)
if (c < 0)
return // null
c += 60 + a
while (1) {
if (p[i + 1] == "'") {
c += 12
i++
} else if (p[i + 1] == ",") {
c -= 12
i++
|
| ︙ | ︙ | |||
340 341 342 343 344 345 346 |
}
} else {
while (1) {
str = a.shift()
if (!str)
break
p = "CCDDEFFGGAAB".indexOf(str[0])
| > > > > > > > > > > | > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 |
}
} else {
while (1) {
str = a.shift()
if (!str)
break
p = "CCDDEFFGGAAB".indexOf(str[0])
if (p < 0)
return // undefined
o = str[1]
switch (o) {
case '#':
case 'b':
p += o == '#' ? 1 : -1
o = Number(str[2])
break
default:
o = Number(str[1])
break
}
if (isNaN(o))
return // undefined
t.push((o + 1) * 12 + p) // C4 = 60
}
}
return t
} // str2tab()
// convert the list of <string number> ':' <fret number>
function minfret(a) {
var sf,
sfa = a.split(' ')
p_v.minfret = {}
while (1) {
sf = sfa.shift()
if (!sf)
break
sf = sf.split(':')
if (sf.length != 2)
break //fixme: error
p_v.minfret[sf[0]] = sf[1]
}
} //minfret()
for (i = 0; i < a.length; i++) {
switch (a[i]) {
case "clef=":
e = a[i + 1]
if (e != "tab")
break
a.splice(i, 1)
// fall thru
case "tab":
a.splice(i, 1)
i--
ok = true
break
case "strings=":
strs = a[++i]
ok = true
break
case "nostems":
p_v.pos.stm = abc2svg.C.SL_HIDDEN
p_v.pos.gst = abc2svg.C.SL_HIDDEN
break
case "capo=":
p_v.capo = Number(a[++i])
break
case "diafret=":
i++
case "diafret":
p_v.diafret = true
break
case "minfret=":
minfret(a[++i])
break
}
}
// define the elements of the tablature
if (ok) {
if (!strs && this.parse.tab) { // if a global definition
strs = this.parse.tab
if (strs.indexOf("diafret") >= 0) {
p_v.diafret = true
strs = strs.replace(/\s*diafret\s*/, "")
}
}
if (strs) {
e = strs.slice(-1)
if (e >= '1' && e <= '9')
tab = str2tab(strs.split(',')) // W.V.'s syntax
else
tab = abc2tab(strs) // ABC syntax
if (!tab) {
this.syntax(1, "Bad strings in tablature")
ok = false
}
|
| ︙ | ︙ | |||
415 416 417 418 419 420 421 |
a.push("clef=") // set the clef
g = this.get_glyphs()
if (tab.length == 3) {
a.push('"tab3"')
if (!g.tab3)
// SMuFL: -none-
g.tab3 = '<text id="tab3"\
| | | | 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 |
a.push("clef=") // set the clef
g = this.get_glyphs()
if (tab.length == 3) {
a.push('"tab3"')
if (!g.tab3)
// SMuFL: -none-
g.tab3 = '<text id="tab3"\
x="-2,-2,-2" y="-4,3,10"\
style="font:bold 8px sans-serif">TAB</text>'
} else if (tab.length == 4) {
a.push('"tab4"')
if (!g.tab4)
// SMuFL: \ue06e
g.tab4 = '<text id="tab4"\
x="-3,-3,-3" y="-8,1,10"\
style="font:bold 12px sans-serif">TAB</text>'
} else if (tab.length == 5) {
a.push('"tab5"')
if (!g.tab5)
// SMuFL: -none-
g.tab5 = '<text id="tab5"\
x="-4,-4,-4" y="-11,-2,7"\
|
| ︙ | ︙ | |||
452 453 454 455 456 457 458 |
of(a)
}, // set_vp()
set_hooks: function(abc) {
abc.draw_symbols = abc2svg.strtab.draw_symbols.bind(abc, abc.draw_symbols)
abc.set_format = abc2svg.strtab.set_fmt.bind(abc, abc.set_format);
abc.set_stems = abc2svg.strtab.set_stems.bind(abc, abc.set_stems)
| < | | 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 |
of(a)
}, // set_vp()
set_hooks: function(abc) {
abc.draw_symbols = abc2svg.strtab.draw_symbols.bind(abc, abc.draw_symbols)
abc.set_format = abc2svg.strtab.set_fmt.bind(abc, abc.set_format);
abc.set_stems = abc2svg.strtab.set_stems.bind(abc, abc.set_stems)
abc.set_vp = abc2svg.strtab.set_vp.bind(abc, abc.set_vp)
// define specific decorations used to force the string number
var decos = abc.get_decos()
decos["1s"] = "0 nul 0 0 0"
decos["2s"] = "0 nul 0 0 0"
decos["3s"] = "0 nul 0 0 0"
decos["4s"] = "0 nul 0 0 0"
decos["5s"] = "0 nul 0 0 0"
decos["6s"] = "0 nul 0 0 0"
if (!user.nul)
user.nul = function() {}
abc.add_style("\n.bn{font:bold 7px sans-serif}")
} // set_hooks()
} // strtab
abc2svg.modules.hooks.push(abc2svg.strtab.set_hooks)
abc2svg.modules.strtab.loaded = true
|
Added modules/tropt.js.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
// tropt.js - module to optimize the notes after transposition
//
// Copyright (C) 2022 Jean-Francois Moine
//
// This file is part of abc2svg.
//
// abc2svg is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// abc2svg is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with abc2svg. If not, see <http://www.gnu.org/licenses/>.
//
// This module is loaded when "%%tropt" appears in a ABC source.
abc2svg.tropt = {
// function called before start of the generation
set_pitch: function(of, last_s) {
if (last_s) { // if not first time
of(last_s)
return
}
var v, p_v, s, m, nt, p, a, np, na,
C = abc2svg.C,
vo_tb = this.get_voice_tb(),
nv = vo_tb.length
// check if some next note has the same pitch without any accidental
function ok(s, p) {
var nt, m
while (s) {
if (s.bar_type)
return 1 //true
if (s.type == C.NOTE) {
for (m = 0; m <= s.nhd; m++) {
nt = s.notes[m]
if (nt.pit == p)
return nt.acc
}
}
s = s.next
}
return 1 //true
} // ok()
for (v = 0; v < nv; v++) {
p_v = vo_tb[v]
if (!p_v.tropt || !p_v.key.k_none)
continue
for (s = p_v.sym; s; s = s.next) {
if (s.type != C.NOTE)
continue
for (m = 0; m <= s.nhd; m++) {
nt = s.notes[m]
if (nt.tie_s) { // if end of tie
nt.pit = nt.tie_s.pit
continue
}
p = nt.pit % 7 // A..G
a = nt.acc
na = 3
switch (a) {
case -1:
switch (p) {
case 2: // C
case 5: // F
break
default:
continue
}
np = nt.pit - 1
break
case -2:
switch (p) {
case 2: // C
case 5: // F
na = -1
break
}
np = nt.pit - 1
break
case 1:
switch (p) {
case 1: // B
case 4: // E
break
default:
continue
}
np = nt.pit + 1
break
case 2:
switch (p) {
case 1: // B
case 4: // E
na = 1
break
}
np = nt.pit + 1
break
default:
continue
}
if (ok(s, np)) {
nt.pit = np
nt.acc = na
}
}
}
}
of(last_s)
}, // set_pitch()
// set the tropt parameter
do_pscom: function(of, text) {
if (text.indexOf("tropt ") == 0)
this.set_v_param("tropt", text.split(/[ \t]/)[1])
else
of(text)
}, // do_pscom()
// set the tropt parameter in the current voice
set_vp: function(of, a) {
var i,
curvoice = this.get_curvoice()
for (i = 0; i < a.length; i++) {
if (a[i] == "tropt=") {
curvoice.tropt = this.get_bool(a[i + 1])
break
}
}
of(a)
}, // set_vp()
set_hooks: function(abc) {
abc.do_pscom = abc2svg.tropt.do_pscom.bind(abc, abc.do_pscom)
abc.set_pitch = abc2svg.tropt.set_pitch.bind(abc, abc.set_pitch)
abc.set_vp = abc2svg.tropt.set_vp.bind(abc, abc.set_vp)
}
} // tropt
abc2svg.modules.hooks.push(abc2svg.tropt.set_hooks)
// the module is loaded
abc2svg.modules.tropt.loaded = 1 //true
|
Changes to package.json.
1 2 |
{
"name": "abc2svg",
| | > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
{
"name": "abc2svg",
"version": "1.22.1",
"description": "ABC music notation translator",
"files": [
"COPYING",
"COPYING.LESSER",
"MIDI-1.js",
"Scc1t2/",
"abc2odt",
"abc2svg",
"abc2svg-1.js",
"abc2svg.ttf",
"abcdoc-1.js",
"abcemb-1.js",
"abcemb1-1.js",
"abcemb2-1.js",
"abcjsc",
"abcqjs",
"abcmjs",
"abcnode",
"abctopdf",
"abcweb-1.js",
"abcweb1-1.js",
"abcweb2-1.js",
"ambitus-1.js",
"break-1.js",
"capo-1.js",
|
| ︙ | ︙ | |||
39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
"edit-pt_BR.js",
"equalbars-1.js",
"err-de.js",
"err-en.js",
"err-fr.js",
"err-it.js",
"err-pt_BR.js",
"grid-1.js",
"grid2-1.js",
"grid3-1.js",
"json-1.js",
"jazzchord-1.js",
"jianpu-1.js",
"mdnn-1.js",
| > | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
"edit-pt_BR.js",
"equalbars-1.js",
"err-de.js",
"err-en.js",
"err-fr.js",
"err-it.js",
"err-pt_BR.js",
"gamelan-1.js",
"grid-1.js",
"grid2-1.js",
"grid3-1.js",
"json-1.js",
"jazzchord-1.js",
"jianpu-1.js",
"mdnn-1.js",
|
| ︙ | ︙ | |||
74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
],
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"bin": {
"abc2odt": "abc2odt",
"abc2svg": "abc2svg",
"abctopdf": "abctopdf"
},
"repository": {
"type": "fossil",
"url": "https://chiselapp.com/user/moinejf/repository/abc2svg"
},
"keywords": [
| > > > > | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
],
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"bin": {
"abc2odt": "abc2odt",
"abc2svg": "abc2svg",
"abcjsc": "abcjsc",
"abcqjs": "abcqjs",
"abcmjs": "abcmjs",
"abcnode": "abcnode",
"abctopdf": "abctopdf"
},
"repository": {
"type": "fossil",
"url": "https://chiselapp.com/user/moinejf/repository/abc2svg"
},
"keywords": [
|
| ︙ | ︙ |
Changes to toabc.js.
1 2 | // abc2svg - toabc.js - convert ABC to ABC // | | | 1 2 3 4 5 6 7 8 9 10 | // abc2svg - toabc.js - convert ABC to ABC // // Copyright (C) 2016-2022 Jean-Francois Moine // // This file is part of abc2svg. // // abc2svg is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
225 226 227 228 229 230 231 |
ln += (s.clef_oct_transp ? '^' : '+') + '8'
else if (s.clef_octave == -7)
ln += (s.clef_oct_transp ? '_' : '-') + '8'
return "clef=" + ln
} // clef_dump()
function deco_dump(a_dd) {
| | > > > | > > | | | > > > > | > > | 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 |
ln += (s.clef_oct_transp ? '^' : '+') + '8'
else if (s.clef_octave == -7)
ln += (s.clef_oct_transp ? '_' : '-') + '8'
return "clef=" + ln
} // clef_dump()
function deco_dump(a_dd) {
var i, n, dd,
ln = ""
//fixme: check if user deco
for (i = 0; i < a_dd.length; i++) {
dd = a_dd[i]
n = dd.name
if (dd.ty) {
if (dd.ty != '@')
line += '!' +dd.ty + n + '!'
else
line += '!@' + dd.x + ',' + dd.y + n + '!'
} else {
if (deco_l[n])
line += deco_l[n]
else
line += '!' + n + '!'
}
}
return ln
} // deco_dump
function dur_dump(dur, grace) {
var d = 0,
l = grace ? C.BLEN / 4 : ulen,
ln = ""
if (dur == l)
return ""
while (1) {
if (dur % l == 0) {
dur /= l
if (dur != 1)
ln += dur.toString()
break
}
dur *= 2
if (d > 6) {
abc2svg.print("% *** bad duration")
break
}
d++
}
if (d > 0)
ln += "//////".slice(0, d)
return ln
} // dur_dump()
var ft_w = ['', 'Thin', 'ExtraLight', 'Light', 'Regular',
'Medium', 'Demi', 'Bold', 'ExtraBold', 'Black']
function font_def(fn, p) {
var c, f,
i = p.indexOf('$')
abc.get_font(fn) // used font
// fixme: one '$' only
if (i >= 0) {
c = p[i + 1]
if (c >= '1' && c <= '9') {
c = "u" + c
f = cfmt[c + "font"] // user font
// f.fid = abc.get_font(c).fid // dump it!
f.fid = 100 + +c
f.used = 1
}
}
font_dump() // dump the new fonts
} // font_def()
function font_dump() {
var k, f, def
|
| ︙ | ︙ | |||
300 301 302 303 304 305 306 | if (!f.used) continue // not used if (old_font[f.fid]) continue // already out old_font[f.fid] = true def = f.name || "" if (f.weight) | | | > > > > > > > > > > > > > > > > > > > > > | < | 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 |
if (!f.used)
continue // not used
if (old_font[f.fid])
continue // already out
old_font[f.fid] = true
def = f.name || ""
if (f.weight)
def += ft_w[(f.weight / 100) | 0]
if (f.style)
def += f.style[0].toUpperCase() + f.style.slice(1)
if (!def)
def = "*"
def += ' ' + (f.size || "*")
if (f.box)
def += ' box'
if (f.pad)
def += ' padding=' + f.pad.toFixed(1)
if (f.class)
def += ' class=' + f.class
if (f.wadj) {
def += ' wadj='
switch (f.wadj) {
case 'spacing':
def += 'space'
break
case 'spacingAndGlyphs':
def += 'glyph'
break
default:
def += 'none'
break
}
}
if (k[0] == "u")
k = "setfont-" + k[1]
abc2svg.print('%%' + k + ' ' + def)
}
} // font_dump()
function gch_dump(a_gch) {
var i, j, gch
for (i = 0; i < a_gch.length; i++) {
|
| ︙ | ︙ | |||
359 360 361 362 363 364 365 |
l = hl[i]
if (info[l])
abc2svg.print(l + ':' + info[l].replace(/\n/g, '\n' + l + ':'))
}
} // header_dump()
function key_dump(s, clef) {
| | > > > > > > > > > | 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 |
l = hl[i]
if (info[l])
abc2svg.print(l + ':' + info[l].replace(/\n/g, '\n' + l + ':'))
}
} // header_dump()
function key_dump(s, clef) {
var ln, i, a
if (s.k_bagpipe) {
bagpipe = true // for grace notes
ln = "K:H" + s.k_bagpipe
} else if (s.k_drum) {
ln = "K:P"
} else if (s.k_none) {
ln = "K:none"
} else {
ln = "K:"
ln += k_tb[s.k_sf + 7 + mode_tb[s.k_mode][0]]
ln += mode_tb[s.k_mode][1]
}
a = s.k_a_acc // accidental list
if (a) {
if (s.k_exp)
ln += ' exp'
ln += ' '
for (i = 0; i < a.length; i++)
ln += note_dump({}, a[i])
}
if (clef && clef.clef_type != 'a')
ln += ' ' + clef_dump(clef)
//fixme: to continue
return ln
} // key_dump()
|
| ︙ | ︙ | |||
448 449 450 451 452 453 454 |
if (s.a_meter[i].bot)
ln += '/' + s.a_meter[i].bot
}
return ln
} // meter_dump()
function note_dump(s, note, tie_ch) {
| | > > | | | | | | | | | | | | | | | | | | | | > > > | | | | > | 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 |
if (s.a_meter[i].bot)
ln += '/' + s.a_meter[i].bot
}
return ln
} // meter_dump()
function note_dump(s, note, tie_ch) {
var p, j, sl, s2, a, d,
ln = ""
if (note.sls) {
for (j = 0; j < note.sls.length; j++) {
sl = note.sls[j];
ln += slti_dump(sl.ty, '(')
s2 = sl.note.s
if (s2.sl2)
s2.sl2++
else
s2.sl2 = 1
}
}
if (note.a_dd)
ln += deco_dump(note.a_dd)
if (note.color)
ln += "!" + note.color + "!"
a = note.acc
if (typeof a == "object") {
d = a[1]
a = a[0]
if (a > 0) {
ln += '^'
} else {
ln += '_'
a = -a
}
ln += dur_dump(C.BLEN / 4 * a / d, true)
} else {
switch (a) {
case -2: ln += '__'; break
case -1: ln += '_'; break
case 1: ln += '^'; break
case 2: ln += '^^'; break
case 3: ln += '='; break
}
}
p = note.pit
if (p >= 23) {
ln += "abcdefg"[p % 7]
if (p >= 30) {
ln += "'"
if (p >= 37)
ln += "'"
}
} else {
p += 7; // for very low notes
ln += "ABCDEFG"[p % 7]
if (p < 23) {
ln += ","
if (p < 16) {
ln += ","
if (p < 9)
ln += ","
}
}
}
if (!tie_ch && note.tie_ty)
ln += slti_dump(note.tie_ty, '-')
while (note.sl2) {
ln += ')'
note.sl2--
}
return ln
} // note_dump()
function slti_dump(fl, ty) {
var ln = ""
if (fl & C.SL_DOTTED)
ln += '.'
ln += ty
switch (fl & 0x07) {
case C.SL_ABOVE:
ln += "'"
break
case C.SL_BELOW:
ln += ','
break
}
return ln
} // slti_dump()
//fixme: missing: '+' (master voice) and '*' (floating voice)
function staves_dump(s) {
var v, p_v, staff, ln,
in_parenth,
vn = [],
|
| ︙ | ︙ | |||
690 691 692 693 694 695 696 |
' ' + s.repeat_k + ']'
}
if (s.tp)
tuplet_dump(s)
if (s.sls) {
for (i = 0; i < s.sls.length; i++) {
sl = s.sls[i];
| | | | 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 |
' ' + s.repeat_k + ']'
}
if (s.tp)
tuplet_dump(s)
if (s.sls) {
for (i = 0; i < s.sls.length; i++) {
sl = s.sls[i];
line += slti_dump(sl.ty, '(')
if (sl.is_note) {
if (sl.note.sl2)
sl.note.sl2++
else
sl.note.sl2 = 1
} else {
if (sl.note.s.sl2)
sl.note.s.sl2++
else
sl.note.s.sl2 = 1
}
}
}
if (s.a_gch)
gch_dump(s.a_gch)
if (s.a_dd)
line += deco_dump(s.a_dd)
if (s.color)
line += "!" + s.color + "!"
switch (s.type) {
case C.BAR:
if (s.beam_on)
line += "!beamon!"
if (s.bar_dotted)
|
| ︙ | ︙ | |||
768 769 770 771 772 773 774 |
s.p_v.pos.stm = C.SL_BELOW
line += "[I:pos stem down]"
}
}
}
tie_ch = s.ti1
if (s.notes.length == 1) {
| | | | | | | 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 |
s.p_v.pos.stm = C.SL_BELOW
line += "[I:pos stem down]"
}
}
}
tie_ch = s.ti1
if (s.notes.length == 1) {
line += note_dump(s, s.notes[0], tie_ch)
} else {
for (i = 0; i < s.notes.length; i++) {
if (!s.notes[i].tie_ty) {
tie_ch = false
break
}
}
line += '['
for (i = 0; i < s.notes.length; i++)
line += note_dump(s, s.notes[i], tie_ch)
line += ']'
}
if (s.grace) {
if (bagpipe) {
tmp = s.dur * 8
} else {
tmp = s.dur * 2
if (s.prev || s.next)
tmp *= 2
}
line += dur_dump(tmp, true)
} else {
tmp = s.notes[0].dur // head duration
if (s.trem2)
tmp /= 2;
line += dur_dump(tmp)
}
if (tie_ch)
line += slti_dump(s.notes[0].tie_ty, '-')
tmp = s.sl2
while (tmp) {
line += ')';
tmp--
}
break
case C.TEMPO:
|
| ︙ | ︙ | |||
820 821 822 823 824 825 826 |
abc2svg.print("%%writefields Q 1")
cfmt.writefields += 'Q'
}
}
tempo_dump(s)
break
case C.REST:
| < | | 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 |
abc2svg.print("%%writefields Q 1")
cfmt.writefields += 'Q'
}
}
tempo_dump(s)
break
case C.REST:
line += (s.invis ? 'x' : 'z') + dur_dump(s.dur_orig)
break
case C.SPACE:
line += 'y'
if (s.width != 10)
line += s.width
break
case C.STAVES:
|
| ︙ | ︙ | |||
896 897 898 899 900 901 902 |
for (v = 0; v < nv; v++) {
vo[v] = ""
vti[v] = 0
}
if (info.Q) {
| | | 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 |
for (v = 0; v < nv; v++) {
vo[v] = ""
vti[v] = 0
}
if (info.Q) {
abc2svg.print("Q:" + info.Q)
for (s = tsfirst; s; s = s.ts_next) {
if (s.time)
break
if (s.type == C.TEMPO)
s.del = true
}
}
|
| ︙ | ︙ | |||
934 935 936 937 938 939 940 |
}
line = "";
// (all voices are synchronized on %%score)
if (s.type != C.STAVES && s.time > vti[v]) {
//fixme: put 'X' if more than one measure
if (s.time > vti[v] + 2) {
| < | | 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 |
}
line = "";
// (all voices are synchronized on %%score)
if (s.type != C.STAVES && s.time > vti[v]) {
//fixme: put 'X' if more than one measure
if (s.time > vti[v] + 2) {
line += 'x' + dur_dump(s.time - vti[v])
}
vti[v] = s.time
}
sym_dump(s)
if (s.dur)
vti[v] = s.time + s.dur
if (s.next) {
|
| ︙ | ︙ |
Changes to tohtml.js.
1 2 | // abc2svg - tohtml.js - HTML+SVG generation // | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
// abc2svg - tohtml.js - HTML+SVG generation
//
// Copyright (C) 2014-2022 Jean-Francois Moine
//
// This file is part of abc2svg.
//
// abc2svg is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// abc2svg is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with abc2svg. If not, see <http://www.gnu.org/licenses/>.
var init_done, pw, ml, mr, pkf, lkf, fn
// replace <>& by XML character references
function clean_txt(txt) {
return txt.replace(/<|>|&.*?;|&/g, function(c) {
switch (c) {
case '<': return "<"
case '>': return ">"
|
| ︙ | ︙ | |||
145 146 147 148 149 150 151 | pw = npw psty += 'width:' + (npw - nml - nmr).toFixed(1) + 'px;' } return psty } // entry point from cmdline | | | 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
pw = npw
psty += 'width:' + (npw - nml - nmr).toFixed(1) + 'px;'
}
return psty
}
// entry point from cmdline
abc2svg.abc_init = function(args) {
var cfmt = abc.cfmt()
// output a header or footer
function gen_hf(type, str) {
var i, page,
lcr = ["l", "c", "r"],
//fixme: handle font changes?
|
| ︙ | ︙ | |||
178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
abc2svg.print('</table>')
}
user.page_format = true
// output the html header
user.img_out = function(str) {
var header = cfmt.header,
footer = cfmt.footer,
topmargin = cfmt.topmargin || "1cm",
botmargin = cfmt.botmargin || "1cm",
media_s = '@media print {\n\
body {margin:0; padding:0; border:0}\n\
.newpage {page-break-before: always}\n\
| > > > > > | 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
abc2svg.print('</table>')
}
user.page_format = true
// output the html header
user.img_out = function(str) {
if (init_done) {
abc2svg.print(str)
return
}
var header = cfmt.header,
footer = cfmt.footer,
topmargin = cfmt.topmargin || "1cm",
botmargin = cfmt.botmargin || "1cm",
media_s = '@media print {\n\
body {margin:0; padding:0; border:0}\n\
.newpage {page-break-before: always}\n\
|
| ︙ | ︙ | |||
247 248 249 250 251 252 253 |
// important for chrome and --headless (abctopdf)
if (abc.page)
abc2svg.print('@page{size:' +
(cfmt.pagewidth / 96).toFixed(2) + 'in ' +
(cfmt.pageheight / 96).toFixed(2) + 'in;margin:0}')
abc2svg.print('</style>\n\
| | | 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 |
// important for chrome and --headless (abctopdf)
if (abc.page)
abc2svg.print('@page{size:' +
(cfmt.pagewidth / 96).toFixed(2) + 'in ' +
(cfmt.pageheight / 96).toFixed(2) + 'in;margin:0}')
abc2svg.print('</style>\n\
<title>' + fn.replace(/.*\//,'')
+ '</title>\n\
<body>')
if (header || footer) {
if (header)
gen_hf("header", header)
if (footer)
gen_hf("footer", footer)
|
| ︙ | ︙ | |||
269 270 271 272 273 274 275 |
init_done = 2 // with header/footer
} else {
init_done = 1
}
// output the first generated string
abc2svg.print(str)
| | | > > > | > > > > > > | 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 |
init_done = 2 // with header/footer
} else {
init_done = 1
}
// output the first generated string
abc2svg.print(str)
}
// get the main ABC source file name
for (var i = 0; i < args.length; i++) {
var a = args[i]
if (a[0] == '-') {
i++
continue
}
fn = a
break
}
}
abc2svg.abc_end = function() {
var font_style = abc.get_font_style()
if (!init_done) // if empty document
|
| ︙ | ︙ |
Changes to tonotes.js.
1 2 | // abc2svg - tonotes.js - convert ABC to a list of MIDI notes // | | | 1 2 3 4 5 6 7 8 9 10 | // abc2svg - tonotes.js - convert ABC to a list of MIDI notes // // Copyright (C) 2021-2023 Jean-Francois Moine // // This file is part of abc2svg. // // abc2svg is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
33 34 35 36 37 38 39 |
// The time and the durations are in 1/100s.
// Lines starting with '#' are comments.
// don't load tohtml.js
abc2svg.abc_init = function(args) {
}
| | > | > > > > > > > > > > > > > | | | > > | 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
// The time and the durations are in 1/100s.
// Lines starting with '#' are comments.
// don't load tohtml.js
abc2svg.abc_init = function(args) {
}
// but load the sound generator and the chord generator
abc2svg.loadjs('util/sndgen.js')
abc2svg.loadjs('util/chord.js')
abc2svg.abc_end = function() {
function pit(v) {
if (v - (v | 0))
return v.toFixed(2)
return v.toString()
} // pit()
var e, t, vn,
audio = ToAudio(), // (in sndgen.js)
po = { // play object
conf: { // configuration
speed: 1
},
tgen: 3600, // generate by (for) 1 hour
get_time: function() { return -.3}, // (move the time origin)
midi_ctrl: function(po, s, t) {
abc2svg.print(' v:' + s.v
+ ' MIDI control ' + s.ctrl + ' ' + s.val)
}, // midi_ctrl()
midi_prog: function(po, s) {
if (s.instr)
abc2svg.print(' v:' + s.v
+ ' MIDI program '
+ (s.chn + 1) + ' '
+ s.instr)
else
abc2svg.print(' v:' + s.v
+ ' MIDI channel ' + (s.chn + 1))
}, // midi_prog()
note_run: function(po, s, k, t, d) {
abc2svg.print(' ' + (t * 100).toFixed(0) +
'\t' + po.c_i[po.v_c[s.v]] +
'\t' + pit(k) +
'\t' + (d * 100).toFixed(0) +
'\t' + vn[s.p_v.id])
}, // note_run()
v_c: [], // voice to channel
c_i: [] // channel to instrument
},
tunes = abc.tunes.slice(0) // get a copy of the generated tunes
// define the voice numbers
function dvn(v_tb) {
var i, n, p_v,
v = 0
|
| ︙ | ︙ |
Changes to toxhtml.js.
| ︙ | ︙ | |||
237 238 239 240 241 242 243 |
abc2svg.print('@page{size:' +
(cfmt.pagewidth / 96).toFixed(2) + 'in ' +
(cfmt.pageheight / 96).toFixed(2) + 'in;margin:0}')
else
abc2svg.print('@page{margin:' + topmargin + ' 0 ' +
botmargin + ' 0}')
abc2svg.print('</style>\n\
| | | 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
abc2svg.print('@page{size:' +
(cfmt.pagewidth / 96).toFixed(2) + 'in ' +
(cfmt.pageheight / 96).toFixed(2) + 'in;margin:0}')
else
abc2svg.print('@page{margin:' + topmargin + ' 0 ' +
botmargin + ' 0}')
abc2svg.print('</style>\n\
<title>' + abc.parse.fname.replace(/.*\//, '') + '</title>\n\
</head>\n\
<body>')
if (header)
gen_hf("header", header)
if (footer)
gen_hf("footer", footer);
|
| ︙ | ︙ |
Changes to util/abcdoc.js.
| ︙ | ︙ | |||
69 70 71 72 73 74 75 |
}
return c
})
}
// function to load javascript files
abc2svg.loadjs = function(fn, relay, onerror) {
| | | < | | > > > | < < < < | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
}
return c
})
}
// function to load javascript files
abc2svg.loadjs = function(fn, relay, onerror) {
var s = document.createElement('script')
if (/:\/\//.test(fn))
s.src = fn // absolute URL
else
s.src = jsdir + fn
s.onload = relay
s.onerror = function() {
if (onerror)
onerror(fn)
else
alert('error loading ' + fn)
}
document.head.appendChild(s)
}
// search the ABC tunes and add their rendering as SVG images
function render() {
var i = 0, j, k, res, re,
re_stop = /\n<|\n%.begin/g, // stop on "<" and skip "%%begin"
abc = new abc2svg.Abc(user);
// get the ABC insertion mode
if (page.indexOf('<script type="text/vnd.abc"') >= 0)
re = /<script type="text\/vnd.abc"/g
else
re = /\n%abc|\nX:/g
for (;;) {
// get the start of a ABC sequence
res = re.exec(page)
if (!res)
break
j = re.lastIndex - res[0].length;
|
| ︙ | ︙ |
Changes to util/abcweb.js.
| ︙ | ︙ | |||
47 48 49 50 51 52 53 |
alert("window error: " + msg.type + ' ' + msg.target.src)
else
alert("window error: " + msg)
return false
}
var user,
| | | | < < < < < < < < < | < | < < < > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | > > > > | 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 |
alert("window error: " + msg.type + ' ' + msg.target.src)
else
alert("window error: " + msg)
return false
}
var user,
abcplay // (usable for volume or tempo changes)
if (typeof abc2svg == "undefined")
var abc2svg = {}
abc2svg.mu = "" // container of the current played tune
abc2svg.abc_end = function() {} // accept page formatting
// get the path to the abc2svg scripts
abc2svg.jsdir = document.currentScript ?
document.currentScript.src.match(/.*\//) :
(function() {
var s_a = document.getElementsByTagName('script')
for (var k = 0; k < s_a.length; k++) {
if (s_a[k].src.indexOf("abcweb") >= 0)
return s_a[k].src.match(/.*\//) || ''
}
return "" // ??
})()
// function to load javascript files
abc2svg.loadjs = function(fn, relay, onerror) {
var s = document.createElement('script')
if (/:\/\//.test(fn))
s.src = fn // absolute URL
else
s.src = abc2svg.jsdir + fn
s.onload = relay
s.onerror = function() {
if (onerror)
onerror(fn)
else
alert('error loading ' + fn)
}
document.head.appendChild(s)
} // loadjs()
// function called when abcweb-1.js is fully loaded
function dom_loaded() {
var abc, src, outb, err,
a_inc = {},
tune_lst = [], // array of [tsfirst, voice_tb, info, cfmt] per tune
// created on playback start
html, // set if some pure HTML in the file
busy,
playing,
playconf = {
onend: function() {
playing = 0 //false
}
}
// check which <div> became visible
// if yes, generate it
function visible() {
var mu, r,
wh = window.innerHeight || document.documentElement.clientHeight
while (1) {
mu = abc2svg.alldiv[0]
if (!mu)
break
r = mu.d.getBoundingClientRect()
if (r.top > wh)
break
musgen(mu)
abc2svg.alldiv.shift()
}
if (abc2svg.alldiv.length) {
if (!abc2svg.onscroll) {
abc2svg.onscroll = visible
window.addEventListener("scroll", visible)
}
} else {
window.removeEventListener("scroll", visible)
}
} // visible()
// get the custom properties of a HTML element
// from 'class="<class>"' and from 'style="--<key>:<value>"'
function get_p(e) {
var i, j, k, r,
o = '',
sh = document.styleSheets,
s = e.style
// from class=".."
c = e.getAttribute("class")
if (c) {
c = '.' + c // selector
for (i = 0; i < sh.length; i++) {
r = sh[i].rules
for (j = 0; j < r.length; j++) {
if (r[j].selectorText == c)
break
}
if (j < r.length)
break
}
if (i < sh.length) {
r = r[j] // rule
for (i = 0; i < r.style.length; i++) {
k = r.style[i]
if (k[0] == '-' && k[1] == '-')
o += '%%' + k.slice(2) + ' '
+ r.style.getPropertyValue(k)
+ '\n'
}
}
}
// from style=".."
for (i = 0; i < s.length; i++) {
k = s[i]
if (k[0] == '-' && k[1] == '-')
o += '%%' + k.slice(2) + ' '
+ s.getPropertyValue(k)
+ '\n'
}
return o
} // get_p()
// move the musique sequences to <script> text/vnd.abc
// <mei> .. </mei>
// <anytag .. class="abc" .. > ..ABC.. </anytag>
// %abc-n ..ABC.. '<' with skip %%beginxxx .. %%endxxx
// X:n ..ABC.. '<' with skip %%beginxxx .. %%endxxx
function move_music(src) {
var re, res, i, j, k, t,
re_stop = /\n<|\n%.begin[^\s]+/g,
ss = 0,
out = ""
if (/<[^>]* class="[^"]*abc[^"]*/.test(src)) // "
re = '<[^>]* class="[^"]*abc[^"]*'
else
re = '%abc-\\d|X:\\s*\\d'
re = new RegExp('(^|\n)(' + re + ')', 'g')
while (1) {
res = re.exec(src)
if (!res)
break
i = re.lastIndex - res[0].length // end of HTML
if (i > ss) {
out += src.slice(ss, i) // copy HTML
html = 1
}
t = res[2]
if (t[0] == '<') {
i = src.indexOf('>', i) + 1 // start of ABC
j = res[2].indexOf(' ') // get the tag
t = res[2].slice(1, j)
j = src.indexOf('</' + t + '>', i)
ss = j + t.length + 4
} else { // %abc or X:
// get the end of the ABC sequence
// including the %%beginxxx/%%endxxx sequences
// (that may contain XML)
re_stop.lastIndex = i
while (1) {
res = re_stop.exec(src)
if (!res || res[0] == "\n<")
break
k = src.indexOf(res[0].replace("begin", "end"),
re_stop.lastIndex)
if (k < 0)
break
re_stop.lastIndex = k
}
if (!res || k < 0)
j = src.length
else
j = re_stop.lastIndex - 1
ss = j
}
out += '<script type="text/vnd.abc">\n'
+ src.slice(i, j)
+ '</script>\n'
re.lastIndex = ss // new HTML start
}
out += src.slice(ss) // copy the last HTML sequence
if (abc2svg.page && html)
out += '\
<pre class="nop" style="background:#ff8080">\
Printing may be bad because the file contains pure HTML and %%pageheight\
</pre>\n'
document.body.innerHTML = out
} // move_music()
// save the music sequences and replace them by empty <div>'s
function save_music() {
var i, k, div, c, s, sa
// save MEI sequences
function save_spe(ty) {
var s, div
while (1) {
s = document.getElementsByTagName(ty)[0]
if (!s)
break
div = document.createElement('div')
abc2svg.music.push({
n: 'mus' + abc2svg.music.length,
t: s.outerHTML,
d: div
})
s.parentNode.replaceChild(div, s)
}
} // save_spe()
// get the global parameters
abc2svg.music = [{
t: "", // global parameters
n: "mus0"
}]
// get the parameters from the query string of the URL
k = location.search
if (k) {
k = k.substr(1).split("&")
for (i = 0; i < k.length; i++)
abc2svg.music[0].t += "%%"
+ decodeURIComponent(k[i].replace('=', ' '))
+ '\n'
}
// search the <script>'s of the HTML page
// and replace the music <script>'s by empty <div>'s
while (1) {
sa = document.getElementsByTagName('script')
for (i = 0; i < sa.length; i++) {
s = sa[i]
if (s.type == 'text/vnd.abc')
break
}
if (i >= sa.length)
break
c = get_p(s) // get custom properties
div = document.createElement('div')
if (s.text.indexOf('\nX:') < 0) {
abc2svg.music[0].t += c + s.innerHTML // global
if (!abc2svg.music[0].d)
abc2svg.music[0].d = div
} else {
abc2svg.music.push({
n: "mus" + abc2svg.music.length,
t: c + s.innerHTML,
d: div
})
}
s.parentNode.replaceChild(div, s)
}
// special treatment for MEI
save_spe('mei')
} // save_music()
// generate a music sequence
// @mu = object { t: music source, d: <div> }
function musgen(mu) {
var t = mu.t
if (busy) {
mu.w = 1 //true
return
}
busy = 1 //true
// render a music sequence
function render() {
var i, j, e
// start the generation
outb = err = ""
abc.tosvg(mu.n, t) // music source
abc2svg.abc_end() // close the page if %%pageheight
if (err)
outb += '<pre class="nop" style="background:#ff8080">'
+ err + "</pre>\n"
if (abc.cfmt().with_source && outb)
outb = '<pre class="source">'
+ clean_txt(t)
+ '</pre>\n\
<div class="source">\n'
+ outb
+ '</div>\n'
mu.d.innerHTML = outb // update the browser
mu.d.addEventListener('click', abc2svg.playseq)
e = mu.d.getElementsByTagName('svg')
for (i = 0; i < e.length; i++) {
j = e[i].getAttribute('class')
if (!j)
continue // (page formatting)
j = j.match(/tune(\d+)/)
if (!j)
continue
j = j[1] // tune number
tune_lst[j] = null // get new play references
}
// if some generation waiting, start it
mu.w = busy = 0 //false
for (i = 1; i < abc2svg.music.length; i++) {
if (abc2svg.music[i].w) {
musgen(abc2svg.music[i])
break
}
}
} // render()
// load the possible %%abc-include files
function include() {
var i, j, fn, r,
k = 0
while (1) {
i = t.indexOf('%%abc-include ', k)
if (i < 0) {
render()
return
}
i += 14
j = t.indexOf('\n', i)
fn = t.slice(i, j).trim()
if (!a_inc[fn])
break
k = j
}
// %%abc-include found: load the file
r = new XMLHttpRequest()
r.open('GET', fn, true) // (async)
r.onload = function() {
if (r.status === 200) {
a_inc[fn] = r.responseText
if (abc2svg.modules.load(a_inc[fn], include))
include()
} else {
a_inc[fn] = '%\n'
alert('Error getting ' + fn + '\n' + r.statusText)
include()
}
}
r.onerror = function () {
a_inc[fn] = '%\n'
alert('Error getting ' + fn + '\n' + r.statusText)
include()
}
r.send()
} // include()
// load the required modules and the include files before rendering
if (abc2svg.modules.load(t, include))
include()
} // musgen()
//test
abc2svg.musgen = musgen
// -- abc2svg init argument
user = {
read_file: function(fn) {
return a_inc[fn]
}, // read_file()
errmsg: function(msg, l, c) { // get the errors
err += clean_txt(msg) + '\n'
},
img_out: function(p) { // image output
outb += p
}
}
// replace <>& by XML character references
function clean_txt(txt) {
return txt.replace(/<|>|&.*?;|&/g, function(c) {
switch (c) {
case '<': return "<"
case '>': return ">"
case '&': return "&"
}
return c
})
}
// function called on click on the music
abc2svg.playseq = function(evt) {
if (playing) { // stop playing
abcplay.stop()
return
}
var i, j,
svg = evt.target,
e = svg // keep the clicked element
// search if click in a SVG image
while (svg.tagName != 'svg') {
svg = svg.parentNode
|
| ︙ | ︙ | |||
151 152 153 154 155 156 157 |
// check if click on a music symbol
// (this works when 'follow' is active)
s = tune_lst[i][0] // first symbol of the tune
i = e.getAttribute('class')
if (i)
i = i.match(/abcr _(\d+)_/)
| < < < < < > > > > > > > > > | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > | > | < > | < | | | > > > | | > > | | | | | | < < | < < | > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 |
// check if click on a music symbol
// (this works when 'follow' is active)
s = tune_lst[i][0] // first symbol of the tune
i = e.getAttribute('class')
if (i)
i = i.match(/abcr _(\d+)_/)
if (i) {
i = i[1] // symbol offset in the source
while (s && s.istart != i)
s = s.ts_next
if (!s) { // fixme: error ?!
alert("play bug: no such symbol in the tune")
return
}
}
// keep the container of the tune being played
while (s && !s.fname) // (no .fname in the 1st %%staves)
s = s.ts_next
for (i = 1; i < abc2svg.music.length; i++) {
if (abc2svg.music[i].n == s.fname)
break
}
abc2svg.mu = abc2svg.music[i] // current container
playing = 1 //true
abcplay.play(s, null)
} // playseq()
// --- dom_loaded() main code ---
// load the abc2svg core if not done by <script>
src = document.body.innerHTML
if (!abc2svg.Abc) {
abc2svg.loadjs(src.indexOf("<mei ") >= 0 ?
"mei2svg-1.js" :
"abc2svg-1.js",
dom_loaded)
return
}
if (src.indexOf('type="text/vnd.abc"') < 0)
move_music(src)
save_music() // save the music sequences and replace them by <div>
// initialize the generation
abc = new abc2svg.Abc(user)
if (typeof follow == "function") // if snd-1.js loaded
follow(abc, user, playconf) // initialize the play follow
if (abc2svg.music[0].t) {
abc.tosvg(abc2svg.music[0].n, // global definitions
abc2svg.music[0].t)
if (abc.cfmt().with_source
&& abc.cfmt().with_source.indexOf('nohead') < 0) {
abc2svg.music[0].d.innerHTML = '<pre class="source">'
+ clean_txt(abc2svg.music[0].t)
+ '</pre>\n'
}
}
// create a list of all <div>'s
abc2svg.alldiv = []
for (var i = 1; i < abc2svg.music.length; i++)
abc2svg.alldiv.push(abc2svg.music[i])
visible()
} // dom_loaded()
// ---- interface for changing the music source and redisplaying it ----
// get the music source of a <div> element
abc2svg.get_music = function(d) {
var i, mu
for (var i = 1; i < abc2svg.music.length; i++) {
mu = abc2svg.music[i]
if (mu.d == d)
return mu.t
}
// return ""
} // get_music()
// set the music source of a <div> element and redisplay it
abc2svg.set_music = function(d, t) {
var i, mu
for (var i = 1; i < abc2svg.music.length; i++) {
mu = abc2svg.music[i]
if (mu.d == d) {
mu.t = t
abc2svg.musgen(mu)
break
}
}
} // set_music()
// wait for the scripts to be loaded
window.addEventListener("load", dom_loaded, {once:true})
|
Changes to util/abcweb1.js.
1 2 | // abcweb1-1.js file to include in html pages with abc2svg-1.js // | | | 1 2 3 4 5 6 7 8 9 10 | // abcweb1-1.js file to include in html pages with abc2svg-1.js // // Copyright (C) 2019-2022 Jean-Francois Moine // // This file is part of abc2svg. // // abc2svg is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
218 219 220 221 222 223 224 |
// function to load javascript files
abc2svg.loadjs = function(fn, relay, onerror) {
var s = document.createElement('script')
if (/:\/\//.test(fn))
s.src = fn // absolute URL
else
s.src = jsdir + fn
| < | | > > > | | 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
// function to load javascript files
abc2svg.loadjs = function(fn, relay, onerror) {
var s = document.createElement('script')
if (/:\/\//.test(fn))
s.src = fn // absolute URL
else
s.src = jsdir + fn
s.onload = relay
s.onerror = function() {
if (onerror)
onerror(fn)
else
alert('error loading ' + fn)
}
document.head.appendChild(s)
} // loadjs()
// build a list of the tunes
abc2svg.get_sel = function() {
var j, k,
|
| ︙ | ︙ | |||
338 339 340 341 342 343 344 | errtxt = "" } // add the menu new_page += '\ <div id="dd" class="dd nop">\ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" class="db">\ | | > > > > > | 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 |
errtxt = ""
}
// add the menu
new_page += '\
<div id="dd" class="dd nop">\
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" class="db">\
<path d="M4 6h15v2.5H4zm0 5h15v2.5H4zm0 5h15v2.5H4z" fill="black"/>\
</svg>\
<div id="dc" class="dc">\
<label id="edit" onclick="abc2svg.src_edit()">Source edit</label>\
<label id="list" onclick="abc2svg.get_sel()">Tune list</label>\
<label id="play" onclick="abc2svg.st_scroll()">Scroll</label>\
</div>\
</div>\
<label id="ss" class="dd nop" onclick="abc2svg.st_scroll()">Scroll<br/>stop</label>'
// change the page
try {
document.body.innerHTML = new_page
} catch (e) {
alert("abc2svg bad generated SVG: " + e.message +
"\nStack:\n" + e.stack)
return
}
// add the event handlers
var elts = document.getElementsByTagName('svg')
for (var i = 0; i < elts.length; i++)
elts[i].addEventListener('click', click)
// update the menu
setTimeout(function() {
// remove scroll in menu if play or not a big tune
if (typeof AbcPlay != "undefined"
|| document.documentElement.scrollHeight <= window.innerHeight)
document.getElementById("play").style.display = "none"
|
| ︙ | ︙ | |||
419 420 421 422 423 424 425 |
abc2svg.loadjs("abc2svg-1.js", dom_loaded)
return
}
// get the page content
page = fix_abc(document.body.innerHTML)
| | | | < | | > > > | > > > | 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 |
abc2svg.loadjs("abc2svg-1.js", dom_loaded)
return
}
// get the page content
page = fix_abc(document.body.innerHTML)
// click on a SVG element
function click(evt) {
if (playing) { // stop playing
abcplay.stop()
return
}
var e, s, j,
c = evt.target
// remove the menu if active
e = document.getElementById("dc")
if (e && e.classList.contains("show")) {
e.classList.remove("show") // remove the menu
return
}
// search if click in a SVG image
e = c // keep the clicked element
while (1) {
if (c == document)
return
if (c.tagName.toLowerCase() == 'svg')
break
c = c.parentNode
}
c = c.getAttribute('class')
if (!c)
return
// if click in the menu button, show the menu
if (c == "db") {
e = document.getElementById("dc")
e.classList.toggle("show")
return
}
|
| ︙ | ︙ | |||
497 498 499 500 501 502 503 |
alert("play bug: no such symbol in the tune")
return
}
}
playing = true
abcplay.play(s, null)
| | | 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 |
alert("play bug: no such symbol in the tune")
return
}
}
playing = true
abcplay.play(s, null)
} // click()
// accept page formatting
abc2svg.abc_end = function() {}
// load the required modules, then render the music
if (abc2svg.modules.load(page, include))
include()
} // dom_loaded()
// wait for the scripts to be loaded
window.addEventListener("load", dom_loaded)
|
Changes to util/chord.js.
1 2 | // chord.js - generation of accompaniment // | | | 1 2 3 4 5 6 7 8 9 10 | // chord.js - generation of accompaniment // // Copyright (C) 2020-2022 Jean-Francois Moine and Seymour Shlien // // This file is part of abc2svg. // // abc2svg is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
94 95 96 97 98 99 100 | case '-': v -= 12; break } r.push(v) } return r } // chcr() | | | | < | > | > > > < | < < > > > > > | 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
case '-': v -= 12; break
}
r.push(v)
}
return r
} // chcr()
// get the playback part of the first chord symbol
function filter(a_cs) {
var i, cs, t
for (i = 0; i < a_cs.length; i++) {
cs = a_cs[i]
if (cs.type != 'g')
continue
t = cs.otext
if (t.slice(-1) == ')') // if alternate chord
t = t.replace(/\(.*/, '') // remove it
return t.replace(/\(|\)|\[|\]/g,'') // remove ()[]
}
} // filter()
// generate a chord
function gench(sb) {
var r, ch, b, m, n, not,
a = filter(sb.a_gch),
s = {
v: vch.v,
p_v: vch,
type: C.NOTE,
time: sb.time,
notes: []
}
if (!a)
return
a = a.match(/([A-GN])([#♯b♭]?)([^/]*)\/?(.*)/)
// a[1] = note, a[2] = acc, a[3] = type, a[4] = bass
if (!a)
return
r = abc2svg.letmid[a[1]] // root
if (r == undefined) {
if (a[1] != "N")
return
s.type = C.REST // ("N") = no chord
ch = [0]
r = 0
|
| ︙ | ︙ | |||
167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
if (b == undefined)
b = 0
ch = chcr(b, ch)
// generate the notes of the chord
n = ch.length
r += trans
for (m = 0; m < n; m++) {
not = {
midi: r + ch[m]
}
s.notes.push(not)
}
s.nhd = n - 1
| > > | 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
if (b == undefined)
b = 0
ch = chcr(b, ch)
// generate the notes of the chord
n = ch.length
r += trans
if (sb.p_v.tr_snd)
r += sb.p_v.tr_snd
for (m = 0; m < n; m++) {
not = {
midi: r + ch[m]
}
s.notes.push(not)
}
s.nhd = n - 1
|
| ︙ | ︙ | |||
206 207 208 209 210 211 212 213 214 215 216 217 |
//fixme: no inversion
chnm[k] = [ vch ]
}
} else {
chnm = abc2svg.ch_names
}
// create the chord voice
vch = {
v: voice_tb.length,
id: "_chord",
time: 0,
| > > > > > > > > > | | > > > | > > < | | < < < < < < < < < | 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
//fixme: no inversion
chnm[k] = [ vch ]
}
} else {
chnm = abc2svg.ch_names
}
// define the MIDI channel
k = 0
for (i = 0; i < voice_tb.length; i++) {
if (k < voice_tb[i].chn)
k = voice_tb[i].chn
}
if (k == 8)
k++ // skip the channel 10
// create the chord voice
vch = {
v: voice_tb.length,
id: "_chord",
time: 0,
sym: {
type: C.BLOCK,
subtype: "midiprog",
chn: k + 1,
instr: cfmt.chord.prog || 0,
time: 0,
ts_prev: first,
ts_next: first.ts_next
},
vol: cfmt.chord.vol || .6 // (external default 76.2)
}
vch.last_sym = vch.sym
voice_tb.push(vch)
first.ts_next = vch.sym
// loop on the symbols and add the accompaniment chords
gchon = cfmt.chord.gchon
s = first
while (1) {
if (!s.ts_next) {
if (gchon)
|
| ︙ | ︙ |
Changes to util/follow.js.
1 2 3 4 5 | // follow-1.js - file included in snd-1.js // // This script permits to follow the notes while playing. // Scrolling the music may be disabled setting 'no_scroll' in the window object. // | | < | < | > > > > > > | > > | > | | | < < | < | | < < | < | | | > > > > > | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
// follow-1.js - file included in snd-1.js
//
// This script permits to follow the notes while playing.
// Scrolling the music may be disabled setting 'no_scroll' in the window object.
//
// Copyright (C) 2015-2022 Jean-Francois Moine
//
// This file is part of abc2svg.
//
// abc2svg is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// abc2svg is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with abc2svg. If not, see <http://www.gnu.org/licenses/>.
// init
function follow(abc, user, playconf) {
var keep_types = {
note: true,
rest: true
}
user.anno_stop = function(type, start, stop, x, y, w, h) {
if (!keep_types[type])
return
// create a rectangle
abc.out_svg('<rect class="abcr _' + start + '_" x="');
abc.out_sxsy(x, '" y="', y);
abc.out_svg('" width="' + w.toFixed(2) +
'" height="' + abc.sh(h).toFixed(2) + '"/>\n')
}
playconf.onnote = function(i, on) {
var b, i, e, elts,
x = 0,
y = 0
if (abc2svg.mu) // if many tunes with same offsets
elts = abc2svg.mu.d.getElementsByClassName('_' + i + '_')
else
elts = document.getElementsByClassName('_' + i + '_')
if (!elts || !elts.length)
return // no symbol?
e = elts[0]
e.style.fillOpacity = on ? 0.4 : 0
// scroll for the element to be in the screen
if (on && !window.no_scroll) {
b = e.getBoundingClientRect()
// normal
if (b.top < 0
|| b.bottom > window.innerHeight * .8)
y = b.top - window.innerHeight * .3
// single line
if (b.left < 0
|| b.right > window.innerWidth * .8)
x = b.left - window.innerWidth * .3
if (x || y)
window.scrollBy({
top: y,
left: x,
behavior: (x < 0 || y)
? 'instant'
: 'smooth'
})
}
}
} // follow()
// create the style of the rectangles
(function () {
var sty = document.createElement("style")
sty.innerHTML = ".abcr {fill: #d00000; fill-opacity: 0; z-index: 15}"
document.head.appendChild(sty)
})()
|
Changes to util/play.js.
| ︙ | ︙ | |||
115 116 117 118 119 120 121 | // set the current output changing the play functions current = out[o] == 'sf2' ? audio5 : midi5; abcplay.play = current.play; abcplay.stop = current.stop if (current.set_output) current.set_output(out[o]); | < < < < < < < < < | 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | // set the current output changing the play functions current = out[o] == 'sf2' ? audio5 : midi5; abcplay.play = current.play; abcplay.stop = current.stop if (current.set_output) current.set_output(out[o]); abcplay.play(init.istart, init.i_iend, init.a_e); } // play2() // set default configuration values conf.gain = 0.7; conf.speed = 1; |
| ︙ | ︙ |
Changes to util/sndaud.js.
1 2 | // sndaud.js - audio output using HTML5 audio // | | | 1 2 3 4 5 6 7 8 9 10 | // sndaud.js - audio output using HTML5 audio // // Copyright (C) 2019-2023 Jean-Francois Moine // // This file is part of abc2svg. // // abc2svg is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
123 124 125 126 127 128 129 | a = b.getChannelData(0) // destination = array of float32 for (i = 0; i < s.length; i++) a[i] = s[i] / 196608 // volume divided by 6 } // create all notes of an instrument | | | | | | | | | 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
a = b.getChannelData(0) // destination = array of float32
for (i = 0; i < s.length; i++)
a[i] = s[i] / 196608 // volume divided by 6
}
// create all notes of an instrument
function sf2_create(instr, sf2par, sf2pre) { // parser, presets
// get the instrument parameters
// adapted from getInstruments() in sf2-parser.js
function get_instr(i) {
var instrument = sf2par.instrument,
zone = sf2par.instrumentZone,
j = instrument[i].instrumentBagIndex,
jl = instrument[i + 1]
? instrument[i + 1].instrumentBagIndex
: zone.length,
info = []
while (j < jl) {
instrumentGenerator =
sf2par.createInstrumentGenerator_(zone, j)
// instrumentModulator =
// sf2par.createInstrumentModulator_(zone, j)
info.push({
generator: instrumentGenerator.generator,
// modulator: instrumentModulator.modulator
})
j++
}
//console.log('created instr: '+instrument[i].instrumentName)
return {
// name: instrument[i].instrumentName,
info: info
}
} // get_instr()
// sf2_create
var i, j, k, sid, gen, parm, gparm, sample, infos,
sampleRate, scale,
b = instr >> 7, // bank
p = instr % 128, // preset
pr = sf2pre
rates[instr] = []
// search the bank:preset
for (i = 0; i < pr.length; i++) {
gen = pr[i].header
if (gen.preset == p
|
| ︙ | ︙ | |||
221 222 223 224 225 226 227 | if (gen.sampleModes && gen.sampleModes.amount & 1) parm.sm = 1 if (!gen.sampleID) // (empty generator!) continue sid = gen.sampleID.amount | | | | | | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 |
if (gen.sampleModes && gen.sampleModes.amount & 1)
parm.sm = 1
if (!gen.sampleID) // (empty generator!)
continue
sid = gen.sampleID.amount
sampleRate = sf2par.sampleHeader[sid].sampleRate
sample = sf2par.sample[sid]
parm.buffer = ac.createBuffer(1,
sample.length,
sampleRate)
parm.hold += parm.attack
parm.decay += parm.hold
// sustain > 40dB is not audible
if (parm.sustain >= .4)
parm.sustain = 0.01 // must not be null
else
parm.sustain = 1 - parm.sustain / .4
sample_cp(parm.buffer, sample)
if (parm.sm) {
parm.loopStart = sf2par.sampleHeader[sid].startLoop /
sampleRate
parm.loopEnd = sf2par.sampleHeader[sid].endLoop /
sampleRate
}
// define the notes
scale = (gen.scaleTuning ?
gen.scaleTuning.amount : 100) / 100,
tune = (gen.coarseTune ? gen.coarseTune.amount : 0) +
(gen.fineTune ? gen.fineTune.amount : 0) / 100 +
sf2par.sampleHeader[sid].pitchCorrection / 100 -
(gen.overridingRootKey ?
gen.overridingRootKey.amount :
sf2par.sampleHeader[sid].originalPitch)
for (j = gen.keyRange.lo; j <= gen.keyRange.hi; j++) {
rates[instr][j] = Math.pow(Math.pow(2, 1 / 12),
(j + tune) * scale)
params[instr][j] = parm
}
}
}
} // sf2_create()
// load an instrument (.js file)
function load_instr(instr) {
w_instr++
abc2svg.loadjs(conf.sfu + '/' + instr + '.js',
function() {
var sf2par = new sf2.Parser(b64dcod(abcsf2[instr]))
sf2par.parse()
var sf2pre = sf2par.getPresets()
sf2_create(instr, sf2par, sf2pre)
if (--w_instr == 0)
play_start()
},
function() {
errmsg('could not find the instrument ' +
((instr / 128) | 0).toString() + '-' +
(instr % 128).toString())
if (--w_instr == 0)
play_start()
})
} // load_instr()
// define the instruments of the tune
function def_instr(s, f, sf2par, sf2pre) {
var i,
bk = [], // bank number per voice
nv = -1, // highest voice number
vb = 0 // bitmap of voices with instruments
// scan from the beginning of the tune
s = s.p_v.sym
while (s.ts_prev)
s = s.ts_prev
for ( ; s; s = s.ts_next) {
if (s.v < nv) { // if new voice
nv = s.v
bk[nv] = 0 // bank 0
if (p_v.midictl) {
if (p_v.midictl[0]) // MSB
bk[s.v] = (bk[s.v] & ~0x1fc000)
+ (p_v.midictl[0] << 14)
if (p_v.midictl[32]) // LSB
bk[s.v] = (bk[s.v] & ~0x3f80)
+ (p_v.midictl[32] << 7)
}
}
switch (s.subtype) {
case "midiprog":
break
case "midictl":
if (s.ctrl != 0 && s.ctrl != 32)
continue // not bank LSB or MSB
if (bk[s.v] == undefined)
bk[s.v] = 0
if (s.ctrl == 0) // MSB
bk[s.v] = (bk[s.v] & ~0x1fc000)
+ (s.val << 14)
else // LSB
bk[s.v] = (bk[s.v] & ~0x3f80)
+ (s.val << 7)
// continue
default:
continue
}
vb |= 1 << s.v
i = s.instr
if (i == undefined) { // channel only
if (s.chn != 9)
continue
i = bk[s.v] ? 0 : 128 * 128 // bank 256 program 0
}
if (bk[s.v])
i += bk[s.v] // bank number
if (!params[i]) {
params[i] = [] // instrument being loaded
f(i, sf2par, sf2pre) // sf2_create or load_instr
}
}
nv = (2 << nv) - 1
if (!(nv & vb) // if some voice(s) without instrument
&& !params[0]) {
params[0] = [] // load the piano
f(0, sf2par, sf2pre)
}
} // def_instr()
// load the needed instruments
function load_res(s) {
if (abc2svg.sf2
|| conf.sfu.slice(-4) == ".sf2"
|| conf.sfu.slice(-3) == ".js") {
// if the soundfont is loaded as .js
if (abc2svg.sf2) {
if (!parser) {
parser = new sf2.Parser(b64dcod(abc2svg.sf2))
parser.parse()
presets = parser.getPresets()
}
// load the soundfont if not done yet
} else if (!parser) {
if (conf.sfu.slice(-3) == ".js") {
abc2svg.loadjs(conf.sfu,
function() {
load_res(s) // load the instruments
},
function() {
|
| ︙ | ︙ | |||
335 336 337 338 339 340 341 |
errmsg('could not load the sound file '
+ conf.sfu)
}
r.send()
return
}
| | < < < < | < < < < | < < < < < | < < < < < | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 |
errmsg('could not load the sound file '
+ conf.sfu)
}
r.send()
return
}
// create the instruments and start playing
def_instr(s, sf2_create, parser, presets)
} else {
// (case instruments as base64 encoded js file,
// one file per instrument)
def_instr(s, load_instr)
}
} // load_res()
// return the play real time in seconds
function get_time(po) {
return po.ac.currentTime
} // get_time()
// MIDI control
function midi_ctrl(po, s, t) {
switch (s.ctrl) {
case 0: // bank MSB
if (po.v_b[s.v] == undefined)
po.v_b[s.v] = 0
po.v_b[s.v] = (po.v_b[s.v] & ~0x1fc000)
+ (s.val << 14)
break
case 7: // volume
s.p_v.vol = s.val / 127
break
case 32: // bank LSB
if (po.v_b[s.v] == undefined)
po.v_b[s.v] = 0
po.v_b[s.v] = (po.v_b[s.v] & ~0x3f80)
+ (s.val << 7)
break
}
} // midi_ctrl()
// MIDI prog or channel
function midi_prog(po, s) {
var i = s.instr
po.v_c[s.v] = s.chn
if (i == undefined) {
if (s.chn != 9) // if not channel 9
return
i = po.v_b[s.v] ? 0 : 128 * 128 // bank 256 program 0
}
if (po.v_b[s.v])
i += po.v_b[s.v]
po.c_i[s.chn] = i
//console.log('prog i:'+i+' ch:'+s.chn+' v:'+s.v)
} // midi_prog()
// create a note
// @po = play object
// @s = symbol
// @key = MIDI key + detune
// @t = audio start time
// @d = duration adjusted for speed
function note_run(po, s, key, t, d) {
//console.log('run c:'+po.v_c[s.v]+' i:'+po.c_i[po.v_c[s.v]])
var g, st,
c = po.v_c[s.v],
instr = po.c_i[c],
k = key | 0,
parm = params[instr][k],
o = po.ac.createBufferSource(),
v = s.p_v.vol == undefined ? 1 : s.p_v.vol // volume (gain)
if (!v // mute voice
|| !parm) // if the instrument could not be loaded
return // or if it has not this key
o.buffer = parm.buffer
|
| ︙ | ︙ | |||
431 432 433 434 435 436 437 438 439 440 441 442 443 444 |
// start the note
o.start(t)
o.stop(t + d)
} // note_run()
// wait for all resources, then start playing
function play_start() {
if (po.stop) { // stop playing
po.onend(repv)
return
}
// all resources are there
gain.connect(ac.destination)
| > | 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 |
// start the note
o.start(t)
o.stop(t + d)
} // note_run()
// wait for all resources, then start playing
function play_start() {
//console.log('- play start')
if (po.stop) { // stop playing
po.onend(repv)
return
}
// all resources are there
gain.connect(ac.destination)
|
| ︙ | ︙ | |||
511 512 513 514 515 516 517 518 519 520 521 522 523 | s_end: i_end, // last music symbol / null s_cur: i_start, // current music symbol // repn: false, // don't repeat repv: i_lvl || 0, // repeat variant number tgen: 2, // // generate by 2 seconds get_time: get_time, midi_ctrl: midi_ctrl, note_run: note_run, timouts: [], // audio specific ac: ac, gain: gain, | > > > > < > > > | 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 |
s_end: i_end, // last music symbol / null
s_cur: i_start, // current music symbol
// repn: false, // don't repeat
repv: i_lvl || 0, // repeat variant number
tgen: 2, // // generate by 2 seconds
get_time: get_time,
midi_ctrl: midi_ctrl,
midi_prog: midi_prog,
note_run: note_run,
timouts: [],
v_c: [], // voice to channel
c_i: [], // channel to instrument
v_b: [], // voice to bank
// audio specific
ac: ac,
gain: gain,
rates: rates
}
w_instr++ // play lock
load_res(i_start)
if (--w_instr == 0) // all resources are there
play_start()
}, // play()
// stop playing
stop: function() {
po.stop = true
po.timouts.forEach(function(id) {
clearTimeout(id)
|
| ︙ | ︙ |
Changes to util/sndgen.js.
1 2 | // sndgen.js - sound generation // | | | 1 2 3 4 5 6 7 8 9 10 | // sndgen.js - sound generation // // Copyright (C) 2019-2023 Jean-Francois Moine // // This file is part of abc2svg. // // abc2svg is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
22 23 24 25 26 27 28 | // s.ptim = play time // - in BAR // rep_p = on a right repeat bar, pointer to the left repeat symbol // rep_s = on the first repeat variant, array of pointers to the next symbols, // indexed by the repeat number // - in NOTE and REST // s.pdur = play duration | < < | | | < < | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
// s.ptim = play time
// - in BAR
// rep_p = on a right repeat bar, pointer to the left repeat symbol
// rep_s = on the first repeat variant, array of pointers to the next symbols,
// indexed by the repeat number
// - in NOTE and REST
// s.pdur = play duration
// - in the notes[] of NOTE
// s.notes[i].midi
if (!abc2svg)
var abc2svg = {}
function ToAudio() {
return {
// generate the play data of a tune
add: function(first, // starting symbol
voice_tb, // voice table
cfmt) { // tune parameters
var toaud = this,
C = abc2svg.C,
p_time = 0, // last playing time
abc_time = 0, // last ABC time
play_fac = C.BLEN / 4 * 120 / 60, // play time factor - default: Q:1/4=120
i, n, dt, d, v,
s = first,
rst = s, // left repeat (repeat restart)
rst_fac, // play factor on repeat restart
rsk = [], // repeat variant array (repeat skip)
b_tim, // time of last measure bar
b_typ // type of last measure bar
// build the information about the parts (P:)
function build_parts(first) {
var i, j, c, n, v,
s = first,
p = s.parts,
st = [],
|
| ︙ | ︙ | |||
119 120 121 122 123 124 125 | if (first.parts[i] == v) first.p_s[i] = s } } } } // build_parts() | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > > < < | | | > | < < < < < < < < < < < < < < < < < | 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
if (first.parts[i] == v)
first.p_s[i] = s
}
}
}
} // build_parts()
// generate the grace notes
function gen_grace(s) {
var g, i, n, t, d, s2,
next = s.next
// before beat
if (s.sappo) {
d = C.BLEN / 16
} else if ((!next || next.type != C.NOTE)
&& s.prev && s.prev.type == C.NOTE) {
d = s.prev.dur / 2
// on beat
} else {
d = next.dur / 12
if (!(d & (d - 1)))
d = next.dur / 2 // no dot
else
d = next.dur / 3
if (s.p_v.key.k_bagpipe)
d /= 2
next.time += d
next.dur -= d
}
//fixme: assume the grace notes in the sequence have the same duration
n = 0
for (g = s.extra; g; g = g.next)
n++
d /= n * play_fac
t = p_time
for (g = s.extra; g; g = g.next) {
g.ptim = t
g.pdur = d
t += d
}
} // gen_grace()
// change the tempo
function set_tempo(s) {
var i,
d = 0,
n = s.tempo_notes.length
for (i = 0; i < n; i++)
d += s.tempo_notes[i]
return d * s.tempo / 60
} // set_tempo()
function set_variant(s) {
var d,
n = s.text.match(/[1-8]-[2-9]|[1-9,.]|[^\s]+$/g)
while (1) {
d = n.shift()
if (!d)
break
if (d[1] == '-')
for (i = d[0]; i <= d[2]; i++)
rsk[i] = s
else if (d >= '1' && d <= '9')
rsk[Number(d)] = s
else if (d != ',')
rsk.push(s) // last
}
} // set_variant()
// add() main
// if some MIDI stuff, load the associated module
if (cfmt.chord)
abc2svg.chord(first, voice_tb, cfmt)
if (s.parts)
build_parts(s)
// set the time parameters
rst_fac = play_fac
while (s) {
if (s.noplay) { // in display macro sequence
s = s.ts_next
continue
}
|
| ︙ | ︙ | |||
306 307 308 309 310 311 312 |
}
switch (s.type) {
case C.BAR:
if (s.time != b_tim) {
b_tim = s.time
b_typ = 0
}
| | > | | | | < < < | 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
}
switch (s.type) {
case C.BAR:
if (s.time != b_tim) {
b_tim = s.time
b_typ = 0
}
if (s.text // if new variant
&& rsk.length > 1
&& s.text[0] != '1') {
if (b_typ & 1)
break
b_typ |= 1
set_variant(s)
play_fac = rst_fac
rst = rsk[0] // reinit the restart
}
// right repeat
if (s.bar_type[0] == ':') {
if (b_typ & 2)
break
b_typ |= 2
s.rep_p = rst // :| to |:
if (rst == rsk[0])
s.rep_v = rsk // to know the number of variants
}
// 1st time repeat
if (s.text) {
if (s.text[0] == '1') {
if (b_typ & 1)
break
b_typ |= 1
s.rep_s = rsk = [rst] // repeat skip
// and memorize the restart
if (rst.bar_type
&& rst.bar_type.slice(-1) != ':')
rst.bar_type += ':' // restart confirmed
set_variant(s)
rst_fac = play_fac
}
// left repeat
} else if (s.rbstop == 2) {
if (s.bar_type.slice(-1) == ':') {
if (b_typ & 4)
break
b_typ |= 4
} else {
if (b_typ & 8)
break
b_typ |= 8
}
rst = s // new possible restart
rst_fac = play_fac
}
break
case C.GRACE:
if (s.time == 0 // if before beat at start time
&& abc_time == 0) {
dt = 0
if (s.sappo)
dt = C.BLEN / 16
else if (!s.next || s.next.type != C.NOTE)
|
| ︙ | ︙ | |||
386 387 388 389 390 391 392 | dt = d / 2 s.next.time -= dt d -= dt } d /= play_fac s.pdur = d v = s.v | < < < < < < < < < < < | 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 | dt = d / 2 s.next.time -= dt d -= dt } d /= play_fac s.pdur = d v = s.v break case C.TEMPO: if (s.tempo) play_fac = set_tempo(s) break } s = s.ts_next } // loop } // add() } // return } // ToAudio() // play some next symbols // // This function is called to start playing. |
| ︙ | ︙ | |||
428 429 430 431 432 433 434 | // - s_cur: current symbol (next to play) // must be set to the first symbol to be played at startup time // - s_end: stop playing on this symbol // this symbol is not played. It may be null. // - conf // - speed: current speed factor // must be set to 1 at startup time | | | | < | 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 |
// - s_cur: current symbol (next to play)
// must be set to the first symbol to be played at startup time
// - s_end: stop playing on this symbol
// this symbol is not played. It may be null.
// - conf
// - speed: current speed factor
// must be set to 1 at startup time
// - new_speed: new speed factor
// set by the user
// - internal variables
// - stim: start time
// - repn: don't repeat
// - repv: variant number
// - timouts: array of the current timeouts
// this array may be used by the upper function in case of hard stop
// - p_v: voice table used for MIDI control
// - methods
// - onend: (optional)
// - onnote: (optional)
// - note_run: start playing a note
// - get_time: return the time of the underlaying sound system
abc2svg.play_next = function(po) {
// handle a tie
function do_tie(not_s, d) {
var i,
s = not_s.s,
C = abc2svg.C,
v = s.v,
end_time = s.time + s.dur,
repv = po.repv
// search the end of the tie
while (1) {
|
| ︙ | ︙ | |||
474 475 476 477 478 479 480 481 | if (!s.rep_s[repv]) break s = s.rep_s[repv++] end_time = s.time } while (s.ts_next && !s.ts_next.dur) s = s.ts_next } | > | > | < | < | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 |
if (!s.rep_s[repv])
break
s = s.rep_s[repv++]
end_time = s.time
}
while (s.ts_next && !s.ts_next.dur)
s = s.ts_next
continue
}
if (s.time < end_time
|| !s.ti2) // if not end of tie
continue
i = s.notes.length
while (--i >= 0) {
note = s.notes[i]
if (note.tie_s == not_s) {
d += s.pdur / po.conf.speed
return note.tie_e ? do_tie(note, d) : d
}
}
}
return d
} // do_tie()
// set the MIDI controls up to now
function set_ctrl(po, s2, t) {
var i,
p_v = s2.p_v,
s = {
subtype: "midictl",
p_v: p_v,
v: p_v.v,
chn: p_v.chn
}
for (i in p_v.midictl) { // MIDI controls at voice start time
s.ctrl = Number(i)
s.val = p_v.midictl[i]
po.midi_ctrl(po, s, t)
}
for (s = p_v.sym; s != s2; s = s.next) {
if (s.subtype == "midictl")
po.midi_ctrl(po, s, t)
else if (s.subtype == 'midiprog')
po.midi_prog(po, s)
}
// if no %%MIDI, set 'grand acoustic piano' as the instrument
i = po.v_c[s2.v]
if (i == undefined)
po.v_c[s2.v] = i = s2.v < 9 ? s2.v : s2.v + 1
if (po.c_i[i] == undefined)
po.c_i[i] = 0 // piano
po.p_v[s2.v] = true // synchronization done
} // set_ctrl()
// start and continue to play
function play_cont(po) {
var d, i, st, m, note, g, s2, t, maxt, now,
C = abc2svg.C,
s = po.s_cur
// search the end of a sequence of variants
function var_end(s) {
var i, s2, s3,
a = s.rep_v || s.rep_s
ti = 0
for (i = 1; i < a.length; i++) {
s2 = a[i]
if (s2.time > ti) {
ti = s2.time
s3 = s2
}
}
for (s = s3; s != po.s_end; s = s.ts_next) {
if (s.time == ti)
continue
if (s.rbstop == 2)
break
}
po.repv = 1 // repeat end
return s
} // var_end()
if (po.stop) {
if (po.onend)
po.onend(po.repv)
return
}
|
| ︙ | ︙ | |||
555 556 557 558 559 560 561 562 563 564 565 |
maxt = t + po.tgen // max time = now + 'tgen' seconds
po.timouts = []
while (1) {
if (!po.p_v[s.v]) // if new voice
set_ctrl(po, s, t) // set the MIDI controls
switch (s.type) {
case C.BAR:
if (s.rep_p) { // right repeat
po.repv++
if (!po.repn // if repeat a first time
&& (!s.rep_v // and no variant (anymore)
| > | < < | > | | | < | < < < < < < > > | > | | | > > > > > > > > > > > > | 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 |
maxt = t + po.tgen // max time = now + 'tgen' seconds
po.timouts = []
while (1) {
if (!po.p_v[s.v]) // if new voice
set_ctrl(po, s, t) // set the MIDI controls
switch (s.type) {
case C.BAR:
s2 = null
if (s.rep_p) { // right repeat
po.repv++
if (!po.repn // if repeat a first time
&& (!s.rep_v // and no variant (anymore)
|| po.repv <= s.rep_v.length)) {
s2 = s.rep_p // left repeat
po.repn = true
} else {
if (s.rep_v)
s2 = var_end(s)
po.repn = false
}
}
if (s.rep_s) { // first variant
s2 = s.rep_s[po.repv] // next variant
if (s2) {
po.repn = false
if (s2 == s)
s2 = null
} else { // end of variants
s2 = var_end(s)
if (s2 == po.s_end)
break
}
}
if (s.bar_type.slice(-1) == ':' // left repeat
&& s.bar_type[0] != ':') // but not ::
po.repv = 1
if (s2) { // if skip
po.stim += (s.ptim - s2.ptim) / po.conf.speed
s = s2
while (s && !s.dur)
s = s.ts_next
if (!s)
break // no ending variant
t = po.stim + s.ptim / po.conf.speed
break
}
if (!s.part1) {
while (s.ts_next && !s.ts_next.seqst) {
s = s.ts_next
if (s.part1)
break
}
|
| ︙ | ︙ | |||
620 621 622 623 624 625 626 627 628 629 630 631 632 |
if (s && s != po.s_end) {
switch (s.type) {
case C.BAR:
break
case C.BLOCK:
if (s.subtype == "midictl")
po.midi_ctrl(po, s, t)
break
case C.GRACE:
for (g = s.extra; g; g = g.next) {
d = g.pdur / po.conf.speed
for (m = 0; m <= g.nhd; m++) {
note = g.notes[m]
| > > > | | > | | | 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 |
if (s && s != po.s_end) {
switch (s.type) {
case C.BAR:
break
case C.BLOCK:
if (s.subtype == "midictl")
po.midi_ctrl(po, s, t)
else if (s.subtype == 'midiprog')
po.midi_prog(po, s)
break
case C.GRACE:
for (g = s.extra; g; g = g.next) {
d = g.pdur / po.conf.speed
for (m = 0; m <= g.nhd; m++) {
note = g.notes[m]
if (!note.noplay)
po.note_run(po, g,
note.midi,
t + g.ptim - s.ptim,
//fixme: there may be a tie...
d)
}
}
break
case C.NOTE:
case C.REST:
d = s.pdur / po.conf.speed
if (s.type == C.NOTE) {
for (m = 0; m <= s.nhd; m++) {
note = s.notes[m]
if (note.tie_s // end of tie
|| note.noplay) // (%%voicecombine)
continue // already generated
po.note_run(po, s,
note.midi,
t,
note.tie_e ?
do_tie(note, d) : d)
}
}
// follow the notes/rests while playing
if (po.onnote && s.istart) {
i = s.istart
|
| ︙ | ︙ |
Changes to util/sndmem.js.
1 2 | // sndmem.js - generate play events for use with toaudio5 or tomidi5 // | | | 1 2 3 4 5 6 7 8 9 10 | // sndmem.js - generate play events for use with toaudio5 or tomidi5 // // Copyright (C) 2020-2022 Jean-Francois Moine // // This file is part of abc2svg. // // abc2svg is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
40 41 42 43 44 45 46 |
// @k = MIDI key + detune
// @t = audio start time (ms)
// @d = duration adjusted for speed (ms)
function note_run(po, s, k, t, d) {
po.a_e.push(new Float32Array([
s.istart,
t,
| | | 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
// @k = MIDI key + detune
// @t = audio start time (ms)
// @d = duration adjusted for speed (ms)
function note_run(po, s, k, t, d) {
po.a_e.push(new Float32Array([
s.istart,
t,
po.c_i[po.v_c[s.v]],
k,
d,
1,
s.v]))
} // note_run()
// return the play real time in seconds
|
| ︙ | ︙ | |||
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
0, // (time - unused)
-1, // MIDI control
s.ctrl,
s.val,
1,
s.v]))
} // midi_ctrl()
// define the play object
po = {
conf: { // configuration
speed: 1
},
tgen: 3600, // generate by (for) 1 hour
get_time: get_time,
midi_ctrl: midi_ctrl,
note_run: note_run,
// sndmem specific
a_e: []
}
// loop on the tunes
while (1) {
| > > > > > > > > > > | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
0, // (time - unused)
-1, // MIDI control
s.ctrl,
s.val,
1,
s.v]))
} // midi_ctrl()
// MIDI channel and/or program
function midi_prog(po, s) {
po.v_c[s.v] = s.chn
if (s.instr)
po.c_i[s.chn] = s.instr
} // midi_prog()
// define the play object
po = {
conf: { // configuration
speed: 1
},
tgen: 3600, // generate by (for) 1 hour
get_time: get_time,
midi_ctrl: midi_ctrl,
midi_prog: midi_prog,
note_run: note_run,
v_c: [], // voice to channel
c_i: [], // channel to instrument
// sndmem specific
a_e: []
}
// loop on the tunes
while (1) {
|
| ︙ | ︙ |
Changes to util/sndmid.js.
1 2 | // sndmid.js - audio output using HTML5 MIDI // | | | 1 2 3 4 5 6 7 8 9 10 | // sndmid.js - audio output using HTML5 MIDI // // Copyright (C) 2019-2023 Jean-Francois Moine // // This file is part of abc2svg. // // abc2svg is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. |
| ︙ | ︙ | |||
62 63 64 65 66 67 68 |
// @s = symbol
// @k = MIDI key + detune
// @t = audio start time (s)
// @d = duration adjusted for speed (s)
function note_run(po, s, k, t, d) {
var j,
a = (k * 100) % 100, // detune in cents
| | | < < < < < < < < < < < < < < < < < | 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
// @s = symbol
// @k = MIDI key + detune
// @t = audio start time (s)
// @d = duration adjusted for speed (s)
function note_run(po, s, k, t, d) {
var j,
a = (k * 100) % 100, // detune in cents
c = po.v_c[s.v],
i = po.c_i[c]
k |= 0 // remove the detune value
t *= 1000 // convert to ms
d *= 1000
if (a && Midi5.ma.sysexEnabled) { // if microtone
// fixme: should cache the current microtone values
po.op.send(new Uint8Array([
0xf0, 0x7f, // realtime SysEx
0x7f, // all devices
0x08, // MIDI tuning standard
0x02, // note change
|
| ︙ | ︙ | |||
113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
// send a MIDI control
function midi_ctrl(po, s, t) {
po.op.send(new Uint8Array([0xb0 + s.chn,
s.ctrl, s.val]),
t * 1000)
} // midi_ctrl()
// MIDI output is possible,
// return the possible ports in return to get_outputs()
function send_outputs(access) {
var o, os,
out = []
| > > > > > > > > > > > > > > > > > > > > > > > > > > | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
// send a MIDI control
function midi_ctrl(po, s, t) {
po.op.send(new Uint8Array([0xb0 + s.chn,
s.ctrl, s.val]),
t * 1000)
} // midi_ctrl()
// change the channel and/or send a MIDI program
function midi_prog(po, s) {
var i,
c = s.chn
po.v_c[s.v] = c
if (s.instr != undefined)
return
i = po.c_i[c]
// at channel start, reset and initialize the controllers
if (i == undefined) {
//fixme: does not work with fluidsynth
po.op.send(new Uint8Array([0xb0 + c, 121, 0]))
if (s.p_v.midictl) {
for (i in s.p_v.midictl)
po.op.send(new Uint8Array([0xb0 + c,
i,
s.p_v.midictl[i]]))
}
}
po.c_i[c] = i = s.instr
po.op.send(new Uint8Array([0xc0 + c, i & 0x7f])) // program
} // midi_prog()
// MIDI output is possible,
// return the possible ports in return to get_outputs()
function send_outputs(access) {
var o, os,
out = []
|
| ︙ | ︙ | |||
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
s_end: i_end, // last music symbol / null
s_cur: i_start, // current music symbol
// repn: false, // don't repeat
repv: i_lvl || 0, // repeat variant number
tgen: 2, // generate by 2 seconds
get_time: get_time,
midi_ctrl: midi_ctrl,
note_run: note_run,
timouts: [],
// MIDI specific
op: op, // output port
c_i: [] // channel to instrument
}
if (0) {
// temperament
op.send(new Uint8Array([
0xf0, 0x7f, // realtime SysEx
0x7f, // all devices
| > > | 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
s_end: i_end, // last music symbol / null
s_cur: i_start, // current music symbol
// repn: false, // don't repeat
repv: i_lvl || 0, // repeat variant number
tgen: 2, // generate by 2 seconds
get_time: get_time,
midi_ctrl: midi_ctrl,
midi_prog: midi_prog,
note_run: note_run,
timouts: [],
// MIDI specific
op: op, // output port
v_c: [], // voice to channel
c_i: [] // channel to instrument
}
if (0) {
// temperament
op.send(new Uint8Array([
0xf0, 0x7f, // realtime SysEx
0x7f, // all devices
|
| ︙ | ︙ |