
    3j                    p   d dl mZ d dlmZ d dlZd dlmZ d dlmZ d dlmZ d dlm	Z	 d dlm
Z
 d d	lmZ d d
lmZ d dlmZ  G d d      Z G d de      Z G d de      Z G d de      ZddZ G d de      Z G d de      Z G d dej,                        Zedk(  rd dlZ ej2                  e       yy)    )annotations)deepcopyN)duration)expressions)interval)note)pitch)stream)aligner)ornamentRecognizerc                  "    e Zd ZdZd Zd Zd Zy)OMRMidiFixerz
    Base class for future fixers
    changes is a list of changes associated with the midiStream and omrStream,
    not a list of lists
    c                .    || _         || _        || _        y N)changes
midiStream	omrStream)selfr   r   r   s       I/DATA/.local/lib/python3.12/site-packages/music21/alpha/analysis/fixer.py__init__zOMRMidiFixer.__init__   s    $"    c                     y r    )r   s    r   fixzOMRMidiFixer.fix$   s    r   c                n    t        |t        j                        rt        |t        j                        ryy)NTF)
isinstancer   Noter   midiRefomrRefs      r   checkIfNoteInstancez OMRMidiFixer.checkIfNoteInstance'   s#    gtyy)j.Kr   N)__name__
__module____qualname____doc__r   r   r!   r   r   r   r   r      s    
#
r   r   c                  "     e Zd ZdZ fdZ xZS )DeleteFixera  
    The DeleteFixer was designed to fit the specifications of the OpenScore project.
    The goal of the OpenScore project is to open-source music with open source software
    (like music21!). OpenScore will use a combination of computer and human power
    to digitize classical music scores and put them in the public domain. One idea is
    that software can identify wrong recognized notes in a scanned score and mark or
    delete the entire measure that that note is in and pass it off to a human corrector to
    re-transcribe the entire measure. The DeleteFixer could be the computer power in
    this method of score correction that OpenScore is using.

    CAUTION: this does really weird things still.
    c                Z   t         |           | j                  D ]  \  }}}| j                  ||      du rt	        |t
        j                        r|t
        j                  j                  k(  rT|j                  t        j                        }| j                  j                  |        y )NF)superr   r   r!   r   r   	ChangeOpsNoChangegetContextByClassr
   Measurer   remove)r   r   r    opm	__class__s        r   r   zDeleteFixer.fix9   s    %)\\!Wfb''8EA "g//0R7;L;L;U;U5U((8ANN!!!$ &2r   )r"   r#   r$   r%   r   __classcell__r1   s   @r   r'   r'   ,   s    % %r   r'   c                  N     e Zd ZdZ fdZd Zd Zd Zd Zd Z	d Z
