/***************************/
/* dyn.c                   */
/***************************/

#include <stdio.h>
#include <stdlib.h>
#include "maintypes.h"
#include "defines.h"
#include "dyn.h"

void dyn_init()
{
       int ii;

       global = 1;
       for (ii=0; ii < MAXTRACKS; ii++) {
               begin[ii] = NULL;
               remember[ii] = NULL;
       }
}

void ins_dyn_event(tnr, mark, phr, nn, dom, oct, pit, loud, beg, dur)
       char mark, *phr;
       int tnr, nn, dom, oct, pit, loud, beg, dur;
{
       /* insdmark1 */
       if ((dynhelp = (struct bind *) malloc (sizeof(struct bind))) == NULL) {
               fprintf(stderr, "malloc error\n");
               exit(10);
       }
       dynhelp->marker = mark;
       dynhelp->time = beg;

       /* insdmark2 */
       switch (mark) {
               case 'n': if ((not = (struct Note *) malloc (sizeof(struct Note))) == NULL) {
                               fprintf(stderr, "malloc error\n");
                               exit(10);
                         }
                         not->octave = oct;
                         not->pitch = pit;
                         not->loud = loud;
                         not->duration = dur;
                         not->end = 0;
                         not->flags = 0;
                         if (((not->octave) * 12 + (not->pitch)) < 0x20) not->flags = 0x0200;
                         if (((not->octave) * 12 + (not->pitch)) > 0x29) not->flags = 0x0100;
                         not->beam_nr = 0;
                         not->slur_nr = 0;
                         not->note_pos = 0;
                         not->slur_pos = 0;
                         not->beam_pos = 0;
                         not->treated = 0;
                         not->next_beamn_kind = 0;     /* type of next beam note */
                         not->accord_next = NULL;
                         dynhelp->data = (void *) not;
                         break;
               case 't': if ((ts = (struct TimeSig *) malloc (sizeof(struct TimeSig))) == NULL) {
                               fprintf(stderr, "malloc error\n");
                               exit(10);
                         }
                         ts->nom = nn;
                         ts->denom = dom;
                         dynhelp->data = (void *) ts;
                         break;
               case 'l': if ((ly = (struct Lyric *) malloc (sizeof(struct Lyric))) == NULL) {
                               fprintf(stderr, "malloc error\n");
                               exit(10);
                         }
                         if ((ly->text = (char *) malloc (strlen(phr)+1)) == NULL) {
                               fprintf(stderr, "malloc error\n");
                               exit(10);
                         }
                         strcpy(ly->text, phr);
                         dynhelp->data = (void *) ly;
                         break;
               case 'k': if ((ks = (struct KeySig *) malloc (sizeof(struct KeySig))) == NULL) {
                               fprintf(stderr, "malloc error\n");
                               exit(10);
                         }
                         ks->sign = nn;
                         dynhelp->data = (void *) ks;
                         break;
               case 'b': if ((bar = (struct Barre *) malloc (sizeof(struct Barre))) == NULL) {
                               fprintf(stderr, "malloc error\n");
                               exit(10);
                         }
                         bar->takt_duration = dur;
                         bar->number_of_voices = 1;
                         dynhelp->data = (void *) bar;
                         break;
       }

       dynhelp->next = NULL;

       /* insdmark3 */
       if (begin[tnr] == NULL) {
               begin[tnr]=dynhelp;
               akt[tnr]=dynhelp;
       }
       else {
               if ((remember[tnr] != NULL) && ((remember[tnr]->time) < beg))
                       akt[tnr] = remember[tnr];
               else akt[tnr] = begin[tnr];
               prev[tnr] = NULL;
               while ((akt[tnr] != NULL) && ((akt[tnr]->time) < beg)) {
                       prev[tnr] = akt[tnr];
                       akt[tnr] = akt[tnr]->next;
               }
               if ((akt[tnr] == NULL) || ((akt[tnr]->time) > beg) || (mark == 'b')) {
                       if (prev[tnr] != NULL) prev[tnr]->next = dynhelp;
                       else begin[tnr] = dynhelp;
                       dynhelp->next = akt[tnr];
               }
               else {  /* insert elements with equal time into list in correct permutation */
                       if (akt[tnr]->marker == 'n') not = (struct Note *) akt[tnr]->data;
                       while ( (akt[tnr] != NULL) && ((akt[tnr]->time) == beg) &&
                               ( ((akt[tnr]->marker) == 'b') ||
                                 (((akt[tnr]->marker) == 'k') && (mark != 'k')) ||
                                 (((akt[tnr]->marker) == 't') && ((mark == 'l') || (mark == 'n'))) ||
                                 (((akt[tnr]->marker) == 'l') && (mark == 'n')) ||
                                 (((akt[tnr]->marker) == 'n') && (mark == 'n') &&
                                  ((((not->octave) * 12) + (not->pitch)) < ((oct * 12) + pit))) ) ) {
                               prev[tnr] = akt[tnr];
                               akt[tnr] = akt[tnr]->next;
                               if ((akt[tnr]) && (akt[tnr]->marker == 'n')) not = (struct Note *) akt[tnr]->data;
                       }
                       if (prev[tnr] != NULL) prev[tnr]->next = dynhelp;
                       else begin[tnr] = dynhelp;
                       dynhelp->next = akt[tnr];
               }
       }
}

void split_notes(Track, pq)
       int Track;
       short int pq;
{
       int notend, h;
       unsigned long barrtime;

       /* splnmark1: initiation */
       dynhelp3 = begin[Track];
       dynhelp2 = dynhelp3;
       notend = 1;
       while (notend) {
               /* splnmark2: loop now */
               while ((dynhelp3 != NULL) && ((dynhelp3->marker) != 'b')) dynhelp3 = dynhelp3->next;
               if (dynhelp3 == NULL) {
                       notend = 0;
               }
               else {
                       barrtime = dynhelp3->time;
                       dynhelp3 = dynhelp3->next;
               }
               while (dynhelp2 && ((!dynhelp3) || (barrtime > (dynhelp2->time)))) {
                if (dynhelp2->marker == 'n') {
                       not = (struct Note *) dynhelp2->data;
                       h = (dynhelp2->time) + (not->duration);

                       /* note should be splited because of long time */
                       if (((not->duration) > (4 * pq)) && ((!dynhelp3) || (((dynhelp2->time) + (4 * pq)) < barrtime))) {
                               ins_dyn_event(Track, 'n', 0, 0, 0, not->octave, not->pitch,
                                             not->loud, (dynhelp2->time) + (4 * pq), (not->duration) - (4 * pq));
                               (not->duration) = 4 * pq;
                       }
                       else {
                               /* note sounds about next barre */
                               if ((dynhelp3) && (h > barrtime)) {
                                       (not->duration) = barrtime - (dynhelp2->time);
                                       ins_dyn_event(Track, 'n', 0, 0, 0, not->octave, not->pitch,
                                               not->loud, barrtime, h - barrtime);
                               }
                       }
                }
                dynhelp2 = dynhelp2->next;
               }
       }
}

/* the following funktion returns one in case of existing a note that begins    */
/* on time timepoint, zero else                                                 */
/* right region was found -> okflag returns 1 else 0                            */

short note_with_time(bplocal, timepoint, bpp, okflag)
       struct bind *bplocal, **bpp;
       char *okflag;
       unsigned long timepoint;
{
       struct bind *bhelp;
       char remem;
       struct Note *nhelp;

       /* notes shorter than 1/4 allow for beams */
       if ((*okflag) > 4) remem = 0;
       else remem = 1;

       /* delete bit 4 */
       *okflag &= 0x3;

       while ((bplocal) && (((bplocal->time) < timepoint) || ((bplocal->marker) != 'n'))) bplocal = bplocal->next;
       if ((bplocal) && ((bplocal->time) == timepoint) && ((bplocal->marker) == 'n')) {
               if (*okflag) {
                       nhelp = (struct Note *) bplocal->data;
                       bhelp = bplocal;
                       while ( (bhelp) && ((bhelp->time) == timepoint) &&
                               (!((!((nhelp->flags) & 0x200)) && (*okflag == 1) &&
                                (remem || (!((nhelp->flags) & 0x20))) )) &&
                               (!((!((nhelp->flags) & 0x100)) && (*okflag == 2) &&
                                (remem || (!((nhelp->flags) & 0x20))) )) ) {
                               bhelp = bhelp->next;
                               if ((bhelp) && ((bhelp->time) == timepoint))
                                       nhelp = (struct Note *) bhelp->data;
                       }
                       if ((bhelp) && ((bhelp->time) == timepoint)) {
                               *okflag = 1;
                               *bpp = bhelp;
                               return(1);
                       }
                       else {
                               *okflag = 0;
                               *bpp = bplocal;
                               return(1);
                       }
               }
               else {
                       if (remem) {
                               *okflag = 1;
                               *bpp = bplocal;
                               return(1);
                       }
                       else {
                               nhelp = (struct Note *) bplocal->data;
                               bhelp = bplocal;
                               while ( (bhelp) && ((bhelp->time) == timepoint) && ((nhelp->flags) & 0x20)) {
                                       bhelp = bhelp->next;
                                       if ((bhelp) && ((bhelp->time) == timepoint))
                                               nhelp = (struct Note *) bhelp->data;
                               }
                               if ((bhelp) && ((bhelp->time) == timepoint)) {
                                       *okflag = 1;
                                       *bpp = bhelp;
                                       return(1);
                               }
                               else {
                                       *okflag = 0;
                                       *bpp = bplocal;
                                       return(1);
                               }
                       }
               }
       }
       else {
               *okflag = 0;
               return(0);
       }
}

short barre_between(bploc, reftime)
       struct bind *bploc;
       unsigned long reftime;
{
       short rem = 0;
       while ((bploc) && ((bploc->time) < reftime)) {
               if ((bploc->marker) == 'b') rem = 1;
               bploc = bploc->next;
       }
       return(rem);
}

