abcpp 1.3.2


Guido Gonzato, Ph.D.

1. Introduzione

abcpp e' un preprocessore progettato per trattare i file ABC (http://staffweb.cms.gre.ac.uk/~c.walshaw/abc/), e non solo quelli. Supporta l'output condizionale, macro, inclusione di file e consente di rinominare i simboli. L'ho scritto per due motivi: prima di tutto, volevo superare le incompatibilita' che ci sono tra diversi programmi per ABC; e poi volevo essere in grado di scrivere file ABC piu' portabili e leggibili.

abcpp trae ispirazione dai preprocessori del C e di S-Lang (http://www.s-lang.org), e supporta varie direttive che permettono un po' di trucchi. Si scrive il file ABC con direttive come #define o #ifdef, definendo delle macro o escludendo parti di testo a seconda di determinate condizioni. Quindi, si preprocessa il file con abcpp, producendo un file di output adatto al particolare programma o voce. In breve, botte piena e moglie ubriaca!

La home page di abcpp e altri programmi di utilita' per ABC e' http://abcplus.sourceforge.net.

1.1. Output condizionale

Normalmente, se si scrive per una certa applicazione ABC si possono usare estensioni che altri programmi magari non supportano. Ad esempio, io scrivo soprattutto brani corali che poi converto con abcm2ps (http://moinejf.free.fr). abcm2ps supporta questo tipo di campo Q:

Q: "Allegro" 1/4 = 100

e mi va bene, e' standard nella musica stampata. Pero', abc2midi (http://abc.sourceforge.net/abcMIDI) non accetta questa estensione, ma solo un campo Q: fatto cosi':

Q: 1/4 = 100

Ci sono molte incompatibilita' come questa. Quindi, se volessi ascoltare il brano che ho scritto dovrei modificare il sorgente ABC! Non esiste...

La soluzione e' usare direttive condizionali, come #ifdef... #else... #endif, per escludere parti che certe applicazioni non supportano:

#ifndef MIDI
Q: "Allegro" 1/4 = 100
#else
Q: 1/4 = 100
#endif

L'output condizionale permette anche di estrarre parti di un brano:

#ifdef SOPRANO ALL
V: 1
...
#endif
#ifdef ALTO ALL
V: 2
...
#endif
#ifdef TENOR ALL
V: 3
...
#endif
#ifdef BASS ALL
V: 1
...
#endif

1.2. Macro

Ho sempre pensato che i nomi delle decorazioni come !crescendo(! o !diminuendo(! sono troppo lunghi. Preferirei usare un equivalente piu' corto, diciamo !<(! o !>(!, ma nessuna applicazione ABC che io conosca supporta macro di questo tipo.

La soluzione e' ridefinire i nomi delle decorazioni. Inoltre, usando le macro si possono ridefinire i nomi dei campi:

#define !<(! !crescendo(!
#define !<)! !crescendo)!
#define Title: T:
#define Composer: C:
#define System: %%staves
#ifdef MIDI
#define !x! z
#else
#define !x! x
#endif

1.3. Inclusione di file

Non e' elegante riempire il sorgente ABC di definizioni di macro. E' meglio scriverle in un file esterno, quindi includerlo nel sorgente:

#include <fancyheader.abp>
#include "my own macros.abp"

2. Installazione

Scompattate l'archivio, date il comando 'make' e spostate abcpp in una directory nel $PATH. Suggerisco /usr/local/bin per i sistemi Unix, C:\WINDOWS per Windows 9x/ME.

3. Direttive supportate

D'ora in avanti, <qualcosa> indica un argomento obbligatorio, mentre [qualcosa] un argomento opzionale.

Le direttive devono iniziare alla colonna 1, e non appariranno nell'output. La corrente versione supporta le seguenti direttive:

#
usato per inserire commenti.
#abc
annulla la definizione delle note italiane; vedi #doremi
#define <definizione> <sostituzione>''
definisce una semplice macro (fino a 100); <sostituzione> sostituisce <definizione>. Le macro non si possono usare in definizioni successive; cioe', non si puo' fare
#define GU   Guido
#define GG   GU_Gonzato
Le definizioni di una macro non possono contenere spazi, a meno che non vengano racchiuse tra virgolette. Se un carattere " (doppie virgolette) deve essere sostituito, precedetelo con un backslash: \". Lo stesso vale per il carattere backslash.
#define \"C \"^Do 
In alternativa, usate il carattere '~' dove dovrebbe apparire uno spazio. Ad esempio,

#define GG Guido~Gonzato
#define AMP "abcpp mi piace"
espande 'GG' in 'Guido Gonzato', e AMP in "abcpp mi piace" (senza le virgolette). Se non mettete <sostituzione> e <definizione> esiste, la macro <definizione> verra' cancellata. Per esempio,
#define !lph! !longphrase!
...
#define !lph!
annulla la definizione di !lph! e incrementa il numero di macro disponibili. Notate che non e' la stessa cosa di definire una macro vuota! Per definire una macro con una stringa vuota, si fa cosi':
      #define VUOTA ""

Infine, per impedire una sostituzione di macro, si usa il carattere '\' per saltare la macro. Per esempio:

#define do c
#define re d
#define mi e
C: Gui\do, il \re dei \mi\mi
non sostituisce le sillabe 'do 're' 'mi' nel campo C:.
#doremi
definisce le macro 'do', 're', 'mi', 'fa', 'sol', 'la', 'si' (anche le versioni in maiuscolo) che verranno sostituite da 'c', 'd', 'e', 'f', 'g', 'a', 'b'.

#ifdef <def1> [def2 def3 ...]
le linee che seguono #ifdef, e prima del successivo #endif o #else, verranno preprocessate solo se almeno uno dei simboli e' definito. Non si possono annidare definizioni #ifdef, ed e' obbligatorio terminarle con #endif.

#ifndef <def1> [def2 def3 ...]
come #ifdef, ma la condizione e' valida se nessuno dei simboli e' definito. Non si possono annidare definizioni #ifndef, ed e' obbligatorio terminarle con #endif.
#else
stabilisce una condizione alternativa dopo #ifdef o #ifndef.
#elifdef <def1> [def2 def3 ...]
equivalente a #else seguito da #ifdef.

#elifndef <def1> [def2 def3 ...]
equivalente a #else seguito da #ifndef.
#endif
termina una condizione #ifdef o #ifndef.

#include <filename> o "filename"
preprocessa <filename> e lo include nell'output. Se il nome del file e' racchiuso tra <...>, abcpp cerca il file nella sua directory di libreria: C:\ABCPP sotto Windows, oppure /usr/share/abcpp sotto Unix.

#undefine
sospende la sostituzione delle macro per le linee seguenti.

#redefine
riprende la sostituzione delle macro.

4. Uso

abcpp e' un programma a linea di comando. Si usa in questo modo:

$ abcpp [-s] [-c] [-h] [-def1 -def2 ...] [inputfile] [outputfile]
-s
toglie all'input le decorazioni e le linee w:
-c
toglie all'input gli accordi di accompagnamento
-p
cambia gli accordi delimitati da '+' in accordi delimitati da '[]'
-h
mostra un aiuto

4.1. Esempio 1: Macro e condizionali

Il brano ABC che segue contiene direttive per creare diversi header, a soconda che il simbolo MIDI sia definito o no. Alcuni simboli e decorazioni sono ridefiniti per creare un look alla M-Tx:

% my_music.abp
%
#define Index:  X:
#define Title:  T:
#define Meter:  M:
#define Length: L:
#define Tempo:  Q:
#define Voice:  V:
#define Key:    K:
#define Style:  %%staves
#define Duet    [1~2]
#define !<(!  !crescendo(!
#define !<)!  !crescendo)!
#define !>(!  !diminuendo(!
#define !>)!  !diminuendo)!
#define !H!   !fermata!
Index: 1
Title: ABCPP test
Meter: 4/4
Length: 1/4
#ifdef MIDI
Tempo: 1/4 = 80
#else
Tempo: "Allegro"
Voice: 1 clef=treble name="Flute"
Voice: 2 clef=treble name="Violin"
Style: Duet
#endif
Key: C
%
Voice: 1
cdef|!<(!cde!<)!f|!>(!CDE!>)!F|!H!G4|
Voice: 2
ccee|ccgg        |g f e d     |!H!C4|
%
% End of file my_music.abp

Non e' male, ma si puo' fare di meglio. Scriviamo un file chiamato my_defines.abp, con scritto:

# my_defines.abp
#
#define Index:  X:
#define Title:  T:
#define Meter:  M:
#define Length: L:
#define Tempo:  Q:
#define Voice:  V:
#define Key:    K:
#define Style:  %%staves
#define Duet    [1~2]
#define !<(!  !crescendo(!
#define !<)!  !crescendo)!
#define !>(!  !diminuendo(!
#define !>)!  !diminuendo)!
#define !H!   !fermata!

Ora riscriviamo my_music.abp:

% my_music.abp
%
#
#include my_defines.abp
#
Index: 1
Title: ABCPP test
Meter: 4/4
Length: 1/4
#ifdef MIDI
Tempo: 1/4 = 80
#else
Tempo: "Allegro"
Voice: 1 clef=treble name="Flute"
Voice: 2 clef=treble name="Violin"
Style: Duet
#endif
Key: C
%
Voice: 1
cdef|!<(!cde!<)!f|!>(!CDE!>)!F|!H!G4|
Voice: 2
ccee|ccgg        |g f e d     |!H!C4|
%
% End of file my_music.abp

Vi piace cosi'? A me sembra molto piu' leggibile. Siamo pronti per preprocessare my_music.abp con abcpp:

$ abcpp my_music.abp my_music_nomidi.abc
$ abcpp -MIDI my_music.abp my_music_midi.abc

La prima linea non definisce alcun simbolo, mentre la seconda definisce il simbolo MIDI. Quest'ultimo viene usato per produrre un header alternativo. Otteniamo quindi due file ABC: uno per la stampa, l'altro per fare un file midi.

Se non ve ne siete accorti, notate che ho usato l'estensione .abp per i file ABC con direttive abcpp.

4.2. Esempio 2: note italiane

In Italia, le note vengono scritte con la notazione di Guido d'Arezzo: do re mi fa sol la si -> c d e f g a b. Utilizzando alcune macro predefinite e un po' di attenzione, potrete scrivere file ABC usando do re mi... invece delle note anglosassoni. Pero' tale sostituzione non deve avvenire nelle linee w:.

Scriviamo un semplice brano:

% doremi.abp
#doremi
X: 1
T: Do \re \mi -> c d e
C: Gui\do
M: 4/4
L: 1/4
Q: 1/4 = 100
K: C
%
#define !tieni! !fermata!
DO RE MI FA|SOL LA SI !tieni!do|do SI LA SOL|FA MI RE DO|
#abc
w: do re mi fa sol la si do, do si la sol fa mi re do.
#doremi
DO RE MI FA|SOL LA SI !tieni!do|do SI LA SOL|FA MI RE DO|
#abc
w: do re mi fa sol la si do, do si la sol fa mi re do.
%
% End of file doremi.abp

Che ne dite? Questo trucchetto consente di scrivere file ABC anche a chi non ha dimestichezza con le note in notazione anglosassone (studenti...). Notate che le sillabe nell'header iniziano con '\': questo per impedire che vengano sostituite dalla loro definizione.

4.3. Esempio 3: estrazione di parti

Il file ABC seguente e' scritto per SATB. Vediamo come fare per ottenere quattro diversi file ABC, uno per voce:

X: 1
T: Part extraction
C: Guido Gonzato
M: 4/4
L: 1/4
Q: 1/4 = 60
%%staves [S A T B]
V: S clef=treble name="Soprano" sname="S"
V: A clef=treble name="Alto"    sname="A"
V: T clef=treble name="Tenor"   sname="T"
V: B clef=bass   name="Bass"    sname="B"
K: C
%
#ifdef SOPRANO ALL
[V: S] cccc|eeee|gggg|c'c'c'c'|
#endif
#ifdef ALTO ALL
[V: A] cccc|GGGG|cccc|eeee|
#endif
#ifdef TENOR ALL
[V: T] CCCC|EEEE|GGGG|cccc|
#endif
#ifdef BASS ALL
[V: B] CCCC|G,G,G,G,|CCCC|EEEE|
#endif
%

Create i quattro file con questi comandi:

$ abcpp -SOPRANO parts-soprano.abc
$ abcpp -ALTO parts-alto.abc
$ abcpp -TENOR parts-tenor.abc
$ abcpp -BASS parts-bass.abc

e il brano completo con:

$ abcpp -ALL parts.abc parts-all.abc

Normalmente, per estrarre le parti sara' meglio usare il programma abc2prt; vedete alla home page.

5. + Esempio 4: Accordi in italiano

Come e' noto, gli accordi di accompagnamento in ABC sono definiti solo con le note anglosassoni. Se volete stamparli con le note italiane, ecco come si puo' fare:

% doremi.abp
#ifndef MIDI
#define \"C\" \"^Do\"
#define \"G\" \"^Sol\"
#endif
X: 1
T: do re mi
M: 4/4
L: 1/4
K: C
%
"C"CDEF|"G"GABc|"C"C2"G"G2|"C"C2z2|

6. Altre caratteristiche

6.1. Opzioni di linea di comando

-s
questa opzione toglie tutte le linee w: e le decorazioni. Puo' servire per quelle applicazioni ABC che seguono il vecchio standard 1.6.
-c
toglie tutti gli accordi di accompagnamento. In molti file ABC, gli "accordi di accompagnamento" sono in realta' delle annotazioni testuali. abc2midi cerchera' di suonarli, ovviamente con orribili risultati; meglio toglierli.
-p
cambia gli accordi delimitati da '+' in accordi delimitati da '' e ''
-b
toglie i '!' singoli (estensione abc2win per forzare una nuova linea).
-k
sostituisce i '!' singoli con !break!.
-h
mostra l'help.

6.2. Disabilitare le macro

Le definizioni di macro possono interferire l'una con l'altra. Per impedire una sostituzione in certi punti, usate il carattere '\'. Ad esempio, se la sillaba 'do' viene #definita come 'c', la parola 'Guido' diventera' 'Guic', ma 'Gui\do' diventera' 'Guido'.

6.3. Limitazioni

  1. possono esserci fino a 20 definizioni nella linea di comando.
  2. una direttiva puo' contenere fino a 20 simboli.
  3. la lunghezza di un simbolo va da 0 a 50 caratteri.
  4. possono esserci fino a 100 macro.
  5. le definizioni di macro possono interferire l'una con l'altra.

Prima o poi trovero' il tempo di cambiare tutte le strutture statiche di abcpp con equivalenti dinamiche.


7. Da fare...

  1. se -s e' attiva, togliere anche le linee con simboli ridefiniti con U:
  2. una versione grafica con Fltk (http://www.fltk.org)
  3. implementare il campo 'Dyn:' per aggiungere una linea di dinamica che si fonde con la prossima linea (reso superfluo dal campo d: di abcm2ps)
  4. la stessa cosa, con il campo 'Text:'
  5. suggerimenti?

8. Copyright e Licenza


abcpp e' copyright di Guido Gonzato <guido . gonzato at univr . it> 2001-2003, e viene rilasciato sotto la General Public Licence. Se trovate che questo programma sia utile, o trovate degli errori, o avete critiche o suggerimenti, scrivetemi. abcpp mi e' molto utile, spero che possa essere utile anche ad altre persone.

Ciao,

Guido =8-)



This document was generated using AFT v5.095