d
d	Z xZS )EnharmonicFixera/  
    Fixes incorrectly spelled enharmonics
    initialized with self.changes -- a list of tuples in this form:
    (MIDIReference, OMRReference, op)
    MIDIReference and OMRReference are actual note/rest/chord object in some stream
    op is a ChangeOp that relates the two references

    TEST 1, no changes in OMR stream

    >>> omrStream1 = stream.Stream()
    >>> midiStream1 = stream.Stream()

    >>> omrNote1 = note.Note('A#4')
    >>> omrNote2 = note.Note('A#4')
    >>> midiNote1 = note.Note('B-4')
    >>> midiNote2 = note.Note('B-4')

    >>> omrStream1.append([omrNote1, omrNote2])
    >>> midiStream1.append([midiNote1, midiNote2])
    >>> subOp = alpha.analysis.aligner.ChangeOps.Substitution

    >>> ct1 = (midiNote1, omrNote1, subOp)
    >>> ct2 = (midiNote2, omrNote2, subOp)
    >>> changes1 = [ct1, ct2]

    >>> fixer1 = alpha.analysis.fixer.EnharmonicFixer(changes1, None, None)
    >>> fixer1.fix()
    >>> omrStream1[0]
    <music21.note.Note A#>
    >>> omrStream1[1]
    <music21.note.Note A#>

    TEST 2, no changes in OMR stream

    >>> omrStream2 = stream.Stream()
    >>> midiStream2 = stream.Stream()

    >>> omr2Note1 = note.Note('A#4')
    >>> omr2Note2 = note.Note('A#4')
    >>> midi2Note1 = note.Note('A#4')
    >>> midi2Note2 = note.Note('A#4')

    >>> omrStream2.append([omr2Note1, omr2Note2])
    >>> midiStream2.append([midi2Note1, midi2Note2])
    >>> ncOp = alpha.analysis.aligner.ChangeOps.NoChange

    >>> ct2_1 = (midi2Note1, omr2Note1, ncOp)
    >>> ct2_2 = (midi2Note2, omr2Note2, ncOp)
    >>> changes2 = [ct2_1, ct2_2]

    >>> fixer2 = alpha.analysis.fixer.EnharmonicFixer(changes2, None, None)
    >>> fixer2.fix()
    >>> omrStream2[0]
    <music21.note.Note A#>
    >>> omrStream1[1]
    <music21.note.Note A#>

    TEST 3 (case 1)

    >>> midiNote3 = note.Note('A4')
    >>> omrNote3 = note.Note('An4')

    >>> subOp = alpha.analysis.aligner.ChangeOps.Substitution

    >>> ct3 = (midiNote3, omrNote3, subOp)
    >>> changes3 = [ct3]
    >>> omrNote3.pitch.accidental
    <music21.pitch.Accidental natural>
    >>> fixer3 = alpha.analysis.fixer.EnharmonicFixer(changes3, None, None)
    >>> fixer3.fix()
    >>> omrNote3.pitch.accidental

    TEST 4 (case 2-1) e.g MIDI = g#, ground truth = a-, OMR = an

    >>> midiNote4 = note.Note('G#4')
    >>> omrNote4 = note.Note('An4')

    >>> subOp = alpha.analysis.aligner.ChangeOps.Substitution

    >>> ct4 = (midiNote4, omrNote4, subOp)
    >>> changes4 = [ct4]
    >>> omrNote4.pitch.accidental
    <music21.pitch.Accidental natural>
    >>> fixer4 = alpha.analysis.fixer.EnharmonicFixer(changes4, None, None)
    >>> fixer4.fix()
    >>> omrNote4.pitch.accidental
    <music21.pitch.Accidental flat>

    TEST 5 (case 2-2) e.g midi = g-, gt = f#, omr = fn

    >>> midiNote5 = note.Note('G-4')
    >>> omrNote5 = note.Note('Fn4')

    >>> subOp = alpha.analysis.aligner.ChangeOps.Substitution

    >>> ct5 = (midiNote5, omrNote5, subOp)
    >>> changes5 = [ct5]
    >>> omrNote5.pitch.accidental
    <music21.pitch.Accidental natural>
    >>> fixer5 = alpha.analysis.fixer.EnharmonicFixer(changes5, None, None)
    >>> fixer5.fix()
    >>> omrNote5.pitch.accidental
    <music21.pitch.Accidental sharp>

    TEST 6.1 (case 3) e.g. midi = g#, gt = g#, omr = gn or omr = g-

    >>> midiNote6_1 = note.Note('G#4')
    >>> midiNote6_2 = note.Note('G#4')
    >>> omrNote6_1 = note.Note('Gn4')
    >>> omrNote6_2 = note.Note('G-4')

    >>> subOp6_1 = alpha.analysis.aligner.ChangeOps.Substitution
    >>> subOp6_2 = alpha.analysis.aligner.ChangeOps.Substitution
    >>> ct6_1 = (midiNote6_1, omrNote6_1, subOp6_1)
    >>> ct6_2 = (midiNote6_2, omrNote6_2, subOp6_2)
    >>> changes6 = [ct6_1, ct6_2]

    >>> omrNote6_1.pitch.accidental
    <music21.pitch.Accidental natural>
    >>> omrNote6_2.pitch.accidental
    <music21.pitch.Accidental flat>
    >>> fixer6 = alpha.analysis.fixer.EnharmonicFixer(changes6, None, None)
    >>> fixer6.fix()
    >>> omrNote6_1.pitch.accidental
    <music21.pitch.Accidental sharp>
    >>> omrNote6_2.pitch.accidental
    <music21.pitch.Accidental sharp>

    TEST 7 (case 4-1, 4-2) notes are on different step, off by an interval of 2:
    * 4-1: e.g. midi = g#, gt = a-, omr = a#
    * 4-2: e.g. midi = a-, gt = g#, omr = g-

    >>> midiNote7_1 = note.Note('G#4')
    >>> omrNote7_1 = note.Note('A#4')

    >>> midiNote7_2 = note.Note('A-4')
    >>> omrNote7_2 = note.Note('G-4')

    >>> subOp7_1 = alpha.analysis.aligner.ChangeOps.Substitution
    >>> subOp7_2 = alpha.analysis.aligner.ChangeOps.Substitution
    >>> ct7_1 = (midiNote7_1, omrNote7_1, subOp7_1)
    >>> ct7_2 = (midiNote7_2, omrNote7_2, subOp7_2)
    >>> changes7 = [ct7_1, ct7_2]

    >>> omrNote7_1.pitch.accidental
    <music21.pitch.Accidental sharp>
    >>> omrNote7_2.pitch.accidental
    <music21.pitch.Accidental flat>
    >>> fixer7 = alpha.analysis.fixer.EnharmonicFixer(changes7, None, None)
    >>> fixer7.fix()

    >>> omrNote7_1.pitch.step
    'A'
    >>> omrNote7_1.pitch.accidental
    <music21.pitch.Accidental flat>

    >>> omrNote7_2.pitch.step
    'G'
    >>> omrNote7_2.pitch.accidental
    <music21.pitch.Accidental sharp>
    c                n   t         |           | j                  D ]  \  }}}d|j                  _        | j                  ||      du r.t        |t        j                        r|t        j                  j                  k(  rf| j                  ||d      r{| j                  |      r6| j                  ||      rd|j                  _        |j                  |j                  kD  ro|j                  j                  t!        j"                  d            j                  |j                        st        j$                  d      |j                  _        9|j                  |j                  k  sT|j                  j                  t!        j"                  d            j                  |j                        st        j$                  d	      |j                  _        | j'                  |      r]| j)                  ||      rK| j+                  |      r'|j                  j                  |j                  _        d|j                  _        1| j'                  |      r| j-                  ||      rn|j                  |j                  kD  r|j                  j                  t        j$                  d	      k(  s|j                  j                  t!        j"                  d
            j                  |j                        st        j$                  d      |j                  _        |j                  |j                  k  s'|j                  j                  t        j$                  d      k(  sU|j                  j                  t!        j"                  d            j                  |j                        st        j$                  d	      |j                  _        |j                  |j                  k7  s| j'                  |      s| j)                  ||      s|j                  |_         y)z[
        Fixes the enharmonic errors in the OMR by changing the pitch of the note.
        blackF   )setIntNflat   sharp   )r)   r   r   stylecolorr!   r   r   r*   r+   intervalTooBig	hasNatAccisEnharmonicr	   
