summaryrefslogtreecommitdiff
path: root/macros/texmuse/Program
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/texmuse/Program
Initial commit
Diffstat (limited to 'macros/texmuse/Program')
-rw-r--r--macros/texmuse/Program/texmuse.mf990
-rw-r--r--macros/texmuse/Program/texmuse.tex624
-rw-r--r--macros/texmuse/Program/txmfont.mf405
3 files changed, 2019 insertions, 0 deletions
diff --git a/macros/texmuse/Program/texmuse.mf b/macros/texmuse/Program/texmuse.mf
new file mode 100644
index 0000000000..21fe02800c
--- /dev/null
+++ b/macros/texmuse/Program/texmuse.mf
@@ -0,0 +1,990 @@
+% Look for "to make flexible" and "to change into" items, and "necessary?"
+numeric temp_a[], temp_b;
+numeric horizontal_span, vertical_span;
+numeric no_of_instr, char_no, index, instr_, last_note[];
+numeric vert_shift, instr_shift[];
+numeric quanta[], width[], stretched_width[], to_stretch, last_stretch;
+numeric note_axis[], ltx[], rtx[], rtx_[]; % rtx_ is the extreme of the current char.
+numeric correction[]; % x in the equations
+numeric note, a[], b[], c[], d[], e[], f[], g[];
+%numeric aggr_note[][]; % Highest (if #1 is 1) or lowest (#1=-1) note at instr_
+numeric aggr_note[][][];
+numeric instr_clef[], lowest_note[], highest_note[];
+numeric stem_dir[][], stem_coef[], stem_extreme;
+numeric i, j, s; % To change into i_, j_
+numeric stem_axis[][];
+numeric multi_beam_offset;
+pair stem_point[][];
+path temp_path;
+picture note_[][]; % Old char_; [index][instr_]
+picture pict_, _pict;
+numeric next_level, curr_level;
+string arg_text, temp_text;
+string to_do, doing_, horizontal_elements[];
+string curr_instr;
+string staff_[];
+numeric bar_type[]; % Three-digit number. :|: is 111. | is (0)10.
+numeric clef_sep, key_sep;
+numeric total_natural_length; % In pt
+numeric total_factors; % Total spacing factors (results of sf_, function of the quanta)
+numeric spacing_unit; % What the stretching function multiplies. Default: a sharp's width
+numeric least_spaced; % Quanta of the least-spaced rhythmic value. Usually 32 or 16
+numeric no_of_blocks; % Number of blocks so far included in the line.
+numeric index_offset; % To convert the first index of a line into 1
+numeric no_of_beams; % Number of beams in the current line.
+string beam_list[]; % The different beams to be traced at the end of the line.
+string tie_list[];
+numeric no_of_ties, tie_[], open_tie[], closed_tie[];
+string clef_changes;
+
+%Initialization
+to_do:="";
+for octave=1 upto 8:
+ g[octave]=3.5*(octave-4);
+ a[octave]=g[octave]-3;
+ b[octave]=g[octave]-2.5;
+ c[octave]=g[octave]-2;
+ d[octave]=g[octave]-1.5;
+ e[octave]=g[octave]-1;
+ f[octave]=g[octave]-.5;
+endfor;
+index:=0;
+instr_:=0;
+stem_length=3.5;
+clef_sep=2interline;
+key_sep=horizontal_axis;
+horizontal_span:=10regular_width;
+vertical_span:=10interline;
+multi_beam_offset:=1/4;
+note_axis0:=0;
+width0 := 0;
+stretched_width0:=0;
+curr_level:=0;
+next_level:=0;
+total_natural_length:=0;
+least_spaced:=32;
+spacing_unit:=horizontal_axis+framingspace;
+first_included:=1;
+no_of_blocks := 0;
+total_factors := 0;
+next_char:=1;
+no_of_beams := 0;
+no_of_ties:=0;
+index_offset := 0;
+
+% Level-1 elements.
+
+def add_halfheads(text nhs) =
+ for s=nhs:
+ note:=s+instr_clef[instr_];
+ lowest_note[instr_] := min(lowest_note[instr_],note);
+ highest_note[instr_] := max(highest_note[instr_],note);
+ half_note_head shifted(0,interline*note); % To change into notehead.
+% Ledger lines follow. To make flexible.
+ if (note>3.5) or (note<-1.5) :
+ pickup penrazor xscaled line_thick rotated 90;
+ for i:=(1+note/abs(note)*3) step (note/abs(note)) until note :
+ draw (-.5regular_width,i*interline)--(.5regular_width,i*interline);
+ endfor;
+ fi;
+ endfor;
+ stem_axis[index][instr_] := xpart(stem_point[index][instr_]);
+ find_extremes(nhs); % Vertical extremes
+ enddef;
+
+def add_noteheads(text nhs) =
+ for s=nhs:
+ note:=s+instr_clef[instr_];
+ lowest_note[instr_] := min(lowest_note[instr_],note);
+ highest_note[instr_] := max(highest_note[instr_],note);
+ regular_note_head shifted(0,interline*note); % To change into notehead.
+ note_axis[index] := 1/2regular_width;
+ width[index] := 1/2regular_width;
+% Ledger lines follow. To make flexible.
+ if (note>3.5) or (note<-1.5) :
+ pickup penrazor xscaled line_thick rotated 90;
+ for i:=(1+note/abs(note)*3) step (note/abs(note)) until note :
+ draw (-.5regular_width,i*interline)--(.5regular_width,i*interline);
+ endfor;
+ fi;
+ endfor;
+ stem_axis[index][instr_] := xpart(stem_point[index][instr_]);
+ find_extremes(nhs); % Vertical extremes
+ enddef;
+
+def add_rest(expr p, q) =
+ addto currentpicture also rest_[p] shifted (0, q*interline);
+ width[index] := rest_width[p];
+ enddef;
+
+def add_wholeheads(text nhs) =
+ for s=nhs:
+ note:=s+instr_clef[instr_];
+ lowest_note[instr_] := min(lowest_note[instr_],note);
+ highest_note[instr_] := max(highest_note[instr_],note);
+ whole_note shifted(0,interline*note); % To change into notehead.
+% Ledger lines follow. To make flexible.
+ if (note>3.5) or (note<-1.5) :
+ pickup penrazor xscaled line_thick rotated 90;
+ for i:=(1+note/abs(note)*3) step (note/abs(note)) until note :
+ draw (-.5regular_width,i*interline)--(.5regular_width,i*interline);
+ endfor;
+ fi;
+ endfor;
+ stem_axis[index][instr_] := xpart(stem_point[index][instr_]);
+ find_extremes(nhs); % Vertical extremes
+ enddef;
+
+
+def barline_(expr number) =
+ %The first digit indicates pre-barline stuff.
+ temp:=floor(number/100);
+ %The middle digit indicates the barline itself.
+ temp:=floor(number/10 - 10temp);
+ if temp = 1 :
+ pickup penrazor xscaled line_thick;
+ draw (0, min(scantokens staff_[instr_])*interline)--(0, max(scantokens staff_[instr_])*interline);
+% rtx_[instr_]:=-1/2regular_width;
+ stem_dir[index][instr_] := 0;
+ elseif temp=2 :
+ pickup penrazor xscaled line_thick;
+ draw (0, min(scantokens staff_[instr_])*interline)--
+ (0, max(scantokens staff_[instr_])*interline);
+ pickup penrazor xscaled 1/2interline;
+ draw (1/2interline+1/2line_thick, min(scantokens staff_[instr_])*interline)--
+ (1/2interline+1/2line_thick, max(scantokens staff_[instr_])*interline);
+% rtx_[instr_]:=-1/2regular_width;
+% ltx[instr_]:=interline-1/2regular_width;
+ width[index] := 3/4interline + 1/2line_thick;
+ stem_dir[index][instr_] := 0;
+ fi;
+ %The last digit indicates post-barline stuff.
+ enddef;
+
+% Level-2 elements.
+
+def add_dot (suffix nhs) =
+ temp_text:= str nhs;
+ if curr_level < 2 : % Deferring...
+ to_do := if next_level>0 : to_do & fi curr_instr & "add_dot(" & temp_text & ");";
+ curr_instr := "";
+ next_level:=2;
+ else: % Doing...
+ for i:=nhs :
+ note:=floor(i+instr_clef[instr_])+.5;
+ pickup pencircle scaled 1/3interline;
+ drawdot (1/2regular_width+framingspace, note*interline);
+ endfor;
+ fi;
+ enddef;
+
+def add_flag (suffix number) =
+ temp_text := str number;
+ if curr_level < 2 : % Deferring...
+ to_do := if next_level>0 : to_do & fi curr_instr & "add_flag(" & temp_text & ");";
+ curr_instr := "";
+ next_level:=2;
+ else: % Doing...
+ temp_a := scantokens temp_text;
+ if number = 1 :
+ eighth_flag((0, interline*aggr_note[index][instr_][-stem_coef[instr_]]))
+ if stem_coef[instr_]=1 :
+ reflectedabout ((stem_axis[index][instr_],0),(stem_axis[index][instr_],1));
+ rtx_[instr_]:=max(rtx_[instr_],horizontal_axis);
+ else:
+ rotatedaround ((0, interline*aggr_note[index][instr_][-stem_coef[instr_]]),180)
+ fi;
+ fi;
+ fi;
+ enddef;
+
+def regular_stem =
+ if curr_level<2: % Deferring...
+ to_do := if next_level>0 : to_do & fi curr_instr & "regular_stem;";
+ curr_instr := "";
+ next_level:=2;
+ else: % Doing...
+ if unknown stem_dir[index][instr_] :
+ stem_dir[index][instr_] = stem_coef[instr_];
+ fi;
+ pickup penrazor xscaled line_thick;
+ draw (stem_axis[index][instr_],interline*aggr_note[index][instr_][stem_dir[index][instr_]])
+ --(stem_axis[index][instr_],
+ interline*(aggr_note[index][instr_][stem_dir[index][instr_]]+stem_dir[index][instr_]*stem_length));
+ fi;
+ enddef;
+
+% Level-3 elements.
+
+def add_flat(suffix notext) =
+ temp_text:=str notext;
+ if curr_level<3 :
+ to_do := if next_level>0 : to_do & fi curr_instr & "add_flat(" & temp_text & ");";
+ curr_instr := "";
+ next_level :=3;
+ else:
+ temp_a:= scantokens temp_text;
+ addto currentpicture also flat shifted (-1/2regular_width-ltx[instr_],interline*(_note(temp_a,instr_,index)));
+ ltx[instr_] := ltx[instr_]+horizontal_axis;
+ fi;
+ enddef;
+
+def add_natural(suffix notext) =
+ temp_text:=str notext;
+ if curr_level<3: % Deferring...
+ to_do := if next_level>0 : to_do & fi curr_instr & "add_natural(" & temp_text & ");";
+ curr_instr := "";
+ next_level:=3;
+ else: % Doing...
+ temp_a:= scantokens temp_text;
+ addto currentpicture also natural shifted (-1/2regular_width-ltx[instr_],interline*(_note(temp_a,instr_,index)));
+ ltx[instr_] := ltx[instr_]+horizontal_axis;
+ fi;
+ enddef;
+
+def add_sharp(suffix notext) =
+ temp_text:=str notext;
+ if curr_level<3: % Deferring...
+ to_do := if next_level>0 : to_do & fi curr_instr & "add_sharp(" & temp_text & ");";
+ curr_instr := "";
+ next_level:=3;
+ else: % Doing...
+ temp_a:= scantokens temp_text;
+ addto currentpicture also sharp shifted (-1/2regular_width-ltx[instr_],interline*(_note(temp_a,instr_,index)));
+ ltx[instr_] := ltx[instr_]+horizontal_axis-framingspace;
+ fi;
+ enddef;
+
+% Level-4 elements.
+
+% Level-5 elements.
+
+def beam(text t_) =
+ no_of_beams := no_of_beams + 1;
+ beam_list[no_of_beams] := decimal(instr_);
+ for i:= t_ :
+ beam_list[no_of_beams] := beam_list[no_of_beams] & "," & decimal(i);
+ endfor;
+ enddef;
+
+def beams_ =
+ for k := 1 upto no_of_beams :
+ temp_text:="extract_beam_data(" & beam_list[k] & ");";
+ scantokens temp_text;
+ beam_list[k] := "";
+ prepare_beam;
+ currentpicture:=note_[closest_index][instr_];
+ draw_beam;
+ draw_stems;
+ note_[closest_index][instr_]:=currentpicture;
+ currentpicture:=note_[index][instr_];
+ endfor;
+ enddef;
+
+def add_tie (text nhs) =
+ forsuffixes s:=nhs :
+ tie_list[instr_] := if known tie_list[instr_] : tie_list[instr_] & "," & fi decimal index & "," & str s;
+ endfor;
+ enddef;
+
+def close_tie (text nhs) =
+ if index > 1 :
+ forsuffixes s:=nhs :
+ tie_list[instr_] := tie_list[instr_] & ",-" & decimal index & "," & str s;
+ endfor;
+ fi;
+ enddef;
+
+def ties_ =
+ for i := 1 upto no_of_instr :
+ if known tie_list[i] :
+ k:=100;
+ for j:= scantokens tie_list[i] :
+ if k=100 : % j is an index
+ if j>0 : % this is an opening index
+ no_of_ties:=no_of_ties+1;
+ open_tie[no_of_ties]:=j;
+ k:=200;
+ else: % this is a closing index
+ k:=-j;
+ fi;
+ elseif k=200 : % j is an opening note
+ tie_[no_of_ties] := j;
+ k:=100;
+ else: % j is a closing note
+ for l:=1 upto no_of_ties :
+ if tie_[l] = j : % this is it
+ closed_tie[l] := k;
+ fi;
+ endfor;
+ k:=100;
+ fi;
+ endfor;
+ for j:=1 upto no_of_ties :
+ if known closed_tie[j] :
+ draw_tie(i, open_tie[j],closed_tie[j],_note(tie_[j],i,open_tie[j]));
+ else:
+ draw_open_tie(i, open_tie[j],_note(tie_[j],i,open_tie[j]));
+ fi;
+ endfor;
+ numeric tie_[], open_tie[], closed_tie[];
+ no_of_ties:=0;
+ fi;
+ endfor;
+ enddef;
+
+def draw_tie(expr ins_, oi_, ci_, tn_) =
+ tie_coef := -stem_dir[oi_][ins_];
+ begingroup; save x, y;
+ path p;
+ clearit;
+ z0 = (0, interline*(tn_));
+ x2=total_width(oi_)
+ for m:=oi_+1 upto ci_-1 : + note_axis[m] + total_width(m) endfor
+ + note_axis[ci_];
+ y2=y0;
+ y1=y0+tie_coef*interline;
+ x1 = .5[x0,x2];
+ p = z0..{right}z1..z2;
+ z3 = p intersectionpoint
+ ((1/2horizontal_axis, interline*(tn_-1))--(1/2horizontal_axis, interline*(tn_+1)));
+ z4 = p intersectionpoint
+ ((x2-1/2horizontal_axis,interline*(tn_-1))--(x2-1/2horizontal_axis,interline*(tn_+1)));
+ penpos3(line_thick, 90+notehead_angle);
+ penpos1(2line_thick, 90);
+ penpos4(line_thick, 90-notehead_angle);
+ penstroke z3e..{right}z1e..z4e;
+ addto note_[oi_][ins_] also currentpicture
+ shifted (tie_coef*.5framingspace, tie_coef*2line_thick);%*(tn_-floor(tn_)));
+ clearit;
+ endgroup;
+ enddef;
+
+def draw_open_tie(expr ins_, oi_, tn_) =
+ tie_coef := -stem_dir[oi_][ins_];
+ begingroup; save x, y;
+ path p;
+ clearit;
+ z0 = (0, interline*(tn_));
+ x2=total_width(oi_)
+ for m:=oi_+1 upto index : + note_axis[m] + total_width(m) endfor
+ if (tn_ < max(scantokens staff_[instr_]) + 1) and
+ (tn_ > min(scantokens staff_[instr_]) - 1) :
+ + regular_width
+ fi;
+ y2=y0;
+ y1=y0+tie_coef*interline;
+ x1 = .5[x0,x2];
+ p = z0..{right}z1..z2;
+ z3 = p intersectionpoint
+ ((1/2horizontal_axis, interline*(tn_-1))--(1/2horizontal_axis, interline*(tn_+1)));
+ z4 = p intersectionpoint
+ ((x2-1/2horizontal_axis,interline*(tn_-1))--(x2-1/2horizontal_axis,interline*(tn_+1)));
+ penpos3(line_thick, 90+notehead_angle);
+ penpos1(2line_thick, 90);
+ penpos4(line_thick, 90-notehead_angle);
+ penstroke z3e..{right}z1e..z4e;
+ addto note_[oi_][ins_] also currentpicture
+ shifted (framingspace, tie_coef*2line_thick);%*(tn_-floor(tn_)));
+ clearit;
+ endgroup;
+ enddef;
+
+% Functions
+
+def clef_ (expr number) =
+ clef_changes := decimal(index) & "," & decimal(instr_) & "," & decimal(instr_clef[instr_])
+ if known clef_changes : & "," & clef_changes fi;
+ instr_clef[instr_]:=number;
+ small_clef(number);
+ enddef;
+
+def small_clef (expr number) =
+ if curr_level < 4 : % Deferring...
+ to_do := if next_level>0 : to_do & fi curr_instr & "small_clef(" & decimal(number) & ");";
+ curr_instr := "";
+ next_level:=4;
+ else: % Doing...
+ addto currentpicture also
+ if instr_clef[instr_] = 0 :
+ small_treble_clef shifted (-2.8interline-1/2regular_width-ltx[instr_],0);
+ ltx[instr_] := ltx[instr_] + 2.4interline+1/2regular_width + framingspace;
+ elseif instr_clef[instr_] = 6 :
+ small_bass_clef shifted (-2.75interline-1/2regular_width-ltx[instr_],0);
+ ltx[instr_] := ltx[instr_] + 2.4interline + 1/2regular_width + framingspace;
+% pickup pencircle scaled line_thick;
+% draw (-ltx[instr_],-interline)--(-ltx[instr_],3interline);
+ fi;
+ fi;
+ enddef;
+
+def draw_beam =
+ hor_start := stem_axis[index][instr_]+.5line_thick
+ for i:=closest_index upto (index-1): + note_axis[i+1] + total_width(i) endfor;
+ pickup penrazor xscaled .5interline rotated 90;
+ for i:=beam_elements downto 2 :
+ hor_end := hor_start
+ for j:=beam_index[i-1] upto (beam_index[i]-1) : - total_width(j) - note_axis[j+1] endfor
+ -stem_axis[index][instr_] + stem_axis[beam_index[i]][instr_] -line_thick;
+ for j := 1 upto beam_no[i] :
+ draw ((hor_start,interline*(beam_lift - beam_coef*(3j-2)/4))--
+ (hor_end,interline*(beam_lift - beam_coef*(3j-2)/4))) transformed yslanted;
+ endfor;
+% An extra parameter for each note of the stem will indicate whether it's + or - horizontal_axis
+ if beam_no[i] > beam_no[i+1] :
+ for j :=2 upto beam_no[i] :
+ draw ((hor_start,interline*(beam_lift - beam_coef*(3j-2)/4))--
+ (hor_start-horizontal_axis,interline*(beam_lift - beam_coef*(3j-2)/4))) transformed yslanted;
+ endfor
+ fi;
+ for j:= (beam_no[i-1]+1) upto beam_no[i] :
+ undraw ((hor_start-line_thick,interline*(beam_lift - beam_coef*(3j-2)/4))--
+ (hor_end+line_thick,interline*(beam_lift - beam_coef*(3j-2)/4))) transformed yslanted;
+ endfor;
+ highest_note[instr_]:=max(highest_note[instr_], ypart((
+ if beam_dir < 0 : hor_end else: hor_start fi
+ , beam_lift*interline) transformed yslanted)/interline);
+ lowest_note[instr_]:=min(lowest_note[instr_], ypart((
+ if beam_dir < 0 : hor_end else: hor_start fi
+ , beam_lift*interline) transformed yslanted)/interline);
+ hor_start := hor_end + line_thick;
+ endfor;
+ enddef;
+
+def draw_stems =
+ pickup penrazor xscaled line_thick;
+ hor_start := stem_axis[index][instr_]
+ for i:=closest_index upto (index-1): + note_axis[i+1] + total_width(i) endfor;
+ for i:=beam_elements downto 1 :
+ draw (xpart(stem_point[beam_index[i]][instr_])
+ for j:=closest_index upto (beam_index[i]-1): + note_axis[j+1] + total_width(j) endfor
+ for j:=beam_index[i] upto (closest_index-1): - note_axis[j+1] - total_width(j) endfor,
+ ypart(stem_point[beam_index[i]][instr_])
+ + interline * if beam_coef =1 : min else: max fi (beam_aggr[i]1,
+ for j:=1 upto beam_aggr[i]0 : , beam_aggr[i][j] endfor))
+ --((xpart(stem_point[beam_index[i]][instr_])
+ for j:=closest_index upto (beam_index[i]-1): + note_axis[j+1] + total_width(j) endfor
+ for j:=beam_index[i] upto (closest_index-1): - note_axis[j+1] - total_width(j) endfor,
+ interline*beam_lift) transformed yslanted);
+ endfor;
+ enddef;
+
+def end_of_block =
+ temp:=quanta[index];
+ quanta[index]:=0;
+ if unknown desired_width : % A \musicbox
+ desired_width:=ideal_width;
+ else :
+ no_of_blocks := no_of_blocks + 1;
+ if abs(desired_width-ideal_width) > abs(desired_width - ideal_width*(no_of_blocks+1)/no_of_blocks) : % Don't make the line.
+ else :
+ make_line(next_char);
+ fi
+ fi;
+ quanta[index]:=temp;
+ enddef;
+
+def ideal_width =
+ (total_natural_length + (
+ for i := 1 upto index-1 :
+ max(sf_(quanta[i])*spacing_unit/pt-correction[i+1]/pt,0) +
+ endfor
+ sf_(quanta[index])*spacing_unit/pt))
+ enddef;
+
+def sf_(expr number) =
+% if number 1.618 ** (mlog(if number = 0 : 1 else : number/least_spaced fi)/mlog(2))
+ if number = 0 : 0
+ else :
+ 1.618 ** (mlog(abs(number)/least_spaced)/mlog(2))
+ fi
+ enddef;
+
+def stretch_chars =
+ for i := 1 upto index :
+ total_factors := total_factors + sf_(quanta[i]);
+ endfor;
+ forever:
+ temp := 0;
+ note_axis[index+1]:=0;
+ correction[index+1]:=0;
+ for i := 1 upto index :
+ stretched_width[i] :=
+ max(sf_(quanta[i])*(desired_width-total_natural_length)/total_factors
+ - correction[i+1]/pt,0);
+ stretched_width[i] := stretched_width[i]*pt;
+ temp := temp + (note_axis[i] + total_width(i))/pt;
+ endfor;
+ exitif (desired_width - temp >= 0) and (desired_width - temp <=0.005);
+ total_natural_length := total_natural_length - (desired_width - temp);
+ endfor;
+ enddef;
+
+def end_of_char =
+ note_[index][instr_]:=currentpicture;
+ clearit;
+ ensure_info;
+ curr_level := next_level;
+ next_level := 0;
+ doing_ := to_do & "end_of_char;";
+ to_do := "";
+ instr_:=0;
+ if curr_level = 0 : % Which means last next_level=0
+ finalize_char;
+ else:
+ scantokens doing_;
+ fi;
+ enddef;
+
+def ensure_info =
+ if ((next_level=0) and (curr_level<6)) or (next_level=6) :
+ if index = 1 :
+ for i:= 1 upto no_of_instr :
+ note_axis1 := max(note_axis1, ltx[i]);
+ endfor;
+ else:
+ for i:=1 upto no_of_instr :
+ if totalweight note_[index][i]>0 :
+ avlbl_space := 0 for j:=last_note[i]+1 upto index-1 :
+ + note_axis[j] + width[j] endfor + note_axis[index];
+ if avlbl_space < (rtx[i] + ltx[i]) :
+ find_new_axis(i);
+ fi;
+ fi;
+ endfor;
+ fi;
+ fi;
+ enddef;
+
+def extract_beam_data(text t) =
+ j:=0;
+ numeric beam_elements, beam_index[], beam_no[], beam_aggr[][];
+ beam_index0:=0;
+ beam_elements:=0;
+ instr_ := 0;
+ for i:=t :
+ if instr_ = 0 : instr_:=i;
+ else :
+ j:=j+1;
+ if j=1 : % New element, index
+ beam_elements:=beam_elements+1;
+ beam_index[beam_elements]:=i-index_offset;
+ elseif j=2 : % No. of beams
+ beam_no[beam_elements]:=i;
+ elseif j<1 : % One of the notes in the aggr. Position 0 in the array is no. of notes.
+ beam_aggr[beam_elements][1-j] := _note(i, instr_, beam_index[beam_elements]);
+ else : % Number of notes
+ beam_aggr[beam_elements][0]:=i;
+ j:=-i;
+ fi;
+ fi;
+ endfor;
+ beam_no[beam_elements+1]:=0;
+ enddef;
+
+def finalize_char =
+ for i:=1 upto no_of_instr :
+ if totalweight(note_[index][i])>0 : last_note[i]:=index; rtx[i]:=rtx_[i]; fi;
+% prev_staff(i);
+ endfor;
+ find_pos;
+ total_natural_length:=total_natural_length+(note_axis[index]+width[index])/pt;
+ curr_level:=0;
+ enddef;
+
+def find_extr(expr p_, coeff_) =
+ clearit;
+ tx:= coeff_ * horizontal_span;
+ fx:=0;
+ pickup pencircle scaled epsilon
+ forever: xtx:=.5[tx,fx]; exitif abs(tx-fx)<=.1;
+ currentpicture:=p_;
+ undraw(xtx,-vertical_span)--(xtx,vertical_span);
+ if totalweight(currentpicture)>=totalweight(p_) : tx else: fx fi
+ :=xtx;
+ endfor;
+ xtx[instr_]:= coeff_*xtx;
+ clearit;
+ enddef;
+
+def find_extremes(text notes_) = % Will be a text expresion, this macro decides everything
+ aggr_note[index][instr_][1]:=-100; % Top note
+ aggr_note[index][instr_][-1]:=100; % Bottom note
+ for i:=notes_ :
+ aggr_note[index][instr_][1]:=max(aggr_note[index][instr_][1],i+instr_clef[instr_]);
+ aggr_note[index][instr_][-1]:=min(aggr_note[index][instr_][-1],i+instr_clef[instr_]);
+ endfor;
+ stem_coef[instr_]:= if (aggr_note[index][instr_][1]+aggr_note[index][instr_][-1])>=2: - fi 1;
+ enddef;
+
+def find_inclination (text options) =
+ yslanted := identity;
+ beam_height := 0;
+ pair beam_pt[]; % The definition of beam_pt's has to happen even if there's no decision to be made,
+ % because find_position uses beam_pt1.
+ beam_pt[closest_no] := (0,0);
+ for i:=closest_no-1 downto 1:
+ xpart beam_pt[i] = xpart(beam_pt[i+1])-stem_axis[beam_index[i]][instr_]-note_axis[beam_index[i]]
+ for j:=beam_index[i] upto (beam_index[i+1]-1) :
+ - note_axis[j] - total_width(j) endfor
+ + note_axis[beam_index[i]] + stem_axis[beam_index[i]][instr_];
+ ypart beam_pt[i] = interline * (beam_aggr[i]1-closest_note);
+ endfor;
+ for i:=closest_no+1 upto beam_elements:
+ xpart beam_pt[i] = xpart(beam_pt[i-1]) - stem_axis[beam_index[i]][instr_] - note_axis[beam_index[i]]
+ for j:=beam_index[i-1] upto (beam_index[i]-1) :
+ + note_axis[j] + total_width(j) endfor
+ + note_axis[beam_index[i]] + stem_axis[beam_index[i]][instr_];
+ ypart beam_pt[i] = interline * (beam_aggr[i]1-closest_note);
+ endfor;
+ if beam_dir <> 0 :
+ transform yslanted[];
+ total_beam_width:=xpart(beam_pt[beam_elements])-xpart(beam_pt1);
+ temp_a := 0;
+ for i:= 1 upto beam_elements :
+ temp_a := temp_a - beam_coef*ypart(beam_pt[i]);
+ endfor;
+%if beam_index[1]=1 :
+% show beam_dir;
+% for l:=1 upto beam_elements:
+% show beam_pt[l];
+% endfor;
+%fi;
+ for i:= scantokens options :
+ temp_b := -i*xpart(beam_pt1)/4total_beam_width;
+ (0,1) transformed yslanted[i] = (0,1);
+ (xpart(beam_pt1),0) transformed yslanted[i] = (xpart(beam_pt1),interline*temp_b);
+ (xpart(beam_pt[beam_elements]),0) transformed yslanted[i] =
+ (xpart(beam_pt[beam_elements]),interline*(temp_b-i/4));
+ temp_a[i]:=0;
+ for j := 1 upto beam_elements :
+ if ypart (-beam_coef*(beam_pt[j] transformed yslanted[i])) >= -0.001 :
+ temp_a[i] := temp_a[i] - beam_coef*ypart(beam_pt[j] transformed yslanted[i]);
+ else:
+ temp_a[i] := 1000;
+ fi;
+ exitif temp_a[i] = 1000;
+ endfor;
+ if temp_a[i] - temp_a < .05 :
+ transform yslanted;
+ (0,1) transformed yslanted = (0,1);
+ (-1,0) transformed yslanted = (-1,0) transformed yslanted[i] reflectedabout((0,0),(1,0));
+ (1,0) transformed yslanted = (1,0) transformed yslanted[i] reflectedabout((0,0),(1,0));
+ temp_a := temp_a[i];
+ beam_height := -i/4;
+ fi;
+ endfor;
+ fi;
+ enddef;
+
+def find_ltx(expr p_) = find_extr(p_,-1); enddef;
+
+def find_new_axis (expr inst) =
+show index;
+ pict_:=note_[last_note[inst]][inst] shifted %
+ (width[last_note[inst]] for i:=(last_note[inst]+1) upto (index-1):
+ -note_axis[i]-width[i] endfor,0);
+ _pict:=note_[index][inst];
+ cull _pict keeping (1,infinity);
+ cull pict_ keeping (1,infinity);
+ tx:=rtx[inst]+ltx[inst]+note_axis[index];
+ fx:=ltx[inst];
+%fx will be customized so that the user can indicate what fraction of ltx[inst] has to be taken into account.
+%In any case, fx (the minimum new axis), being exactly ltx, makes room for the whole width of the previous note.
+%Which is what is needed, because the stems are not yet drawn.
+ nax:=tx;
+ forever:
+ clearit;
+ exitif abs(tx-fx)<=.01;
+ currentpicture := pict_;
+ addto currentpicture also _pict shifted (nax,0);
+ cullit;
+ if totalweight(currentpicture)<totalweight(pict_)+totalweight(_pict):
+ fx else: tx fi :=nax;
+ nax:=.5[tx,fx];
+ endfor;
+ correction[index] := max(note_axis[index],nax) - note_axis[index];
+ note_axis[index] := note_axis[index] + correction[index];
+ enddef;
+
+def find_pos =
+% last_stretch:=sfcode
+% *to_stretch*regular_width/total_space_factors;
+ stretched_width[index]:=0;
+ enddef;
+
+def find_position =
+ temp_a := closest_note + beam_coef*(stem_length-1/2);
+ (ypart(beam_pt[beam_elements] transformed yslanted)-ypart(beam_pt[beam_elements]))/interline + beam_lift =
+ round(temp_a+.01beam_coef) + beam_coef/4;
+ enddef;
+
+def instr_no(expr number) =
+ no_of_instr:=number;
+ for i:=1 step 1 until number:
+ highest_note[i]:=3;
+ lowest_note[i]:=-1;
+ last_note[i]:=0;
+ rtx[i]:=0;
+ note_0[i]:=nullpicture;
+ instr_clef[i]:=0;
+ endfor;
+ enddef;
+
+def key_sign = relax
+ if curr_level < 4 :
+ to_do := if next_level>0 : to_do & fi "key_sign;";
+ curr_instr := ""; % Maybe unnecessary
+ next_level := 4;
+ else:
+ % Key signatures
+ note_[index][instr_] := currentpicture;
+ temp_text := "7";
+ if key_/abs(key_+.1) = 1 : % Sharps
+ relax;
+ else : % Flats
+ j := 1;
+ for i := 1 upto -key_ :
+ temp_text := decimal j & "," & temp_text;
+ j := if odd(i): 1.5 else: -2 fi + j;
+ endfor;
+ for i := 1 upto no_of_instr :
+ ltx[i] := ltx[i] +key_sep;
+ for s:= scantokens(temp_text) :
+ exitif s = 7;
+ addto note_[index][i] also flat
+ shifted (-ltx[i]-horizontal_axis,
+ interline * (s if instr_clef[i]=6:-1fi));
+ ltx[i] := ltx[i] + horizontal_axis;
+ endfor;
+ endfor;
+ fi;
+ fi;
+ enddef;
+
+def normal_clefs =
+ if curr_level < 4 : % Deferring...
+ to_do := if next_level>0 : to_do & fi "normal_clefs;";
+ curr_instr := ""; % Maybe unnecessary
+ next_level:=4;
+ else: % Doing...
+ %Clefs. To do: the font has to draw the clefs from 'trebleaxis' and 'bassaxis'
+ note_[index][instr_] := currentpicture;
+ for i := 1 upto no_of_instr :
+ addto note_[index][i] also
+ if instr_clef[i] = 0 :
+ treble_clef shifted (-3interline - clef_sep - ltx[i],0);
+% note_axis[index] := max(note_axis[index], 3interline + clef_sep);
+ ltx[i] := ltx[i] + 3interline + clef_sep;
+ elseif instr_clef[i] = 6 :
+ bass_clef shifted (-2.7interline - clef_sep - ltx[i],0);
+% note_axis[index] := max(note_axis[index], 2.7interline + clef_sep);
+ ltx[i] := ltx[i] + 2.7interline + clef_sep;
+ fi;
+ endfor;
+ fi;
+ enddef;
+
+def make_line(expr number) =
+ if index > 0:
+ quanta[index]:=0;
+ stretch_chars;
+ instr_shift1:=0;
+ begingroup; save index;
+ beams_;
+ ties_;
+ endgroup;
+ for i:=2 upto no_of_instr:
+ instr_shift[i]:=4+instr_shift[i-1]+highest_note[i-1]-lowest_note[i];
+ endfor;
+ line_height:=(instr_shift[no_of_instr]+highest_note[no_of_instr]+2)*interline#;
+ line_depth:=-(lowest_note1-1)*interline#;
+ for i:= 1 upto index:
+ for j:=1 upto no_of_instr :
+ clearit;
+ staff_lines(i,scantokens staff_[j]);
+ addto note_[i][j] also currentpicture;
+ endfor;
+ beginchar(number+i-1,(note_axis[i]+width[i]+stretched_width[i])*pt#/pt,line_height,line_depth);
+ clearit;
+ if no_of_instr > 1 :
+ if i=1 : % Bracket
+ pickup penrazor xscaled line_thick;
+ draw (-1/2line_thick,-interline)--(-1/2line_thick,interline*(instr_shift2+3));
+ pickup pencircle xscaled 1/2interline yscaled line_thick rotated (-90-notehead_angle);
+ top rt z0 = (-2framingspace, interline*(instr_shift2+3));
+ bot lft z1 = (-horizontal_axis, interline*(instr_shift2/2+1)-1/2line_thick);
+ z2 = .5[z0,z1];
+ draw z0{dir(-90-notehead_angle)}..z2..{dir(-135)}z1;
+ pickup pencircle xscaled 1/2interline yscaled line_thick rotated (90+notehead_angle);
+ draw (z0{dir(-90-notehead_angle)}..z2..{dir(-135)}z1)
+ reflectedabout ((0,interline*(instr_shift2/2+1)),(1,interline*(instr_shift2/2+1)));
+ fi;
+ if quanta[i]<=0 : % Inter-staff barline
+ pickup penrazor xscaled line_thick;
+ draw (note_axis[i],3interline)--(note_axis[i],interline*(instr_shift2-1));
+ fi;
+ fi;
+ for j:=1 upto no_of_instr:
+ addto currentpicture also
+ note_[i][j] shifted (note_axis[i],interline*instr_shift[j]-(-1**i)*0/2line_thick);
+ note_[i][j]:=nullpicture;
+ endfor;
+ endchar;
+ endfor;
+ fi;
+ next_char:= index + number;
+ index_offset := index_offset+index;
+ index:=0;
+ total_natural_length:=0;
+ total_factors := 0;
+ no_of_blocks := 0;
+ no_of_beams := 0;
+ string beam_list[], tie_list[];
+ numeric stem_dir[][];
+ string clef_changes;
+ clearit;
+showstats;
+ enddef;
+
+def time_sign = relax enddef;
+
+def new_char(expr number) =
+ curr_level:=1;
+ next_level:=0;
+ if index = 0 :
+ to_do := to_do & "time_sign;" & "key_sign;" & "normal_clefs;";
+ next_level := 4;
+ fi;
+ index:=index+1;
+ quanta[index]:= if number = 0 : least_spaced else : number fi;
+% total_factors := total_factors + abs(sf_(number));
+ if (number < 17) and (number > 0) : least_spaced:=16 fi;
+ width[index]:=0;
+ note_axis[index]:= 0;
+ correction[index] := 0;
+ for i:=1 upto no_of_instr:
+ rtx_[i] := 0;
+ ltx[i]:=0;
+ note_[index][i]:=nullpicture;
+ endfor;
+ enddef;
+
+def _note(expr n_, i_, _ix) = % Note, instrument, index
+ hide (
+ _note_:=n_+instr_clef[i_];
+ if known clef_changes :
+ k:=0;
+ for temp:=scantokens clef_changes :
+ if k=0 : % An index
+ k:= if temp<=_ix : - fi 1;
+ elseif k=1 : % An instrument
+ if temp<i_ :
+ k:=2;
+ elseif temp=i_ :
+ k:=3;
+ else:
+ k:=4;
+ fi;
+ elseif k=2 : % Good index, but wrong instr
+ k:=0;
+ elseif k=3 : % This is it
+ _note_:=n_+temp;
+ k:=0;
+ else : % Good index, missed instr
+ k:=0;
+ fi;
+ exitif k=-1;
+ endfor;
+ fi;
+ )
+ _note_
+ enddef;
+
+
+def prepare_beam =
+% Direction of stems
+ extr_beam_note1 := -100;
+ extr_beam_note[-1] := 100;
+ for i:=1 upto beam_elements :
+ for j:=1 upto beam_aggr[i][0] :
+ extr_beam_note1:=max(extr_beam_note1,beam_aggr[i][j]); % Top note
+ extr_beam_note[-1]:=min(extr_beam_note[-1],beam_aggr[i][j]); % Bottom note
+ endfor;
+ endfor;
+ beam_coef := if (extr_beam_note1-1) >= (1-extr_beam_note[-1]) : - fi 1; % Direction of stems
+ for i:=1 upto beam_elements :
+ if unknown stem_dir[beam_index[i]][instr_] :
+ stem_dir[beam_index[i]][instr_] = beam_coef;
+ fi;
+ index := beam_index[beam_elements];
+ endfor;
+% General direction (depending on the farthest-away note-heads in the first and last notes)
+ temp_a := beam_aggr[1][1];
+ temp_b := beam_aggr[beam_elements]1;
+ for i:=2 upto beam_aggr[1][0] :
+ temp_a := if beam_coef=1 : min else: max fi (temp_a,beam_aggr1[i]);
+ endfor;
+ for i:=2 upto beam_aggr[beam_elements]0 :
+ temp_b := if beam_coef=1 : min else: max fi (temp_b,beam_aggr1[i]);
+ endfor;
+ beam_dir := if temp_a = temp_b : 0* elseif temp_a > temp_b : - fi 1;
+% Reduction to relevant notes (irrelevant notes are put in positions 2 and up of beam_aggr).
+% and finding of the closest note, having any inner beams into account too.
+ closest_note:=-100beam_coef;
+ for i:=if (beam_coef*beam_dir) >= 0 : 1 upto beam_elements else: beam_elements downto 1 fi:
+ if beam_aggr[i]0 > 1 :
+ if (beam_coef*beam_aggr[i]1) < (beam_coef*beam_aggr[i]2) :
+ temp_a := beam_aggr[i]1;
+ beam_aggr[i]1 := beam_aggr[i]2;
+ beam_aggr[i]2 := temp_a;
+ fi;
+ fi;
+ temp_b := if beam_coef = 1 : max else: min fi
+ (closest_note,beam_aggr[i]1+beam_coef*beam_no[i]/100);
+ if closest_note <> temp_b :
+ closest_index := beam_index[i]; closest_no:=i; fi;
+ closest_note := temp_b;
+ endfor;
+ closest_note:=round(10temp_b)/10;
+% "Mode" (careful or not)
+ numeric beam_lift;
+ temp_a := closest_note + beam_coef * (stem_length - 3*(beam_no[closest_no]-1)/4);
+ transform yslanted;
+ if (temp_a < max(scantokens staff_[instr_]) + 1) and (temp_a > min(scantokens staff_[instr_]) - 1) :
+ "careful beam";
+ find_inclination("beam_dir");
+ find_position;
+ else :
+ find_inclination("2beam_dir, beam_dir");
+ beam_lift := closest_note + beam_coef * (1/4 + stem_length);
+ fi;
+ enddef;
+
+def prev_staff (expr number) =
+ clearit;
+ staff_lines(index-1,scantokens staff_[number]);
+ addto note_[index-1][number] also currentpicture;
+ clearit;
+ enddef;
+
+def staff_lines(expr char_ind)(text t) =
+ pickup pencircle scaled line_thick;
+ for j=t:
+ draw ((0,j*interline)--(note_axis[char_ind]+width[char_ind]+stretched_width[char_ind],j*interline)) %
+ shifted (-note_axis[char_ind],0);
+ endfor;
+ enddef;
+
+def this_staff =
+ for i:=1 upto no_of_instr:
+ clearit;
+ staff_lines(index,scantokens staff_[i]);
+ addto note_[index][i] also currentpicture;
+ clearit;
+ endfor;
+ enddef;
+
+def total_width(expr idx_) =
+ (width[idx_] + stretched_width[idx_])
+ enddef;
diff --git a/macros/texmuse/Program/texmuse.tex b/macros/texmuse/Program/texmuse.tex
new file mode 100644
index 0000000000..740b75b12b
--- /dev/null
+++ b/macros/texmuse/Program/texmuse.tex
@@ -0,0 +1,624 @@
+\makeatletter
+\newcommand{\TeXmuse}{\TeX{\itshape\kern-.1em m\kern-.05em use}}
+%Declarations
+\newtoks\@temptoks
+\newtoks\quant@toks
+\newtoks\curr@note
+\newtoks\this@note
+\newtoks\to@write
+\newtoks\extracted@line
+\newtoks\@plainnote
+\newtoks\@atnote
+\newtoks\@@atnote
+\newwrite\written@tm@file
+\newwrite\instrument@file
+\newread\read@tm@file
+\@tempswafalse % (tempswa = repeat@test)
+\newif\if@tempswb \@tempswbtrue % (tempswb = first@file)
+\newif\ifnot@written\not@writtentrue
+\newif\ifbeam@sw % Whether the note has to be added to a beam
+\newif\ifblock@done % Whether the last block is over (to catch pre-barline material)
+\newcount\@octave
+\newcount\@key
+\newcount\block@period
+\newcount\instrument@number
+\newcount\@no@of@instr % No. of instruments included in the system
+\newcount\extracted@number
+\newcount\current@quantum\current@quantum=0\relax
+\newcount\quantum@skip\quantum@skip=0\relax
+\newcount\char@no
+\newcount\block@no
+\newcount\file@no
+\newcount\s@factor
+\newcount\@restshift\@restshift0
+\newcount\@tempcntd
+\newcount\@hookels
+\newcount\@@break
+\newcount\@firstmf
+\newcount\FontSplit % Number of characters per font
+\newcount\beam@no %Number of beam lines in the beam (modified by \e@n, etc.)
+\chardef\@ther=12
+\chardef\@i=1
+\chardef\@ii=2
+\chardef\@iii=3
+\chardef\@iv=4
+\chardef\@v=5
+\chardef\@vi=6
+\chardef\@vii=7
+\chardef\@viii=8
+\chardef\@ix=9
+\chardef\@z=0
+\newenvironment{texmuse}{\bgroup%
+ \catcode`\[=13 \catcode`\]=13
+ \catcode`\|=13
+ \catcode`A=13 \lccode`A=`A
+ \catcode`B=13 \lccode`B=`B
+ \catcode`C=13 \lccode`C=`C
+ \catcode`D=13 \lccode`D=`D
+ \catcode`E=13 \lccode`E=`E
+ \catcode`F=13 \lccode`F=`F
+ \catcode`G=13 \lccode`G=`G
+ \catcode`R=13 \lccode`R=`R
+ \catcode`\!=\@ther \lccode`\!=`\1 \catcode`1=\active
+ \catcode`\?=\@ther \lccode`\?=`\2 \catcode`2=\active
+ \catcode`\_=\@ther \lccode`\_=`\3 \catcode`3=\active
+ \catcode`\$=\@ther \lccode`\$=`\4 \catcode`4=\active
+ \catcode`\/=\@ther \lccode`\/=`\5 \catcode`5=\active
+ \catcode`\^=\@ther \lccode`\^=`\6 \catcode`6=\active
+ \catcode`\&=\@ther \lccode`\&=`\7 \catcode`7=\active
+ \catcode`\*=\@ther \lccode`\*=`\8 \catcode`8=\active
+ }{\egroup}
+%Newinstrument
+\newcommand\newinstrument[2][\trebleclef]{%
+ \expandafter\newtoks\csname #2@toks\endcsname%
+ \expandafter\def\csname #2\endcsname{\global\csname #2@toks\endcsname}%
+ \bgroup
+ \edef\trebleclef{\gdef\expandafter\noexpand\csname #2@clef\endcsname{0}}%
+ \edef\bassclef{\gdef\expandafter\noexpand\csname #2@clef\endcsname{6}}%
+ #1
+ \egroup}
+ %
+%Constant definitions
+\def\quant@note#1{\let\@let@token=#1\@quant@note}
+\def\@quant@note{\let\next\@let@token
+ \ifx\@let@token-\let\next\quant@note
+ \else\ifx\@let@token+\let\next\quant@note
+ \else\ifx\@let@token.\let\next\quant@dot
+ \else\ifx=\@let@token\let\next\@@quant@note
+ \else\def\next{\@@quant@note\@let@token}%
+ \fi\fi\fi\fi\next}
+\def\quant@dot#1{\let\@let@token=#1\@quant@dot}
+\def\@quant@dot{\let\next\@let@token
+ \ifx\@let@token.\let\next\@quant@dot % Not sure it works like this
+ \else\ifx=\@let@token\let\next\@@quant@dot
+ \else\def\next{\@@quant@dot\@let@token}%
+ \fi\fi\next}
+\def\@@quant@dot{\global\quant@toks\expandafter{\the\quant@toks\quant@@dot\@note\quant@@undot}}
+\def\@@quant@note{\global\quant@toks\expandafter{\the\quant@toks\@note}}
+\def\quant@sixtif{\quantum@skip4\relax}
+\def\quant@thirt{\quantum@skip8\relax}
+\def\quant@sixt{\quantum@skip16\relax}
+\def\quant@eighth{\quantum@skip32\relax}
+\def\quant@quarter{\quantum@skip64\relax}
+\def\quant@half{\quantum@skip128\relax}
+\def\quant@whole{\quantum@skip256\relax}
+\def\quant@double{\quantum@skip512\relax}
+\def\quant@@dot{\multiply\quantum@skip3\divide\quantum@skip2\relax}
+\def\quant@@undot{\multiply\quantum@skip2\divide\quantum@skip3\relax}
+\def\quant@barline{\global\quant@toks\expandafter{\the\quant@toks\no@note0\current@quantum0\relax}}
+%\@note
+\def\@note{%
+ \if@tempswa\else\read\read@tm@file to \matrix@line
+ \expandafter\extract@from@line\matrix@line
+ \fi
+ \@tempswafalse
+ \def\next{\global\advance\current@quantum\quantum@skip\relax}%
+ \ifnum\block@period>\current@quantum\relax
+ \ifnum\extracted@number=\current@quantum\relax
+ \edef\to@write{\the\extracted@number:\the\extracted@line,%
+ 1.}%
+ \else\ifnum\extracted@number>\current@quantum\relax
+ \@tempswatrue
+ \@tempcnta=\instrument@number\relax
+ \edef\to@write{\the\current@quantum:\noexpand\@gobble}%
+ \loop\ifnum\@tempcnta>1\relax\edef\to@write{\to@write,0}%
+ \advance\@tempcnta-1\relax\repeat
+ \edef\to@write{\to@write,1.}%
+ \else% (extracted@number<current@quantum)
+ \let\next\@note
+ \edef\to@write{\the\extracted@number:%
+ \the\extracted@line,0.}%
+ \fi\fi
+ \immediate\write\written@tm@file{\to@write}%
+ \else
+ \def\next{\@tempswatrue\no@note0\current@quantum0\relax\@note}%
+ \fi
+ \next}
+\def\no@note#1{%
+ \if@tempswa\else\read\read@tm@file to \matrix@line
+ \expandafter\extract@from@line\matrix@line
+ \fi
+ \@tempswafalse
+ \let\@next\relax
+ \ifnum\extracted@number=\current@quantum\relax
+ \edef\to@write{\the\extracted@number:\the\extracted@line,%
+ #1.}%
+ \else\ifnum\extracted@number>\current@quantum\relax
+ \@tempswatrue
+ \@tempcnta=\instrument@number\relax
+ \edef\to@write{\the\current@quantum:\noexpand\@gobble}%
+ \loop\ifnum\@tempcnta>1\relax\edef\to@write{\to@write,0}%
+ \advance\@tempcnta-1\relax\repeat
+ \edef\to@write{\to@write,#1.}%
+ \else% (extracted@number<current@quantum)
+ \def\@next{\no@note{#1}}%
+ \edef\to@write{\the\extracted@number:%
+ \the\extracted@line,0.}%
+ \fi\fi
+ \immediate\write\written@tm@file{\to@write}%
+ \@next}
+\def\@stem{\immediate\write\written@tm@file{\space\space\space regular_stem;}}
+\def\@rest#1{\immediate\write\written@tm@file{\space\space\space add_rest(\the\beam@no,#1);}}
+\begin{texmuse}
+\lowercase{%
+%Octave handling
+ \global\def\rangefrom#!{\numbers@as@numbers\relax\@tempcnta=4\relax
+ \expandafter\@rangefrom\noexpand#!}%
+ \global\def\@rangefrom#!#?{%
+ \global\@tempcntb=#?\relax\global\@tempcnta=#?\relax\global\advance\@tempcnta1\relax\egroup
+ \expandafter\@@la\the\@tempcnta\relax
+ \ifx#!A\expandafter\@@la\the\@tempcntb\else
+ \ifx#!B\expandafter\@@ti\the\@tempcntb\else
+ \ifx#!C\expandafter\@@do\the\@tempcntb\else
+ \ifx#!D\expandafter\@@re\the\@tempcntb\else
+ \ifx#!E\expandafter\@@mi\the\@tempcntb\else
+ \ifx#!F\expandafter\@@fa\the\@tempcntb\else
+ \expandafter\@@sol\the\@tempcntb\relax
+ \fi\fi\fi\fi\fi\fi
+ }
+ \global\def\@@sol#!{\global\defG{\@octave#!\def\@pitch{g}\@tempswafalse\@@octave}}%
+ \global\def\@@fa#!{\@@sol#!\global\defF{\@octave#!\def\@pitch{f}\@tempswafalse\@@octave}}%
+ \global\def\@@mi#!{\@@fa#!\global\defE{\@octave#!\def\@pitch{e}\@tempswafalse\@@octave}}%
+ \global\def\@@re#!{\@@mi#!\global\defD{\@octave#!\def\@pitch{d}\@tempswafalse\@@octave}}%
+ \global\def\@@do#!{\@@re#!\global\defC{\@octave#!\def\@pitch{c}\@tempswafalse\@@octave}}%
+ \global\def\@@ti#!{\@@do#!\global\defB{\@octave#!\def\@pitch{b}\@tempswafalse\@@octave}}%
+ \global\def\@@la#!{\@@ti#!\global\defA{\@octave#!\def\@pitch{a}\@tempswafalse\@@octave}}}
+\gdef\numbers@as@numbers{\bgroup% Esto también tiene que ser un loop
+ \def1{\@i}\def2{\@ii}\def3{\@iii}\def4{\@iv}\def5{\@v}\def6{\@vi}\def7{\@vii}\def8{\@viii}}
+%Accidentals
+\gdef\#{\open@block\this@note\expandafter{\the\this@note\string\@sharp}}%
+\gdef\b{\open@block\this@note\expandafter{\the\this@note\string\@flat}}%
+\gdef\n{\open@block\this@note\expandafter{\the\this@note\string\@natural}}%
+%Beams and rhythmic notation
+ \gdef\rhythm@not{\stem@kind}%
+ \gdef[{\@open@beam}\gdef]{\@close@beam}%
+ \gdef\@open@beam{%
+ \open@block
+ \edef\current@block{\current@block\relax\string\next@note\string\open@beam}%
+ \def\rhythm@not{\string\add@tobeam}%
+ \not@writtenfalse}%
+ \gdef\@close@beam{\edef\current@block{\current@block\string\close@beam\relax}%
+ \def\rhythm@not{\stem@kind}}%
+%%notes
+\lowercase{%
+ \gdef\@add@note#!#?{%
+ \open@block
+ \ifnot@written% When \@open@beam has been called, it already added \next@note
+ \edef\current@block{\current@block\relax\string\next@note}%
+ \fi
+ \edef\current@block{\current@block
+ \@value\the\this@note\the\@atnote\the\@@atnote\string\add@note{#!#?}\rhythm@not}%
+ \@atnote{}%
+ \@@atnote{}%
+ \this@note\@plainnote
+ \not@writtentrue
+ \advance\current@quantum\quantum@skip\relax
+ \block@donefalse}%
+ \global\defR{\@ifnextchar-{\advance\@restshift-!\relax\@firstoftwoR}\@@rest}%
+ \global\def\@@rest{\@ifnextchar+{\advance\@restshift!\relax\@firstoftwo\@@rest}\@@@rest}
+ \gdef|{\def\@barline{!0}\current@quantum0\relax}%
+ }%
+\gdef\@@@rest{%
+ \open@block
+ \def\rhythm@not{\string\@rest{\the\@restshift}}%
+ \ifnot@written%
+ \edef\current@block{\current@block\relax\string\next@note}%
+ \fi
+ \edef\current@block{\current@block%
+ \@value\the\this@note\the\@@atnote\rhythm@not}%
+ \this@note\@plainnote
+ \@@atnote{}%
+ \not@writtentrue
+ \@restshift0\relax
+ \def\rhythm@not{\stem@kind}%
+ \advance\current@quantum\quantum@skip\relax
+ \block@donefalse}%
+%clefs
+\gdef\trebleclef{\this@note\expandafter{\the\this@note\string\@clef0}}
+\gdef\bassclef{\this@note\expandafter{\the\this@note\string\@clef\string6}}
+%blocks
+\gdef\open@block{%
+ \ifnum\block@period>\current@quantum\else\current@quantum0\relax\fi
+ \ifnum\current@quantum=0\relax
+ \end@block
+ \fi}
+\gdef\end@block{%
+ \ifblock@done\else
+ \immediate\write\instrument@file{%
+ \current@block\string\end@of@block}%
+ \immediate\write\instrument@file\expandafter{%
+ \the\this@note\string\@bar@line{\@barline}\string\relax}%
+ \def\current@block{\@gobble}%
+ \this@note\@plainnote
+ \let\@barline\barline@default
+ \fi
+ \block@donetrue}
+%bars
+%rhythmic values
+ \global\def2{\quant@thirt\global\quant@toks\expandafter{\the\quant@toks\quant@thirt}%
+ \def\@value{\string\t@n}\def\stem@kind{\string\@stem\string\@flag}}%
+ \global\def3{\quant@sixt\global\quant@toks\expandafter{\the\quant@toks\quant@sixt}%
+ \def\@value{\string\s@n}\def\stem@kind{\string\@stem\string\@flag}}%
+ \global\def4{\quant@eighth\global\quant@toks\expandafter{\the\quant@toks\quant@eighth}%
+ \def\@value{\string\e@n}\def\stem@kind{\string\@stem\string\@flag}}%
+ \global\def5{\quant@quarter\global\quant@toks\expandafter{\the\quant@toks\quant@quarter}%
+ \def\@value{\string\q@n}\def\stem@kind{\string\@stem}}%
+ \global\def6{\quant@half\global\quant@toks\expandafter{\the\quant@toks\quant@half}%
+ \def\@value{\string\h@n}\def\stem@kind{\string\@stem}}%
+ \global\def7{\quant@whole\global\quant@toks\expandafter{\the\quant@toks\quant@whole}%
+ \def\@value{\string\w@n}\def\stem@kind{\string\relax}}%
+ \global\def8{\quant@double\global\quant@toks\expandafter{\the\quant@toks\quant@double}%
+ \def\@value{\string\d@n}\def\stem@kind{\string\relax}}%
+%The actual reading of the user's input for quantization (redefinition of musical commands)
+\lowercase{%
+ \global\def\key#!{\numbers@as@numbers\global\@key=#!\relax\egroup}
+ \global\def\meter#!#?{\numbers@as@numbers\global\block@period?/^\relax
+ \global\divide\block@period by #?\relax %If any argument is a two-digit number, this does not yet work
+ \global\multiply\block@period by #!\relax\egroup}
+ \global\def\extr@quant@toks#!{%
+ \begin{texmuse}%Meaning of commands for quantization purposes.
+ \let[\relax\let]\relax
+ \let|\quant@barline
+ \letA\quant@note\letB\quant@note\letC\quant@note\letD\quant@note
+ \letE\quant@note\letF\quant@note\letG\quant@note\letR\quant@note
+ \let\rangefrom\@gobble
+ \let\#\relax\let\n\relax\let\b\relax
+ \expandafter\the#!%
+ \global\quant@toks\expandafter{\the\quant@toks\quant@instr@end\relax}%
+ \end{texmuse}}}%
+\end{texmuse}
+\def\@@octave#1{\let\next\@@octave
+ \ifx#1-\advance\@octave-1\else\ifx#1+\advance\@octave1\relax
+ \else\if@tempswa\else\@add@note{\@pitch}{\the\@octave}\@tempswatrue\fi
+ \ifx=#1\add@tie{\expandafter\@pitch\the\@octave}\let\next\relax
+ \else\ifx#1.\add@dot{\@pitch}{\the\@octave}%
+ \else\let\next#1%
+ \fi\fi
+ \fi\fi\next}
+%Quantization functions
+\def\quant@instr@end{\let\next\quant@instr@end
+ \if@tempswa\else\read\read@tm@file to \matrix@line
+ \expandafter\extract@from@line\matrix@line
+ \fi
+ \ifnum\extracted@number=9999\relax
+ \immediate\write\written@tm@file{\matrix@line}%
+ \immediate\closeout\written@tm@file\immediate\closein\read@tm@file\current@quantum0\relax
+ \let\next\relax
+ \else
+ \edef\to@write{\the\extracted@number:%
+ \the\extracted@line,0.}%
+ \immediate\write\written@tm@file{\to@write}%
+ \@tempswafalse
+ \fi\next}
+%Character construction functions
+\def\read@blocks#1{\@for\curr@instr:=#1\do
+ {\expandafter\read\csname\curr@instr @file\endcsname to \@tempcs
+ \csname\curr@instr @blocktoks\endcsname\expandafter{\@tempcs}%
+ \expandafter\extract@note\csname\curr@instr @blocktoks\endcsname}}
+\def\open@beam{\expandafter\let\csname\curr@instr @beam\endcsname\@gobble}
+\def\close@beam{\immediate\write\written@tm@file\expandafter{\space\space\space
+ beam(\csname\curr@instr @beam\endcsname);}%
+ \beam@swfalse}
+\def\t@n{\beam@no3\relax\def\notehead@kind{add_noteheads}}
+\def\s@n{\beam@no2\relax\def\notehead@kind{add_noteheads}}
+\def\e@n{\beam@no1\relax\def\notehead@kind{add_noteheads}}
+\def\q@n{\beam@no0\relax\def\notehead@kind{add_noteheads}}
+\def\h@n{\beam@no-1\relax\def\notehead@kind{add_halfheads}}
+\def\w@n{\beam@no-2\relax\def\notehead@kind{add_wholeheads}}
+\def\d@n{\beam@no-3\relax\def\notehead@kind{add_doubleheads}}
+\def\@flag{\immediate\write\written@tm@file{\space\space\space add_flag(\the\beam@no);}}
+\def\@sharp#1\add@note#2{#1\relax\add@note{#2}\immediate\write\written@tm@file{\space\space\space add_sharp(#2);}}
+\def\@flat#1\add@note#2{#1\relax\add@note{#2}\immediate\write\written@tm@file{\space\space\space add_flat(#2);}}
+\def\@natural#1\add@note#2{#1\relax\add@note{#2}\immediate\write\written@tm@file{\space\space\space add_natural(#2);}}
+\def\add@note#1{\def\@@note{#1}%
+ \immediate\write\written@tm@file{\space\space\space\notehead@kind(\@@note);}}
+\def\add@dot#1#2{{\divide\quantum@skip2\relax
+ \global\advance\current@quantum\quantum@skip}%
+ \edef\current@block{\current@block
+ \the\this@note\string\@dot{#1#2}}%
+ \not@writtentrue}%
+\def\add@tie#1{\expandafter\expandafter\expandafter\add@@tie#1}
+\def\add@@tie#1#2{%
+ \edef\current@block{\current@block
+ \the\this@note\string\@tie{#1#2}}%
+ \not@writtentrue
+ {\@temptoks{\string\close@tie{#1#2}}\global\@@atnote\expandafter{\the\@temptoks}}%
+ }%
+\def\@tie#1{\immediate\write\written@tm@file{\space\space\space add_tie(#1);}}
+\def\close@tie#1{\immediate\write\written@tm@file{\space\space\space close_tie(#1);}}
+\def\@dot#1{\immediate\write\written@tm@file{\space\space\space add_dot(#1);}}
+\def\@clef#1{\expandafter\def\csname\curr@instr @clef\endcsname{#1}%
+ \immediate\write\written@tm@file{\space\space\space clef_(#1);}}
+\def\add@tobeam{\expandafter\edef\csname\curr@instr @beam\endcsname{%
+ \csname\curr@instr @beam\endcsname,\the\char@no,\the\beam@no,1,\@@note}} % 1 is for just one note-head
+\def\init@char{%
+ \immediate\write\written@tm@file{new_char(\the\s@factor);}}
+\def\extract@note#1{\expandafter\extract@@note\the#1\relax
+ #1\expandafter{\the\@temptoks}}
+\def\extract@@note#1\next@note#2\end@of@block{\curr@note{#1}\@temptoks{#2\next@note\end@of@block}}
+%Auxiliary functions
+\def\get@instr#1,#2,. {\def\curr@instr{#1}\edef\temp@instr@list{#2\noexpand\@gobble}}
+\def\open@tm@files{\if@tempswb\immediate\openout\written@tm@file=\jobname.tm1\relax
+ \immediate\openin\read@tm@file=\jobname.tm2\relax
+ \else\immediate\openout\written@tm@file=\jobname.tm2\relax
+ \immediate\openin\read@tm@file=\jobname.tm1\relax
+ \fi}
+\def\extract@from@line#1:#2. {\extracted@number=#1\relax\extracted@line{#2}}
+\def\@gobbleline#1.{\relax}
+\def\strip@spaces#1{%
+ \@temptoks#1%
+ \@temptoks\expandafter{\the\@temptoks{\relax} }%
+ \quant@toks{}%
+ \@tempswatrue
+ \loop\if@tempswa
+ \expandafter\strip@@spaces\the\@temptoks{\relax} \@nil
+ \repeat
+ #1\quant@toks}
+\def\strip@@spaces#1 #2#3\@nil{\quant@toks\expandafter{\the\quant@toks#1}%
+ \ifx#2\relax\@tempswafalse\fi
+ \@temptoks{#2#3}}
+%Music Boxes
+\def\music#1{%
+ \def\@desiredwidth{\the\textwidth}%
+ \def\@break{1}\@@break\@break
+ \def\@afterblock{\ }%
+ \def\@lastbreak{numeric desired_width}%
+ \def\last@barline{20}%
+ \def\instr@list{#1}%
+ \def\block@chars{\@gobble}%
+ \def\music@font@splits{\@gobble}%
+ \@no@of@instr0\relax
+ \instrument@number0\relax
+ \@quantization
+ \mf@files
+ \@compose
+ \global\@firstmf\file@no\global\advance\@firstmf1\relax}
+\def\excerpt#1{%
+ \def\@desiredwidth{desired_width}%
+ \def\@break{0}\@@break\@break
+ \def\@afterblock{\relax}%
+ \def\@lastbreak{\@gobble}%
+ \def\last@barline{0}%
+ \def\instr@list{#1}%
+ \def\block@chars{\@gobble}%
+ \def\music@font@splits{\@gobble}%
+ \@no@of@instr0\relax
+ \instrument@number0\relax
+ \@quantization
+ \mf@files
+ \@compose
+ \global\@firstmf\file@no\global\advance\@firstmf1\relax}
+\def\@quantization{%
+ %First the quantization
+ \init@quantization
+ \@for\curr@instr:=\instr@list\do
+ {\expandafter\strip@spaces\csname\curr@instr @toks\endcsname%
+ \advance\@no@of@instr1\relax
+ \quant@toks{}\current@quantum0\relax
+ \extr@quant@toks{\csname\curr@instr @toks\endcsname}%
+ \@tempswafalse
+ \advance\instrument@number1\relax
+ \if@tempswb\@tempswbfalse\else\@tempswbtrue\fi\open@tm@files
+ \the\quant@toks
+ %Then, the writing of the auxiliary files for each instrument
+ \this@note\@plainnote
+ \def\current@block{\@gobble}%
+ \current@quantum0\relax
+ \block@donetrue
+ \immediate\openout\instrument@file=\curr@instr.tms\relax
+ \expandafter\the\csname\curr@instr @toks\endcsname
+ \ifnum\current@quantum=0% Which means there was '|' at the end
+ \end@block
+ \else
+ \immediate\write\instrument@file{\current@block\string\end@of@block}%
+ \fi
+ \immediate\closeout\instrument@file}%
+ \count@chars}
+\def\mf@files{%
+ \open@matrix
+ \open@tms
+ \char@no0
+ \block@no0
+ \newtoks\previous@line
+ \@tempswatrue
+ \file@no\@firstmf
+ \mf@@headers
+ \let\music@@font@splits\music@font@splits%
+ \extracted@number0\relax
+ \read\read@tm@file to \matrix@line
+ \expandafter\extract@from@line\matrix@line
+ \loop\ifnum\extracted@number<9999\relax
+ \expandafter\check@split\music@font@splits,1000\@nil
+ \read@blocks{\instr@list}%
+ \let\next\build@block
+ \build@block
+ \repeat}
+\def\build@block{%
+ \edef\temp@instr@list{\instr@list}%
+ \previous@line\expandafter{\the\extracted@line}%
+ \@tempcnta\extracted@number\relax
+ \read\read@tm@file to \matrix@line
+ \expandafter\extract@from@line\matrix@line
+ \ifnum\extracted@number=0\relax
+ \let\next\finish@block
+ \else
+ \advance\char@no1\relax
+ \ifnum\extracted@number=9999\relax
+ \ifnum\@tempcnta=\block@period
+ \def\next{\finish@block\finish@music}%
+ \else
+ \def\next{\last@block\finish@music}%
+ \fi
+ \extracted@number\block@period\relax
+ \fi
+ \find@sf
+ \init@char
+ \@for\matrix@number:=\the\previous@line\do
+ {\expandafter\get@instr\temp@instr@list,,.
+ \ifnum\matrix@number>0\relax
+ \global\block@donefalse
+ \immediate\write\written@tm@file{\curr@instr;}%
+ \expandafter\extract@note\csname\curr@instr @blocktoks\endcsname
+ \the\curr@note
+ \fi}%
+ \immediate\write\written@tm@file{end_of_char;}%
+ \fi
+ \next
+ }
+\def\finish@block{%
+ \advance\char@no1\relax
+ \immediate\write\written@tm@file{new_char(-least_spaced);}%
+ \@for\curr@instr:=\instr@list\do
+ {\expandafter\read\csname\curr@instr @file\endcsname to \@tempcs
+ \immediate\write\written@tm@file{\curr@instr;}%
+ \@tempcs}%
+ \immediate\write\written@tm@file{end_of_char;}%
+ \ifcase\@@break %\@@break is set in the instruments' tokens
+ \or\immediate\write\written@tm@file{end_of_block;}% 1 default for \music: breakable block
+ \advance\block@no1\relax
+ \or\immediate\write\written@tm@file{make_line(next_char);}% 2 is forced break
+ \fi
+ \@@break\@break\relax}
+\def\last@block{%
+ \advance\char@no1\relax
+ \immediate\write\written@tm@file{new_char(-least_spaced);}%
+ \@for\curr@instr:=\instr@list\do
+ {\immediate\write\written@tm@file{\curr@instr;}%
+ \immediate\write\written@tm@file{\space\space\space barline_(\last@barline);}}%
+ \immediate\write\written@tm@file{end_of_char;}}
+\def\finish@music{%
+ \extracted@number9999\relax
+ \immediate\write\written@tm@file{\@lastbreak; end_of_block; make_line(next_char);}%
+ \immediate\write\written@tm@file{showstats; end.}%
+ \immediate\closeout\written@tm@file}
+\def\@compose{%
+ \file@no\@firstmf
+ \block@no-1\relax
+ {%
+ \char@no0\relax
+ \@tempcnta0\relax
+ \font\@musicfont=\jobname\the\@firstmf\relax
+ \@for\@tempcsa:=\block@chars\do
+ {\advance\block@no1\relax
+ \@musicfont
+ \@whilenum\char@no<\@tempcsa\do
+ {\advance\char@no1\relax
+ \message{\the\char@no}\mbox{\char\the\char@no}%
+ }%
+ \message{|}\@afterblock %
+ \expandafter\check@@split\music@@font@splits,0\@nil
+ }%
+ }}
+\def\@bar@line#1{\immediate\write\written@tm@file{\space\space\space barline_(#1);}}
+
+\def\find@sf{%
+ \bgroup
+ \advance\extracted@number-\@tempcnta
+ \global\s@factor\extracted@number
+ \egroup}
+\def\count@chars{%
+ \open@matrix
+ \extracted@number0\relax
+ \char@no0\relax
+ \@tempcnta-1\relax % The number of blocks
+ \@tempcntb0\relax % The number of the last character in the last block
+ \loop\ifnum\extracted@number<9999\relax
+ \read\read@tm@file to \matrix@line
+ \expandafter\extract@from@line\matrix@line
+ \ifnum\char@no>\FontSplit\relax
+ \edef\music@font@splits{\music@font@splits,\the\@tempcnta}%
+ \advance\char@no-\@tempcntb\relax
+ \fi
+ \ifnum\extracted@number=0\relax % To fix all this with the new model.
+ \advance\@tempcnta1\relax
+ \@tempcntb\char@no\relax
+ \edef\block@chars{\block@chars,\the\char@no}%
+ \fi
+ \advance\char@no1\relax
+ \repeat
+ \edef\block@chars{\block@chars,\the\char@no}%
+ \edef\music@font@splits{\music@font@splits,1000}%
+ \immediate\closein\read@tm@file}
+\def\check@split#1,#2\@nil{%
+ \ifnum\block@no=#1\relax %This block was the last to write into the current file
+ \char@no0\relax
+ \close@@line
+ \global\advance\file@no1\relax
+ \mf@@headers
+ \def\music@font@splits{#2}%
+ \fi}
+\def\check@@split#1,#2\@nil{%
+ \ifnum\block@no=#1%
+ \char@no0\relax
+ \global\advance\file@no1\relax
+ \font\@musicfont=\jobname\the\file@no
+ \def\music@@font@splits{#2}%
+ \@musicfont\newline
+ \fi}
+\def\mf@@headers{%
+ \immediate\openout\written@tm@file=\jobname\the\file@no.mf%
+ \immediate\write\written@tm@file{mode_setup;}%
+ \immediate\write\written@tm@file{input txmfont;}%
+ \immediate\write\written@tm@file{input texmuse;}%
+ \immediate\write\written@tm@file{instr_no(\the\@no@of@instr);}%
+ \@tempcnta0\relax
+ \immediate\write\written@tm@file{key_ := \the\@key;}%
+ \immediate\write\written@tm@file{desired_width := \@desiredwidth/pt;}%
+ \@tempcnta0\relax
+ \@for\curr@instr:=\instr@list\do
+ {\advance\@tempcnta1\relax
+ \immediate\write\written@tm@file{staff_\the\@tempcnta="-1,0,1,2,3";}%
+ \immediate\write\written@tm@file{bar_type\the\@tempcnta=\barline@default;}%
+ \immediate\write\written@tm@file{instr_clef\the\@tempcnta :=
+ \csname\curr@instr @clef\endcsname;}%
+ \immediate\write\written@tm@file{def \curr@instr\space =}%
+ \immediate\write\written@tm@file{\space\space\space curr_instr:="\curr@instr;";}%
+ \immediate\write\written@tm@file{\space\space\space note_[index][instr_]:=currentpicture;}%
+ \immediate\write\written@tm@file{\space\space\space instr_:=\the\@tempcnta;}%
+ \immediate\write\written@tm@file{\space\space\space currentpicture:=note_[index][instr_];}%
+ \immediate\write\written@tm@file{\space\space\space enddef;}}%
+ \@tempswatrue}
+\def\close@@line{%
+ \immediate\write\written@tm@file{make_line(next_char); showstats; end.}%
+ \immediate\closeout\written@tm@file}
+%Initializations
+\def\init@quantization{\@tempswbtrue
+ \immediate\openout\written@tm@file=\jobname.tm1\relax%
+ \immediate\write\written@tm@file{9999: 0.}%
+ \immediate\closeout\written@tm@file\relax}%
+\def\open@matrix{\immediate\openin\read@tm@file=\jobname.tm\ifodd\instrument@number 2\else1\fi\relax}
+\def\open@tms{%
+ \@for\curr@instr:=\instr@list\do
+ {\expandafter\newread\csname\curr@instr @file\endcsname
+ \immediate\openin\csname\curr@instr @file\endcsname=\curr@instr.tms%
+ \expandafter\newtoks\csname\curr@instr @blocktoks\endcsname}}
+\@plainnote{}
+\@atnote{}
+\@hookels0
+\@firstmf1\relax
+\FontSplit=180\relax
+\def\barline@default{10}
+\let\@barline\barline@default
+
+\makeatother
+
diff --git a/macros/texmuse/Program/txmfont.mf b/macros/texmuse/Program/txmfont.mf
new file mode 100644
index 0000000000..653cb73c3a
--- /dev/null
+++ b/macros/texmuse/Program/txmfont.mf
@@ -0,0 +1,405 @@
+font_size 20pt#;
+bassdepth#:=140/108pt#; % depth of bass-clef below baseline = depth of comma in cmr
+interline#:=140/36pt#; % inter line space in staff = depth of descenders in cmr
+framingspace#:=9/32interline#; % calculated from the bass-clef
+long_axis#=1.5interline#-line_thick#; % long axis in note-heads ellipse.
+notehead_angle=26; % the angle of rotation of the notehead ellipse.
+horizontal_axis#=long_axis#*cosd(notehead_angle);
+stemcorrection#=1/10interline#;
+define_pixels(long_axis,horizontal_axis,stemcorrection);
+short_axis=.65long_axis;
+regular_width#=2framingspace#+horizontal_axis#;
+define_pixels(bassdepth,interline,bassdepth,framingspace,regular_width);
+curve_sidebar=round 10/36pt;
+line_thick#=1/10interline#;
+special_space#=1/9interline#; % I used to use line_thick for some spaces, but it does not
+% work when line_thick is changed. So, special_space is
+% equal to the value of line_thick I used then.
+staff_h#=3interline#; % staff height
+define_pixels(line_thick,staff_h,special_space)
+museangle=75; % angle for musecircles
+stem_heigth=3.5;
+% Font-dimens:
+font_normal_space:=0pt#;
+font_normal_stretch:=100pt#;
+font_normal_shrink:=0pt#;
+font_quad:=horizontal_axis#;
+font_x_height:=interline#;
+font_extra_space:=0pt#;
+% Width of different types of character
+barline_sep:=1.5horizontal_axis;
+numeric widths[];
+def musecircle(suffix i,j,k,l) = % center, edge, suffixes for new points. k=+, l=-
+ numeric museradius, anglefrom;
+ museradius=abs(length (z.i-z.j));
+ anglefrom=angle (z.j-z.i);
+ z.k-z.i=museradius*dir(anglefrom+museangle);
+ z.l-z.i=museradius*dir(anglefrom-museangle);
+ fill fullcircle scaled 2museradius shifted z.i
+ enddef;
+def note_head =
+ fullcircle xscaled long_axis yscaled short_axis rotated notehead_angle
+ enddef;
+small_rests_radius:=1/2(interline-3line_thick);
+def put_rest_unit(expr base, width) =
+ if known x.circlecenter:
+ else:
+ x.circlecenter=x.circlebottom=-small_rests_radius;
+ y.circlecenter=y.circlebottom+small_rests_radius=y.restpoint-line_thick=1.5interline;
+ x.restpoint-small_rests_radius=x.restbottom=0;
+ y.restbottom:=1/2line_thick;
+ numeric rests_angle;
+ rests_angle=angle(z.restpoint-z.restbottom);
+ penpos.restpoint(small_rests_radius,rests_angle);
+ z.circlebottom.l=z.circlebottom;
+ z.circlebottom.r=z.circlepoint;
+ z.restright.l=z.restpoint.l; z.restright.r=z.restpoint.r shifted(1/2line_thick,0);
+ penpos.restbottom(width,0);
+ fi
+ musecircle(circlecenter,circlebottom,circlepoint,secondcirclepoint) shifted base;
+ penstroke (z.circlebottom.e{right}..z.restpoint.e--z.restright.e--z.restbottom.e)%
+ shifted base;
+ enddef;
+def regular_note_head =
+ note_axis[index] := max(note_axis[index],1/2regular_width);
+ width[index] := max(width[index],1/2regular_width);
+ stem_point[index][instr_] := (stem_dir[index][instr_]*(xpart(directionpoint up of (note_head))-.5line_thick),
+ stem_dir[index][instr_]*ypart(directionpoint up of (note_head)));
+ fill note_head
+ enddef;
+picture half_notehead;
+begingroup; save x, y;
+ clearit;
+ path p[];
+ p1=fullcircle xscaled long_axis yscaled .7long_axis;
+ numeric t[];
+ forsuffixes s=1,2,3,4:
+ z.s=directionpoint dir(90+s*90) of p1;
+ endfor;
+ z5=z1+7/24short_axis*down; z6=z2+line_thick*right;
+ z7=z3+7/24short_axis*up; z8=z4+line_thick*left;
+ p2=(superellipse(z8,z5,z6,z7,.8)) rotated notehead_angle;
+ fill p1 rotated notehead_angle;
+ unfill p2;
+ cullit;
+half_notehead := currentpicture; clearit;
+endgroup;
+
+def half_note_head =
+ note_axis[index] := max(note_axis[index],1/2regular_width);
+ width[index] := max(width[index],1/2regular_width);
+ stem_point[index][instr_] := (stem_dir[index][instr_]*(xpart(directionpoint up of (note_head))-.5line_thick),
+ stem_dir[index][instr_]*ypart(directionpoint up of (note_head)));
+ addto currentpicture also half_notehead
+ enddef;
+
+vardef whole_test(expr scale) =
+ ypart(directionpoint left of p)-%
+ ypart(directionpoint left of (p scaled scale rotated (90+notehead_angle)))%
+ <line_thick enddef;
+
+picture whole_notehead;
+ path p;
+ p=fullcircle xscaled (1.5interline+line_thick) yscaled (interline+1/2line_thick);
+ numeric true_scale;
+ true_scale=solve whole_test(1,0);
+ fill p; unfill p scaled true_scale rotated (90+notehead_angle);
+ whole_notehead=currentpicture; clearit;
+
+def whole_note =
+ note_axis[index] := max(note_axis[index],1.5interline+1/2line_thick);
+ width[index] := max(note_axis[index],1.5interline+1/2line_thick);
+ stem_point[index][instr_] := (stem_dir[index][instr_]*1.5interline,
+ stem_dir[index][instr_]*.5interline);
+ addto currentpicture also whole_notehead
+ enddef;
+
+picture rest_[];
+ pickup penrazor xscaled line_thick rotated 90;
+ draw (-1/regular_width, 2interline)--(1/2regular_width, 2interline);
+ pickup penrazor xscaled 1/2interline rotated 90;
+ draw (-1/horizontal_axis, 1.75interline)--(1/2horizontal_axis, 1.75interline);
+rest_[-2]:=currentpicture; clearit; rest_width[-2]:= 1/2regular_width + framingspace;
+ draw (-1/2horizontal_axis, 1.25interline)--(1/2horizontal_axis, 1.25interline);
+ pickup penrazor xscaled line_thick rotated 90;
+ draw (-1/2regular_width, interline)--(1/2regular_width, interline);
+rest_[-1]:=currentpicture; clearit; rest_width[-1]:= 1/2regular_width + framingspace;
+ z1=(.65short_axis,line_thick);
+ z2=(x1,2interline-.5line_thick);
+ z3=(0,interline-.5line_thick);
+ path p[];
+ p1=z2{z3-z2}..{down}z3..{z1-z3}z1;
+ z4=point .2 of p1;
+ y5=interline+.5line_thick;
+ vardef tooleft(expr x) =
+ length((x,y5)-z3)>.5interline enddef;
+ x5=solve tooleft(-short_axis,short_axis);
+ z6-z4=z5-z3;
+ x7r-x5=x5+.75short_axis;
+ z7r-z2=whatever*(z5-z1);
+ penpos7(line_thick,90+angle(z7r-z4));
+ penpos1(-1.5line_thick,90+angle(z1-z5));
+ fill z7l--z4{z3-z2}..{down}z3..{z1l-z3}z1l--z1r---z5{z6-z5}..{up}z6..{z7r-z6}z7r--cycle;
+ z8=(-line_thick/2,-.5interline);
+ penpos8(line_thick,90+angle(z1-z5));
+ z9l=(-.65short_axis,y1);
+ penpos9(-.4interline,angle(z5-z3));
+ penstroke z1e{z5-z1l}..z9e{down}..{z1l-z5}z8e;
+ cullit;
+rest_[0]:=currentpicture; clearit; rest_width[0] := 1/2regular_width + framingspace;
+begingroup; save x,y;
+ z0=(3/2small_rests_radius,0);
+ put_rest_unit(z0, line_thick);
+rest_[1] := currentpicture; clearit; rest_width[1] := 3/2small_rests_radius + framingspace;
+endgroup;
+begingroup; save x,y;
+ x0-1/2(5small_rests_radius+framingspace)=1/2(5small_rests_radius+framingspace)-x1=%
+ 1/2cosd(rests_angle)/sind(rests_angle)*interline;
+ y0=0; y1=-interline;
+ put_rest_unit(z0, 1/3line_thick);
+ put_rest_unit(z1, line_thick);
+rest_[2] := currentpicture shifted(-2small_rests_radius,0);
+clearit; rest_width[2] := 2small_rests_radius + 2framingspace;
+endgroup;
+%transform u;
+%xpart u=0;
+%xxpart u=1;
+%xypart u=0;
+%ypart u=0;
+%yxpart u=sind(17)/cosd(17);
+%yypart u=1;
+%vardef higher(expr y) =
+% ypart((bot (short_axis-line_thick,y)) transformed u)>interline enddef;
+picture sharp;
+begingroup;
+ save x, y;
+ transform t;
+ (0, .5interline) transformed t = (0,.5interline);
+ (0, 1) transformed t = (0, 1);
+ (horizontal_axis, .5interline) transformed t = (horizontal_axis, .8interline);
+ pickup penrazor xscaled .3interline rotated 90;
+ z1 = (-1/2horizontal_axis, .5interline); z2 = (1/2horizontal_axis, .5interline);
+ draw (z1--z2) transformed t;
+ pickup penrazor xscaled line_thick;
+ ypart(z3 transformed t) = 1.5interline;
+ x3=x2-.35interline;
+ draw (z3--(x3, -y3)) transformed t;
+ addto currentpicture also currentpicture rotatedabout ((0,0),180);
+endgroup;
+sharp := (currentpicture shifted (-1/2horizontal_axis,0));
+clearit;
+picture natural;
+begingroup;
+ save x, y;
+ transform t;
+ (0, .5interline) transformed t = (0,.5interline);
+ (0, 1) transformed t = (0, 1);
+ (horizontal_axis, .5interline) transformed t = (horizontal_axis, .8interline);
+ z1 = (-1/2horizontal_axis, .5interline); z2 = (1/2horizontal_axis, .5interline);
+% draw (z1--z2) transformed t;
+ ypart(z3 transformed t) = 1.5interline;
+ x3 = x2-.35interline;
+ pickup penrazor xscaled .3interline rotated 90;
+ z4 = (z1--z2) intersectionpoint (z3--(x3,-y3));
+ draw ((-x4, y4)--(x4+1/2line_thick, y4)) transformed t;
+ pickup penrazor xscaled line_thick;
+ draw (z4--(x3, -y3)) transformed t;
+ addto currentpicture also currentpicture rotatedabout ((0,0),180);
+endgroup;
+natural := (currentpicture shifted (.15interline-1/2horizontal_axis,0));
+clearit;
+picture flat;
+begingroup;
+ save x, y;
+ numeric scratch_angle; scratch_angle=25;
+ penpos1(line_thick,-90);
+ x1=1/2framingspace+line_thick; y1=-1/2line_thick;
+ penpos2(6/14interline,1/2scratch_angle);
+ y2r-y1r=1/2interline+sind(scratch_angle)/cosd(scratch_angle)*(long_axis-line_thick-2framingspace);
+ x2r=long_axis-line_thick-1/2framingspace;
+ penpos3(line_thick,90+scratch_angle);
+ x3=1/2[x2l,x1]; y3=interline+1/2sind(scratch_angle)/cosd(scratch_angle)*(x3-x1);
+ penpos4(2/7interline,90);
+ x4=x1;
+ y4r=interline-1/2sind(scratch_angle)/cosd(scratch_angle)*(x3-x1);
+ penstroke z1e{dir scratch_angle}..z2e{up}..z3e{dir (180+scratch_angle)}..z4e;
+ pickup penrazor scaled line_thick;
+ draw (x1-1/2line_thick, y1r)--(x1-1/2line_thick,2interline+line_thick);
+endgroup;
+flat := (currentpicture shifted (-horizontal_axis,-1/2interline));
+clearit;
+
+picture treble_clef;
+picture small_treble_clef;
+clearit;
+begingroup
+save x,y,u;
+ u:=1/10staff_h; % bottom circle radius
+ numeric edgeshift, scratchangle, scratchdistance;
+ edgeshift:=1/4interline;
+ path p[];
+ z10l=(framingspace,edgeshift);
+ penpos10(2line_thick,0);
+ y1=-2interline;
+ z2-z1=1.2u*dir-135;
+ trebleaxis = x1+u;
+ z3=(trebleaxis,-2.5interline); z4l=(x1+3u,y1);
+ z5l=(trebleaxis,2.5interline);
+ z17=(x10r+2u+interline,line_thick); % treble center
+ x17-x5l=x4l-x17;
+ z4r-z4l=whatever*(z17-z4l) rotated 90;
+ penpos4(line_thick,angle(z17-z4l)+90);
+ z5r-z5l=z4r-z4l;
+ penpos3(line_thick,90);
+ musecircle(1,2,15,16);
+ z2l=z2; z2r=z15;
+ penstroke z2e..{right}z3e..{up}z4e{z17-z4l}..z5e;
+ scratchangle=-45;
+ z8l=z5r; penpos8(1/2interline,scratchangle);
+ z9l=(1/2[x5r,x10],2interline); penpos9(1/2interline,scratchangle);
+ z11=(trebleaxis,-interline); penpos11(line_thick,90);
+ z13l=(x17,interline+line_thick); penpos13(1/2interline,-90);
+ penstroke z8e..{z9-z8}z9e..z10e..z11e{right};
+ p1=(x11,y11-1/2special_space){right}..{left}z13l; p2=fullcircle rotated -90 scaled 2interline shifted z17;
+ pickup pencircle scaled .1pt;
+ numeric t,v;
+ (t,v)=p1 intersectiontimes p2;
+ z12=p1 intersectionpoint p2; penpos12(line_thick,angle direction v of p2 + 90);
+ penstroke z11e{right}..z12e..{left}z13e;
+% point 14, the end of the central ball, is as far from 17 as it is from the curve downthere.
+% And that distance should be the one called scratchdistance.
+ z18=point 1/3 of (z9r{z9-z8}..{down}z10r); % to get the distance between the ball and the stem
+ scratchdistance=length(z18-z17)-interline;
+ p3=fullcircle scaled 4scratchdistance shifted z17;
+ p4=z10r{down}..z11r{right};
+ z19=p3 intersectionpoint p4; z14=1/2[z19,z17];
+ treblewidth = x14;
+ numeric t,v; (t,v)=p3 intersectiontimes p4;
+ penpos14(.5line_thick, angle direction v of p4+90);
+ penstroke z13e{left}..{direction v of p4}z14e;
+% crown
+ z6l=(xpart(p1 intersectionpoint (z4l--z5l)),4interline); penpos6(1/2interline,95);
+ pair interpoint;
+ interpoint=(whatever,3.1interline);
+ interpoint-z5r=whatever*(z5l-z4l);
+ fill z5l{z5l-z4l}..{right}z6l--z6r{z8l-z5l}..{down}interpoint..{z4l-z5l}z5r--cycle;
+ x7l-x17=x17-x5r; y7l=3.6interline; penpos7(2special_space,-30);
+ fill z6l{right}..{down}z7l..tension1.6..z8l--z8r..{up}z7r..{curl2}z6r--cycle;
+endgroup;
+treble_clef:=currentpicture; clearit;
+begingroup
+save x,y,u;
+ u:=1/10staff_h; % bottom circle radius
+ numeric edgeshift, scratchangle, scratchdistance;
+ edgeshift:=0/4interline;
+ path p[];
+ z10l=(1framingspace,edgeshift);
+ penpos10(1.7line_thick,0);
+ y1=-1.5interline;
+ z2-z1=u*dir-155;
+ trebleaxis:=x1+.85u;
+ z3=(trebleaxis,-2interline); z4l=(x1+2.5u,y1);
+ z5l=(trebleaxis,2.2interline);
+ z17=(x10r+1.2u+interline,0); % treble center
+ x17-x5l=x4l-x17;
+ z4r-z4l=whatever*(z17-z4l) rotated 90;
+ penpos4(line_thick,angle(z17-z4l)+90);
+ z5r-z5l=z4r-z4l;
+ penpos3(line_thick,90);
+ musecircle(1,2,15,16);
+ z2l=z2; z2r=z15;
+ penstroke z2e..{right}z3e..{up}z4e{z17-z4l}..z5e;
+ scratchangle=-45;
+ z8l=z5r; penpos8(2/5interline,scratchangle);
+ z9l=(1/2[x5r,x10],1.7interline); penpos9(2/5interline,scratchangle);
+ z11=(trebleaxis,-.85interline); penpos11(line_thick,90);
+ z13l=(x17,.85interline); penpos13(2/5interline,-90);
+ penstroke z8e..{z9-z8}z9e..z10e..z11e{right};
+ p1=z11l{right}..{left}z13l; p2=fullcircle rotated -90 scaled 1.8interline shifted z17;
+ x12 = x17; y12=y11; penpos12(line_thick, 90);
+ penstroke z11e..z12e{right}..{left}z13e;
+ z18=point 1/3 of (z9r{z9-z8}..{down}z10r); % to get the distance between the ball and the stem
+ scratchdistance=length(z18-z17)-.8interline;
+ p3=fullcircle scaled 4scratchdistance shifted z17;
+ p4=z10r{down}..z11r{right};
+ z19=p3 intersectionpoint p4; z14=1/2[z19,z17];
+ numeric t,v; (t,v)=p3 intersectiontimes p4;
+ penpos14(.5line_thick, angle direction v of p4+90);
+ penstroke z13e{left}..{direction v of p4}z14e;
+ z6l=(xpart(p1 intersectionpoint (z4l--z5l)),3.5interline); penpos6(2/5interline,95);
+ pair interpoint;
+ interpoint=(whatever,2.8interline);
+ interpoint-z5r=whatever*(z5l-z4l);
+ fill z5l{z5l-z4l}..{right}z6l--z6r{z8l-z5l}..{down}interpoint..{z4l-z5l}z5r--cycle;
+ x7l-x17=x17-x5r; y7l=3.2interline; penpos7(1.7special_space,-30);
+ fill z6l{right}..{down}z7l..tension1.6..z8l--z8r..{up}z7r..{curl2}z6r--cycle;
+endgroup;
+small_treble_clef:=currentpicture; clearit;
+picture bass_clef, small_bass_clef;
+begingroup
+save x, y, u;
+ u=1/16staff_h;
+ y1=y4r=2interline;
+ x1=3u; z2-z1=2u*dir190;
+ musecircle(1,2,7,6);
+ scratchradius=x1-x2;
+ bassaxis=scratchradius/2;
+ penpos3(line_thick,-100);
+ penpos4(1.4scratchradius,170);
+ x5=0; y5=-bassdepth;
+ x4r=x1+3.1scratchradius;
+ y3l=staff_h; x3r=1/2[x4r,x1];
+ basswidth = x4l - bassaxis;
+ pickup pencircle scaled .1pt;
+ fill z2{dir100}..{right}z3l..{down}z4l..{dir-170}z5%
+ --(x5,y5+1){dir10}..{up}z4r..{left}z3r..{down}z6..cycle;
+ fill fullcircle scaled scratchradius %
+ shifted (staff_h-framingspace-.5scratchradius, 2.5interline);
+ fill fullcircle scaled scratchradius %
+ shifted (staff_h-framingspace-.5scratchradius, 1.5interline);
+endgroup;
+bass_clef:=currentpicture; clearit;
+begingroup
+save x, y, u;
+ u:=1/6interline;
+ y1=y4r=2interline;
+ x1=3u; z2-z1=2u*dir190;
+ musecircle(1,2,7,6);
+ scratchradius:=x1-x2;
+ penpos3(line_thick,-100);
+ penpos4(1.4scratchradius,170);
+ x5=0; y5=0;
+ x4r=x1+3.1scratchradius;
+ y3l=2.9interline; x3r=1/2[x4r,x1];
+ pickup pencircle scaled .1pt;
+ fill z2{dir100}..{right}z3l..{down}z4l..{dir-170}z5%
+ --(x5,y5+1){dir10}..{up}z4r..{left}z3r..{down}z6..cycle;
+ fill fullcircle scaled scratchradius %
+ shifted (2.75interline-framingspace-.5scratchradius, 2.5interline);
+ fill fullcircle scaled scratchradius %
+ shifted (2.75interline-framingspace-.5scratchradius, 1.5interline);
+endgroup;
+small_bass_clef:=currentpicture; clearit;
+def universal_flag(expr flag_height,stemmed_length,extreme_shift_ratio,collision_angle) =
+ path q[];
+ q1=note_head;
+ numeric flag_time;
+ pair flag_top, flag_extreme, flag_bottom, flag_middle;
+ pair extremel, extremer;
+ flag_extreme=(extreme_shift_ratio*short_axis)*dir(notehead_angle+90);
+ flag_top=(xpart(directionpoint up of q1)-1/2line_thick,ypart(flag_extreme)+flag_height);
+ flag_extreme=1/2[extremel,extremer];
+ extremer=extremel+(.5special_space,0) rotated notehead_angle;
+ flag_top-flag_bottom=(0,stemmed_length-1/2line_thick);
+ q2=extremer{dir(90+notehead_angle)}..%
+ {dir(collision_angle)}flag_bottom-(1/2line_thick,0)--flag_bottom-(7/16line_thick,0);
+ flag_time=directiontime dir(90-notehead_angle) of q2;
+ flag_middle-directionpoint dir(90-notehead_angle) of q2= %
+ line_thick*dir(180-notehead_angle);
+ q3=extremel{dir(90+notehead_angle)}..{dir(90-notehead_angle)}flag_middle%
+ ..{dir(88)}flag_top-(1/2line_thick,0)--flag_top-(7/16line_thick,0);
+ fill (q2--reverse q3--cycle)
+enddef;
+def eighth_flag(expr notehead_center) =
+ universal_flag(3interline-line_thick,interline,1/2,10) shifted(notehead_center)
+enddef;