void detect_note_value(reg, tr, notedurat, flagptr, endptr, begint, bindptr, slurnrpt, pq)
       int notedurat, *slurnrpt;
       short int pq, *flagptr, tr;
       unsigned long *endptr, begint;
       struct bind *bindptr;
       char reg;
{
       int i;
       char ok;        /* allow slur only to be in one region */
       char newslur;   /* for setting the slur-begin flag */
       short desicion;

       /* dnvmark1 */
       *flagptr = *flagptr | 0x80;
       i = 0;
       while ((i<21) && ((NORMFAKTOR * notedurat) > (faktors[i] * pq))) i++;
       if (i==21) {
               fprintf(stderr,"warning: cut very long note\n");
               *flagptr = *flagptr | note_codes[20];
               *endptr = begint + (7 * pq);
       }
       else {
               if ((NORMFAKTOR * notedurat) == (faktors[i] * pq)) {
                       /* dnvmark2: input ok forces a special region */
                       if (!reg && ((*flagptr) & 0x0100)) ok = 1;
                       else    if (!reg && ((*flagptr) & 0x0200)) ok = 2;
                               else ok = 0;
                       desicion = note_with_time(bindptr, notedurat + begint, &dynhelp, &ok);
                       /* dnvmark3 */
                       if ((i<15) && (!desicion)) {
                               if (barre_between(bindptr, begint + (notedurat * 4))) {
                                       /* call it a normal note */
                                       *flagptr = *flagptr | (note_codes[i]);
                                       *endptr = begint + notedurat;
                               }
                               else {
                                       /* staccato detected */
                                       *flagptr = *flagptr | ((note_codes[i+6]) + 4);
                                       *endptr = begint + (notedurat * 4);
                               }
                       }
                       else {
                               /* dnvmark4 */
                               if (dynhelp) not = (struct Note *) dynhelp->data;
                               if (((i>=15) && (!desicion)) ||
                                   ((desicion) && (!ok)) || (not->slur_nr)) {
                                       /* call it a normal note */
                                       *flagptr = *flagptr | (note_codes[i]);
                                       *endptr = begint + notedurat;
                               }
                               else {
                                       /* legato detected */
                                       *flagptr = *flagptr | (note_codes[i]);
                                       *flagptr = *flagptr & 0xff7f;
                                       *endptr = begint + notedurat;
                                       newslur = 0;
                                       if (!(*slurnrpt)) {
                                               newslur = 1;
                                               *slurnrpt = global++;
                                       }
                                       *flagptr = *flagptr | ((not->flags) & 0x0300);
                                       not->flags = not->flags | ((*flagptr) & 0x0300);
                                       not->slur_nr = *slurnrpt;
                                       if (newslur) not->slur_pos |= 0x40;
                               }
                       }
               }
               else {
                       /* normal note detected */
                       *flagptr = *flagptr | (note_codes[i]);
                       *endptr = begint + ((faktors[i] * pq) / NORMFAKTOR);
               }
       }
       if (!(*slurnrpt)) *flagptr = *flagptr & 0xff7f;
}

void insert_notetimes_and_slurs(reg, Track, pq)
       int Track;
       short int pq;
       char reg;
{
       akt[Track] = begin[Track];
       while (akt[Track]) {
               if ((akt[Track]->marker) == 'n') {
                       not = (struct Note *) akt[Track]->data;
                       detect_note_value(reg, Track, not->duration, &(not->flags), &(not->end), akt[Track]->time, akt[Track], &(not->slur_nr), pq);
               }
               akt[Track] = akt[Track]->next;
       }
}

void detect_accords(reg, Track)
       int Track;
       char reg;
{
       char attention; /* remembers the region */

       /* deacmark1 */
       akt[Track] = begin[Track];

       while (akt[Track]) {
               /* deacmark2 */
               if ((akt[Track]->marker) == 'n') {
                       not2 = (struct Note *) akt[Track]->data;
                       dynhelp = akt[Track]->next;
                       dynhelp2 = akt[Track];
                       /* prevent accords over two regions */
                       if ((((not2->octave) * 12 + (not2->pitch)) < 0x20) && (!reg)) attention = 1;
                       else attention = 0;
                       /* deacmark3 */
                       while ((dynhelp) && ((dynhelp->time) == (akt[Track]->time))) {
                               not = (struct Note *) dynhelp->data;
                               if (((not->duration) == (not2->duration)) &&
                                   ((!attention) || (((not->octave) * 12 + (not->pitch)) < 0x2a))) {
                                       while (not2->accord_next) not2 = not2->accord_next;
                                       not2->accord_next = not;
                                       dynhelp2->next = dynhelp->next;
                                       free(dynhelp);
                                       dynhelp = dynhelp2->next;
                               }
                               else {
                                       dynhelp2 = dynhelp;
                                       dynhelp = dynhelp->next;
                               }
                       }
               }
               akt[Track] = akt[Track]->next;
       }
}

void beam_detect(reg, Track)
       int Track;
       char reg;
{
       struct bind *found;
       char ok, remsign;
       unsigned long remtime;
       short helpshort;

       /* bdmark1 */
       akt[Track] = begin[Track];
       while (akt[Track]) {
               if (akt[Track]->marker == 'n') {
                       not = (struct Note *) akt[Track]->data;
                       if (!((not->flags) & 0x20)) {
                               /* bdmark2: 1/8 or shorter found */
                               dynhelp = akt[Track]->next;
                               while ((dynhelp) && ((dynhelp->marker) != 'b'))
                                       dynhelp = dynhelp->next;
                               if (((not->flags) & 0x100) && (!reg)) ok = 9;
                               else    if (((not->flags) & 0x200) && (!reg)) ok = 10;
                                       else ok = 8;
                               /* bdmark3 */
                               if ((note_with_time(akt[Track], not->end, &found, &ok)) && (found) &&
                                   (ok) && ((!dynhelp) || ((found->time) < (dynhelp->time)))) {
                                       not2 = (struct Note *) found->data;
                                       remsign = 0;
                                       if (((((not->slur_nr) && (!((not->flags) & 0x80))) || ((not2->slur_nr) && (!((not2->slur_pos) & 0x40)))) &&
                                           ((not->slur_nr) != (not2->slur_nr))) || (not2->beam_nr)) {
                                               remtime = found->time;
                                               found = found->next;
                                               remsign = 1;
                                               /* while the restrictions of time and regions are not injured   */
                                               /* try to search a valid beam_note                              */
                                               /* bdmark4 */
                                               while ((found) && ((found->time) == remtime) && (remsign) &&
                                                      (!(((not->flags) & 0x200) && (!reg) && ((not2->flags) & 0x100))) ) {
                                                       not2 = (struct Note *) found->data;
                                                       if ((!(not2->beam_nr)) && (not->slur_nr) && (!((not->flags) & 0x80)) &&
                                                           ((not2->slur_nr) == (not->slur_nr)) && (!((not2->flags) & 0x200))) remsign = 0;
                                                       if ((!(not2->beam_nr)) && (!((not->slur_nr) && (!((not->flags) & 0x80)))) && (((not2->slur_nr)  &&
                                                           ((not2->slur_pos) & 0x40)) || (!not2->slur_nr)) && (!((not2->flags) & 0x200))) remsign = 0;
                                                       if (remsign) found = found->next;
                                               }
                                       }
                                       /* bdmark5 */
                                       if (!remsign) {
                                               /* beam found */
                                               if (not->beam_nr) {
                                                       not->flags &= 0xffbf;
                                                       not2->beam_nr = not->beam_nr;
                                               }
                                               else {
                                                       not->beam_nr = global;
                                                       not2->beam_nr = global++;
                                               }
                                               not2->flags |= 0x40;
                                               helpshort = not->flags & 0x300;
                                               not->flags |= (not2->flags) & 0x300;
                                               not2->flags |= helpshort;
                                       }
                               }
                       }
               }
               akt[Track] = akt[Track]->next;
       }
}

void other_niveau(cr, of, pf, osp, psp)
       char cr;
       short of, pf, *osp, *psp;
{
       if (cr) {
               if (pf) {
                       *psp = pf - 1;
                       *osp = of;
               }
               else {
                       *psp = 11;
                       *osp = (of >> 1);
               }
       }
       else {
               if (pf != 11) {
                       *psp = pf + 1;
                       *osp = of;
               }
               else {
                       *psp = 0;
                       *osp = (of << 1);
               }
       }
}

void detect_note_positions_with_signs(track)
       int track;
{
       char cross;
       int signhelp;
       int i;
       short o, osecond, psecond, rem_o;
       int p;

       /* dnpsmark1 */
       akt[track] = begin[track];
       cross = 1;

       while (akt[track]) {
               switch (akt[track]->marker) {
                       case 'n': /* dnpsmark2 */
                                 not = (struct Note *) akt[track]->data;
                                 do {
                                         o = not->octave;
                                         o = (1 << o);
                                         p = not->pitch;
                                         if (process[p] & 0x40) {
                                               /* hit whole tone */
                                               if (process[p] & o) {
                                                       /* sign active */
                                                       other_niveau(cross, o, p, &osecond, &psecond);
                                                       if (process[psecond] & 0x40) {
                                                               /* hit whole tone */
                                                               if (process[psecond] & osecond) {
                                                                       /* sign active */
                                                                       osecond >>= 1;
                                                                       while (osecond) {
                                                                               osecond >>= 1;
                                                                               not->note_pos += 7;
                                                                       }
                                                                       not->note_pos += pitch_to_pos[psecond];
                                                               }
                                                               else {
                                                                       process[p] -= o;
                                                                       o >>= 1;
                                                                       while (o) {
                                                                               o >>= 1;
                                                                               not->note_pos += 7;
                                                                       }
                                                                       not->note_pos += pitch_to_pos[p];
                                                                       not->note_pos |= 0xc0;
                                                               }
                                                       }
                                                       else {
                                                               /* hit half tone */
                                                               process[p] -= o;
                                                               o >>= 1;
                                                               while (o) {
                                                                       o >>= 1;
                                                                       not->note_pos += 7;
                                                               }
                                                               not->note_pos += pitch_to_pos[p];
                                                               not->note_pos |= 0xc0;
                                                       }
                                               }
                                               else {
                                                       o >>= 1;
                                                       while (o) {
                                                               o >>= 1;
                                                               not->note_pos += 7;
                                                       }
                                                       not->note_pos += pitch_to_pos[p];
                                               }
                                         }
                                         else {
                                               /* hit half tone */
                                               other_niveau(cross, o, p, &osecond, &psecond);
                                               rem_o = osecond;
                                               osecond >>= 1;
                                               while (osecond) {
                                                       osecond >>= 1;
                                                       not->note_pos += 7;
                                               }
                                               not->note_pos += pitch_to_pos[psecond];
                                               if (!(process[psecond] & rem_o)) {
                                                       process[psecond] |= rem_o;
                                                       if (cross) not->note_pos |= 0x40;
                                                       else not->note_pos |= 0x80;
                                               }
                                         }
                                         not = not->accord_next;
                                 } while (not);
                                 break;
                       case 'k': /* dnpsmark3 */
                                 ks = (struct KeySig *) akt[track]->data;
                                 if ((ks->sign) & 0x80) cross = 0;
                                 else cross = 1;
                                 for (i=0; i<12; i++) process[i] &= 0x40;
                                 signhelp = (ks->sign) & 0x7;
                                 while (signhelp--)
                                       if (cross) process[crosses[signhelp]] |= 0xbf;
                                       else process[bs[signhelp]] |= 0xbf;
                                 break;
                       case 'b': /* dnpsmark4 */
                                 for(i=0; i<12; i++) {
                                       process[i] &= 0xc0;
                                       if (process[i] & 0x80) process[i] |= 0x3f;
                                 }
                                 break;
                       default : break;
               }
               akt[track] = akt[track]->next;
       }
}