accidental	transposer   Interval
AccidentalhasSharpFlatAccstepEqhasAcc	stepNotEq)r   r   r    r/   r1   s       r   r   zEnharmonicFixer.fix   s    	%)\\!Wfb!(FLL''8EA "g//0R7;L;L;U;U5U ""7F1"=~~f%$$Wf5.2FLL+ ||gmm3!<<11(2C2CB2G 44@L4OP6;6F6Fv6NFLL3
  5!<<11(2C2CA2F 44@L4OP6;6F6Fw6OFLL3 %%f-$++gv2N;;v&.5mm.F.FFLL+.2FLL+%%f-$..&2Q <<'--/||..%2B2B72KK!<<11(2C2CB2G 44@L4OP6;6F6Fv6NFLL3 \\GMM1||..%2B2B62JJ!<<11(2C2CA2F 44@L4OP6;6F6Fw6OFLL3 ,,'--/,,W5GV4&}}C &2r   c                L    |j                   j                  |j                         S )zZ
        Returns True if the omrRef is enharmonic to the midiRef, False otherwise
        )r	   rD   r   s      r   rD   zEnharmonicFixer.isEnharmonic1  s     }}))&,,77r   c                2    |j                   j                  duS )zO
        Returns True if the omrRef has an accidental, False otherwise
        N)r	   rE   r   r    s     r   rK   zEnharmonicFixer.hasAcc7  s     ||&&d22r   c                n    | j                  |      xr# |j                  j                  j                  dk(  S )zV
        Returns True if the omrRef has a natural accidental, False otherwise
        naturalrK   r	   rE   namerO   s     r   rC   zEnharmonicFixer.hasNatAcc=  -     {{6"Pv||'>'>'C'Cy'PPr   c                n    | j                  |      xr# |j                  j                  j                  dk7  S )z\
        Returns True if the omrRef has a sharp or flat accidental, False otherwise
        rQ   rR   rO   s     r   rI   zEnharmonicFixer.hasSharpFlatAccC  rT   r   c                4    |j                   |j                   k(  S )zF
        Returns True if the steps are equal, False otherwise
        stepr   s      r   rJ   zEnharmonicFixer.stepEqI       ||v{{**r   c                4    |j                   |j                   k7  S )zJ
        Returns True if the steps are not equal, False otherwise
        rW   r   s      r   rL   zEnharmonicFixer.stepNotEqO  rY   r   c                L    t        j                  ||      j                  |kD  ryy)z
        Returns True if the intervalClass between the two notes is greater than setInt.

        Note that intervalClass and not actual interval size is used.
        TF)r   notesToChromaticintervalClass)r   r   r    r9   s       r   rB   zEnharmonicFixer.intervalTooBigU  s%     $$Wf5CCfLr   )r8   )r"   r#   r$   r%   r   rD   rK   rC   rI   rJ   rL   rB   r2   r3   s   @r   r5   r5   F   s6    `BF-R83QQ++r   r5   c                  T     e Zd ZdZd
 fd	ZddZdd	 	 	 	 	 ddZddddd	Z xZS )OrnamentFixera<  
    Fixes missed ornaments in OMR using expanded ornaments in MIDI
    initialized with self.changes -- a list of tuples in this form:
    (MIDIReference, OMRReference, op)
    MIDIReference and OMRReference are actual note/rest/chord object in some stream
    op is a ChangeOp that relates the two references

    recognizers can be a single recognizer or list of recognizers,
    but self.recognizers is always a list.
    recognizers take in stream of busy notes and optional stream of simple note(s)
    and return False or an instance of the ornament recognized
    c                    t         |   |||       t        |t              s|g| _        || _        y || _        || _        y r   )r)   r   r   listrecognizersmarkChangeColor)r   r   r   r   rb   rc   r1   s         r   r   zOrnamentFixer.__init__l  sD    *i8+t, +}D  /  +D.r   c                X    | j                   D ]  }|j                  ||      }|s|c S  y)a?  
        Finds an ornament in busyNotes based from simpleNote
        using provided recognizers.

        :param busyNotes: stream of notes
        :param simpleNotes: stream of notes

        Tries the recognizers in order, returning the result of the first
        one to successfully recognize an ornament.
        )simpleNotesN)rb   	recognize)r   	busyNotesre   rornaments        r   findOrnamentzOrnamentFixer.findOrnamentt  s3     !!A{{9+{FH " r   Fshowc                   t        d |j                  D              s9|j                  j                  |       |r| j                  |j                  _        yy)a  
        Adds the ornament to the selectedNote when selectedNote has no ornaments already.

        * selectedNote: Note.note to add ornament to
        * ornament: Expressions.ornament to add to note
        * show: True when note should be colored blue

        Returns True if added successfully, or False if there was already an
        ornament on the note and it wasn't added.
        c              3  P   K   | ]  }t        |t        j                           y wr   )r   r   Ornament).0es     r   	<genexpr>z,OrnamentFixer.addOrnament.<locals>.<genexpr>  s      Y@X1:a!5!56@Xs   $&TF)anyr   appendrc   r@   rA   )r   selectedNoteri   rl   s       r   addOrnamentzOrnamentFixer.addOrnament  sI     Y@X@XYY$$++H5+/+?+?""(r   T)rl   inPlacec               (   | j                   }d}g }g }|s]t        | j                        }t        | j                        }t	        j
                  ||      }|j                          |j                   }|D ]  \  }	}
}|t        j                  j                  u s|t        j                  j                  u r@|
|v rEt        |	|
j                        }d}|D ]
  }||v sd} n |ro| j                  |t        |
      g      }|s||z  }|j                  |
       | j                  |
