From 796f655278b62a879076d404aafa3d62facfac2f Mon Sep 17 00:00:00 2001
From: Reinhold Kainhofer <reinhold@kainhofer.com>
Date: Mon, 19 Jul 2010 14:27:17 +0200
Subject: [PATCH] Implement rhythmic models

-) Store the current rhythmic model in a global variable, loop index variable
-) Factor out raw duration and notehead functions to parse values also for
   rhythmic models
-) Reset rhythmic model as soon as a new explicit duration is encountered
---
 pae2xml.pl                      | 88 ++++++++++++++++++++++++++-------
 sample_files/Rhythmic-model.pae |  7 +++
 2 files changed, 76 insertions(+), 19 deletions(-)
 create mode 100644 sample_files/Rhythmic-model.pae

diff --git a/pae2xml.pl b/pae2xml.pl
index 3c555bc..e38fe27 100755
--- a/pae2xml.pl
+++ b/pae2xml.pl
@@ -63,6 +63,8 @@ $old_duration = $divisions;
 $old_type = "";
 $old_octave = 4;
 $BEAM = 0;
+@rhythmic_model = ();
+$rhythmic_model_index = 0;
 
 # Store all alterations already used in the current measure, so that e.g.
 # xCC also detects the second note as a Cis! Needs to be reset at the
@@ -269,6 +271,10 @@ sub parse_notes {
     } elsif ($notes =~ /^r(.*)$/) {  # End grace
       $notes = $1;
       $qq = 0;
+    } elsif ($notes =~ /^([0-9]\.?(?:\s?[0-9]+\.?)+)\s*(.*)$/) {  # Rhythmic model
+      ($model, $notes) = ($1, $2);
+      @rhythmic_model = parse_rhythmic_model ($1);
+      $rhythmic_model_index = -1;
     } elsif ($notes =~ /^\=(\d*)(\/.*)$/) {  # multi-measure rests
       $measrest = $1;
       $notes = $2;
@@ -504,8 +510,24 @@ sub parse_note {
 				</pitch>
 ';
   }
+  # We are using a rhythmic model, extract the correct duration
+  $this_duration = "";
+  $this_head = "";
+  if (($dur.$dot eq "") && scalar(@rhythmic_model)) {
+    if ($chord ne "^") {
+      $rhythmic_model_index = ($rhythmic_model_index +1 ) % scalar(@rhythmic_model);
+    }
+    $this_duration = $rhythmic_model[$rhythmic_model_index][0];
+    $this_head = $rhythmic_model[$rhythmic_model_index][1];
+  } elsif ($dur.$dot ne "" && scalar(@rhythmic_model)) {
+    # The rhythmic model ends when a new new rhythmic value appears!
+    @rhythmic_model = ();
+  }
   if ($gracecue ne "g") {
-    print OUT '				<duration>'.(duration($dur, $dot)*$normalnotes/$actualnotes).'</duration>
+    if (!$this_duration) {
+      $this_duration = duration ($dur, $dot);
+    }
+    print OUT '				<duration>'.($this_duration*$normalnotes/$actualnotes).'</duration>
 ';
   }
 
@@ -533,7 +555,10 @@ sub parse_note {
   if ($gracecue eq "g") {
     print OUT "					<type>eighth</type>\n";
   } else {
-    print OUT notehead ($dur, $dot);
+    if (!$this_head) {
+      $this_head = notehead ($dur, $dot);
+    }
+    print OUT $this_head;
   }
   # If we have an explicit accidental on the note, print the <accidental> tag
   print OUT accidental_explicit ($acc);
@@ -632,20 +657,56 @@ sub accidental_explicit {
   }
 }
 
+sub raw_notehead {
+  my ($duration, $dots) = @_;
+  my %du=("0", "long", "9", "breve", "1", "whole", "2", "half", "4", "quarter",
+          "8", "eighth", "6", "16th", "3", "32nd", "5", "64th", "7", "128th");
+  if ($duration && $du{$duration}) {
+    my $res = "				<type>$du{$duration}</type>\n";
+    $res .= repeat ("				<dot/>\n", length ($dots));
+    return $res;
+  }
+}
 sub notehead {
   my ($duration, $dots) = @_;
   if ($duration.$dots ne "") {
-    my %du=("0", "long", "9", "breve", "1", "whole", "2", "half", "4", "quarter",
-            "8", "eighth", "6", "16th", "3", "32nd", "5", "64th", "7", "128th");
-    my $res = "				<type>$du{$duration}</type>\n";
-    $res .= repeat ("					<dot/>\n", length ($dots));
-    $old_type = $res;
+    my $head = raw_notehead ($duration, $dots);
+    $old_type = $head if $head;
   }
   return $old_type;
 }
 
+sub parse_rhythmic_model {
+  (my $model) = @_;
+  my @m = ();
+  while ($model =~ s/^([0-9])\s*(\.?)\s*([0-9\.\s]*)$/$3/) {
+    my ($this_dur, $this_dots) = ($1, $2);
+    my $dur = raw_duration ($this_dur, $this_dots);
+    my $notehead = raw_notehead ($this_dur, $this_dots);
+    push @m, [$dur, $notehead];
+  }
+  return @m;
+}
 
 
+sub raw_duration {
+  my ($duration, $dots) = @_;
+  my %du=("1",4*$divisions,"2",2*$divisions,"4",$divisions,
+          "8",$divisions/2,"6",$divisions/4,"3",$divisions/8,
+          "5",$divisions/16,"7",$divisions/32,
+          "9",$divisions*8,"0",$divisions*16); # breve/long
+  my $res = $du{$duration};
+  if ($res) {
+    my $add = $res;
+    while ($dots ne "") {
+      $add /= 2;
+      $res += $add;
+      $dots =~ /^.(.*)$/gs;
+      $dots = $1;
+    }
+  }
+  return $res;
+}
 sub duration {
   my ($duration, $dots) = @_;
   if ($duration.$dots eq "7.") {
@@ -653,21 +714,10 @@ sub duration {
   }
 
   if ($duration.$dots ne "") {
-    my %du=("1",4*$divisions,"2",2*$divisions,"4",$divisions,
-            "8",$divisions/2,"6",$divisions/4,"3",$divisions/8,
-            "5",$divisions/16,"7",$divisions/32,
-            "9",$divisions*8,"0",$divisions*16); # breve/long
-    $old_duration = $du{$duration};
+    $old_duration = raw_duration ($duration, $dots);
     if ($old_duration eq "") {
       print_error("strange duration '$duration'\n");
     }
-    my $add = $old_duration;
-    while ($dots ne "") {
-      $add /= 2;
-      $old_duration += $add;
-      $dots =~ /^.(.*)$/gs;
-      $dots = $1;
-    }
   }
   return $old_duration;
 }
diff --git a/sample_files/Rhythmic-model.pae b/sample_files/Rhythmic-model.pae
new file mode 100644
index 0000000..813fb20
--- /dev/null
+++ b/sample_files/Rhythmic-model.pae
@@ -0,0 +1,7 @@
+Test Composer
+Test case for a rhythmic model
+1.1.1: S rhythmic model
+plain&easy: %G-2@6/8� '2.C/'8.68{AB''C}{DEF}/{GAB}{'''CDE}/8'CDEFGA//
+
+Test Library
+00000000
\ No newline at end of file
-- 
GitLab