<div>ties are a presentation-level issue, the underlying (sound) representation is a single note.  i suggest</div><div><br></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">Doc = [Note]</font></div>
<div><br></div><div>where Notes have fields for their measure location and duration.  then there&#39;s no issue with overlapping notes, and start/end times are easy to calculate.  ties can be calculated easily later for graphical layout by asking if durations overlap given boundaries (usually measure boundaries, but also measure centers).</div>
<div><br></div><div>i use a natural rhythm EDSL here:</div><a href="http://code.google.com/p/h1ccup/source/browse/trunk/theory/haskell/src/LiveCode.hs">http://code.google.com/p/h1ccup/source/browse/trunk/theory/haskell/src/LiveCode.hs</a><div>
<br></div><div>here&#39;s the rhythm-related part (doesn&#39;t handle varying tempo).  it lets you say things like:</div><div><div><br></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">Note {measure = 3, beat = 2, dur = Dotted $ Triplet Quarter}</font></div>
</div><div><br></div><div>------------------------</div><div><br></div><div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">{-# LANGUAGE ExistentialQuantification, ScopedTypeVariables, RecordWildCards, RankNTypes #-}</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">tempo     = 200 -- bpm</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">timeSig   = TimeSig { numBeats = 4</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">                    , unit     = Quarter</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">                    }</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">data DurBase = Whole | Half | Quarter | Eighth | Sixteenth | ThirtySecond deriving (Enum, Bounded, Show, Eq)</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">data ModDur = forall x. NoteDur x =&gt; Dotted x | Triplet DurBase</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br>
</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">data TimeSig = TimeSig {</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">      numBeats :: Int</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">    , unit     :: DurBase</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">    }</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br>
</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">data Note = forall x . NoteDur x =&gt; Note {</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">      midiNum :: Int -- 0-255</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">    , vel     :: Int -- 0-255</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">    , chan    :: Int -- 0-15</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">    , measure :: Integral a =&gt; a</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">    , beat    :: Int</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">    , subdiv  :: (Real a, Fractional a) =&gt; a -- % of beat</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">    , dur     :: x</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">    }</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">class NoteDur a where</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">    quarters :: (Real x, Fractional x) =&gt; a -&gt; x </font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">     </font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">    calcDurMS :: (Real x, Fractional x) =&gt; a -&gt; x</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">    calcDurMS d = 1000 * 60 * beats d / realToFrac tempo</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">    beats :: (Real x, Fractional x) =&gt; a -&gt; x   </font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">    beats d = uncurry (/) $ both quarters (d, unit timeSig)</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">        where both (f :: forall a b. (NoteDur a, Real b, Fractional b) =&gt; a -&gt; b) (x, y) = (f x, f y)</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">instance NoteDur DurBase where</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">    quarters x = z where Just z = lookup x . zip [minBound .. maxBound] $ map (fromRational . (2 ^^)) [2, 1 ..]</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">instance NoteDur ModDur where</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">    quarters (Dotted  x) = quarters x * 3 / 2</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">    quarters (Triplet x) = quarters x * 2 / 3</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br></font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">instance NoteDur Note where</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">     quarters Note{..} = quarters dur</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">calcStartMS :: (Real a, Fractional a) =&gt; Note -&gt; a</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">calcStartMS n = realToFrac (subdiv n + (fromIntegral $ (measure n * numBeats timeSig) + beat n)) * (calcDurMS $ unit timeSig)</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br>
</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">measureMS :: (Real a, Fractional a) =&gt; a</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">measureMS = calcStartMS Note { measure = 1</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">                             , beat    = 0</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">                             , subdiv  = 0</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">                             , midiNum = undefined</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">                             , vel     = undefined</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">                             , chan    = undefined</font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">                             , dur     = undefined :: DurBase -- ugh</font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">                             }</font></div></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><br></font></div><div>
<font class="Apple-style-span" face="&#39;courier new&#39;, monospace">-e</font></div>