3
{ Decide which lines of paragraphs go where; test total duration of lines. }
5
interface uses control, globals;
7
procedure testParagraph;
8
procedure describeParagraph;
9
procedure paragraphSetup (var voice: voice_index0);
10
procedure includeStartString;
12
implementation uses mtx, strings, lyrics, mtxline, uptext,
15
procedure includeStartString;
16
var voice: voice_index;
17
mus: paragraph_index0;
18
begin for voice:=1 to nvoices do
19
begin mus:=musicLineNo(voice); if mus>0 then
20
P[mus]:=startString(voice)+P[mus];
24
function describe(nbar,extra: integer): string;
25
begin describe:=toString(nbar)+' bar'+plural(nbar)+' + '+
26
toString(extra)+'/64 notes';
29
procedure testParagraph;
30
var voice, leader, nv: voice_index0;
31
mus: paragraph_index0;
32
extra, l, nbar: integer;
34
nbars:=0; pickup:=0; nleft:=0; if top>bottom then exit;
35
pickup:=0; nv:=0; leader:=0; multi_bar_rest := false;
36
for voice:=top to bottom do
37
begin mus:=musicLineNo(voice);
38
if mus>0 then {* -------------- Voice is present ---- }
39
begin inc(nv); line_no:=orig_line_no[mus];
41
if multi_bar_rest and (nv>1) then error(
42
'Multi-bar rest allows only one voice',print);
43
if not pmx_preamble_done then
44
if voice=top then pickup:=l
45
else if pickup<>l then
46
error3(voice,'The same pickup must appear in all voices');
47
nbar := numberOfBars(voice); extra := extraLength(voice);
48
if multi_bar_rest and ((nbar>0) or (extra>0)) then error3(voice,
49
'Multi-bar rest allows no other rests or notes');
50
if (nbar>nbars) or (nbar=nbars) and (extra>nleft) then
51
begin nbars:=nbar; nleft:=extra; leader:=voice; end;
52
if not final_paragraph and (meternum>0) and (extra>0) then
53
begin writeln('Line has ', describe(nbar,extra));
54
error(' Line does not end at complete bar',print);
56
if pmx_preamble_done and (l>0) and (meternum>0) then
57
error3(voice,'Short bar with no meter change');
60
if not pmx_preamble_done then
62
xmtrnum0 := pickup/one_beat; { Don't want an integer result }
63
if beVerbose then writeln ('Pickup = ', pickup, '/64');
66
for voice:=top to bottom do if musicLineNo(voice)>0 then
68
begin mus:=musicLineNo(voice);
69
line_no:=orig_line_no[mus];
70
if (numberOfBars(voice)<>numberOfBars(leader))
71
or (extraLength(voice)<>extraLength(leader)) then
73
writeln('Following line has ',
74
describe(numberOfBars(voice), extraLength(voice)));
75
writeln(musicLine(voice));
76
writeln('Longest line has ',
77
describe(numberOfBars(leader), extraLength(leader)));
78
writeln(musicLine(leader));
79
error('Line duration anomaly',print);
84
procedure describeParagraph;
85
var voice: voice_index0;
86
begin writeln('---- Paragraph ',paragraph_no,
87
' starting at line ', orig_line_no[1], ' bar ', bar_no);
88
for voice:=top to bottom do describeVoice(voice,lyricsReport(voice));
91
procedure paragraphSetup (var voice: voice_index0);
97
procedure maybeUptext(i: integer);
98
begin if not doUptext then exit;
99
if (length(w)=1) then if (voice=nvoices) then
100
warning('Uptext line below bottom voice should be labelled',print);
101
if length(w)=1 then {* Standard chord line ------ }
102
begin k:=voice+1; if k>nvoices then dec(k);
103
setUptextLineNo(k,i);
105
else {* Labelled chord line ---- }
106
begin predelete(w,1); k:=findVoice(w);
107
if k=0 then error('Uptext line belongs to unknown voice',print)
108
else setUptextLineNo(k,i);
112
procedure maybeChords(i: integer);
113
begin if not doChords then exit;
114
if (length(w)=1) and (voice=0) and pedanticWarnings then
115
warning('Chord line above top voice should be labelled',print);
116
if length(w)=1 then {* Standard chord line ------ }
117
begin k:=voice; if k=0 then k:=1;
120
else {* Labelled chord line ---- }
121
begin predelete(w,1); k:=findVoice(w);
122
if k=0 then error('Chord line belongs to unknown voice',print)
123
else setChordLineNo(k,i);
127
procedure analyzeParagraph;
128
var i: paragraph_index;
129
begin voice:=0; bottom:=0; top:=nvoices+1;
130
clearLabels; clearTags; clearUptext;
131
for i:=1 to para_len do { ----- Paragraph analysis main loop ----- }
132
if (P[i]<>'') and (P[i,1]<>comment) then
134
w:=NextWord(P[i],blank,colon); line_no := orig_line_no[i];
136
is_labelled := (w[l]=colon) and (w[l-1]<>barsym);
138
begin P_keep := P[i]; predelete(P[i],l); shorten(w,l-1);
139
k:=findVoice(w); { First look for a voice label }
141
begin voice:=k; setMusicLineNo(voice,i);
143
else if w[1]='L' then maybeLyrics(voice,i,w)
144
else if w[1]='C' then maybeChords(i)
145
else if w[1]='U' then maybeUptext(i)
146
else begin {* ------------ Maybe Space command ------------ }
147
if startsWithIgnoreCase(w,'SPACE') then
148
begin setSpace(P[i]); must_respace:=true;
150
else {* ------------ Maybe Voices command ------------ }
151
if startsWithIgnoreCase(w,'VOICES') then
152
begin selectVoices(P[i]); must_restyle:=true;
154
else begin {* Could be sticky attribute *}
155
P[i] := P_keep; is_labelled := false;
156
if not isNoteOrRest(w) then error('Unknown line label',print);
160
if not is_labelled then
161
begin inc(voice); setMusicLineNo(voice,i);
163
if voice>bottom then bottom:=voice;
164
if (voice>0) and (voice<top) then top:=voice;
168
procedure obliterate;
169
var i: paragraph_index;
172
for i:=1 to para_len do if startsWithIgnoreCase(P[i],'only:')
173
then begin new_only:=P[i]; P[i]:='%'; end;
174
if new_only<>'' then setOnly(new_only)
175
else for i:=1 to para_len do if omitLine(i) then P[i]:='%';
178
begin obliterate; analyzeParagraph; reviseLyrics;