void slur_geometry(t)
       int t;
{
       unsigned long endtime;
       char used[42], sp, nothalt;
       int i;
       int minimum, maximum;
       char beginposmin, beginposmax, endposmin, endposmax;

       akt[t] = begin[t];
       while (akt[t]) {
               /* sgeomark1 */
               if ((akt[t]->marker) == 'n') {
                       not = (struct Note *) akt[t]->data;
                       if (((not->slur_nr) > 0) && (((not->slur_pos) & 0x3f) == 0)) {
                               /* first slur note found */

                               /* sgeomark2: next are for setting endtime */
                               dynhelp = akt[t];
                               not3 = not;
                               while (!(((not3->flags) & 0x80) && ((not->slur_nr) == (not3->slur_nr)))) {
                                       dynhelp = dynhelp->next;
                                       while ((dynhelp->marker) != 'n') dynhelp = dynhelp->next;
                                       not3 = (struct Note *) dynhelp->data;
                               }
                               endtime = dynhelp->time;

                               /* sgeomark3 */
                               for (i=0; i<42; i++) used[i] = 0;
                               maximum = 0;
                               minimum = 41;
                               not2 = not;
                               dynhelp = akt[t];
                               beginposmin = (not->note_pos) & 0x3f;
                               not3 = not2;
                               while (not3->accord_next) not3 = not3->accord_next;
                               beginposmax = (not3->note_pos) & 0x3f;
                               nothalt = 1;
                               while (nothalt) {
                                       if ((not->slur_nr) == (not2->slur_nr)) {
                                               not3 = not2;
                                               while (not3->accord_next) not3 = not3->accord_next;
                                               if (minimum > ((not2->note_pos) & 0x3f)) minimum = (not2->note_pos) & 0x3f;
                                               if (maximum < ((not3->note_pos) & 0x3f)) maximum = (not3->note_pos) & 0x3f;
                                       }
                                       if (((dynhelp->time) != endtime) && ((dynhelp->time) != akt[t]->time)) {
                                               not3 = not2;
                                               while (not3->accord_next) not3 = not3->accord_next;
                                               for (i=((not2->note_pos) & 0x3f);i<=((not3->note_pos) & 0x3f);i++)
                                                       used[i] = 1;
                                       }
                                       if (((not2->flags) & 0x80) && ((not->slur_nr) == (not2->slur_nr))) nothalt = 0;
                                       else {
                                               dynhelp = dynhelp->next;
                                               while ((dynhelp->marker) != 'n') dynhelp = dynhelp->next;
                                               not2 = (struct Note *) dynhelp->data;
                                       }
                               }
                               /* sgeomark4 */
                               endposmin = (not2->note_pos) & 0x3f;
                               not3 = not2;
                               while (not3->accord_next) not3 = not3->accord_next;
                               endposmax = (not3->note_pos) & 0x3f;
                               if (maximum < 38) maximum += 3;
                               else maximum = 41;
                               if (minimum > 3) minimum -= 3;
                               else minimum = 0;
                               while ((maximum < 41) && (used[maximum])) maximum++;
                               while ((minimum > 0) && (used[minimum])) minimum--;
                               if ((((maximum - beginposmax) + (maximum - endposmax)) <=
                                   ((beginposmin - minimum) + (endposmin - minimum))) && (maximum != 41)) {
                                       sp = maximum;
                                       sp |= 0x80;
                               }
                               else sp = minimum;
                               /* sgeomark5 */
                               dynhelp = akt[t];
                               not2 = not;
                               nothalt = 1;
                               while (nothalt) {
                                       if (((not2->flags) & 0x80) && ((not->slur_nr) == (not2->slur_nr))) nothalt = 0;
                                       if ((not2->slur_nr) == (not->slur_nr)) {
                                               not3 = not2;
                                               while (not3->accord_next) {
                                                       not3->slur_pos &= 0x40;
                                                       not3->slur_pos |= sp;
                                                       not3 = not3->accord_next;
                                               }
                                               not3->slur_pos &= 0x40;
                                               not3->slur_pos |= sp;

                                               if (((sp & 0x80) && ((sp & 0x3f) <= (LAMBDA + ((not3->note_pos) & 0x3f))))
                                                   || ((!(sp & 0x80)) && (((sp & 0x3f) + LAMBDA) <= ((not2->note_pos) & 0x3f)))) {
                                                       /* set lower stem */
                                                       not3 = not2;
                                                       while (not3) {
                                                               not3->flags |= 0x400;
                                                               not3 = not3->accord_next;
                                                       }
                                               }
                                       }
                                       else {
                                               not3 = not2;
                                               while (not3->accord_next) not3 = not3->accord_next;

                                               /* if neccesary set lower stems */
                                               if (((sp & 0x80) && (((sp & 0x3f) + SLURWIDE ) <= (LAMBDA + ((not3->note_pos) & 0x3f)))
                                                    && (((sp & 0x3f) + SLURWIDE ) > ((not2->note_pos) & 0x3f)))
                                                   || ((!(sp & 0x80)) && (((sp & 0x3f) - SLURWIDE ) <= (LAMBDA + ((not3->note_pos) & 0x3f)))
                                                    && (((sp & 0x3f) - SLURWIDE ) > ((not2->note_pos) & 0x3f)))) {
                                                       not3 = not2;
                                                       while (not3) {
                                                               not3->flags |= 0x400;
                                                               not3 = not3->accord_next;
                                                       }
                                               }
                                       }

                                       if (nothalt) {
                                               dynhelp = dynhelp->next;
                                               while ((dynhelp->marker) != 'n') dynhelp = dynhelp->next;
                                               not2 = (struct Note *) dynhelp->data;
                                       }
                               }
                       }
               }
               akt[t] = akt[t]->next;
       }
}

void reset_treat_info(track)
       int track;
{
       akt[track] = begin[track];
       while (akt[track]) {
               if ((akt[track]->marker) == 'n') {
                       not = (struct Note *) akt[track]->data;
                       not->treated = 0;
               }
               akt[track] = akt[track]->next;
       }
}

void set_slur_regions(track)
       int track;
{
       short region, count, sum;

       akt[track] = begin[track];
       count = 1;
       sum = 0;
       while (akt[track]) {
               if ((akt[track]->marker) == 'n') {
                       not = (struct Note *) akt[track]->data;
                       if ((not->slur_nr) && (!(not->treated))) {
                               /* now look forward and treat */
                               dynhelp = akt[track];
                               not2 = not;
                               while (!(((not2->slur_nr) == (not->slur_nr)) && ((not2->flags) & 0x80))) {
                                       if ((not2->slur_nr) == (not->slur_nr)) {
                                               count++;
                                               sum += (not2->note_pos) & 0x3f;
                                       }
                                       dynhelp = dynhelp->next;
                                       while ((dynhelp->marker) != 'n') dynhelp = dynhelp->next;
                                       not2 = (struct Note *) dynhelp->data;
                               }
                               /* last note of current slur found */
                               sum += (not2->note_pos) & 0x3f;
                               region = (not2->flags) & 0x300;
                               if ((!region) && ((sum / count) > 20)) region = 0x100;
                               if (!region) region = 0x200;
                               /* set slur-begin flag */
                               not->slur_pos |= 0x40;
                               dynhelp = akt[track];
                               not2 = not;
                               while (!(((not2->slur_nr) == (not->slur_nr)) && ((not2->flags) & 0x80))) {
                                       if ((not2->slur_nr) == (not->slur_nr)) {
                                               not2->treated = 1;
                                               not2->flags |= region;
                                               /* correct the begin flag */
                                               if (not2 != not) {
                                                       while (not2) {
                                                               not2->slur_pos &= 0xbf;
                                                               not2 = not2->accord_next;
                                                       }
                                               }
                                       }
                                       dynhelp = dynhelp->next;
                                       while ((dynhelp->marker) != 'n') dynhelp = dynhelp->next;
                                       not2 = (struct Note *) dynhelp->data;
                               }
                               /* set all value to the last note of slur */
                               not2->treated = 1;
                               not2->flags |= region;
                               while (not2) {
                                       not2->slur_pos &= 0xbf;
                                       not2 = not2->accord_next;
                               }
                       }
               }
               akt[track] = akt[track]->next;
       }
}

void set_beam_regions(track)
       int track;
{
       short region, count, sum;

       akt[track] = begin[track];
       count = 0;
       sum = 0;
       while (akt[track]) {
               if ((akt[track]->marker) == 'n') {
                       /* sbrmark1 */
                       not = (struct Note *) akt[track]->data;
                       if ((not->beam_nr) && (!(not->treated))) {
                               /* now look forward and treat */
                               dynhelp = akt[track];
                               not2 = not;
                               while (!(((not2->beam_nr) == (not->beam_nr)) && ((not2->flags) & 0x40))) {
                                       if ((not2->beam_nr) == (not->beam_nr)) {
                                               count++;
                                               sum += (not2->note_pos) & 0x3f;
                                       }
                                       dynhelp = dynhelp->next;
                                       while ((dynhelp->marker) != 'n') dynhelp = dynhelp->next;
                                       not2 = (struct Note *) dynhelp->data;
                               }
                               /* last note of current beam found */
                               region = (not2->flags) & 0x300;
                               if (!region) {
                                       /* last note has no concrete region -> set it! */
                                       if ((sum / count) > 20) region = 0x100;
                                       else region = 0x200;
                                       not2->flags |= region;
                               }
                               not2->treated = 1;

                               /* sbrmark2 */
                               /* set the region value to all other notes of current beam */
                               dynhelp = akt[track];
                               not2 = not;
                               while (!(((not2->beam_nr) == (not->beam_nr)) && ((not2->flags) & 0x40))) {
                                       if ((not2->beam_nr) == (not->beam_nr)) {
                                               not2->treated = 1;
                                               not2->flags |= region;
                                       }
                                       dynhelp = dynhelp->next;
                                       while ((dynhelp->marker) != 'n') dynhelp = dynhelp->next;
                                       not2 = (struct Note *) dynhelp->data;
                               }
                       }
               }
               akt[track] = akt[track]->next;
       }
}

void ins_helprest(start, fine, callnumber)
       unsigned long start, fine;
       unsigned int callnumber;
{
       if ((start >= fine) || ((start + 0xffffff) < fine)) {
               fprintf(stderr, "warning: %d --> extreme rest found: start %lx end %lx\n", callnumber, start, fine);
       }

       hres1 = ank;
       hres2 = NULL;
       while ((hres1) && ((hres1->begin) <= start)) {
               hres2 = hres1;
               hres1 = hres1->next;
       }
       if ((hres3 = (struct helprest *) malloc (sizeof(struct helprest))) == NULL) {
               fprintf(stderr, "malloc error\n");
               exit(10);
       }
       hres3->begin = start;
       hres3->end = fine;
       hres3->next = hres1;

       if (hres2) hres2->next = hres3;
       else ank = hres3;
}


