
    rh]                    6   S SK Jr  S SKJr  S SKrS SKJr  S SKJr  S SK	J
r
  S SK	Jr  S SK	Jr  S S	K	Jr  S S
K	Jr   " S S5      r " S S\5      r " S S\5      r " S S5      r " S S\R&                  5      rS r\S:X  a  S SK	r	\	R.                  " \5        gg)    )annotations)deepcopyN)opFrac)OffsetQL)duration)expressions)interval)note)streamc                  >    \ rS rSrSr SS jr S     SS jjrSrg)	OrnamentRecognizer   z
An object to identify if a stream of notes is an expanded ornament.
Busy notes refer to the expanded ornament notes.
Simple note(s) refer to the base note of ornament which is often shown
with the ornament marking on it.
Nc                T    [        U5      nU R                  X5      n[        XC-  5      $ )z
Finds the quarter length value for each ornament note
assuming busy notes all are an expanded ornament.

Expanded ornament total duration is time of all busy notes combined or
duration of the first note in simpleNotes when provided.
)lencalculateOrnamentTotalQlr   )self	busyNotessimpleNotesnumOrnamentNotestotalDurationQuarterLengths        c/home/james-whalen/.local/lib/python3.13/site-packages/music21/alpha/analysis/ornamentRecognizer.pycalculateOrnamentNoteQl*OrnamentRecognizer.calculateOrnamentNoteQl    s.     y>%)%B%B9%Z"0CDD    c                    U(       a  US   R                   R                  $ SnU H%  nU[        UR                   R                  5      -  nM'     [        U5      $ )z
Returns total length of trill assuming busy notes are all an expanded trill.
This is either the time of all busy notes combined or
duration of the first note in simpleNotes when provided.
r   g        )r   quarterLengthfloatr   )r   r   r   trillQlns        r   r   +OrnamentRecognizer.calculateOrnamentTotalQl0   sO     q>**888AuQZZ5566G gr    N)r   zlist[note.GeneralNote]r   zlist[note.GeneralNote] | Nonereturnr   )__name__
__module____qualname____firstlineno____doc__r   r   __static_attributes__r!   r   r   r   r      s=     E& 48) 1 
	 r   r   c                  0    \ rS rSrSrSS jrSS	S jjrSrg)
TrillRecognizerB   aG  
An object to identify if a stream of ("busy") notes is an expanded trill.

By default, does not consider Nachschlag trills, but setting checkNachschlag will consider.