||        |r4| j                  j                          | j                  j                          |s-|+t!        |j                   |j"                  |j$                        S y)z
        Corrects missed ornaments in omrStream according to midiStream
        :param show: Whether to show results
        :param inPlace: Whether to make changes to own omr stream or
        return a new OrnamentFixer with changes
        NsourceStreamtargetStreamFTrk   )r   r   r   r   r   StreamAligneralignr*   r+   DeletiongetNotesWithinDurationr   rj   rt   rv   rl   
TrillFixerr{   rz   )r   rl   rw   r   saomrNotesLabeledOrnament midiNotesAlreadyFixedForOrnamentomrStreamCopymidiStreamCopymidiNoteRef
omrNoteRefchangerg   busyNoteAlreadyUsedbusyNoteornamentFounds                   r   r   zOrnamentFixer.fix  s    ,,)-"$+-($T^^4M%doo6N&&MP^_BHHJjjG/6+KV**333vARARA[A[7[ 44.{J<O<OPI"'%??*.' & # !--i(::N9OPM 0I=0'..z:  ] F1 074 NN!OO  "2>bjj"//2??KKr   )blue)returnzexpressions.Ornament | None)ru   z	note.Noteri   zexpressions.Ornamentr   bool)r   zOMRMidiFixer | None)	r"   r#   r$   r%   r   rj   rv   r   r2   r3   s   @r   r_   r_   _  sG    /* 	"+2 $(	,   5 5r   r_   c                (   |r|| _         t        j                         }| j                  j                  |j                  kD  r|S |j                  | j                  j                  z
  }| j                  dd      }|j                  t        |              |r}||j                  j                  k\  rd|}|j                  dd      }||j                  j                  z  }|j                  t        |             |r||j                  j                  k\  rd|S )a  
    Returns maximal stream of deepcopies of notes, rests, and chords following
    (and including) startingNote which occupy no more than totalDuration combined.

    * startingGeneralNote is a GeneralNote (could be a note, rest, or chord)
    * totalDuration is a duration
    * referenceStream is optionally a stream which the startingGeneralNote's
        active site should be set to when provided
    GeneralNoteT)activeSiteOnly)
