[Pamphlet explaining some fine points in music font design HWN]
+
=head2 Notation with computers
Donald Byrd. ``Music Notation by Computer''. Dissertation Indiana
[Annual editions since 1985, many containing surveys of music
typesetting technology. SP]
-Wael A. Hegazy and John S. Gourlay. ``Optimal line breaking in music''. In
-Document Manipulation and Typography, J.C. van Vliet (ed) 1988.
-
-[This generalizes TeX's breaking algorithm to music HWN]
-
David A. Gomberg; ``A Computer-oriented System for Music Printing.''
Computers and the Humanities, Vol.11, pp 63-80.
[Describes the "parser" which converts MusiCopy MDL to MusiCopy
Simultaneities & columns HWN]
+Wael A. Hegazy and John S. Gourlay. ``Optimal line breaking in
+music''. Technical Report OSU-CISRC-8/87-TR33, Department of Computer
+and Information Science, The Ohio State University, 1987
+
+[This generalizes TeX's breaking algorithm to music. It also appeared in
+Document Manipulation and Typography, J.C. van Vliet (ed) 1988. HWN]
+
Dean K. Roush. ``Using MusiCopy''. Technical Report
OSU-CISRC-18/87-TR31, Department of Computer and Information Science,
The Ohio State University, 1987
1980.
-=head2 other stuff
+=head2 Other stuff
More on GNU Music:
http://dept-info.labri.u-bordeaux.fr/~strandh/Gsharp
-Tablature: http://wabakimi.carleton.ca/~phacket2/guitar/tabfaq.html
-
-
Peter S. Langston, ``Unix music tools at Bellcore''. Software ---
Practice and Experience, Vol. 20(S1), S1/47--S1/61, 1990.
grand idea (not) of using music to monitor complex systems. Imagine
your nuclear plant supervisor to use AC/DC for checking the reactor HWN]
+
+=head2 File formats
+
+Tablature: http://wabakimi.carleton.ca/~phacket2/guitar/tabfaq.html
+
Cindy Grande, NIFF6a Notation Interchange File Format. Grande
-Software Inc., 1995. ftp://blackbox.cartah.washington.edu/pub/
+Software Inc., 1995. ftp://blackbox.cartah.washington.edu/pub/,
+http://www.jtauber.com/music/encoding/niff/
[Specs for NIFF, a comprehensive but binary (yuk) format for notation HWN]
+SMDL, Standard Musical Description Language
+ftp://ftp.ornl.gov/pub/sgml/wg8/smdl/10743.pdf
+
+MPDL,
+
+HMSL, Hierarchical Music Structured Language,
+
+DARMS,
+
+enigma,
+
+SCORE,
+
+
=head1 AUTHORS
References and comments contributed by Han-Wen Nienhuys (HWN), Miguel
Filgueiras, Mark Basinski (MB), Dorothea Blostein, Stephen Page (SP),
-Jan Nieuwenhuizen.
+Jan Nieuwenhuizen, Peter Kerr.
This should really be redone in BibTeX
+
--- /dev/null
+/*
+ gourlay-breaking.cc -- implement Gourlay_breaking
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+#include "gourlay-breaking.hh"
+#include "colhpos.hh"
+#include "spring-spacer.hh"
+#include "debug.hh"
+#include "p-col.hh"
+#include "p-score.hh"
+#include "paper-def.hh"
+
+
+const HAPPY_DOTS_I = 3;
+
+/**
+ Helper to trace back an optimal path
+ */
+struct Break_node {
+ /** this was the previous. If negative, this break should not be
+ considered: this path has infinite energy
+
+ */
+ int prev_break_i_;
+ Real energy_f_;
+ Col_hpositions line_config_;
+ Break_node() {
+ prev_break_i_ = -1;
+ }
+};
+
+/**
+ This algorithms is adapted from
+ */
+
+Array<Col_hpositions>
+Gourlay_breaking::do_solve()const
+{
+
+ Array<Break_node> optimal_paths;
+ Line_of_cols all = all_cols();
+ Array<int> breaks = find_break_indices();
+
+ optimal_paths.set_size(breaks.size());
+
+ Break_node first_node ;
+ first_node.prev_break_i_ = -1;
+ first_node.line_config_.energy_f_ = 0;
+
+ optimal_paths[0] = first_node;
+ int break_idx=1;
+
+
+ for (; break_idx< breaks.size(); break_idx++) {
+ Array<int> candidates;
+ Array<Col_hpositions> candidate_lines;
+ Pointer_list<Line_spacer*> spacer_p_list;
+
+ /*
+ start with a short line, add measures. At some point
+ the line becomes infeasible. Then we don't try to add more
+ */
+ for (int start_idx = break_idx; start_idx--; ){
+ if (break_idx - start_idx > max_measures_i_)
+ break;
+
+ if (optimal_paths[start_idx].prev_break_i_ < 0
+ && optimal_paths[start_idx].line_config_.energy_f_)
+
+ continue;
+
+ Line_of_cols line = all.slice(breaks[start_idx], breaks[break_idx]+1);
+
+ line[0] = line[0]->postbreak_p_;
+ line.top() = line.top()->prebreak_p_;
+
+ if (!feasible(line))
+ break;
+
+ Col_hpositions approx;
+ approx.cols = line;
+
+ approx.spacer_l_ = generate_spacing_problem( line );
+ spacer_p_list.bottom().add(approx.spacer_l_);
+
+ ((Break_algorithm*)this)->approx_stats_.add( approx.cols );
+ approx.approximate_solve_line( );
+
+ if (approx.energy_f_ > energy_bound_f_ ){
+ continue;
+ }
+
+
+ // this is a likely candidate. Store it.
+ candidate_lines.push( approx );
+ candidates.push( start_idx );
+ }
+
+
+ int minimal_j = -1;
+ Real minimal_energy = infinity_f;
+ for (int j=0; j < candidates.size(); j++) {
+ int start = candidates[j];
+ if ( optimal_paths[start].line_config_.energy_f_
+ + candidate_lines[j].energy_f_ > minimal_energy)
+
+ continue;
+
+ if ( !candidate_lines[j].satisfies_constraints_b_) {
+ candidate_lines[j].solve_line( );
+ ((Break_algorithm*)this)->exact_stats_.add ( candidate_lines[j].cols );
+ }
+
+ Real this_energy
+ = optimal_paths[start].line_config_.energy_f_
+ + candidate_lines[j].energy_f_ ;
+
+ if ( this_energy < minimal_energy ) {
+ minimal_j = j;
+ minimal_energy = this_energy;
+ }
+ }
+
+ if (minimal_j < 0) {
+ optimal_paths[break_idx].prev_break_i_ = -1;
+ optimal_paths[break_idx].line_config_.energy_f_ = infinity_f;
+ } else {
+ optimal_paths[break_idx].prev_break_i_ = candidates[minimal_j];
+ optimal_paths[break_idx].line_config_ = candidate_lines[minimal_j];
+ }
+
+ if ( !(break_idx % HAPPY_DOTS_I) )
+ *mlog << "[" << break_idx << "]"<<flush;
+ }
+
+ if ( break_idx % HAPPY_DOTS_I)
+ *mlog << "[" << break_idx << "]"<<flush;
+ print_stats();
+
+
+
+ Array<int> final_breaks;
+
+ /* skip 0-th element, since it is a "dummy" elt*/
+ for (int i = optimal_paths.size()-1; i> 0; ) {
+ final_breaks.push ( i );
+ assert ( i > optimal_paths[i].prev_break_i_);
+ i = optimal_paths[i].prev_break_i_;
+ }
+
+ Array<Col_hpositions> lines;
+ for (int i= final_breaks.size(); i--; )
+ lines.push ( optimal_paths[final_breaks[i]].line_config_ );
+
+
+ return lines;
+}
+
+
+Gourlay_breaking::Gourlay_breaking()
+{
+ get_line_spacer = Spring_spacer::constructor;
+ energy_bound_f_ = infinity_f;
+ max_measures_i_ = INT_MAX;
+}
+
+void
+Gourlay_breaking::do_set_pscore()
+{
+ energy_bound_f_ = pscore_l_->paper_l_->get_var( "gourlay_energybound");
+ max_measures_i_ =int (rint( pscore_l_->paper_l_->get_var( "gourlay_maxmeasures")));
+}
+