void deal_with_takt(tp, bt, attention, fac, reg)
       unsigned long bt;
       int tp;
       char attention, reg;
       short fac;
{
       int changes;
       struct Note *lastSnote;
       char sign, helpsign, nothing;
       unsigned long lastnotetime;

       changes = 1;
       nothing = 1;
       while (changes) {
               lastnotetime = bt;
               changes = 0;
               d2 = d;
               while ((d2) && ((d2->marker) != 'b')) {
                       if ((d2->marker) == 'n') {
                               not = (struct Note *) d2->data;
                               sign = 0;       /* allow processing */
                               if ((not->slur_nr) && (!((not->slur_pos) & 0x40)) && (bt != (d2->time))) sign = 1;
                               if ((attention) && (!((not->flags) & 0x300))) {
                                       d3 = d2->next;
                                       helpsign = 1;
                                       while (d3 && ((d3->marker) != 'b') && helpsign) {
                                               if ((d3->marker) == 'n') {
                                                       not2 = (struct Note *) d3->data;
                                                       if ((not2->flags) & 0x200) {
                                                               if ((not->end) > (d3->time)) sign = 1;
                                                               helpsign = 0;
                                                       }
                                                       else d3 = d3->next;
                                               }
                                               else d3 = d3->next;
                                       }
                               }
                               if ((!(not->treated)) && ((attention == 0) || (!((not->flags) & 0x100))) && (!sign)) {
                                       if ((d2->time) > lastnotetime) {
                                               ins_helprest(lastnotetime, (d2->time), 1);
                                       }
                                       nothing = 0;
                                       not->treated = 1;
                                       if (attention || (reg == 2)) (not->flags) |= 0x200;
                                       else (not->flags) |= 0x100;
                                       lastnotetime = not->end;
                                       if ((not->slur_nr) && (!((not->flags) & 0x80))) {
                                               d2 = d2->next;
                                               lastSnote = not;
                                               helpsign = 1;
                                               while (d2 && ((d2->marker) != 'b') && helpsign) {
                                                       if ((d2->marker) == 'n') {
                                                               not2 = (struct Note *) d2->data;
                                                               if ((not2->slur_nr) == (not->slur_nr)) {
                                                                       not2->treated = 1;
                                                                       lastSnote = not2;
                                                                       lastnotetime = not2->end;
                                                                       if (attention || (reg == 2)) (not2->flags) |= 0x200;
                                                                       else (not2->flags) |= 0x100;
                                                                       if ((not2->flags) & 0x80) helpsign = 0;
                                                               }
                                                       }
                                                       d2 = d2->next;
                                               }
                                               if ((!(d2)) && (!((lastSnote->flags) & 0x80))) lastSnote->flags |= 0x80;
                                       }
                                       changes++;
                                       while ((d2) && ((d2->marker) != 'b') && ((d2->time) < lastnotetime)) d2 = d2->next;
                               }
                               else d2 = d2->next;
                       }
                       else d2 = d2->next;
               }
               if ((d2) && (changes) && ((d2->time) > lastnotetime)) {
                       ins_helprest(lastnotetime, (d2->time), 7);
               }
       }
       if (nothing) {
               if (d2) ins_helprest(bt, (d2->time), 2);
               else {
                       uslonghelp = fac * tp;
                       uslonghelp += bt;
                       ins_helprest(bt, uslonghelp, 3);
               }
       }
}

void process_helprest(perq, tr, bt, tp, reg)
       short reg;
       int tp, tr, perq;
       unsigned long bt;
{
       unsigned long tphelp, dur, i;
       unsigned long b;

       /* debug output */
       hr1=ank;
       while (hr1) {
               hr1 = hr1->next;
       }

       /* first part realizes linking of rests */
       hr1 = ank;
       while (hr1) {
               hr2 = hr1->next;
               hr3 = hr1;
               while (hr2) {
                       while (hr2 && ((hr2->begin) < (hr1->end))) {
                               hr3 = hr2;
                               hr2 = hr2->next;
                       }
                       if (hr2 && ((hr1->end) == (hr2->begin))) {
                               /* link rests */
                               hr1->end = hr2->end;
                               hr3->next = hr2->next;
                               free(hr2);
                               hr2 = hr3->next;
                       }
                       else hr2 = NULL;
               }
               hr1 = hr1->next;
       }

       /* second part splits notes depending on tp */
       hr1 = ank;
       while (hr1) {
               b = bt;
               while (b < (hr1->begin)) b += tp;
               if ((b > (hr1->begin)) && (b < (hr1->end))) {
                       ins_helprest(b, (hr1->end), 4);
                       hr1->end = b;
               }
               else {
                       if (b == (hr1->begin)) {
                               tphelp = 4*tp;
                               dur = (hr1->end) - (hr1->begin);
                               while ((dur < tphelp) && (tphelp > tp)) tphelp = (tphelp >> 1);
                               if (dur > tphelp) {
                                       uslonghelp = (hr1->begin) + tphelp;
                                       ins_helprest(uslonghelp, (hr1->end), 5);
                                       hr1->end = uslonghelp;
                               }
                       }
               }
               hr1 = hr1->next;
       }

       /* third part calculates rest-values and creates rest-events */
       hr1 = ank;
       dy2 = NULL;
       dy = begin[tr];
       while (hr1) {
               dur = (hr1->end) - (hr1->begin);
               i = 0;
               while ((i<6) && ((NORMFAKTOR * dur) > (faktors[i*3] * perq))) i++;
               if ((re = (struct Rest *) malloc (sizeof(struct Rest))) == NULL) {
                       fprintf(stderr, "malloc error\n");
                       exit(10);
               }
               re->flg = 0;
               re->position = reg;
               if ((NORMFAKTOR * dur) == (faktors[i*3] * perq)) re->kind = i;
               else {
                       if (i) {
                               re->kind = i-1;
                               uslonghelp = (faktors[((i-1)*3)]) * perq;
                               uslonghelp = uslonghelp / 16;
                               uslonghelp += (hr1->begin);
                               ins_helprest(uslonghelp, (hr1->end), 6);
                       }
                       else re->kind = 0;
               }
               while (dy && (((dy->time) < (hr1->begin)) ||
                       (((dy->time) == (hr1->begin)) && ((dy->marker) != 'n')))) {
                       dy2 = dy;
                       dy = dy->next;
               }
               if ((bp = (struct bind *) malloc (sizeof(struct bind))) == NULL) {
                       fprintf(stderr, "malloc error\n");
                       exit(10);
               }
               bp->marker = 'r';
               bp->data = (void *) re;
               bp->time = (hr1->begin);
               if (dy2) dy2->next = bp;
               else begin[tr] = bp;
               bp->next = dy;
               dy2 = bp;
               hr1 = hr1->next;
       }

       /* fourth part deletes the helprest-list */
       hr1 = ank;
       while (hr1) {
               hr2 = hr1->next;
               free(hr1);
               hr1 = hr2;
       }
       ank = NULL;
}


void detect_rests(t, regio, pq)
       int t;  /* number of track */
       int pq; /* per quarter */
       char regio;
{
       unsigned long barrtime;
       int taktpart;   /* logical part of takt, depends on nom */
       short factor;

       /* drmark1 */
       akt[t] = begin[t];
       dynhelp = akt[t];
       ank = NULL;
       factor = 4;     /* default is 4/4 */
       taktpart = pq;  /* default is 4/4 */
       barrtime = 0;   /* time of last barre */
       while (akt[t]) {
               /* jump to next bar */
               dynhelp2 = dynhelp;
               while ((dynhelp2) && ((dynhelp2->marker) != 'b')) {
                       if ((dynhelp2->marker) == 't') {
                               ts = (struct TimeSig *) dynhelp2->data;
                               taktpart = pq * 4 /(ts->denom);
                               factor = ts->nom;
                       }
                       dynhelp2 = dynhelp2->next;
               }
               if (dynhelp) {
                       /* drmark2 */
                       d = dynhelp;
                       deal_with_takt(taktpart, barrtime, (regio == 0), factor, regio);
                       if (regio == 1)
                               process_helprest(pq, t, barrtime, taktpart, 0x40);
                       else
                               process_helprest(pq, t, barrtime, taktpart, 0x80);
                       if (!regio) {
                               deal_with_takt(taktpart, barrtime, 0, factor, 1);
                               process_helprest(pq, t, barrtime, taktpart, 0x40);
                       }
               }
               akt[t] = dynhelp2;
               if (akt[t]) {
                       dynhelp = akt[t]->next;
                       barrtime = akt[t]->time;
               }
       }
}