activeSiter
   Streamr   quarterLengthnextrt   r   )startingGeneralNotetotalDurationreferenceStreamnotesdurationQlLeftnextGeneralNotecurrentGeneralNotes          r   r   r     s     )8&MMOE ##11M4O4OO"003F3O3O3]3]]N)..}T.RO	LL-./
n0H0H0V0VV,,11-PT1U,55CCCX012 n0H0H0V0VV Lr   c                  "     e Zd ZdZ fdZ xZS )r   a9  
    Fixes missed trills in OMR using expanded ornaments in MIDI.
    initialized with self.changes -- a list of tuples in this form:
    (MIDIReference, OMRReference, op)
    MIDIReference and OMRReference are actual note/rest/chord object in some stream
    op is a ChangeOp that relates the two references
    c                    t        j                         }t        j                         }d|_        ||g}t        |   ||||       y )NT)r   TrillRecognizercheckNachschlagr)   r   )r   r   r   r   defaultOrnamentRecognizernachschlagOrnamentRecognizerrb   r1   s          r   r   zTrillFixer.__init__  sH    $6$F$F$H!'9'I'I'K$7;$402NO*iEr   r"   r#   r$   r%   r   r2   r3   s   @r   r   r     s    F Fr   r   c                  "     e Zd ZdZ fdZ xZS )	TurnFixeraG  
    Fixes missed turns/inverted turns in OMR using expanded ornaments in MIDI.
    initialized with self.changes -- a list of tuples in this form:
    (MIDIReference, OMRReference, op)
    MIDIReference and OMRReference are actual note/rest/chord object in some stream
    op is a ChangeOp that relates the two references
    c                R    t        j                         }t        |   ||||       y r   )r   TurnRecognizerr)   r   )r   r   r   r   
recognizerr1   s        r   r   zTurnFixer.__init__	  s$    '668
*iDr   r   r3   s   @r   r   r     s    E Er   r   c                  0    e Zd Zd Zd Zd Zd Zd Zd Zy)Testc                2    ddl m}  || t                      y )Nr   )testCopyAll)music21.test.commonTestr   globals)r   r   s     r   testCopyAndDeepcopyzTest.testCopyAndDeepcopy  s    7D')$r   c                p   t        |      t        |      k7  rd}d|fS t        t        |            D ]  }t        ||   j                        t        ||   j                        k7  r,d| d||   j                   d||   j                   d}d|fc S ||   ||   k7  sld| d||    d||    d}d|fc S  y	)
a  
        Returns a tuple of (bool, reason) where the first element is
        whether the measures are equal and the second (`reason`) is a string
        explaining why they are unequal.

        Reason is an empty string if the measures are equal.
        znot equal lengthFzExpressions z
 unequal (z != )z	Elements z are unequal ()T )lenranger   )r   m1m2msgis        r   measuresEqualzTest.measuresEqual  s     r7c"g$C#:s2wA2a5$$%RU->->)??$QCz"Q%2C2C1DDAIZIZH[[\]cz!!u1~!!N2a5'beWAFcz!   r   c                6   |d   }|d   }|d   }|d   }t        j                  ||      }|j                          t        |      }d}	| j	                  | j                  ||j                        d   |	        ||j                  |j                  |j                        }
d}	| j	                  | j                  ||j                        d   |	       |
j                  d	
      }d}	| j                  ||j                        \  }}| j	                  |||	z   |z          d}	| j                  ||
