From 5f94c3ae8a1804e880693edbc28d2c6a838d3149 Mon Sep 17 00:00:00 2001 From: Jan Nieuwenhuizen Date: Wed, 3 Feb 1999 19:30:54 +0100 Subject: [PATCH] patch::: 1.1.26.jcn4: koord vixen pl 26.jcn4 - Chord: handle all chord stuff; lots of chord fixes - bf: Chord-name-engraver: find tonic - bf: my-lily-parser: get_chord --- Generated by janneke@gnu.org using package-diff 0.62, >From = lilypond-1.1.26.jcn3, To = lilypond-1.1.26.jcn4 usage cd lilypond-source-dir; patch -E -p1 < lilypond-1.1.26.jcn4.diff Patches do not contain automatically generated files or (urg) empty directories, i.e., you should rerun autoconf, configure and possibly make outdirs. --state 1.1.26.jcn3 1.1.26.jcn4 ++state --- NEWS | 12 +- VERSION | 2 +- input/test/chord-inversion.ly | 5 +- input/test/chord-preserve.ly | 27 ++ lily/chord-name-engraver.cc | 161 ++---------- lily/chord.cc | 366 ++++++++++++++++++++++++++++ lily/include/chord-name-engraver.hh | 7 +- lily/include/chord.hh | 33 +++ lily/include/lily-proto.hh | 1 + lily/my-lily-parser.cc | 155 +----------- 10 files changed, 468 insertions(+), 301 deletions(-) create mode 100644 input/test/chord-preserve.ly create mode 100644 lily/chord.cc create mode 100644 lily/include/chord.hh diff --git a/NEWS b/NEWS index 45b3718dde..bdb5641679 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,14 @@ ---- ../lilypond-1.1.26.jcn2/NEWS Mon Feb 1 20:58:27 1999 +--- ../lilypond-1.1.26.jcn3/NEWS Wed Feb 3 19:24:58 1999 +++ b/NEWS Wed Feb 3 19:22:08 1999 +@@ -1,3 +1,8 @@ +pl 26.jcn4 + - Chord: handle all chord stuff; lots of chord fixes + - bf: Chord-name-engraver: find tonic + - bf: my-lily-parser: get_chord + + pl 26.jcn3 + - bf's: spring spacer end of measure + - bf: tie/slur rods (dankje, lieverd)--- ../lilypond-1.1.26.jcn2/NEWS Mon Feb 1 20:58:27 1999 ++ b/NEWS Tue Feb 2 21:06:00 1999 @@ -1,3 +1,8 @@ pl 26.jcn3 diff --git a/VERSION b/VERSION index e85c442910..33e070e248 100644 --- a/VERSION +++ b/VERSION @@ -2,7 +2,7 @@ PACKAGE_NAME=LilyPond MAJOR_VERSION=1 MINOR_VERSION=1 PATCH_LEVEL=26 -MY_PATCH_LEVEL=jcn3 +MY_PATCH_LEVEL=jcn4 # use the above to send patches: MY_PATCH_LEVEL is always empty for a # released version. diff --git a/input/test/chord-inversion.ly b/input/test/chord-inversion.ly index 43103eaebc..543502d4a0 100644 --- a/input/test/chord-inversion.ly +++ b/input/test/chord-inversion.ly @@ -9,7 +9,10 @@ inversions = \notes\transpose c''\chords{ c1 c-sus c-6 c/e c/g c/d % now try to find chords with inversions \property Score.chordInversion = 1 - c1 c-sus c-6 c/e c/g + \property Score.chordInversionPreserve = 1 + c1 c-sus c-6 + c/e % c/e is not found because preserving doesn't work fully yet... + c/g c/d % this triggers a warning: no 'd' in chord of c } diff --git a/input/test/chord-preserve.ly b/input/test/chord-preserve.ly new file mode 100644 index 0000000000..b7e3998134 --- /dev/null +++ b/input/test/chord-preserve.ly @@ -0,0 +1,27 @@ +koorden = \chords{ + c1-2/d c-2.3/d +} + + +\score{ + < + \property Score.chordInversion = "1" + \type ChordNames { + \property Score.chordInversionPreserve = "0" + \koorden + \property Score.chordInversionPreserve = "1" + \koorden + } + \type Staff \notes\transpose c''{ + \property Score.chordInversionPreserve = "0" + \koorden + % preserving doesn't work for staff yet + % see lily/chord.cc + \property Score.chordInversionPreserve = "1" + \koorden + } + > + \paper{ + linewidth = -1.; + } +} diff --git a/lily/chord-name-engraver.cc b/lily/chord-name-engraver.cc index df90680dc4..336eacb3ed 100644 --- a/lily/chord-name-engraver.cc +++ b/lily/chord-name-engraver.cc @@ -7,6 +7,7 @@ */ #include "chord-name-engraver.hh" +#include "chord.hh" #include "musical-request.hh" #include "paper-def.hh" #include "lookup.hh" @@ -39,72 +40,6 @@ Chord_name_engraver::do_try_music (Music* m) return false; } - /* - find tonic: after longest line of triads - */ -int -Chord_name_engraver::find_tonic_i () const -{ - int tonic_i = 0; - int longest_i = 0; - for (int i = 0; i < pitch_arr_.size (); i++) - for (int j = 0; j < pitch_arr_.size (); j++) - { - int gap = pitch_arr_[(i + j + 1) % pitch_arr_.size ()].notename_i_ - - pitch_arr_[(i + j) % pitch_arr_.size ()].notename_i_; - while (gap < 0) - gap += 7; - gap %= 7; - if (gap != 2) - { - if (j > longest_i) - { - longest_i = j; - tonic_i = i; - } - break; - } - } - - int biggest_i = 0; - if (!longest_i) - for (int i = 0; i < pitch_arr_.size (); i++) - { - int gap = pitch_arr_[i].notename_i_ - - pitch_arr_[(i - 1 + pitch_arr_.size ()) - % pitch_arr_.size ()].notename_i_; - while (gap < 0) - gap += 7; - gap %= 7; - if (gap > biggest_i) - { - biggest_i = gap; - tonic_i = i; - } - } - return tonic_i; -} - -Array -Chord_name_engraver::rebuild_pitch_arr (int tonic_i) const -{ - Musical_pitch last (0, 0, -5); - Array pitches; - for (int i = 0; i < pitch_arr_.size (); i++) - { - Musical_pitch p = pitch_arr_[(tonic_i + i) % pitch_arr_.size ()]; - if (p < last) - { - p.octave_i_ = last.octave_i_; - if (p < last) - p.octave_i_++; - } - pitches.push (p); - last = p; - } - return pitches; -} - void Chord_name_engraver::do_process_requests () { @@ -125,20 +60,26 @@ Chord_name_engraver::do_process_requests () */ - int tonic_i = 0; - Musical_pitch inversion = pitch_arr_[0]; - Scalar chord_inversions = get_property ("chordInversion", 0); - if (chord_inversions.to_bool ()) + Chord chord (pitch_arr_); + Musical_pitch* inversion = 0; + Scalar chord_inversion = get_property ("chordInversion", 0); + if (chord_inversion.to_bool ()) { - tonic_i = find_tonic_i (); + int tonic_i = chord.find_tonic_i (); if (tonic_i) - pitch_arr_ = rebuild_pitch_arr (tonic_i); + { + inversion = &pitch_arr_[0]; + Scalar preserve = get_property ("chordInversionPreserve", 0); + if (preserve.to_bool ()) + chord.rebuild_from_base (tonic_i); + else + chord.rebuild_insert_inversion (tonic_i); + } } - G_text_item* item_p = new G_text_item; - item_p->text_str_ = banter_str (pitch_arr_, tonic_i, inversion); + item_p->text_str_ = chord.banter_str (inversion); Scalar style = get_property ("textstyle", 0); if (style.length_i ()) @@ -158,75 +99,3 @@ Chord_name_engraver::do_pre_move_processing () text_p_arr_.clear (); pitch_arr_.clear (); } - -String -Chord_name_engraver::banter_str (Array pitch_arr, int tonic_i, Musical_pitch inversion) const -{ - Musical_pitch tonic = pitch_arr[0]; - - Array scale; - scale.push (Musical_pitch (0)); // c - scale.push (Musical_pitch (1)); // d - scale.push (Musical_pitch (2)); // e - scale.push (Musical_pitch (3)); // f - scale.push (Musical_pitch (4)); // g - scale.push (Musical_pitch (5)); // a - // 7 always means 7-... - scale.push (Musical_pitch (6, -1)); // b - - - for (int i = 0; i < scale.size (); i++) - scale[i].transpose (tonic); - - //urg, should do translation in scheme. - char const *acc[] = {"\\textflat\\textflat ", "\\textflat ", "", "\\textsharp " , "\\textsharp\\textsharp "}; - String tonic_str = tonic.str (); - tonic_str = tonic_str.left_str (1).upper_str () - + acc[tonic.accidental_i_ + 2]; - - String add_str; - String sub_str; - String sep_str; - int last_trap = 1; - for (int i=1; i < pitch_arr.size (); i++) - { - Musical_pitch p = pitch_arr[i]; - int trap = p.notename_i_ - tonic.notename_i_ - + (p.octave_i_ - tonic.octave_i_) * 7 + 1; - while (trap - last_trap > 2) - { - last_trap += 2; - sub_str += sep_str + "no" + to_str (last_trap); - sep_str = "/"; - } - last_trap = trap; - int accidental = p.accidental_i_ - scale[(trap - 1) % 7].accidental_i_; - if ((trap == 3) && (accidental == -1)) - tonic_str += "m"; // hmm - else if (accidental || (!(trap % 2) || ((i + 1 == pitch_arr.size ()) && (trap > 5)))) - { - add_str += sep_str; - if ((trap == 7) && (accidental == 1)) - add_str += "maj7"; - else - { - add_str += to_str (trap); - if (accidental) - add_str += accidental < 0 ? "-" : "+"; - } - sep_str = "/"; - } - } - - String inversion_str; - if (tonic_i) - { - inversion_str = inversion.str (); - inversion_str = "/" + inversion_str.left_str (1).upper_str () - + acc[tonic.accidental_i_ + 2]; - - } - - String str = tonic_str + "$^{" + add_str + sub_str + "}$" + inversion_str; - return str; -} diff --git a/lily/chord.cc b/lily/chord.cc new file mode 100644 index 0000000000..26ae4ce271 --- /dev/null +++ b/lily/chord.cc @@ -0,0 +1,366 @@ +/* + chord.cc -- implement Chord + + source file of the GNU LilyPond music typesetter + + (c) 1999 Jan Nieuwenhuizen +*/ + +#include "chord.hh" +#include "warn.hh" + +Chord::Chord (Array pitch_arr) +{ + pitch_arr_ = pitch_arr; +} + +// construct from parser output +// urg: should split this up into understandable chunks +Chord::Chord (Musical_pitch tonic, Array* add_arr_p, Array* sub_arr_p, Musical_pitch* inversion_p) +{ + for (int i = 0; i < add_arr_p->size (); i++) + { + Musical_pitch p = tonic; + Musical_pitch q = (*add_arr_p)[i]; + // duh, c7 should mean + if (q.notename_i_ == 6) + q.accidental_i_--; + p.transpose (q); + (*add_arr_p)[i] = p; + } + add_arr_p->sort (Musical_pitch::compare); + for (int i = 0; i < sub_arr_p->size (); i++) + { + Musical_pitch p = tonic; + Musical_pitch q = (*sub_arr_p)[i]; + // duh, c7 should mean + if (q.notename_i_ == 6) + q.accidental_i_--; + p.transpose (q); + (*sub_arr_p)[i] = p; + } + sub_arr_p->sort (Musical_pitch::compare); + + Musical_pitch third (2); + Musical_pitch mthird (2, -1); + Musical_pitch missing; + missing = tonic; + missing.transpose (third); + + Musical_pitch p; + p = tonic; + p.transpose (third); + p.transpose (mthird); + + /* + must have minimum at 5 (3 is added automatically as missing) + */ + if (!add_arr_p->size ()) + add_arr_p->push (p); + else if ((add_arr_p->top () < p) && (add_arr_p->top ().notename_i_ != p.notename_i_)) + add_arr_p->push (p); + add_arr_p->sort (Musical_pitch::compare); + + Array triads; + triads.push (third); // c e + triads.push (mthird); // d f + triads.push (mthird); // e g + triads.push (third); // f a + triads.push (third); // g b + triads.push (mthird); // a c + triads.push (mthird); // b d + + /* + if first addition is 4, assume sus4 and don't add third implicitely + */ + Musical_pitch sus (3); + sus.transpose (tonic); + if (add_arr_p->size ()) + if ((*add_arr_p)[0] == sus) + missing.transpose (mthird); + + /* + add missing triads + */ + for (int i = 0; i < add_arr_p->size ();) + { + Musical_pitch p = (*add_arr_p)[i]; + if (p > missing) + while (p > missing) + { + if (p.notename_i_ != missing.notename_i_) + { + if ((missing.notename_i_ - tonic.notename_i_ + 7) % 7 == 6) + { + Musical_pitch special_seven = missing; + Musical_pitch lower (0, -1); + special_seven.transpose (lower); + add_arr_p->insert (special_seven, i++); + } + else + add_arr_p->insert (missing, i++); + } + missing.transpose (triads[(missing.notename_i_ - tonic.notename_i_ + 7) % 7]); + } + else if (p.notename_i_ == missing.notename_i_) + missing.transpose (triads[(missing.notename_i_ - tonic.notename_i_ + 7) % 7]); + else + i++; + } + + /* + add tonic + */ + if (!add_arr_p->size () || ((*add_arr_p)[0] != tonic)) + add_arr_p->insert (tonic, 0); + + /* + add all that aren't subtracted + */ + for (int i = 0; i < add_arr_p->size (); i++) + { + Musical_pitch p = (*add_arr_p)[i]; + int j = 0; + for (; j < sub_arr_p->size (); j++) + if (p == (*sub_arr_p)[j]) + { + sub_arr_p->del (j); + j = -1; + break; + } + if (j == sub_arr_p->size ()) + pitch_arr_.push (p); + } + + for (int i = 0; i < sub_arr_p->size (); i++) + warning (_f ("invalid subtraction: not part of chord: %s", + (*sub_arr_p)[i].str ())); + + if (inversion_p) + { + int i = 0; + for (; i < pitch_arr_.size (); i++) + if ((pitch_arr_[i].notename_i_ == inversion_p->notename_i_) + && (pitch_arr_[i].accidental_i_ == inversion_p->accidental_i_)) + break; + if (i == pitch_arr_.size ()) + warning (_f ("invalid inversion pitch: not part of chord: %s", + inversion_p->str ())); + else + { + /* + urg + should be run-time switchable "chordInversionPreserve", howto? + + there are two ways commonly used to rearrange a chord with + an inversion: + + 1. rebuild pitch list, taking inversion as base + */ +#if 0 + rebuild_from_base (i); +#else + /* + or + 2. insert inversion as lowest (at first position) + */ + rebuild_with_bass (i); +#endif + } + delete inversion_p; + } +} + +String +Chord::banter_str (Musical_pitch* inversion) const +{ + Musical_pitch tonic = pitch_arr_[0]; + + Array scale; + scale.push (Musical_pitch (0)); // c + scale.push (Musical_pitch (1)); // d + scale.push (Musical_pitch (2)); // e + scale.push (Musical_pitch (3)); // f + scale.push (Musical_pitch (4)); // g + scale.push (Musical_pitch (5)); // a + // 7 always means 7-... + scale.push (Musical_pitch (6, -1)); // b + + + for (int i = 0; i < scale.size (); i++) + scale[i].transpose (tonic); + + //urg, should do translation in scheme. + char const *acc[] = {"\\textflat\\textflat ", "\\textflat ", "", "\\textsharp " , "\\textsharp\\textsharp "}; + String tonic_str = tonic.str (); + tonic_str = tonic_str.left_str (1).upper_str () + + acc[tonic.accidental_i_ + 2]; + + String add_str; + String sub_str; + String sep_str; + String sub_sep_str; + int last_trap = 1; + for (int i=1; i < pitch_arr_.size (); i++) + { + Musical_pitch p = pitch_arr_[i]; + int trap = p.notename_i_ - tonic.notename_i_ + + (p.octave_i_ - tonic.octave_i_) * 7; + while (trap < 0) + trap += 7; + trap++; + while (trap - last_trap > 2) + { + last_trap += 2; + sub_str += sub_sep_str + "no" + to_str (last_trap); + sub_sep_str = "/"; + } + last_trap = trap; + int accidental = p.accidental_i_ - scale[(trap - 1) % 7].accidental_i_; + if ((trap == 3) && (accidental == -1)) + tonic_str += "m"; // hmm + else if (accidental || (!(trap % 2) || ((i + 1 == pitch_arr_.size ()) && (trap > 5)))) + { + add_str += sep_str; + if ((trap == 7) && (accidental == 1)) + add_str += "maj7"; + else + { + add_str += to_str (trap); + if (accidental) + add_str += accidental < 0 ? "-" : "+"; + // catch "C4/no3"; remove "no3" + if (trap == 4) + { + int i = sub_str.index_i ("no3"); + if (i != -1) + sub_str = sub_str.nomid_str (i, 3); + if (!sub_str.length_i ()) + sub_sep_str = ""; + } + } + sep_str = "/"; + } + } + + String inversion_str; + if (inversion) + { + inversion_str = inversion->str (); + inversion_str = "/" + inversion_str.left_str (1).upper_str () + + acc[tonic.accidental_i_ + 2]; + + } + + if (sub_str.length_i ()) + sub_str = sep_str + sub_str; + String str = tonic_str + "$^{" + add_str + sub_str + "}$" + inversion_str; + return str; +} + +int +Chord::find_tonic_i () const +{ + /* + find tonic + + first try: base of longest line of triads + */ + int tonic_i = 0; + int longest_i = 0; + for (int i = 0; i < pitch_arr_.size (); i++) + { + int no_triad_i = 0; + int last_i = pitch_arr_[i % pitch_arr_.size ()].notename_i_; + int j = 0; + for (; j < pitch_arr_.size (); j++) + { + int cur_i = pitch_arr_[(i + j + 1) % pitch_arr_.size ()].notename_i_; + int gap = cur_i - last_i; + while (gap < 0) + gap += 7; + gap %= 7; + if (gap == 2) + last_i = cur_i; + else + no_triad_i++; + } + if (j - no_triad_i > longest_i) + { + longest_i = j - no_triad_i; + tonic_i = i; + } + } + + /* + second try: note after biggest gap + */ + int biggest_i = 0; + // if (longest_i) + if (longest_i <= 1) + for (int i = 0; i < pitch_arr_.size (); i++) + { + int gap = pitch_arr_[i].notename_i_ + - pitch_arr_[(i - 1 + pitch_arr_.size ()) + % pitch_arr_.size ()].notename_i_; + while (gap < 0) + gap += 7; + gap %= 7; + if (gap > biggest_i) + { + biggest_i = gap; + tonic_i = i; + } + } + return tonic_i; +} + +void +Chord::rebuild_from_base (int base_i) +{ + Musical_pitch last (0, 0, -5); + Array new_arr; + for (int i = 0; i < pitch_arr_.size (); i++) + { + Musical_pitch p = pitch_arr_[(base_i + i) % pitch_arr_.size ()]; + if (p < last) + { + p.octave_i_ = last.octave_i_; + if (p < last) + p.octave_i_++; + } + new_arr.push (p); + last = p; + } + pitch_arr_ = new_arr; +} + +void +Chord::rebuild_insert_inversion (int tonic_i) +{ + Musical_pitch inversion = pitch_arr_.get (0); + rebuild_from_base (tonic_i - 1); + if (pitch_arr_.size ()) + { + inversion.octave_i_ = pitch_arr_[0].octave_i_ - 1; + while (inversion < pitch_arr_[0]) + inversion.octave_i_++; + } + for (int i = 0; i < pitch_arr_.size (); i++) + if (pitch_arr_[i] > inversion) + { + pitch_arr_.insert (inversion, i); + break; + } +} + +void +Chord::rebuild_with_bass (int bass_i) +{ + Musical_pitch inversion = pitch_arr_.get (bass_i); + // is lowering fine, or should others be raised? + if (pitch_arr_.size ()) + while (inversion > pitch_arr_[0]) + inversion.octave_i_--; + pitch_arr_.insert (inversion, 0); +} diff --git a/lily/include/chord-name-engraver.hh b/lily/include/chord-name-engraver.hh index 72b221fe1e..233714f017 100644 --- a/lily/include/chord-name-engraver.hh +++ b/lily/include/chord-name-engraver.hh @@ -15,6 +15,11 @@ #include "lily-proto.hh" +Array rebuild_from_base_pitch_arr (Array pitch_arr, int base_i); +Array rebuild_insert_inversion_pitch_arr (Array pitch_arr, int tonic_i); +Array rebuild_with_bass_pitch_arr (Array pitch_arr, int bass_i); + + class Chord_name_engraver : public Engraver { protected: @@ -31,7 +36,7 @@ private: Array pitch_arr_; Link_array text_p_arr_; - String banter_str (Array pitch_arr, int tonic_i, Musical_pitch inversion) const; + String banter_str (Array pitch_arr, Musical_pitch* inversion) const; int find_tonic_i () const; Array rebuild_pitch_arr (int tonic_i) const; }; diff --git a/lily/include/chord.hh b/lily/include/chord.hh new file mode 100644 index 0000000000..0fc7601aeb --- /dev/null +++ b/lily/include/chord.hh @@ -0,0 +1,33 @@ +/* + chord.hh -- declare Chord + + source file of the GNU LilyPond music typesetter + + (c) 1999 Jan Nieuwenhuizen +*/ + +#ifndef CHORD_HH +#define CHORD_HH + +#include "array.hh" +#include "musical-pitch.hh" +#include "lily-proto.hh" + +class Chord +{ +public: + Chord (Array pitch_arr); + Chord (Musical_pitch tonic, Array* add_arr_p, Array* sub_arr_p, Musical_pitch* inversion_p); + + void rebuild_from_base (int base_i); + void rebuild_insert_inversion (int tonic_i); + void rebuild_with_bass (int bass_i); + + String banter_str (Musical_pitch* inversion) const; + int find_tonic_i () const; + + Array pitch_arr_; + int tonic_i_; +}; + +#endif // CHORD_HH diff --git a/lily/include/lily-proto.hh b/lily/include/lily-proto.hh index fb46f112a2..0c600002f8 100644 --- a/lily/include/lily-proto.hh +++ b/lily/include/lily-proto.hh @@ -50,6 +50,7 @@ struct Break_req; struct Cadenza_req; struct Change_iterator; struct Change_translator; +struct Chord; struct Chord_name_engraver; struct Clef_change_req; struct Clef_item; diff --git a/lily/my-lily-parser.cc b/lily/my-lily-parser.cc index d29b14ff5f..8cbd830662 100644 --- a/lily/my-lily-parser.cc +++ b/lily/my-lily-parser.cc @@ -20,6 +20,7 @@ #include "midi-def.hh" #include "paper-def.hh" #include "identifier.hh" +#include "chord.hh" My_lily_parser::My_lily_parser (Sources * source_l) { @@ -151,159 +152,11 @@ My_lily_parser::get_chord (Musical_pitch tonic, Array* add_arr_p, Simultaneous_music*v = new Request_chord; v->set_spot (here_input ()); - for (int i = 0; i < add_arr_p->size (); i++) - { - Musical_pitch p = tonic; - Musical_pitch q = (*add_arr_p)[i]; - // duh, c7 should mean - if (q.notename_i_ == 6) - q.accidental_i_--; - p.transpose (q); - (*add_arr_p)[i] = p; - } - add_arr_p->sort (Musical_pitch::compare); - for (int i = 0; i < sub_arr_p->size (); i++) - { - Musical_pitch p = tonic; - Musical_pitch q = (*sub_arr_p)[i]; - // duh, c7 should mean - if (q.notename_i_ == 6) - q.accidental_i_--; - p.transpose (q); - (*sub_arr_p)[i] = p; - } - sub_arr_p->sort (Musical_pitch::compare); - - Musical_pitch third (2); - Musical_pitch mthird (2, -1); - Musical_pitch missing; - missing = tonic; - missing.transpose (third); - - Musical_pitch p; - p = tonic; - p.transpose (third); - p.transpose (mthird); - - /* - must have minimum at 5 (3 is added automatically as missing) - */ - if (!add_arr_p->size ()) - add_arr_p->push (p); - else if ((add_arr_p->top () < p) && (add_arr_p->top ().notename_i_ != p.notename_i_)) - add_arr_p->push (p); - add_arr_p->sort (Musical_pitch::compare); - - Array triads; - triads.push (third); // c e - triads.push (mthird); // d f - triads.push (mthird); // e g - triads.push (third); // f a - triads.push (third); // g b - triads.push (mthird); // a c - triads.push (mthird); // b d - - /* - if first addition is 4, assume sus4 and don't add third implicitely - */ - Musical_pitch sus (3); - sus.transpose (tonic); - if (add_arr_p->size ()) - if ((*add_arr_p)[0] == sus) - missing.transpose (mthird); - - /* - add missing triads - */ - for (int i = 0; i < add_arr_p->size (); i++) - { - Musical_pitch p = (*add_arr_p)[i]; - if (p > missing) - while (p > missing) - { - if (p.notename_i_ != missing.notename_i_) - { - if ((missing.notename_i_ - tonic.notename_i_ + 7) % 7 == 6) - { - Musical_pitch special_seven = missing; - Musical_pitch lower (0, -1); - special_seven.transpose (lower); - add_arr_p->insert (special_seven, i++); - } - else - add_arr_p->insert (missing, i++); - } - missing.transpose (triads[(missing.notename_i_ - tonic.notename_i_ + 7) % 7]); - } - else if (p.notename_i_ == missing.notename_i_) - missing.transpose (triads[(missing.notename_i_ - tonic.notename_i_ + 7) % 7]); - else - i++; - } - - /* - add tonic - */ - if (!add_arr_p->size () || ((*add_arr_p)[0] != tonic)) - add_arr_p->insert (tonic, 0); - - Array pitch_arr; - /* - add all that aren't subtracted - */ - for (int i = 0; i < add_arr_p->size (); i++) - { - Musical_pitch p = (*add_arr_p)[i]; - int j = 0; - for (; j < sub_arr_p->size (); j++) - if (p == (*sub_arr_p)[j]) - { - sub_arr_p->del (j); - j = -1; - break; - } - if (j == sub_arr_p->size ()) - pitch_arr.push (p); - } - - for (int i = 0; i < sub_arr_p->size (); i++) - warning (_f ("invalid subtraction: not part of chord: %s", - (*sub_arr_p)[i].str ())); - - if (inversion_p) - { - int i = 0; - for (; i < pitch_arr.size (); i++) - if ((pitch_arr[i].notename_i_ == inversion_p->notename_i_) - && (pitch_arr[i].accidental_i_ == inversion_p->accidental_i_)) - break; - if (i == pitch_arr.size ()) - warning (_f ("invalid inversion pitch: not part of chord: %s", - inversion_p->str ())); - else - { - Array pitches; - Musical_pitch last (0, 0, -5); - for (int j = 0; j < pitch_arr.size (); j++) - { - Musical_pitch p = pitch_arr[(j + i) % pitch_arr.size ()]; - if (p < last) - { - p.octave_i_ = last.octave_i_; - if (p < last) - p.octave_i_++; - } - pitches.push (p); - last = p; - } - pitch_arr = pitches; - } - delete inversion_p; - } + Chord chord (tonic, add_arr_p, sub_arr_p, inversion_p); - for (int i = 0; i < pitch_arr.size (); i++) + for (int i = 0; i < chord.pitch_arr_.size (); i++) { - Musical_pitch p = pitch_arr[i]; + Musical_pitch p = chord.pitch_arr_[i]; Note_req* n = new Note_req; n->pitch_ = p; n->duration_ = d; -- 2.39.5