void beam_geometry(tr)
       int tr;         /* number of track */
{
       char crit, usedpos[42], helpbpos;
       char maxone, helpmaxone, pos, maxb, minb, bestpos, besthigh, bestupperflag;
       int upp, low;
       short slope;
       short measurecounter;   /* for debugging with gdb */
       char orientflag, valid;
       char lowcut, uppcut, realpos, upperflag;
       short sl;
       long sbpos[42];         /* for storing beam and slur numbers */
       unsigned long remtime;
       short i, middle;
       unsigned short counter;
       int loop;
       double arg, helparg;
       struct bind *lastdealt, *last;
       struct Note *notehelp, *prev_note, *helpn, *nohe;

       /* bgmark1 */
       akt[tr] = begin[tr];
       measurecounter = 1;
       dynhelp3 = begin[tr];   /* first event in takt */
       while (akt[tr]) {
               if ((akt[tr]->marker) == 'b') {
                       /* bgmark2 */
                       dynhelp3 = akt[tr]->next;
                       measurecounter++;
               }
               if ((akt[tr]->marker) == 'n') {
                       /* bgmark3 */
                       not = (struct Note *) akt[tr]->data;
                       if ((!(not->treated)) && (not->beam_nr)) {
                               /* bgmark4: found begin of beam */
                               maxb = (not->note_pos) & 0x3f;
                               minb = maxb;
                               not->treated = 1;
                               not->beam_pos = 0x40;
                               /* reset sbpos-array */
                               for (i=0; i<42; i++) sbpos[i] = 0;
                               /* read until first beam note and set slur and beam positions */
                               dynhelp2 = dynhelp3;
                               dynhelp = akt[tr];
                               while (dynhelp2 != dynhelp) {
                                       if ((dynhelp2->marker) == 'n') {
                                               not3 = (struct Note *) dynhelp2->data;
                                               if ((not3->slur_nr) && (!((not3->flags) & 0x80))) {
                                                       for (loop= ((not3->slur_pos) & 0x3f) - 2;loop < ((not3->slur_pos) & 0x3f) + 3; loop++)
                                                               if ((loop >= 0) && (loop <=41)) sbpos[loop] = (not3->slur_nr);
                                               }
                                               else {
                                                       if (not3->slur_nr) {
                                                               for (loop= ((not3->slur_pos) & 0x3f) - 5;loop < ((not3->slur_pos) & 0x3f) + 5; loop++)
                                                                       if ((loop >= 0) && (loop <=41) && (sbpos[loop] == (not3->slur_nr))) sbpos[loop] = 0;
                                                       }
                                               }
                                               if ((not3->beam_nr) && (not3->treated) && (!((not3->flags) & 0x40))) {
                                                       helpbpos = (not3->beam_pos) & 0x3f;
                                                       if ((not3->beam_pos) & 0x80) helpbpos += UPPLOWSHIFT;
                                                       else {
                                                               if (helpbpos > UPPLOWSHIFT) helpbpos -= UPPLOWSHIFT;
                                                               else helpbpos = 0;
                                                       }
                                                       if (helpbpos > 41) helpbpos = 41;
                                                       for (loop = helpbpos -2; loop < helpbpos + 3; loop++)
                                                               if ((loop >= 0) && (loop <=41)) sbpos[loop] = (not3->beam_nr);
                                               }
                                               else    if ((not3->beam_nr) && (not3->treated)) {
                                                               helpbpos = (not3->beam_pos) & 0x3f;
                                                               if ((not3->beam_pos) & 0x80) helpbpos += UPPLOWSHIFT;
                                                               else {
                                                                       if (helpbpos > UPPLOWSHIFT) helpbpos -= UPPLOWSHIFT;
                                                                       else helpbpos = 0;
                                                               }
                                                               if (helpbpos > 41) helpbpos = 41;
                                                               for (loop = helpbpos -5; loop < helpbpos + 6; loop++)
                                                                       if ((loop >= 0) && (loop <=41) && (sbpos[loop] == (not3->beam_nr))) sbpos[loop] = 0;
                                                       }
                                       }
                                       dynhelp2 = dynhelp2->next;
                               }

                               /* bgmark5 */
                               /* now start with processing the beam */
                               lastdealt = akt[tr];
                               /* reset the valid area array */
                               for (i=0; i<42; i++) usedpos [i] = 0;

                               /* specify the first valid region */
                               upp = not->note_pos & 0x3f;
                               while ((upp < 41) && (!(sbpos[upp]))) upp++;
                               low = not->note_pos & 0x3f;
                               while ((low > 0) && (!(sbpos[low]))) low--;
                               for (i=low; i<=upp; i++) usedpos [i] = 1;
                               usedpos [not->note_pos & 0x3f] = 2;

                               remtime = dynhelp->time;
                               counter = 0;

                               /* bgmark6 */
                               /* jump to last possible note of current beam */
                               crit = 1;
                               last = dynhelp2;
                               nohe = (struct Note *) dynhelp2->data;
                               if ((nohe->flags) & 0x40) crit = 0;
                               while (crit) {
                                       dynhelp = dynhelp->next;
                                       if ((dynhelp) && ((dynhelp->time) > remtime) && ((dynhelp->marker == 'n') || (dynhelp->marker == 'r'))) {
                                               counter += 2;
                                               remtime = dynhelp->time;
                                       }
                                       if ((dynhelp) && ((dynhelp->marker) == 'n')) {
                                               not2 = (struct Note *) dynhelp->data;
                                               if ((not->beam_nr) == (not2->beam_nr)) {
                                                       if (!usedpos[(not2->note_pos) & 0x3f]) {
                                                               /* have to split beam */
                                                               dynhelp = lastdealt;
                                                               crit = 0;
                                                               if (akt[tr] == lastdealt) {
                                                                       not->beam_nr = 0;
                                                                       not->beam_pos = 0;
                                                                       not2 = not;
                                                               }
                                                               else {
                                                                       not3 = (struct Note *) lastdealt->data;
                                                                       not3->flags |= 0x40;

                                                                       if (!((not2->flags) & 0x40)) {
                                                                               not2->beam_pos |= 0x40;
                                                                               global++;
                                                                               not2->beam_nr = global;
                                                                               lastdealt = lastdealt->next;
                                                                               while (lastdealt) {
                                                                                       if ((lastdealt->marker) == 'n') {
                                                                                               notehelp = (struct Note *) lastdealt->data;
                                                                                               if ((notehelp->beam_nr) == (not->beam_nr)) {
                                                                                                       notehelp->beam_nr = global;
                                                                                                       if ((notehelp->flags) & 0x40) lastdealt = NULL;
                                                                                               }
                                                                                       }
                                                                                       if (lastdealt) lastdealt = lastdealt->next;
                                                                               }
                                                                       }
                                                                       else {
                                                                               not2->flags &= 0xffbf;
                                                                               not2->beam_nr = 0;
                                                                       }
                                                                       not2 = not3;
                                                               }
                                                       }
                                                       else {
                                                               /* deal with printable beam note */
                                                               last = dynhelp;
                                                               lastdealt = dynhelp;
                                                               helpn = not2;
                                                               while (helpn->accord_next) helpn = helpn->accord_next;
                                                               if (((helpn->note_pos) & 0x3f) > maxb) maxb = (helpn->note_pos) & 0x3f;
                                                               if (((not2->note_pos) & 0x3f) < minb) minb = (not2->note_pos) & 0x3f;
                                                               if ((not2->flags) & 0x40) crit = 0;
                                                               not2->treated = 1;
                                                               usedpos[(not2->note_pos) & 0x3f] = 2;
                                                               if (not2->slur_nr) {
                                                                       if ((not2->slur_pos) & 0x80)
                                                                               for (i=((not2->slur_pos) & 0x3f) - 2; i<42; i++) usedpos[i] = 0;
                                                                       else
                                                                               for (i=((not2->slur_pos) & 0x3f) + 2; i>=0; i--) usedpos[i] = 0;
                                                               }
                                                       }
                                               }
                                               else {
                                                       if (not2->slur_nr) {
                                                               upp = 0;
                                                               for (i=(not2->slur_pos & 0x3f); i<42; i++) if (usedpos[i]) upp++;
                                                               low = 0;
                                                               for (i=(not2->slur_pos & 0x3f); i>=0; i--) if (usedpos[i]) low++;
                                                               if (upp > low)
                                                                       for (i=(not2->slur_pos & 0x3f); i>=0; i--) usedpos[i] = 0;
                                                               else
                                                                       for (i=(not2->slur_pos & 0x3f); i<42; i++) usedpos[i] = 0;
                                                       }
                                                       if (not2->treated) {
                                                               helpbpos = (not2->beam_pos) & 0x3f;
                                                               if ((not2->beam_pos) & 0x80) helpbpos += UPPLOWSHIFT;
                                                               else    if (helpbpos > UPPLOWSHIFT)
                                                                               helpbpos -= UPPLOWSHIFT;
                                                                       else helpbpos = 0;
                                                               for (loop=helpbpos-2; loop < (helpbpos + 3); loop++)
                                                                       if ((loop >= 0) && (loop <= 41)) usedpos[loop] = 0;
                                                       }
                                                       usedpos[(not2->note_pos) & 0x3f] = 2;
                                               }
                                       }
                                       if (dynhelp == NULL) crit = 0;
                               }

                               if ((last == dynhelp2) && ((dynhelp == NULL) || ((nohe->flags) & 0x40))) {
                                       not->beam_nr = 0;
                               }
                               else {
                                       if ((dynhelp == NULL) && (last != dynhelp2)) {
                                               not2 = (struct Note *) last->data;
                                               not2->flags |= 0x40;
                                               dynhelp = last;
                                       }
                               }

                               /* bgmark7 */
                               /* now dynhelp and not2 mark last note of current beam */

                               if (not->beam_nr) {

                                       /* store the difference between the position of the last note   */
                                       /* and the position of the first note                           */

                                       if (((not2->note_pos) & 0x3f) >= ((not->note_pos) & 0x3f)) {
                                               orientflag = 1;
                                               helpmaxone = (((not2->note_pos) & 0x3f) - ((not->note_pos) & 0x3f));
                                       }
                                       else {
                                               orientflag = 0;
                                               helpmaxone = (((not->note_pos) & 0x3f) - ((not2->note_pos) & 0x3f));
                                       }

                                       /* as a value for a middle position */
                                       middle = maxb + minb;

                                       /* set position */
                                       pos = 0x70;

                                       /* depending on middle search for a nice position */
                                       if ((((not->flags) & 0x100) && (middle > (2 * VIOLINEMID))) || (((not->flags) & 0x200) && (middle > (2 * BASSMID)))) {
                                               /* try to find a lower beam */
                                               upperflag = 0;
                                               i = minb -1;
                                               maxone = 0;
                                               if (maxb > BEAMDELTA) lowcut = maxb - BEAMDELTA;
                                               else lowcut = 0;
                                               if ((minb > BEAMTOLMAX) && (lowcut < (minb - BEAMTOLMAX))) lowcut = minb - BEAMTOLMAX;
                                               if (lowcut > helpmaxone) lowcut -= helpmaxone;
                                               else lowcut = 0;
                                               while ((usedpos[i] == 1) && (i > lowcut)) {
                                                       maxone++;
                                                       i--;
                                               }

                                               if (maxone > ((helpmaxone >> 1) + BEAMTOLERANCE)) {
                                                       if (minb > BEAMTOLERANCE) realpos = minb - BEAMTOLERANCE;
                                                       else realpos = 0;
                                                       if (orientflag) {
                                                               if (realpos > (helpmaxone >> 1)) realpos -= (helpmaxone >> 1);
                                                               else realpos = 0;
                                                       }
                                                       pos = realpos + UPPLOWSHIFT;
                                                       if (pos > 41) pos = 41;
                                               }
                                               else {
                                                       /* try to find an upper beam */
                                                       upperflag = 1;
                                                       bestpos = minb - maxone;
                                                       bestupperflag = 0;
                                                       if (maxone > helpmaxone) realpos = bestpos + (helpmaxone >> 2);
                                                       else realpos = bestpos;
                                                       if (realpos > 41) realpos = 41;
                                                       besthigh = maxone;
                                                       i = maxb + 1;
                                                       maxone = 0;
                                                       uppcut = minb + BEAMDELTA;
                                                       if (uppcut > 41) uppcut = 41;
                                                       if (uppcut > (maxb + BEAMTOLMAX)) uppcut = maxb + BEAMTOLMAX;
                                                       uppcut += helpmaxone;
                                                       if (uppcut > 41) uppcut = 41;
                                                       while ((usedpos[i] == 1) && (i < uppcut)) {
                                                               maxone++;
                                                               i++;
                                                       }

                                                       if (maxone > ((helpmaxone >> 1) + BEAMTOLERANCE)) {
                                                               realpos = maxb + BEAMTOLERANCE;
                                                               if (realpos > 41) realpos = 41;
                                                               if (!orientflag) realpos += (helpmaxone >> 1);
                                                               if (realpos > 41) realpos = 41;
                                                               if (realpos > UPPLOWSHIFT) pos = realpos - UPPLOWSHIFT;
                                                               else pos = 0;
                                                       }
                                                       else {
                                                               if (maxone > besthigh) {
                                                                       besthigh = maxone;
                                                                       bestupperflag = 1;
                                                                       bestpos = maxb + maxone;
                                                                       if (maxone > helpmaxone) {
                                                                               if (bestpos > (helpmaxone >> 2)) realpos = bestpos - (helpmaxone >> 2);
                                                                               else realpos = 0;
                                                                       }
                                                                       else realpos = bestpos;
                                                               }
                                                       }
                                               }
                                       }
                                       else {
                                               /* try to find an upper beam */
                                               upperflag = 1;
                                               i = maxb + 1;
                                               maxone = 0;
                                               uppcut = minb + BEAMDELTA;
                                               if (uppcut > 41) uppcut = 41;
                                               if (uppcut > (maxb + BEAMTOLMAX)) uppcut = maxb + BEAMTOLMAX;
                                               uppcut += helpmaxone;
                                               if (uppcut > 41) uppcut = 41;
                                               while ((usedpos[i] == 1) && (i < uppcut)) {
                                                       maxone++;
                                                       i++;
                                               }

                                               if (maxone > ((helpmaxone >> 1) + BEAMTOLERANCE)) {
                                                       realpos = maxb + BEAMTOLERANCE;
                                                       if (realpos > 41) realpos = 41;
                                                       if (!orientflag) realpos += (helpmaxone >> 1);;
                                                       if (realpos > 41) realpos = 41;
                                                       if (realpos > UPPLOWSHIFT) pos = realpos - UPPLOWSHIFT;
                                                       else pos = 0;
                                               }
                                               else {
                                                       /* try to find a lower beam */
                                                       upperflag = 0;
                                                       bestpos = maxb + maxone;
                                                       bestupperflag = 1;
                                                       if (maxone > helpmaxone) {
                                                               if (bestpos > (helpmaxone >> 2)) realpos = bestpos - (helpmaxone >> 2);
                                                               else realpos = 0;
                                                       }
                                                       else realpos = bestpos;
                                                       besthigh = maxone;
                                                       i = minb -1;
                                                       maxone = 0;
                                                       if (maxb > BEAMDELTA) lowcut = maxb - BEAMDELTA;
                                                       else lowcut = 0;
                                                       if ((minb > BEAMTOLMAX) && (lowcut < (minb - BEAMTOLMAX))) lowcut = minb - BEAMTOLMAX;
                                                       if (lowcut > helpmaxone) lowcut -= helpmaxone;
                                                       else lowcut = 0;
                                                       while ((usedpos[i] == 1) && (i > lowcut)) {
                                                               maxone++;
                                                               i--;
                                                       }
                                                       if (maxone > ((helpmaxone >> 1) + BEAMTOLERANCE)) {
                                                               if (minb > BEAMTOLERANCE) realpos = minb - BEAMTOLERANCE;
                                                               else realpos = 0;
                                                               if (orientflag) {
                                                                       if (realpos > (helpmaxone >> 1)) realpos -= (helpmaxone >> 1);
                                                                       else realpos = 0;
                                                               }
                                                               pos = realpos + UPPLOWSHIFT;
                                                               if (pos > 41) pos = 41;
                                                       }
                                                       else {
                                                               if (maxone > besthigh) {
                                                                       besthigh = maxone;
                                                                       bestupperflag = 0;
                                                                       bestpos = minb - maxone;
                                                                       if (maxone > helpmaxone) realpos = bestpos + (helpmaxone >> 2);
                                                                       else realpos = bestpos;
                                                                       if (realpos > 41) realpos = 41;
                                                               }
                                                       }
                                               }
                                       }

                                       /* check middle region for setting the beam position    */
                                       /* (only if not already found one)                      */

                                       valid = 1;
                                       if (pos == 0x70) {
                                               /* search a nice beam position between minb and maxb    */
                                               /* only when MINBEAMBROAD is valid                      */
                                               if ((maxb - minb) < MINBEAMBROAD) valid = 0;

                                               if (valid) {
                                                       if ((((not->note_pos) & 0x3f) <= bestpos) && orientflag) {
                                                               if (bestpos > helpmaxone) bestpos -= helpmaxone;
                                                               else bestpos = 0;
                                                       }
                                                       if ((((not->note_pos) & 0x3f) > bestpos) && (!orientflag)) {
                                                               bestpos += helpmaxone;
                                                               if (bestpos > 41) bestpos = 41;
                                                       }
                                                       maxone = 0;
                                                       for (i=maxb; i>=minb; i--) {
                                                               if (usedpos[i] == 1) maxone++;
                                                               else {
                                                                       if (maxone > besthigh) {
                                                                               besthigh = maxone;
                                                                               bestpos = i;
                                                                               if (besthigh > helpmaxone) {
                                                                                       bestpos += ((besthigh - helpmaxone) >> 1);
                                                                                       realpos = bestpos + (helpmaxone >> 2);
                                                                                       if (!orientflag) bestpos += helpmaxone;
                                                                                       if (bestpos > 41) bestpos = 41;
                                                                                       if (realpos > 41) realpos = 41;
                                                                               }
                                                                               else {
                                                                                       realpos = bestpos + (besthigh >> 2);
                                                                                       if (!orientflag) bestpos += besthigh;
                                                                               }
                                                                               if (((not->note_pos) & 0x3f) <= realpos)
                                                                                       bestupperflag = 1;
                                                                               else bestupperflag = 0;
                                                                       }
                                                                       maxone = 0;
                                                               }
                                                       }
                                                       pos = bestpos;
                                                       if (bestupperflag) {
                                                               if (pos > UPPLOWSHIFT) pos -= UPPLOWSHIFT;
                                                               else pos = 0;
                                                               upperflag = 1;
                                                       }
                                                       else {
                                                               upperflag = 0;
                                                               pos += UPPLOWSHIFT;
                                                               if (pos > 41) pos = 41;
                                                       }
                                                       maxone = besthigh;
                                               }
                                       }

                                       /* bgmark8 */
                                       if (valid) {
                                               if (!counter) counter = 1;
                                               if (maxone >= helpmaxone) arg = helpmaxone;
                                               else arg = maxone;

                                               if (orientflag) slope = 1;
                                               else slope = -1;

                                               helparg = SLOPEFACTOR * counter;
                                               arg /= helparg;

                                               /* the following lines substitute a function atan */
                                               if (arg > 0.94) slope *= 9;
                                               else    if (arg > 0.77) slope *= 8;
                                                       else    if (arg > 0.64) slope *= 7;
                                                               else    if (arg > 0.52) slope *= 6;
                                                                       else    if (arg > 0.41) slope *= 5;
                                                                               else    if (arg > 0.31) slope *= 4;
                                                                                       else    if (arg > 0.21) slope *= 3;
                                                                                               else    if (arg > 0.12) slope *= 2;
                                                                                                       else    if (arg < 0.04) slope = 0;

                                               /* modify position */
                                               if (pos > 41) pos = 41;
                                               else {
                                                       if (pos & 0x80) pos = 0;
                                               }

                                               /* setting of the upp/low-flag */
                                               if (upperflag) pos |= 0x80;

                                               /* generate a flag-mask for slope */
                                               if (slope < 0) {
                                                       sl = 0;
                                                       sl |= 0x8000;
                                                       slope = slope * (-1);
                                               }
                                               else sl = 0;

                                               slope <<= 11;

                                               /* bgmark9 */
                                               /* set the values to all notes of current beam */
                                               sl |= slope;
                                               dynhelp = akt[tr];
                                               crit = 1;
                                               prev_note = NULL;
                                               while (crit) {
                                                       if ((dynhelp->marker) == 'n') {
                                                               not3 = (struct Note *) dynhelp->data;
                                                               if ((not->beam_nr) == (not3->beam_nr)) {
                                                                       if (prev_note) {
                                                                               switch ((not3->flags) & 0x38) {
                                                                                       case 0x0 : (prev_note->next_beamn_kind)++;
                                                                                       case 0x8 : (prev_note->next_beamn_kind)++;
                                                                                       case 0x10: (prev_note->next_beamn_kind)++;
                                                                                       case 0x18: (prev_note->next_beamn_kind)++;
                                                                                                  break;
                                                                                       default  : break;
                                                                               }
                                                                       }
                                                                       prev_note = not3;
                                                                       not3->beam_pos |= pos;
                                                                       not3->flags |= sl;
                                                                       if ((not3->flags) & 0x40) {
                                                                               not3->next_beamn_kind = 0;
                                                                               crit = 0;
                                                                       }
                                                               }
                                                               else {
                                                                       if ((!(not3->slur_nr)) && ((!(not3->beam_nr) || (!(not3->treated)))) && (((not3->flags) & 0x38) != 0x30)) {
                                                                               helpn = not3;
                                                                               while (helpn->accord_next) helpn = helpn->accord_next;

                                                                               /* set lower stems if nessesary */
                                                                               if ((realpos > ((not3->note_pos) & 0x3f)) && ((LAMBDA + ((helpn->note_pos) & 0x3f) + 2) >= realpos)) {
                                                                                       helpn = not3;
                                                                                       while (helpn) {
                                                                                               helpn->flags |= 0x400;
                                                                                               helpn = helpn->accord_next;
                                                                                       }
                                                                               }
                                                                       }
                                                               }
                                                       }
                                                       if (crit) dynhelp = dynhelp->next;
                                               }
                                       }
                                       else {
                                               /* bgmark10 */
                                               /* sorry, this beam is unprintable      */
                                               /* erase it                             */
                                               dynhelp = akt[tr]->next;
                                               crit = 1;
                                               while (crit && dynhelp) {
                                                       if ((dynhelp->marker) == 'n') {
                                                               not3 = (struct Note *) dynhelp->data;
                                                               if ((not3->beam_nr) == (not->beam_nr)) {
                                                                       not3->beam_nr = 0;
                                                                       not3->beam_pos = 0;
                                                                       if ((not3->flags) & 0x40) crit = 0;
                                                                       not3->flags &= 0x7bf;
                                                               }
                                                       }
                                                       if (crit) dynhelp = dynhelp->next;
                                               }
                                               not->beam_nr = 0;
                                               not->beam_pos = 0;
                                               not->flags &= 0x7bf;
                                       }
                               }
                       }
               }
               akt[tr] = akt[tr]->next;
       }
}