j                        \  }}| j	                  |||	z   |z          d}	| j                  |j                  |      \  }}| j	                  |||	z   |z          |
j                  d
      }| j                  ||       d}	| j                  ||
j                        \  }}| j	                  |||	z   |z          d}	| j                  ||      \  }}| j	                  |||	z   |z          y)a  
        testCase is a dictionary with the following keys

        returnDict = {
            'name': string,
            'midi': measure stream,
            'omr': measure stream,
            'expected': fixed measure stream,
        }

        testFixer is an OMRMidiFixer
        omrmidiexpectedrS   ry   z5Expect no changes from creating and aligning aligner.r   z&Expect no changes from creating fixer.F)rw   zB. Expect no changes to aligner source stream, but unequal because z=. Expect no changes to fixer omr stream, but unequal because z8. Appropriate changes in new fixer, but unequal because Tz<. Expect changes in fixer's omr stream, but unequal because z=. Expect changes in original omr stream, but unequal because N)r   r|   r}   r   
assertTruer   rz   r   r{   r   r   assertIsNone)r   testCase	testFixerr   r   expectedOmrtestingNamer   omrCopyassertionCheckfixernotInPlaceResultisEqualreasonfixerInPlaceResults                  r   checkFixerHelperzTest.checkFixerHelper&  s    uoz*v& ""$G

3-P**7BOODQGX "**boorGA**7BOODQGX !99U93],,WbooF~!=!FGX,,WeooF~!=!FGS,,-=-G-GU~!=!FG #YYtY4,k:W,,[%//J~!=!FGX,,[#>~!=!FGr   c                   t        j                  d      }t        j                  d      |_        t	        j
                         }|j                  |       t        |t        j                  d            }| j                  |t        j
                         | j                  |gt        |j                        d       t        |t        j                  d            }| j                  |gt        |j                        d       t        |t        j                  d            }| j                  g t        |j                        d       t	        j                         }t        j                  d      }t        j                  d      |_        t        j                  d	      }t        j                  d      |_        |j                  |||g       t        |t        j                  d            }| j                  |gt        |j                        d       t        |t        j                  d            }| j                  |||gt        |j                        d
       t        |t        j                  d            }| j                  |||gt        |j                        d       t        |t        j                  d            }| j                  ||gt        |j                        d       t        |t        j                  d            }| j                  ||gt        |j                        d       t        |t        j                  d      |      }| j                  |gt        |j                        d       t	        j                         }d|_        t        j                         }t        j                  d      |_        |j                  ||g       t        |t        j                  d            }d}	| j                  ||gt        |j                        |	       t        |t        j                  d      |      }| j                  |||gt        |j                        d       y )NCquarterz$starting note occupies full durationhalfz'starting note occupies partial durationeighthzstarting note too longDEzall notes fill up full durationwholez"all notes fill up partial durationg      ?z some notes fill up full durationg      ?z#some notes fill up partial duration)r   z(partial fill up from reference stream m1m3z#note and rest fill up full durationz fill up from reference stream m2)r   r   r   Durationr
   r   rt   r   assertIsInstanceassertListEqualra   r   r-   idRestnotesAndRests)