When optional stream of simpleNotes are provided, considers if busyNotes are
an expansion of a trill which would be denoted on the first note in simpleNotes.
c                ,    Xl         SU l        SU l        g )N      )checkNachschlagacceptableIntervalminimumLengthForNachschlag)r   r0   s     r   __init__TrillRecognizer.__init__K   s    ."#*+'r   Nc                   [        U5      S::  a  gUS   nUS   nUR                  (       a  UR                  (       d  g[        UR                  R                  UR                  R                  -
  5      U R
                  :  a  gSnSn[        [        U5      5       Hj  nX   nUR                  (       d    gUS-  S:X  a  UR                  UR                  :w  a  Sn  O-US-  S:w  d  ML  UR                  UR                  :w  d  Mh  Sn  O   SnU(       a  OMU R                  (       d  g[        U5      U R                  :  n	U[        U5      S-  :  n
U	(       a
  U
(       a  SnOgU(       d  UR                  R                  UR                  R                  ::  a  [        R                  " 5       nO[        R                  " 5       nU R                  X5      Ul        U(       a  SUl        UR                  R                  b  UR                  R                  Ul        UR!                  U5        U$ US   nUR                  R                  UR                  R                  UR                  R                  4;  a  gUnUnUR                  R                  UR                  R                  :X  a  UnUnUR                  R                  UR                  R                  ::  a  [        R                  " 5       nO[        R                  " 5       nU R                  X5      Ul        U(       a  SUl        UR                  R                  b  UR                  R                  Ul        UR!                  U5        U$ )a  
Tries to identify the busy notes as a trill.

When simple notes is provided, tries to identify busy notes
as the trill shortened by simple notes.
Currently only supports one simple note in simple notes.

Only when checkNachschlag is true, allows last few notes to break trill rules.

Trill interval size is interval between busy notes.

Returns: False if not possible or the Trill Expression
   Fr      T)r   isNoteabspitchmidir1   ranger0   r2   r   TrillInvertedTrillr   r   
nachschlag
accidentalresolveOrnamentalPitches)r   r   r   n1n2twoNoteOscillationinoteConsideringisNachschlaglengthOknotTooMuchNachschlagtrill
simpleNoteendNote	startNotes                  r   	recognizeTrillRecognizer.recognizeP   s    y>Q q\q\yy		rxx}}rxx}},-0G0GG!s9~&A'lO"))1uzo33rxx?%*"Q! 5 5 A%*" ' %%9~)H)HHH#$I(:#: 0#xx}}-#))+#113"&">">y"VE#' xx"".#%88#6#6 **2.L !^
   (FF	  BHHMM1GI ??7==#5#55%%'E--/E"::9R#E==##/&}}77E&&y1r   )r1   r0   r2   )Fr"   )r#   zbool | expressions.Trill)r$   r%   r&   r'   r(   r3   rN   r)   r!   r   r   r+   r+   B   s    ,
^ ^r   r+   c                  6    \ rS rSrS rSS jr S S	S jjrSrg)
TurnRecognizer   c                *   SU l         SU l        [        R                  " S5      [        R                  " S5      [        R                  " S5      [        R                  " S5      [        R                  " S5      [        R                  " S5      /U l        g )	Nr.      M2M-2m2m-2A2zA-2)r1   r2   r	   IntervalacceptableIntervals)r   s    r   r3   TurnRecognizer.__init__   sm    "#*+'d#X%6%6u%=d#X%6%6u%=d#X%6%6u%=$
 r   c                    XR                   ;   $ )z3
Returns whether that interval can occur in a turn
)r[   )r   intervalToChecks     r   isAcceptableInterval#TurnRecognizer.isAcceptableInterval   s     ":":::r   Nc                *   [        U5      S:w  a  gU(       aO  SnSnU H  nXER                  R                  -  nM     [        US   R                  R                  U-
  5      U:  a  gUS   R                  R
                  US   R                  R
                  :w  a  gU(       a5  US   R                  R
                  US   R                  R
                  :w  a  g[        R                  " US   US   S9nU R                  U5      (       d  g[        R                  " US   US   S9nU R                  U5      (       d  g[        R                  " US   US   S9nU R                  U5      (       d  gUR                  UR                  :w  a  gUR                  UR                  :X  a  gUR                  [        R                  " S	5      R                  :X  a  [        R                  " 5       n	O[        R                  " 5       n	U R                  X5      U	l        U	$ )
a  
Tries to identify the busy notes as a turn or inverted turn.

When simple notes is provided, tries to identify busy notes
as the turn shortened by simple notes.
Currently only supports one simple note in simple notes.

Turns and inverted turns have four notes separated by m2, M2, A2.

Turns:
start above base note
go down to base note,
go down again,
and go back up to base note

Inverted Turns:
start below base note
go up to base note,
go up again,
and go back down to base note

When going up or down, must go to the adjacent note name,
so A goes down to G, G#, G flat, G##, etc

Returns: False if not possible or the Turn/Inverted Turn Expression
   Fg?r   r7   r.   )	noteStartnoteEndr6   rV   )r   r   r   r9   r:   r;   r	   rZ   r_   	directionr   TurnInvertedTurnr   )
r   r   r   epstotalBusyNotesDurationr   firstIntervalsecondIntervalthirdIntervalturns
             r   rN   TurnRecognizer.recognize   s   @ y>QC%&"&***B*BB& ;q>**88;QQRUXX Q<""il&8&8&=&==;q>//44	!8J8J8O8OO !))IaL)TU,W((77!**Yq\9UV<X((88 ))IaL)TU,W((77 ""n&>&>>##}'>'>> ""h&7&7&>&H&HH##%D++-D!99)Qr   )r1   r[   r2   )r^   zinterval.Intervalr#   boolr"   )r#   z2bool | expressions.Turn | expressions.InvertedTurn)r$   r%   r&   r'   r3   r_   rN   r)   r!   r   r   rQ   rQ      s(    
; I 
8	I Ir   rQ   c                       \ rS rSr SS jrSrg)_TestConditioni  Nc                X    Xl         X l        X0l        X@l        XPl        X`l        Xpl        g r"   )namer   
isOrnamentr   ornamentSizerG   
isInverted)r   rs   r   rt   r   ru   rG   rv   s           r   r3   _TestCondition.__init__  s*     	"$&(($r   )r   rv   rG   rt   rs   ru   r   )NNFF)r$   r%   r&   r'   r3   r)   r!   r   r   rq   rq     s     MR
%r   rq   c                  &    \ rS rSrS rS rS rSrg)Testi  c                2    SSK Jn  U" U [        5       5        g )Nr   )testCopyAll)music21.test.commonTestr{   globals)r   r{   s     r   testCopyAndDeepcopyTest.testCopyAndDeepcopy  s    7D')$r   c                   / n[         R                  " S5      n[         R                  " S5      n[         R                  " S5      n[         R                  " S5      n[         R                  " S5      [         R                  " S5      [         R                  " S5      [         R                  " S5      /nU H4  nUR                  R                  [	        U5      -  UR                  l        M6     [         R                  " S5      [         R                  " S5      [         R                  " S5      [         R                  " S5      /nSUR                  R                  -  [	        U5      -  US   R                  l        [        S[	        U5      5       H;  n	UR                  R                  S[	        U5      -  -  n
XU	   R                  l        M=     [         R                  " S5      [         R                  " S5      [         R                  " S5      [         R                  " S5      /nS	US   R                  l        S
US   R                  l        SUS   R                  l        SUS   R                  l        [         R                  " S5      [         R                  " S5      [         R                  " S5      [         R                  " S5      /nU H4  nUR                  R                  [	        U5      -  UR                  l        M6     UR                  [        SUSS95        UR                  [        SUU/SS95        UR                  [        SUU/SS95        UR                  [        SUU/SS95        UR                  [        SUU/SS95        UR                  [        SUSS95        UR                  [        SUSS95        UR                  [        SUSSS95        UR                  [        S[         R                  " S5      [         R                  " S5      [         R                  " S5      [         R                  " S5      /SS95        UR                  [        S[         R                  " S5      [         R                  " S5      [         R                  " S5      [         R                  " S5      /SS95        UR                  [        S[         R                  " S5      [         R                  " S5      [         R                  " S5      [         R                  " S5      /SS95        UR                  [        S[         R                  " S5      [         R                  " S5      [         R                  " S5      [         R                  " S5      [         R                  " S5      /SS95        UR                  [        S [         R                  " S5      [         R                  " S5      [         R                  " S5      /SS95        UR                  [        S![         R                  " S5      [         R                  " S5      [         R                  " S5      [         R                  " S5      /U/SS95        U H  n[        5       nUR                  (       a%  UR                  UR                  UR                  S"9nOUR                  UR                  5      nUR                  (       ak  UR                  (       a-  U R                  U[        R                   UR"                  5        M  U R                  U[        R$                  UR"                  5        M  U R'                  XR"                  5        M     g )#NzF#zG-GAEr6   r   r7   g      ?g333333?g?g?r.   zeven turn no simple noteTrs   r   rt   zeven turn with simple noters   r   r   rt   z%even turn with enharmonic simple notez.even turn with wrong simple note still in turnFz,even turn with wrong simple note not in turnz+rubato turn with all notes different lengthzdelayed turnzinverted turn)rs   r   rv   rt   zone wrong noteDznon-adjacent note jumpztrill is not a turnztoo many notes for turnztoo few notes for turnz/total turn notes length longer than simple noter   )r
   Noter   r   r   r<   appendrq   rQ   r   rN   r   rt   rv   assertIsInstancer   rg   rs   rf   assertFalse)r   testConditionsrB   n1EnharmonicnoteInTurnNotBasenoteNotInTurnevenTurnr   delayedTurnrE   smallerDuration
rubatoTurninvertedTurncondturnRecognizerrm   s                   r   testRecognizeTurnTest.testRecognizeTurn  s   YYt_yy IIcN		#IIcNDIIdOTYYs^TYYt_UA'){{'@'@3x='PAJJ$  yy~tyy		#		RVX01BKK4M4M0MPST_P`0`A-q#k*+A kk771s;?O;OPO4CN##1 , iindiiotyy~tyyQUW
/2
1,/2
1,/1
1,/1
1,		#		$3SWYA'){{'@'@3|CT'TAJJ$  	/"!	
 	1"D	!	
 	<")N	!	
 	E"./ 	"	
 	C"*O 	"	
 	B$!	
 	#%!	
 	$&	!	
 	%99S>499T?DIIcNDIIVYN[ "	
 	-99S>499S>499S>499UX>Z "	
 	*99S>499T?DIIcNDIIVZO\ "	
 	.99S>499T?DIIcNDIIVZO99S>+ 	"	
 	-99S>499T?DIIcNK "	
 	F99S>499T?DIIcNDIIVZO\D 	"	
 #D+-N%//DL\L\/]%//???))$0H0H$))T))$0@0@$))L  yy1 #r   c                   / n[         R                  " S5      nSn[        R                  " S5      n[        R                  " S5      n[        R
                  " S5      nX&l         [        R
                  " S5      nX'l         [        R                  " 5       n[        X25      n	Xl	        UR                  U5      S   n
[        U
5      n[        R                  " 5       n[         R                  " U	5      Ul         XS'   UR                  [        S	U
S
US95        UR                  [        SU
U/S
US95        UR                  [        SU
U/S
US95        UR                  [        SU
[        R
                  " S5      /S
US95        UR                  [        SU
[        R
                  " S5      /SS95        UR                  [        SUSS95        [         R                  " S5      nSn[        R                  " S5      n[        R                  " S5      n[        R
                  " S5      nUUl         [        R
                  " S5      nUUl         [         R                  " [        X5      5      n[        R
                  " S5      nUUl         [        R
                  " S5      nUUl         [        R                   " 5       nUR                  UU[        U5      [        U5      [        U5      /5        UR                  [        SUS
US95        UR                  [        SUU/S
US95        UR                  [        SUU/S
US95        [         R                  " S5      nSn[        R                  " S5      n[        R                  " S5      n[        R
                  " S 5      nUUl         [         R                  " [        UU5      5      n[        R
                  " S!5      nUUl         [        R
                  " S 5      nUUl         [        R
                  " S"5      nUUl         [        R
                  " S#5      n UU l         [        R
                  " S$5      n!UU!l         [        R                   " 5       n"U"R                  UU[        U5      [        U5      [        U5      UU U!/5        UR                  [        S%U"SS95        UR                  [        S&U"S
S
US'95        UR                  [        S(U"U/S
S
US)95        [         R                  " S*5      n#[        R
                  " S5      n$U#U$l         [        R
                  " S5      n%U#U%l         UR                  [        S+U$/SS95        UR                  [        S,U$U%/SS95        [         R                  " S*5      n&[        R
                  " S5      n'U&U'l         [        R
                  " S-5      n(U&U(l         [        R                   " 5       n)U)R                  U'U([        U'5      [        U(5      /5        UR                  [        S.U)SS95        [         R                  " S*5      n*[        R
                  " S/5      n+U*U+l         [        R
                  " S5      n,U*U,l         [        R
                  " S5      n-UU-l         [        R                   " 5       n)U)R                  U+U,[        U+5      U-/5        UR                  [        S0U)SS95        U GH  n.[#        5       n/U.R$                  (       a  S
U/l        U.R(                  (       a%  U/R+                  U.R,                  U.R(                  S19n0OU/R+                  U.R,                  5      n0U.R.                  (       GaO  U R1                  U0[        R                  U.R2                  5        U R5                  U0R6                  U.R$                  U.R2                  5        U.R8                  (       a  U.R(                  (       a  U.R(                  S   R:                  R<                  U.R,                  S2   R:                  R<                  :X  a  U0R?                  U.R,                  S2   5      n1O=U0R?                  U.R,                  S   5      n1OU0R?                  U.R,                  S   5      n1U R5                  U1U.R8                  U.R2                  5        GM  GM  U RA                  U0U.R2                  5        GM     g )3Nquarterrb   rU   rV   r   r   r   r6   z,even whole step trill up without simple noteT)rs   r   rt   ru   z)even whole step trill up from simple note)rs   r   r   rt   ru   z'even whole step trill up to simple notez(valid trill up to enharmonic simple notezG##z$valid trill but not with simple noter   Fr   zinvalid trill has rest insider   halfr/   rW   rX   zG#z,odd half step trill down without simple notez'odd half step trill down to simple notezodd trill down from simple note   BC5D5E5F5z1Nachschlag trill when not checking for nachschlagz-Nachschlag trill when checking for nachschlag)rs   r   rG   rt   ru   z?Nachschlag trill when checking for nachschlag up to simple note)rs   r   r   rG   rt   ru   eighthzOne note not a trillzTwo notes not a trillCz+Too big of oscillating interval to be trillFz5Right interval but not oscillating between same notesr   r7   )!r   Durationr	   rZ   r
   r   r   r=   calculateTrillNoteDurationr   realizer   Restr   rq   r   Streamr+   rG   r0   r   rN   r   rt   r   rs   assertEqualr?   ru   r:   r;   getSizer   )2r   r   
n1Duration
t1NumNotest1UpIntervalt1DownIntervaln1Lowern1Uppert1t1NoteDurationt1Notest1NotesWithRestr1
n2Duration
t2NumNotest2UpIntervalt2DownIntervaln2Lowern2Uppert2NoteDurationt2n1t2n2t2Notes
n3Duration
t3NumNotest3UpIntervalt3DownIntervaln3t3NoteDurationt3n1t3n2nachschlagN1nachschlagN2nachschlagN3t3Notes
t4Durationt4n1t4n2t5NoteDurationt5n1t5n2t5Notest6NoteDurationt6n1t6n2t6n3r   trillRecognizerrJ   sizes2                                                     r   testRecognizeTrillTest.testRecognizeTrill  so   &&y1

((.!**51))C.%))C.% 3JK)**W%a("7+YY[''7C!)	+	
 	@!$I)+	
 	>!$I+-	
 	?!!YYu-.+-	
 	;!!YYs^, 	"	
 	4) "	
 &&v.

((.!**51))D/%))C.%!**+Ej+]^yy~&yy&--/dHTNHTNHTNSTC!+	-	
 	>!$I)+	
 	6!$I+-	
 &&y1

((.!**51YYs^ !**+EjR\+]^yy&yy~&yy .yy .yy .--/4$$$,6	

 	H! "	
 	D!!+-	
 	V!D!)+	
 &&x0
yy~"yy~"+& "	
 	,, "	
 "**84yy~&yy~&--/dHTNHTNCDB! "	
 "**84yy~&yy~&yy~&--/dHTND9:L! "	
 #D-/O  26/'11$..dN^N^1_'11$..A%%e[->->		J  !1!143D3DdiiP$$''++A.4499T^^A=N=T=T=Y=YY#(==1B#CD#(==1B#CD$}}T^^A->?$$T4+<+<diiH %   		21 #r   r!   N)r$   r%   r&   r'   r~   r   r   r)   r!   r   r   ry   ry     s    %H2T`3r   ry   c                     UR                   U -  $ r"   )r   )numTrillNotestotalDurations     r   r   r     s    &&66r   __main__)
__future__r   copyr   unittestmusic21.common.numberToolsr   music21.common.typesr   music21r   r   r	   r
   r   r   r+   rQ   rq   TestCasery   r   r$   mainTestr!   r   r   <module>r      s    #   - )     & &Rl( l\Y' Yv% %o38 o3d7 zT r   