void calculate_rest_positions(tr)
       int tr;
{
       char full[42];                          /* used positions */
       char bestpos;                           /* for storing the best position */
       char highcount;                         /* counts free positions */
       char to, mid, from1, to1, from2, to2;   /* variables for looping */
       int i;                                  /* for looping and indexing */
       long cur_slur[42], cur_beam[42];        /* positions used for slurs and beams */
       unsigned long rtime;                    /* store time information */
       char goodpos, goodhigh;                 /* temporal best */
       char minbeam, maxbeam;                  /* to specify the region from beamed note to the beam itself */
       short restcount;                        /* counts the rests of time rtime */
       char topos;                             /* store the slope */
       char upperto;                           /* setting a loopto value */
       short slope;                            /* setting topos */
       short measurecounter;                   /* is useful for gdb to stop at a given measure */

       /* crpmark1 */
       measurecounter = 1;
       akt[tr] = begin[tr];
       for (i=0; i<42; i++) {
               cur_slur[i] = 0;
               cur_beam[i] = 0;
       }
       while (akt[tr]) {
               if ((akt[tr]->marker) == 'b') measurecounter++;
               if ((akt[tr]->marker) == 'r') {
                       /* crpmark2 */
                       restcount = 1;
                       rtime = akt[tr]->time;
                       for (i=0; i<42; i++) {
                               if (cur_slur[i] || cur_beam[i]) full[i] = 1;
                               else full[i] = 0;
                       }
                       dynhelp = akt[tr];      /* store the begin of rest pointer */
                       dynhelp3 = akt[tr];     /* indicates later the last rest of rtime */
                       akt[tr] = akt[tr]->next;
                       while ((akt[tr]) && (rtime == (akt[tr]->time))) {
                               /* deal with rests and notes of time rtime */
                               if ((akt[tr]->marker) == 'n') {
                                       not = (struct Note *) akt[tr]->data;
                                       not2 = not;
                                       while (not2->accord_next) not2 = not2->accord_next;

                                       if (!(not->beam_nr)) {
                                               if (((not->flags) & 0x30) == 0x30) {
                                                       /* whole note without any stem */
                                                       full[(not->note_pos) & 0x3f] = 1;
                                               }
                                               else {
                                                       if ((not->flags) & 0x400) {
                                                               /* lower stem */
                                                               if (((not->note_pos) & 0x3f) > LAMBDA)
                                                                       to = ((not->note_pos) & 0x3f) - LAMBDA;
                                                               else to = 0;
                                                               for (i=((not2->note_pos) & 0x3f); i>=to; i-- ) full[i] = 1;
                                                       }
                                                       else {
                                                               /* upper stem */
                                                               to = ((not2->note_pos) & 0x3f) + LAMBDA;
                                                               if (to > 41) to = 41;
                                                               for (i=((not->note_pos) & 0x3f); i<=to; i++ ) full[i] = 1;
                                                       }
                                               }
                                       }
                                       else {
                                               /* deal with beamed note */
                                               to = not->beam_pos & 0x3f;
                                               if ((not->beam_pos) & 0x80) to += UPPLOWSHIFT;
                                               else    if (to > UPPLOWSHIFT) to -= UPPLOWSHIFT;
                                                       else to = 0;
                                               if (to > 41) to = 41;
                                               slope = (not->flags) & 0x7800;
                                               topos = (slope >> 11) & 0xf;
                                               if ((not->flags) & 0x8000) {
                                                       /* falling beam */
                                                       if (to > topos) minbeam = to - topos;
                                                       else minbeam = 0;
                                                       maxbeam = to;
                                               }
                                               else {
                                                       /* raising beam */
                                                       minbeam = to;
                                                       maxbeam = to + topos;
                                                       if (maxbeam > 41) maxbeam = 41;
                                               }
                                               if (((not2->note_pos) & 0x3f) > maxbeam) maxbeam = ((not2->note_pos) & 0x3f);
                                               if (((not->note_pos) & 0x3f) < minbeam) minbeam = ((not->note_pos) & 0x3f);
                                               for (i=minbeam; i<=maxbeam; i++) full[i] = 1;
                                       }

                                       if ((not->slur_nr) && ((not->slur_pos) & 0x40)) {
                                               /* slur begins here */
                                               if (not->slur_pos & 0x80) {
                                                       /* upper slur */
                                                       to = SLURWIDE + ((not->slur_pos) & 0x3f);
                                                       if (to > 41) to = 41;
                                                       for (i=((not->slur_pos) & 0x3f); i<=to; i++) full[i] = 1;
                                               }
                                               else {
                                                       /* lower slur */
                                                       if (((not->slur_pos) & 0x3f) > SLURWIDE)
                                                               to = ((not->slur_pos) & 0x3f) - SLURWIDE;
                                                       else to = 0;
                                                       for (i=to; i<=((not->slur_pos) & 0x3f); i++) full[i] = 1;
                                               }
                                       }
                               }
                               else {
                                       if ((akt[tr]->marker) == 'r') {
                                               restcount++;
                                               dynhelp3 = akt[tr];
                                       }
                                       else {
                                               /* after rests can only be notes of the same time */
                                               fprintf(stderr, "unknown element found\n");
                                               exit(10);
                                       }
                               }
                               akt[tr] = akt[tr]->next;
                       }

                       do {
                               /* crpmark3 */
                               re = (struct Rest *) dynhelp->data;
                               if ((re->position) & 0x80) {
                                       /* it's a bass rest */
                                       mid = BASSMID;
                                       from1 = mid - halfresthigh[re->kind] -1;
                                       to1 = VIOLINEMID - 2;
                                       from2 = mid + halfresthigh[re->kind] + 6;
                                       to2 = 0;
                               }

                               if ((re->position) & 0x40) {
                                       /* it's a violine rest */
                                       mid = VIOLINEMID;
                                       from1 = mid - halfresthigh[re->kind] -1;
                                       to1 = 41;
                                       from2 = mid + halfresthigh[re->kind] + 6;
                                       to2 = BASSMID + 2;
                               }

                               /* crpmark4 */
                               highcount = 0;
                               goodhigh = 0;
                               bestpos = 60;
                               i = from1;
                               while (i<to1) {
                                       if (!full[i]) {
                                               highcount++;
                                               if (highcount >= (resthigh[re->kind] + RESTTOLERANCE)) {
                                                       bestpos = i - resthigh[re->kind] - HALFRESTTOLERANCE;
                                                       i = 40;
                                               }
                                       }
                                       else {
                                               if (highcount > goodhigh) {
                                                       goodhigh = highcount;
                                                       goodpos = i - highcount;
                                               }
                                               highcount = 0;
                                       }
                                       i++;
                               }

                               /* rests (except of pause and hpause) can use */
                               /* an small upper area because there is enough space */
                               highcount = 0;
                               if ((bestpos == 60) && ((re->kind) < 5)) {
                                       while (!full[i]) {
                                               i--;
                                               highcount++;
                                       }
                                       if (highcount > 2) bestpos = i + 2;
                               }

                               /* crpmark5 */
                               highcount = 0;
                               i = from2;
                               while (i>to2) {
                                       if (!full[i]) {
                                               highcount++;
                                               if ((highcount > (resthigh[re->kind] + RESTTOLERANCE)) &&
                                                   ((abs(bestpos + (halfresthigh[re->kind]) - mid)) >
                                                    (abs((i + HALFRESTTOLERANCE) + (halfresthigh[re->kind]) - mid)))) {
                                                       bestpos = i + HALFRESTTOLERANCE;
                                                       i = 1;
                                               }
                                       }
                                       else {
                                               if (highcount > goodhigh) {
                                                       goodhigh = highcount;
                                                       goodpos = i;
                                               }
                                               highcount = 0;
                                       }
                                       i--;
                               }

                               /* crpmark6 */
                               if (bestpos == 60) {
                                       bestpos = goodpos;
                                       re->flg = 1;
                               }

                               /* crpmark7 */
                               /* half and whole rests needs an odd position */
                               if ((re->kind) > 4) bestpos |= 0x1;
                               re->position |= bestpos;

                               upperto = bestpos + 2 + (resthigh[re->kind]);
                               if (upperto > 41) upperto = 41;
                               for (i=bestpos; i<=upperto; i++) full[i] = 1;
                               restcount--;
                               if (restcount) {
                                       dynhelp = dynhelp->next;
                                       if ((dynhelp->marker) != 'r') {
                                               fprintf(stderr, "error: deal non rest like rest\n");
                                               exit(10);
                                       }
                               }
                       } while (restcount);
                       akt[tr] = dynhelp3;
               }
               if ((akt[tr]->marker) == 'n') {
                       /* crpmark8 */
                       not3 = (struct Note *) akt[tr]->data;
                       if ((not3->beam_nr) && (((not3->beam_pos) & 0x40) || ((not3->flags) & 0x40))) {
                               /* begin or end of beam */
                               to = not3->beam_pos & 0x3f;
                               if ((not3->beam_pos) & 0x80) to += UPPLOWSHIFT;
                               else    if (to > UPPLOWSHIFT) to -= UPPLOWSHIFT;
                                       else to = 0;
                               if (to > 41) to = 41;
                               slope = (not3->flags) & 0x7800;
                               topos = (slope >> 11) & 0xf;
                               if ((not3->flags) & 0x8000) {
                                       /* falling beam */
                                       if (to > topos) topos = to - topos;
                                       else topos = 0;
                                       if (topos > 2) topos -= 2;
                                       else topos = 0;
                                       to += 2;
                                       if (to > 41) to = 41;
                                       if ((not3->beam_pos) & 0x40)
                                               for (i=topos; i<=to; i++) cur_beam[i] = not3->beam_nr;
                                       else {
                                               for (i=topos; i<=to; i++)
                                                       if (cur_beam[i] == not3->beam_nr) cur_beam[i] = 0;
                                       }
                               }
                               else {
                                       /* raising beam */
                                       topos += to;
                                       if (topos > 41) topos = 41;
                                       if (to > 2) to -= 2;
                                       else to = 0;
                                       topos += 2;
                                       if (topos > 41) topos = 41;
                                       if ((not3->beam_pos) & 0x40)
                                               for (i=to; i<=topos; i++) cur_beam[i] = not3->beam_nr;
                                       else {
                                               for (i=to; i<=topos; i++)
                                                       if (cur_beam[i] == not3->beam_nr) cur_beam[i] = 0;
                                       }
                               }
                       }
                       if ((not3->slur_nr) && (((not3->slur_pos) & 0x40) || ((not3->flags) & 0x80))) {
                               /* begin or end of slur */
                               if (not3->slur_pos & 0x80) {
                                       /* upper slur */
                                       to = SLURWIDE + (not3->slur_pos & 0x3f);
                                       if (to > 41) to = 41;
                                       if ((not3->slur_pos) & 0x40)
                                               for (i=((not3->slur_pos) & 0x3f); i!=to; i++)
                                                       cur_slur[i] = not3->slur_nr;
                                       else {
                                               for (i=((not3->slur_pos) & 0x3f); i!=to; i++)
                                                       if (cur_slur[i] == not3->slur_nr) cur_slur[i] = 0;
                                       }
                               }
                               else {
                                       /* lower slur */
                                       if (((not3->slur_pos) & 0x3f) > SLURWIDE)
                                               to = (not3->slur_pos & 0x3f) - SLURWIDE;
                                       else to = 0;
                                       if ((not3->slur_pos) & 0x40)
                                               for (i=to; i!=((not3->slur_pos) & 0x3f); i++)
                                                       cur_slur[i] = not3->slur_nr;
                                       else {
                                               for (i=to; i!=((not3->slur_pos) & 0x3f); i++)
                                                       if (cur_slur[i] == not3->slur_nr) cur_slur[i] = 0;
                                       }
                               }
                       }
               }
               akt[tr] = akt[tr]->next;
       }
}