r   n1r   resultr   n2n3r   r1r   s
             r   testGetNotesWithinDurationzTest.testGetNotesWithinDuration_  sN   YYs^''	2]]_
		"'H,=,=i,HIffmm4bT4#57]^'H,=,=f,EFbT4#57`a'H,=,=h,GHRfll!35MN^^YYs^''1YYs^''1
		2r2,'H,=,=i,HIbT4#57]^'H,=,=f,EFb"b\4+=?`a'H,=,=g,FGb"b\4+=?cd'H,=,=c,BCb"XtFLL'9;]^'H,=,=d,CDb"XtFLL'9;`a (H,=,=f,EWYZbT4#57ab^^YY[''	2
		2r('H,=,=f,EF3b"XtF,@,@'A3G (H,=,=f,EWYZb"b\4+=?abr   c                    d }d }d }d }d } |        |        |        |        |       g}|D ]  }| j                  |t                y )Nc            
     .   t        j                  d      } t        j                  d      }t        j                  d      }| |_         t        j                  d      }||_         t        j                  d      }||_         ||t	        |      t	        |      g}t        j                  d      }t        j                  d      }| |_         t        j                  d      }||_         t        j                  d      }	||	_         |	|t	        |	      t	        |      t	        |	      t	        |      t	        |	      t	        |      g}
t        j                         }|j                  |       |j                  |
       t        j                         }|j                  ||g       t        j                         }t	        |      }t        j                         }t        j                  d      |_        |j                  |_        |j                  j                  |       t	        |      }t        j                         }t        j                  d	      |_        |j                  |_        |j                  j                  |       |j                  ||g       d
|||d}|S )  
            Returns a dictionary with the following keys

            returnDict = {
                'name': string,
                'midi': measure stream,
                'omr': measure stream,
                'expected': measure stream,
            }
            r         ?GAg      ?B3r   zm-2M2zDouble Trill MeasurerS   r   r   r   )r   r   r   r   r   r
   r-   rt   r   Trillr   rG   sizer   )noteDurationtrill1NoteDurationn0r   r   trill1trill2NoteDurationr   n4n5trill2midiMeasure
omrMeasureexpectedFixedOmrMeasuren0WithTrilln0Trilln1WithTrilln1Trill
returnDicts                      r   createDoubleTrillMeasurez5Test.testTrillFixer.<locals>.createDoubleTrillMeasure  s    $,,Y7L "*!2!23!73B&BK3B,BK3B,BK"hrlHRL9F "*!2!25!94B&BK4B,BK3B,BK"hrlHRLrlHRL(2,NF !..*Kv&v&)Jr2h'&,nn&6#"2,K!'')G#,,U3GL$6$D$DG!##**73"2,K!'')G#,,T2GL$6$D$DG!##**73#**K+EF /#!3	J r   c                    t        j                  d      } t        j                  d      }| |_         t        j                  d      }t        j                  d      |_         t        j                  d      }t        j                  d      |_         ||t	        |      t	        |      g}t        j                         }|j                  |       t        j                         }|j                  |       d||t	        |      d}|S )r   r   r   r   r   z*Non-Trill Measure Wrong Oscillate Intervalr   r   r   r   r   r   r
   r-   rt   r   r   r   r   nonTrillr   r   r   s           r   createWrongTrillMeasurez4Test.testTrillFixer.<locals>.createWrongTrillMeasure  s     $,,Y7L3B&BK3B"++C0BK3B"++C0BKBhrl;H ..*Kx()Jb! E#!$Z0	J r   c                    t        j                  d      } t        j                  d      }| |_         t        j                  d      }t        j                  d      |_         t        j                  d      }t        j                  d      |_         ||t	        |      t	        |      g}t        j                         }|j                  |       t        j                         }|j                  |       d||t	        |      d}|S )r   r   r   r   r   r   zNon-Trill Measure Wrong Notesr   r   r   s           r   createNonTrillMeasurez2Test.testTrillFixer.<locals>.createNonTrillMeasure  s     $,,Y7L3B&BK3B"++C0BK3B"++C0BKBhrl;H ..*Kx()Jb! 8#!$Z0	J r   c                 X   t        j                  d      } t        j                  d      }t        j                  d      }| |_         t        j                  d      }||_         t        j                  d      }||_         t        j                  d      }||_         ||t	        |      t	        |      g}t	        |      t	        |      t	        |      |g}||z   }t        j                         }	|	j                  |       t        j                         }
|
j                  |       t        j                         }d|_
        |j                  |_        t        j                         }t	        |      }|j                  j                  t	        |             |j                  |       d|	|
|d}|S )	r   r         ?r   Fr   TzNachschlag Trillr   )r   r   r   r   r   r
   r-   rt   r   r   
nachschlagr   )r   trillDurationr   tn1tn2tn3firstHalfTrillsecondHalfTrillexpandedTrillr   r   nachschlagTrillr   noteWithTrillr   s                  r   createNachschlagTrillMeasurez9Test.testTrillFixer.<locals>.createNachschlagTrillMeasure  s`    $,,Y7L$--d3M3B&BK))C.C(CL))C.C(CL))C.C(CL!3x}EN'}hsmXc]CPO*_<M ..*K}-)Jb!)//1O)-O&,9,G,GO)&,nn&6#$RLM%%,,Xo-FG#**=9 +#!3	J r   c                 f   t        j                  d      } t        j                  d      }t        j                  d      }| |_         t	        j
                         }|j                  |_        |j                  j                  |       t        j                  d      }||_         t        j                  d      }||_         ||t        |      t        |      g}t        j                         }|j                  |       t        j                         }|j                  |       d||t        |      d}	|	S )r   r   r  r  r   zOMR with Trill Notationr   )r   r   r   r   r   r   r   rt   r   r
   r-   )