void ins_levent(tn, type, ltime, value)
       int tn;
       char type;
       unsigned long ltime;
       char value;
{
       /* this function requires the correct setting of dy to the begin of track */
       /* and of dy2 to NULL                                                     */

       while (dy && (((dy->time) < ltime) ||
              (((dy->time) == ltime) && ((dy->marker) != 'n') && ((dy->marker) != 'r')))) {
               dy2 = dy;
               dy = dy->next;
       }

       if ((dynhelp3 = (struct bind *) malloc (sizeof(struct bind))) == NULL) {
               fprintf(stderr, "malloc error\n");
               exit(10);
       }
       if (dy2) dy2->next = dynhelp3;
       else begin[tn] = dynhelp3;
       dynhelp3->next = dy;
       dynhelp3->time = ltime;
       dynhelp3->marker = 'p';

       if ((lo = (struct Loudness *) malloc (sizeof(struct Loudness))) == NULL) {
               fprintf(stderr, "malloc error\n");
               exit(10);
       }
       dynhelp3->data = (void *) lo;
       if (type) {
               lo->dynamics = 0;
               lo->statics = value;
       }
       else {
               lo->dynamics = value;
               lo->statics = 0;
       }
}


void set_loudness_infos(tnr)
       int tnr;
{
       int i, j, k, l, m, n, sum, count, criterium, loop, loopto;
       unsigned long time, stime;
       char staticflag, dynamicflag, dval, sval;

       /* slimark1 */
       akt[tnr] = begin[tnr];
       dy = begin[tnr];
       dy2 = NULL;
       staticflag = 1;
       dynamicflag = 0;
       j = 0;
       for (i=0; i<6; i++) {
               if ((loudrecarr[i] = (struct loudrec *) malloc (sizeof(struct loudrec))) == NULL) {
                       fprintf(stderr, "malloc error\n");
                       exit(10);
               }
               loudrecarr[i]->time = 0;
       }
       /* slimark2 */
       while (akt[tnr]) {
               if ((akt[tnr]->marker) == 'n') {
                       time = akt[tnr]->time;
                       dynhelp = akt[tnr];
                       sum = 0;
                       count = 0;
                       while (dynhelp && (time == (dynhelp->time))) {
                               not = (struct Note *) dynhelp->data;
                               sum += not->loud;
                               count++;
                               dynhelp = dynhelp->next;
                       }
                       criterium = sum / count;
                       i = 0;
                       while ((i < 7) && (loudarray[i] < criterium)) i++;
                       if (staticflag) {
                               ins_levent(tnr, 1, time, i + 1);
                               staticflag = 0;
                       }
                       /* fill the record */
                       loudrecarr[j]->time = time;
                       loudrecarr[j]->criterium = criterium;
                       loudrecarr[j]->range = i;

                       /* slimark3 */
                       j = modulo4pp[j];

                       if (loudrecarr[j]->time) {
                               k = modulo4pp[j];
                               l = modulo4pp[k];
                               m = modulo4pp[l];
                               n = modulo4pp[m];
                               i = modulo4pp[n];

                               if ((loudrecarr[j]->criterium) < (loudrecarr[k]->criterium)) {
                                       if ((loudrecarr[k]->criterium) < (loudrecarr[l]->criterium)) {
                                               if ((loudrecarr[l]->criterium) < (loudrecarr[m]->criterium)) {
                                                       if ((loudrecarr[m]->criterium) < (loudrecarr[n]->criterium)) {
                                                               dval = 3;
                                                               loopto = n;
                                                               if ((loudrecarr[n]->criterium) == (loudrecarr[i]->criterium)) {
                                                                       staticflag = 1;
                                                                       stime = loudrecarr[n]->time;
                                                                       sval = loudrecarr[n]->range;
                                                               }
                                                       }
                                                       else {
                                                               dval = 2;
                                                               loopto = m;
                                                               if ((loudrecarr[m]->criterium) == (loudrecarr[n]->criterium)) {
                                                                       staticflag = 1;
                                                                       stime = loudrecarr[m]->time;
                                                                       sval = loudrecarr[m]->range;
                                                               }
                                                       }
                                               }
                                               else {
                                                       dval = 1;
                                                       loopto = l;
                                                       if ((loudrecarr[l]->criterium) == (loudrecarr[m]->criterium)) {
                                                               staticflag = 1;
                                                               stime = loudrecarr[l]->time;
                                                               sval = loudrecarr[l]->range;
                                                       }
                                               }
                                       }
                                       else {
                                               dval = 0;
                                               loopto = k;
                                               if ((loudrecarr[k]->criterium) == (loudrecarr[l]->criterium)) {
                                                       staticflag = 1;
                                                       stime = loudrecarr[k]->time;
                                                       sval = loudrecarr[k]->range;
                                               }
                                       }
                                       dynamicflag = 1;
                               }
                               else {
                                       if ((loudrecarr[j]->criterium) > (loudrecarr[k]->criterium)) {
                                               if ((loudrecarr[k]->criterium) > (loudrecarr[l]->criterium)) {
                                                       if ((loudrecarr[l]->criterium) > (loudrecarr[m]->criterium)) {
                                                               if ((loudrecarr[m]->criterium) > (loudrecarr[n]->criterium)) {
                                                                       dval = 7;
                                                                       loopto = n;
                                                                       if ((loudrecarr[n]->criterium) == (loudrecarr[i]->criterium)) {
                                                                               staticflag = 1;
                                                                               stime = loudrecarr[n]->time;
                                                                               sval = loudrecarr[n]->range;
                                                                       }
                                                               }
                                                               else {
                                                                       dval = 6;
                                                                       loopto = m;
                                                                       if ((loudrecarr[m]->criterium) == (loudrecarr[n]->criterium)) {
                                                                               staticflag = 1;
                                                                               stime = loudrecarr[m]->time;
                                                                               sval = loudrecarr[m]->range;
                                                                       }
                                                               }
                                                       }
                                                       else {
                                                               dval = 5;
                                                               loopto = l;
                                                               if ((loudrecarr[l]->criterium) == (loudrecarr[m]->criterium)) {
                                                                       staticflag = 1;
                                                                       stime = loudrecarr[l]->time;
                                                                       sval = loudrecarr[l]->range;
                                                               }
                                                       }
                                               }
                                               else {
                                                       dval = 4;
                                                       loopto = k;
                                                       if ((loudrecarr[k]->criterium) == (loudrecarr[l]->criterium)) {
                                                               staticflag = 1;
                                                               stime = loudrecarr[k]->time;
                                                               sval = loudrecarr[k]->range;
                                                       }
                                               }
                                               dynamicflag = 1;
                                       }
                                       else {  /* loudness is equal */
                                               loop = j;
                                               while ((loop != i) && ((loudrecarr[loop]->criterium) == (loudrecarr[modulo4pp[loop]]->criterium))) {
                                                       loop = modulo4pp[loop];
                                               }
                                               loopto = loop;
                                       }
                               }

                               if (dynamicflag) {
                                       ins_levent(tnr, 0, loudrecarr[j]->time, dval + 1);
                                       dynamicflag = 0;
                               }
                               if (staticflag) {
                                       loopto = modulo4pp[loopto];
                                       ins_levent(tnr, 1, stime, sval + 1);
                                       staticflag = 0;
                               }
                               /* slimark4 */
                               loop = j;
                               while (loop != loopto) {
                                       loudrecarr[loop]->time = 0;
                                       loop = modulo4pp[loop];
                               }
                       }
                       akt[tnr] = dynhelp;
               }
               else akt[tnr] = akt[tnr]->next;
       }
}

void debug_out()
{
       int tnr, barrcounter;

       printf("\nListing the whole dynamic structure:\n");
       for (tnr = 0; tnr < MAXTRACKS; tnr++) {
               dynhelp = begin[tnr];
               barrcounter = 0;
               while (dynhelp != NULL) {
                       printf("tnr: %i begin: %lx marker %c ",tnr, dynhelp->time, dynhelp->marker);
                       switch (dynhelp->marker) {
                               case 'n': not = (struct Note *) dynhelp->data;
                                         printf("\tduration: %x oct: %i pit: %i\n", not->duration, not->octave, not->pitch);
                                         printf("\tend: %lx loudness: %x flags: %x \n", not->end, not->loud, not->flags);
                                         if (not->beam_nr) {
                                               printf("\t");
                                               if ((not->flags) & 0x40) printf("end\t");
                                               if ((not->beam_pos) & 0x40) printf("begin\t");
                                               printf("beam_number: %d beam_pos: %c orientation: ", not->beam_nr, positions[(not->beam_pos) & 0x3f]);
                                               if ((not->beam_pos) & 0x80) printf("upper\n");
                                               else printf("lower\n");
                                         }
                                         if (not->accord_next) printf("\taccorded: yes\n");
                                         else printf("\taccorded: no\n");
                                         if (not->slur_nr) {
                                               printf("\t");
                                               if ((not->flags) & 0x80) printf("end\t");
                                               if ((not->slur_pos) & 0x40) printf("begin\t");
                                               printf("slur_number: %d slur_pos: %c orientation: ", not->slur_nr, positions[(not->slur_pos) & 0x3f]);
                                               if ((not->slur_pos) & 0x80) printf("upper\n");
                                               else printf("lower\n");
                                         }
                                         printf("\tNotenausgabe: ");
                                         if (((not->note_pos) & 0xc0) == 0xc0) printf("Aufhebung ");
                                         else if (((not->note_pos) & 0xc0) == 0x80) printf("b ");
                                              else if (((not->note_pos) & 0xc0) == 0x40) printf("Kreuz ");
                                         if (((not->note_pos) & 0x3f) < 5) printf("'");
                                         printf("%c\n", positions[(not->note_pos) & 0x3f]);
                                         break;
                               case 't': ts = (struct TimeSig *) dynhelp->data;
                                         printf("nn: %i dom: %i\n",ts->nom, ts->denom);
                                         break;
                               case 'l': ly = (struct Lyric *) dynhelp->data;
                                         printf("text: %s\n",ly->text);
                                         break;
                               case 'k': ks = (struct KeySig *) dynhelp->data;
                                         printf("sign: %x\n",ks->sign);
                                         break;
                               case 'b': printf("end_of_measure: %d\n", ++barrcounter);
                                         break;
                               case 'r': re = (struct Rest *) dynhelp->data;
                                         printf("kind: %x position: %x\n",re->kind, re->position);
                                         break;
                               case 'p': lo = (struct Loudness *) dynhelp->data;
                                         if (lo->statics) printf("static with value: %x\n", lo->statics);
                                         else printf("dynamic with value: %x\n", lo->dynamics);
                                         break;
                               default : printf("unknown marker\n");
                                         break;
                       }
                       dynhelp = dynhelp->next;
               }
       }
}