r   r  r  trillr	  r
  r  r   r   r   s
             r   createMeasureWithTrillAlreadyz:Test.testTrillFixer.<locals>.createMeasureWithTrillAlreadyM  s     $,,Y7L$--d3M IIcNM%1M"%%'E"/"="=E%%,,U3))C.C(CL))C.C(CL #x}hsmDM ..*K}-)Jm, 2#!$Z0	J r   )r   r   )r   r   r  r  r  r  testConditionsr   s           r   testTrillFixerzTest.testTrillFixer  sc    <	|!	F"	H/	b%	P %&#%!#(*)+
 'H!!(J7 'r   c                x    d }d }d } |        |        |       g}|D ]  }| j                  |t                y )Nc                 d   t        j                         } t        j                  d      }t	        j
                  d      |_        | j                  |       t        j                         }t        |      }|j                  j                  t        j                                |j                  |       t        j                         }t        j                  d      t        j                  d      t        j                  d      t        j                  d      g}|j                  |       d|| |d}|S )r   r  r   r   r   zSingle Turn Measurer   )r
   r-   r   r   r   r   rt   r   r   r   Turn)r   omrNoter   expectedOmrNoter   turnr   s          r   createSingleTurnMeasurez3Test.testTurnFixer.<locals>.createSingleTurnMeasure  s      )JiinG'009Gg&&,mmo#&w/O''..{/?/?/AB#**?; ..*KIIcNDIIcNDIIcNDIIcNSDt$ .#!3	J r   c                 X   t        j                         } t        j                  d      }t        j                  d      }t        j                  d      }| j	                  |||g       t        j
                         }t        |      }|j                  j	                  t        j                                t        |      }|j                  j	                  t        j                                |j	                  |t        |      |g       t        j                         }t        j                  d      t        j                  d      t        j                  d      t        j                  d      g}t        j                  d      t        j                  d      t        j                  d      t        j                  d      g}	|D ]  }
t        j                  d      |
_	         |	D ]  }
t        j                  d      |
_	         |j	                  g |t        |      |	       d	|| |d
}|S )r   zB-r   r   C5zG#zA#Br   z>Inverted turns with accidentals separated By non-ornament Noter   )r
   r-   r   r   rt   r   r   r   InvertedTurnr   r   )r   omrNote1
middleNoteomrNote2r   expectOmrNote1expectOmrNote2r   turn1turn2nr   s               r   createDoubleInvertedTurnMeasurez;Test.testTurnFixer.<locals>.createDoubleInvertedTurnMeasure  s     )JyyH3JyyHxX>? '-mmo#%h/N&&--k.F.F.HI%h/N&&--k.F.F.HI#**NHZ<PR`+ab ..*KYYs^TYYt_diiotyyQUWEYYt_diiotyy~tyyQUWE%..s3
 %..s3
 EE(<EuEF Y#!3	J r   c                    t        j                         } t        j                  d      }t	        j
                  d      |_        | j                  |       t        j                         }t        j                  d      t        j                  d      t        j                  d      t        j                  d      g}|j                  |       d|| t        |       d}|S )r   r   r   r   r   r  zNon-Turn Measurer   )r
   r-   r   r   r   r   rt   r   )r   r  r   r  r   s        r   createNonTurnMeasurez0Test.testTurnFixer.<locals>.createNonTurnMeasure  s      )JiinG'009Gg& ..*KIIcNDIIcNDIIcNDIIcNSDt$ +#!$Z0	J r   )r   r   )r   r  r*  r,  r  r   s         r   testTurnFixerzTest.testTurnFixer  sJ    	B(	T	8 239;.02 'H!!(I6 'r   N)	r"   r#   r$   r   r   r   r   r  r-  r   r   r   r   r     s'    %(7Hr5cng8Rm7r   r   __main__r   )
__future__r   copyr   unittestmusic21r   r   r   r   r	   r
   music21.alpha.analysisr   r   r   r'   r5   r_   r   r   r   TestCaser   r"   mainTestr   r   r   <module>r6     s    #         * 5 &%, %4Wl WrqL qf@F F
E 
E_78 _7D zGT r   