<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/halo"
               xmlns:d="http://ns.adobe.com/fxg/2008/dt"
               xmlns:ai="http://ns.adobe.com/ai/2009" 
               xmlns:igimc="com.igetitmusic.components.*"
               xmlns:i="com.igetitmusic.components.intervalSlider.*"
               xmlns:k="com.igetitmusic.components.keyboard.*"
               xmlns:j="com.igetitmusic.JIMS_Sonoflash.*"
               xmlns:audio="assets.audio.*"
               minWidth="365" minHeight="325"
               width="365" height="325" 
               viewSourceURL="srcview/index.html">    
    
    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
    <!-- Declarations                                                                -->
    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
    
    <fx:Declarations>
        <igimc:OneCorrectRadioButtonGroup id="grpQuestion1" correctIndex="0"/>
        <igimc:OneCorrectRadioButtonGroup id="grpQuestion2" correctIndex="1"/>
        <igimc:OneCorrectRadioButtonGroup id="grpQuestion3" correctIndex="1"/>
        <igimc:OneCorrectRadioButtonGroup id="grpQuestion4" correctIndex="1"/>
        <igimc:OneCorrectRadioButtonGroup id="grpQuestion5" correctIndex="1"/>
        <igimc:OneCorrectRadioButtonGroup id="grpQuestion6" correctIndex="1"/>
        
        <!-- playBobThenFred -->
        <s:Parallel id="playBobThenFred">
            <j:PingEffect frequency="{centsToHz(ctlBobInterval.value)}" duration="2000"/>
            
            <s:Sequence>
                <s:Pause duration="100"/>
                <j:PingEffect frequency="{centsToHz(ctlBobInterval.value + ctlFredInterval.value)}" duration="1900"/>
            </s:Sequence>
        </s:Parallel>
        
        <s:Sequence id="playSmokeRiff">
            <j:PingEffect target ="{this}" frequency="{centsToHz(ctlBobInterval.value) + LA_CENTS}" duration="500"/>
            
            <s:SetAction target="{ctlFredInterval}" property="value" value="{DO_CENTS}"/>
            <s:Pause duration="500"/>
            
            <s:SetAction target="{ctlFredInterval}" property="value" value="{RE_CENTS}"/>
            <s:Pause duration="750"/>
            
            <s:SetAction target="{ctlFredInterval}" property="value" value="{LA_CENTS}"/>
            <s:Pause duration="500"/>
            
            <s:SetAction target="{ctlFredInterval}" property="value" value="{DO_CENTS}"/>
            <s:Pause duration="500"/>
            
            <s:SetAction target="{ctlFredInterval}" property="value" value="{ME_CENTS}"/>
            <s:Pause duration="250"/>
            
            <s:SetAction target="{ctlFredInterval}" property="value" value="{RE_CENTS}"/>
            <s:Pause duration="1000"/>
            
            <s:SetAction target="{ctlFredInterval}" property="value" value="{LA_CENTS}"/>
            <s:Pause duration="500"/>
            
            <s:SetAction target="{ctlFredInterval}" property="value" value="{DO_CENTS}"/>
            <s:Pause duration="500"/>
            
            <s:SetAction target="{ctlFredInterval}" property="value" value="{RE_CENTS}"/>
            <s:Pause duration="750"/>
            
            <s:SetAction target="{ctlFredInterval}" property="value" value="{DO_CENTS}"/>
            <s:Pause duration="500"/>
            
            <s:SetAction target="{ctlFredInterval}" property="value" value="{LA_CENTS}"/>
            <s:Pause duration="750"/>
        </s:Sequence>
        
        <s:GlowFilter id="redGlowFilter" blurX="20" blurY="20" color="0xFF0000"/>
    </fx:Declarations>
    
    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
    <!-- States                                                                      -->
    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
    
    <s:states>
        <s:State name="start" stateGroups="narrowRange"/>
        <s:State name="s1" stateGroups="narrowRange"/>
        <s:State name="s2" stateGroups="narrowRange"/>
        <s:State name="q2" stateGroups="narrowRange"/>
        <s:State name="name" stateGroups="wideRange"/>
        <s:State name="fred" stateGroups="wideRange"/>
        <s:State name="q4" stateGroups="wideRange"/>
        <s:State name="q5" stateGroups="wideRange"/>
        <s:State name="q6" stateGroups="wideRange"/>
        <s:State name="like" stateGroups="wideRange"/>
        <s:State name="end" stateGroups="wideRange"/>
    </s:states>
    
    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
    <!-- Transitions                                                                 -->
    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
    
    <s:transitions>          
        <!-- start -->
        <s:Transition fromState="*" toState="start">
            <s:Sequence>
            </s:Sequence>
        </s:Transition>
        
        <!-- s1 -->
        <s:Transition fromState="*" toState="s1"> 
            <s:Sequence>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c01_earlier_MP3}"/>                
                <s:Parallel>             
                    <s:SetAction target="{ctlKeyword}" property="text" value="Interval"/>
                    <s:SetAction target="{ctlKeyword}" property="visible" value="{true}"/>
                </s:Parallel>
                
                <mx:SoundEffect target="{this}" useDuration="false" source="{c02_wasA_MP3}"/>            
                <s:Parallel>             
                    <s:SetAction target="{ctlDefinition}" property="text" value="Relationship between two frequencies"/>
                    <s:SetAction target="{ctlDefinition}" property="visible" value="{true}"/>
                </s:Parallel>                
                <mx:SoundEffect target="{this}" useDuration="false" source="{c03_relationshipFrequencies_MP3}"/>
                <s:Pause duration="500"/>
                <s:SetAction target="{ctlKeyword}" property="visible" value="{false}"/>
                <s:SetAction target="{ctlDefinition}" property="visible" value="{false}"/>
                
                <mx:SoundEffect target="{this}" useDuration="false" source="{c04_andThatThis_MP3}"/>
                <s:CallAction target="{this}" functionName="doPlaySmokeRiff"/> <s:Pause duration="8000"/>                
                <mx:SoundEffect target="{this}" useDuration="false" source="{c05_isA_MP3}"/>
                <s:SetAction target="{ctlDefinition}" property="text" value="Sequence of intervals, in rhythm"/>
                <s:SetAction target="{ctlDefinition}" property="visible" value="{true}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c06_sequenceOfIntervals_MP3}"/>
                <s:Pause duration="500"/>
                <s:SetAction target="{ctlDefinition}" property="visible" value="{false}"/>
                         
                <mx:SoundEffect target="{this}" useDuration="false" source="{c07_weAlsoLearned_MP3}"/>
                    <s:Animate duration="1000" target="{ctlBobInterval}">
                        <fx:Vector type="spark.effects.animation.MotionPath">
                            <s:MotionPath property="value">
                                <s:Keyframe  time="0" value="{0}" />
                                <s:Keyframe  time="1000" value="{MIN_BOB}" />
                            </s:MotionPath>
                        </fx:Vector>
                    </s:Animate>
                <s:CallAction target="{this}" functionName="doPlaySmokeRiff"/> <s:Pause duration="8000"/>    
                    
                <mx:SoundEffect target="{this}" useDuration="false" source="{c08_useTheseControls_MP3}"/>
                <s:SetAction target="{ctlState}" property="visible" value="{true}"/>
                <s:SetAction target="{grpBob}" property="enabled" value="{true}"/>
                <s:SetAction target="{ctlBobButton}" property="enabled" value="{true}"/>
            </s:Sequence>
        </s:Transition>
        
        <!-- s2 -->
        <s:Transition fromState="*" toState="s2"> 
            <s:Sequence>
                <s:SetAction target="{ctlBobInterval}" property="value"/>
                <s:SetAction target="{ctlFredInterval}" property="value" value="{0}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c09_beforeWeCanStudy_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c10_the1stIntervalToLearn_MP3}"/>
                
                <s:SetAction target="{ctlKeyword}" property="text" value="Octave"/>
                <s:SetAction target="{ctlKeyword}" property="visible" value="{true}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c11_isTheOctave_MP3}"/>
                
                <s:SetAction target="{ctlKeyword}" property="text" value="Octave = 2-to-1"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c12_twoToOne_MP3}"/>
                
                <mx:SoundEffect target="{this}" useDuration="false" source="{c13_if1SoundsFreq_MP3}"/>
                <s:SetAction target="{ctlKeyword}" property="visible" value="{false}"/>
                
                <mx:SoundEffect target="{this}" useDuration="false" source="{c14_consider1TimesBob_MP3}"/>                
                <s:AnimateFilter target="{oneBob}"
                                 bitmapFilter="{redGlowFilter}"
                                 duration="250" 
                                 repeatCount="6"
                                 repeatBehavior="reverse">
                    <s:SimpleMotionPath property="alpha" valueFrom="0.2" valueTo="1"/>
                </s:AnimateFilter>
                
                <mx:SoundEffect target="{this}" useDuration="false" source="{c15_and2TimesBob_MP3}"/>            
                <s:AnimateFilter target="{twoBob}"
                                 bitmapFilter="{redGlowFilter}" 
                                 duration="250" 
                                 repeatCount="6"
                                 repeatBehavior="reverse">
                    <s:SimpleMotionPath property="alpha" valueFrom="0.2" valueTo="1"/>
                </s:AnimateFilter>
                
                <mx:SoundEffect target="{this}" useDuration="false" source="{c16_2BobIsTwice1Bob_MP3}"/>
                <s:SetAction target="{octaveLine1}" property="visible"/>
                
                <mx:SoundEffect target="{this}" useDuration="false" source="{c17_soTheyAreOctaveApart_MP3}"/>
                
                <s:Parallel>
                    <mx:SoundEffect target="{this}" useDuration="false" source="{c18_likewise_MP3}"/>        
                    <s:AnimateFilter target="{oneBob}"
                                     bitmapFilter="{redGlowFilter}" 
                                     duration="250" 
                                     repeatCount="12"
                                     repeatBehavior="reverse">
                        <s:SimpleMotionPath property="alpha" valueFrom="0.2" valueTo="1"/>
                    </s:AnimateFilter>    
                    <s:AnimateFilter target="{halfBob}"
                                     bitmapFilter="{redGlowFilter}" 
                                     duration="250" 
                                     repeatCount="12"
                                     repeatBehavior="reverse">
                        <s:SimpleMotionPath property="alpha" valueFrom="0.2" valueTo="1"/>
                    </s:AnimateFilter>
                </s:Parallel>
                
                <s:SetAction target="{octaveLine2}" property="visible" value="true"/>
                <s:Move target="{octaveLine2}" duration="1000" yFrom="15" yTo="100"/>                
                <mx:SoundEffect target="{this}" useDuration="false" source="{c19_soTheyAreOctaveApartToo_MP3}"/>
                
                <s:SetAction target="{ctlQuestion1}" property="visible"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c20_question1_MP3}"/>
            </s:Sequence>
        </s:Transition>
        
        <!-- q2 -->
        <s:Transition fromState="*" toState="q2"> 
            <s:Sequence>
                <s:SetAction target="{ctlQuestion2}" property="visible"/>
            <mx:SoundEffect target="{this}" useDuration="false" source="{c21_question2_MP3}"/>
            </s:Sequence>
        </s:Transition>
        
        <!-- name -->
        <s:Transition fromState="*" toState="name"> 
            <s:Sequence>
                <s:SetAction target="{ctlFredInterval}" property="value" value="{0}"/>
                <s:SetAction target="{octaveLine1}" property="visible" value="false"/>
                <s:SetAction target="{octaveLine2}" property="visible" value="false"/>
                <s:SetAction target="{octaveLine3}" property="visible" value="false"/>
                <s:SetAction target="{octaveLine4}" property="visible" value="false"/>
                <s:SetAction target="{ctlBobInterval}" property="value" value="0"/>
                <s:SetAction target="{fourBob}" property="visible" value="{false}"/>
                <s:SetAction target="{fourthBob}" property="visible" value="{false}"/>
                
                <mx:SoundEffect target="{this}" useDuration="false" source="{c22_theHumanEar_MP3}"/>
                
                <s:Parallel>
                    <mx:SoundEffect target="{this}" useDuration="false" source="{c22a_letsIncreaseFredsRange_MP3}"/>
                    
                    <s:Sequence>
                        <s:Animate duration="1000" target="{ctlFredInterval}">
                            <fx:Vector type="spark.effects.animation.MotionPath">
                                <s:MotionPath property="height">
                                    <s:Keyframe  time="0" value="{FRED_HEIGHT}" />
                                    <s:Keyframe  time="1000" value="{FRED_HEIGHT/2}" />
                                </s:MotionPath>
                            </fx:Vector>
                        </s:Animate>
                        
                        <s:SetAction target="{twoBob}" property="visible" value="{true}"/>
                        <s:SetAction target="{halfBob}" property="visible" value="{true}"/>
                        
                        <s:Parallel>
                            <s:Animate duration="1000" target="{ctlFredInterval}">
                                <fx:Vector type="spark.effects.animation.MotionPath">
                                    <s:MotionPath property="maximum">
                                        <s:Keyframe  time="0" value="{CENTS_PER_OCTAVE}" />
                                        <s:Keyframe  time="1000" value="{2*CENTS_PER_OCTAVE}" />
                                    </s:MotionPath>
                                </fx:Vector>
                            </s:Animate>
                            
                            <s:Animate duration="1000" target="{ctlFredInterval}">
                                <fx:Vector type="spark.effects.animation.MotionPath">
                                    <s:MotionPath property="minimum">
                                        <s:Keyframe  time="0" value="{-CENTS_PER_OCTAVE}" />
                                        <s:Keyframe  time="1000" value="{-2*CENTS_PER_OCTAVE}" />
                                    </s:MotionPath>
                                </fx:Vector>
                            </s:Animate>                    
                        </s:Parallel>
                        
                        <s:Animate duration="1000" target="{ctlFredInterval}">
                            <fx:Vector type="spark.effects.animation.MotionPath">
                                <s:MotionPath property="height">
                                    <s:Keyframe  time="0" value="{FRED_HEIGHT/2}" />
                                    <s:Keyframe  time="1000" value="{FRED_HEIGHT}" />
                                </s:MotionPath>
                            </fx:Vector>
                        </s:Animate>
                        
                        <s:SetAction target="{fourBob}" property="visible" value="{true}"/>
                        <s:SetAction target="{fourthBob}" property="visible" value="{true}"/>
                    </s:Sequence>                        
                </s:Parallel>
                
                <mx:SoundEffect target="{this}" useDuration="false" source="{c23_nowFredsSlider_MP3}"/>
                
                <s:SetAction target="{octaveLine1}" property="visible" value="true"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c24_one_MP3}"/>
                
                <s:Pause duration="500"/>
                <s:SetAction target="{octaveLine2}" property="visible" value="true"/>
                <s:Parallel>
                    <mx:SoundEffect target="{this}" useDuration="false" source="{c25_two_MP3}"/>
                    <s:Move target="{octaveLine2}" duration="1000"/>
                </s:Parallel>
                
                <s:Pause duration="500"/>
                <s:SetAction target="{octaveLine3}" property="visible" value="true"/>
                <s:Parallel>
                    <mx:SoundEffect target="{this}" useDuration="false" source="{c26_three_MP3}"/>
                    <s:Move target="{octaveLine3}" duration="1000"/>
                </s:Parallel>
                
                <s:Pause duration="500"/>
                <s:SetAction target="{octaveLine4}" property="visible" value="true"/>
                <s:Parallel>
                    <mx:SoundEffect target="{this}" useDuration="false" source="{c27_four_MP3}"/>
                    <s:Move target="{octaveLine4}" duration="1000"/>
                </s:Parallel>
                
                <s:Pause duration="1000"/>
                <s:SetAction target="{octaveLine1}" property="visible" value="false"/>
                <s:SetAction target="{octaveLine2}" property="visible" value="false"/>
                <s:SetAction target="{octaveLine3}" property="visible" value="false"/>
                <s:SetAction target="{octaveLine4}" property="visible" value="false"/>
                
                <s:SetAction target="{grpFred}" property="enabled"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c27a_useFredsSlider_MP3}"/>
            </s:Sequence>
        </s:Transition>
        
        <!-- fred -->
        <s:Transition fromState="*" toState="fred"> 
            <s:Sequence>
                <s:SetAction target="{ctlFredInterval}" property="value"/>
                <s:SetAction target="{ctlFredInterval}" property="minimum"/>
                <s:SetAction target="{ctlFredInterval}" property="maximum"/>
                <s:SetAction target="{ctlFredButton}" property="visible"/>
                <s:CallAction target="{grpFred}" functionName="invalidateDisplayList"/>
                
                <s:Parallel>
                    <s:Move target="{grpFred}" duration="1500"/>
                    <s:Resize target="{grpFred}" duration="1500"/>
                    <mx:SoundEffect target="{this}" useDuration="false" source="{c28_fredUsesASimpler_MP3}"/>
                </s:Parallel>                    
                
                <s:Parallel>                    
                    <mx:SoundEffect target="{this}" useDuration="false" source="{c29_heCallsOneTimesBob_MP3}"/>
                    <s:AnimateFilter target="{oneBob}"
                                     bitmapFilter="{redGlowFilter}" 
                                     duration="250" 
                                     repeatCount="12"
                                     repeatBehavior="reverse">
                        <s:SimpleMotionPath property="alpha" valueFrom="0.2" valueTo="1"/>
                    </s:AnimateFilter>
                    
                    <s:SetAction target="{oneBob}" property="octave" value="{0}"/>    
                    <s:SetAction target="{oneBob}" property="showOctave" value="true"/>
                    <s:SetAction target="{oneBob}" property="intervalName" value="1*Bob = Bob"/>
                </s:Parallel>
                
                <mx:SoundEffect target="{this}" useDuration="false" source="{c30_bobZeroIsThe_MP3}"/>
                <s:SetAction target="{ctlBobInterval}" property="value" value="{MAX_BOB}"/>                
                
                <mx:SoundEffect target="{this}" useDuration="false" source="{c31_low_MP3}"/>
                <s:SetAction target="{ctlBobInterval}" property="value" value="{MIN_BOB}"/>
                
                <mx:SoundEffect target="{this}" useDuration="false" source="{c32_orAnywhereInBetween_MP3}"/>
                <s:Animate duration="1000" target="{ctlBobInterval}">
                    <fx:Vector type="spark.effects.animation.MotionPath">
                        <s:MotionPath property="value">
                            <s:Keyframe  time="0" value="{MIN_BOB}" />
                            <s:Keyframe  time="1000" value="{MAX_BOB}" />
                            <s:Keyframe  time="2000" value="{0}" />
                        </s:MotionPath>
                    </fx:Vector>
                </s:Animate>                    
                
                <s:Parallel>
                    <mx:SoundEffect target="{this}" useDuration="false" source="{c32a_theFreqThats1OctHigher_MP3}"/>
                    <s:AnimateFilter target="{twoBob}"
                                     bitmapFilter="{redGlowFilter}" 
                                     duration="250" 
                                     repeatCount="12"
                                     repeatBehavior="reverse">
                        <s:SimpleMotionPath property="alpha" valueFrom="0.2" valueTo="1"/>
                    </s:AnimateFilter>                    
                    <s:SetAction target="{octaveLine2}" property="visible" value="{true}"/>
                </s:Parallel>
                <s:SetAction target="{ctlFredInterval}" property="value" value="{CENTS_PER_OCTAVE}"/>
                
                <s:SetAction target="{twoBob}" property="octave" value="{1}"/>    
                <s:SetAction target="{twoBob}" property="showOctave" value="true"/>
                <s:SetAction target="{twoBob}" property="intervalName" value="2*Bob = Bob"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c33_fredCallsBob1_MP3}"/>    
                <s:AnimateFilter target="{twoBob}"
                                 bitmapFilter="{redGlowFilter}" 
                                 duration="250" 
                                 repeatCount="12"
                                 repeatBehavior="reverse">
                    <s:SimpleMotionPath property="alpha" valueFrom="0.2" valueTo="1"/>
                </s:AnimateFilter>
                
                <mx:SoundEffect target="{this}" useDuration="false" source="{c33a_bob1IsOneOctHigher_MP3}"/>
                <s:SetAction target="{octaveLine1}" property="visible" value="{true}"/>
                
                <s:Parallel>
                    <s:AnimateFilter target="{fourBob}"
                                     bitmapFilter="{redGlowFilter}" 
                                     duration="250" 
                                     repeatCount="24"
                                     repeatBehavior="reverse">
                        <s:SimpleMotionPath property="alpha" valueFrom="0.2" valueTo="1"/>
                    </s:AnimateFilter>
                    
                    <s:Sequence>
                        <mx:SoundEffect target="{this}" useDuration="false" source="{c34_4TimesBobIs_MP3}"/>
                        <s:SetAction target="{ctlFredInterval}" property="value" value="{2*CENTS_PER_OCTAVE}"/>
                        <s:SetAction target="{fourBob}" property="octave" value="{2}"/>    
                        <s:SetAction target="{fourBob}" property="showOctave" value="true"/>
                        <s:SetAction target="{fourBob}" property="intervalName" value="4*Bob = Bob"/>
                        <mx:SoundEffect target="{this}" useDuration="false" source="{c35_soFredCallsItBob2_MP3}"/>                        
                    </s:Sequence>
                </s:Parallel>
                
                <s:SetAction target="{octaveLine1}" property="visible" value="{false}"/>
                <s:SetAction target="{octaveLine2}" property="visible" value="{false}"/>
                <s:SetAction target="{octaveLine3}" property="visible" value="{true}"/>
                <s:Parallel>
                    <s:Sequence>
                        <mx:SoundEffect target="{this}" useDuration="false" source="{c36_1OctaveBelowBob0_MP3}"/>
                        <s:SetAction target="{ctlFredInterval}" property="value" value="{-CENTS_PER_OCTAVE}"/>
                        <mx:SoundEffect target="{this}" useDuration="false" source="{c37_fredUsesNegative_MP3}"/>
                    </s:Sequence>
                    <s:AnimateFilter target="{halfBob}"
                                     bitmapFilter="{redGlowFilter}" 
                                     duration="250" 
                                     repeatCount="48"
                                     repeatBehavior="reverse">
                        <s:SimpleMotionPath property="alpha" valueFrom="0.2" valueTo="1"/>
                    </s:AnimateFilter>
                </s:Parallel>
                <s:SetAction target="{halfBob}" property="octave" value="{-1}"/>    
                <s:SetAction target="{halfBob}" property="showOctave" value="true"/>
                <s:SetAction target="{halfBob}" property="intervalName" value="½*Bob = Bob"/>
                <s:Pause duration="1000"/>
                
                <s:SetAction target="{octaveLine4}" property="visible" value="{true}"/>
                <s:Parallel>
                    <s:Sequence>
                        <mx:SoundEffect target="{this}" useDuration="false" source="{c38_one4thTimesBob_MP3}"/>
                        <s:SetAction target="{ctlFredInterval}" property="value" value="{-2*CENTS_PER_OCTAVE}"/>
                        <s:SetAction target="{fourthBob}" property="octave" value="{-2}"/>    
                        <s:SetAction target="{fourthBob}" property="showOctave" value="true"/>
                        <s:SetAction target="{fourthBob}" property="intervalName" value="¼*Bob = Bob"/>
                        <mx:SoundEffect target="{this}" useDuration="false" source="{c39_soFredCallsItBobMinus2_MP3}"/>
                    </s:Sequence>
                    <s:AnimateFilter target="{fourthBob}"
                                     bitmapFilter="{redGlowFilter}" 
                                     duration="250" 
                                     repeatCount="20"
                                     repeatBehavior="reverse">
                        <s:SimpleMotionPath property="alpha" valueFrom="0.2" valueTo="1"/>
                    </s:AnimateFilter>
                </s:Parallel>
                
                <s:SetAction target="{octaveLine1}" property="visible" value="{false}"/>
                <s:SetAction target="{octaveLine2}" property="visible" value="{false}"/>
                <s:SetAction target="{octaveLine3}" property="visible" value="{false}"/>
                <s:SetAction target="{octaveLine4}" property="visible" value="{false}"/>
                
                <mx:SoundEffect target="{this}" useDuration="false" source="{c40_usingFredsOctaveNaming_MP3}"/>
                <s:SetAction target="{ctlQuestion3}" property="visible"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c41_q1freq3OctAbove_MP3}"/>
            </s:Sequence>
        </s:Transition>
        
        <!-- q4 -->
        <s:Transition fromState="*" toState="q4"> 
            <s:Sequence>
                <s:SetAction target="{ctlQuestion4}" property="visible"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c42_q2freq4OctAbove_MP3}"/>
            </s:Sequence>
        </s:Transition>
        
        <!-- q5 -->
        <s:Transition fromState="*" toState="q5"> 
            <s:Sequence>
                <s:SetAction target="{ctlQuestion5}" property="visible"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c43_q3freq3OctBelow_MP3}"/>
            </s:Sequence>
        </s:Transition>
        
        <!-- q6 -->
        <s:Transition fromState="*" toState="q6"> 
            <s:Sequence>
                <s:SetAction target="{ctlQuestion6}" property="visible"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c44_q4freq4OctBelow_MP3}"/>
            </s:Sequence>
        </s:Transition>
        
        <!-- like -->
        <s:Transition fromState="*" toState="like"> 
            <s:Sequence>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c45_iLikeFredsNaming_MP3}"/>
            </s:Sequence>
        </s:Transition>
        
        <!-- end -->
        <s:Transition fromState="*" toState="end"> 
            <s:Sequence>
            </s:Sequence>
        </s:Transition>
    </s:transitions>
    
    
    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
    <!-- Visual Elements                                                               -->
    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
    
    <s:Button horizontalCenter="0" y="105" label="Start Learning"
              click="{this.currentState='s1'}"
              includeIn="start"/>
    
    <s:Label id="ctlKeyword" horizontalCenter="0" 
             verticalAlign="middle"
             textAlign="center" 
             visible="false"
             fontSize="48"
             includeIn="s1, s2"/>
    
    <s:RichText id="ctlDefinition" 
                horizontalCenter="0" verticalCenter="-25"
                width="66%" height="30%"
                textAlign="center" verticalAlign="middle"
                fontStyle="italic" fontSize="24"
                includeIn="s1"/>
    
    <!-- Bob -->
    <s:Group id="grpBob"
             left="25" verticalCenter="0" width="20" height="140"
             visible="true"
             visible.start="false" visible.end="false" visible.like="false"
             enabled="false"
             enabled.s1="true"
             enabled.s2="false"
             includeInLayout="true">
        
        <s:VSlider id="ctlBobInterval"
                   horizontalCenter="0" verticalCenter="0" height="80%"
                   minimum="{MIN_BOB}" maximum="{MAX_BOB}"
                   value="0"
                   value.narrowRange="0"
                   value.wideRange="0"
                   snapInterval="100"
                   liveDragging="true"
                   change="ctlBobInterval_changeHandler(event);"
                   valueCommit="ctlBobInterval_valueCommitHandler(event);"
                   thumbRelease.s1="doPlaySmokeRiff()"
                   thumbRelease.s2="doPlaySmokeRiff()"/>
        
        <s:Label horizontalCenter="0" top="0" text="High" fontSize="12" textAlign="center"/>
        <s:Label horizontalCenter="0" bottom="0" text="Low" fontSize="12" textAlign="center"/>
    </s:Group>
    
    <s:Button id="ctlBobButton"
              label="Bob" 
              left="0" verticalCenter="0"
              rotation="270"
              textAlign="center"
              visible="true" visible.start="false" visible.end="false"  visible.like="false"
              enabled="false"
              enabled.s1="true"
              click="{bobSound.frequency = centsToHz(ctlBobInterval.value); bobSound.start();}"/>
    
    <!-- Fred -->
    <i:IntervalSliderGroup id="grpFred" 
             height="200" verticalCenter="{_fredsVerticalCenter}"
             x="280" x.fred="255" x.q4="255" x.q5="255" x.q6="255" x.like="255"
             width="85" width.name="110" width.fred="110" width.q4="110" width.q5="110" width.q6="110" width.like="110"
             visible="true" visible.start="false" visible.end="false"  visible.like="false"
             enabled="false" enabled.name="true"
             includeInLayout="true">
        
        <s:VSlider id="ctlFredInterval"
                   left="10" verticalCenter="0" height="{FRED_HEIGHT}"
                   minimum="{-CENTS_PER_OCTAVE}" maximum="{CENTS_PER_OCTAVE}" value="0"
                   minimum.name="{-2*CENTS_PER_OCTAVE}" maximum.name="{2*CENTS_PER_OCTAVE}" value.name="0"
                   minimum.fred="{-2*CENTS_PER_OCTAVE}" maximum.fred="{2*CENTS_PER_OCTAVE}" value.fred="0"
                   minimum.q4="{-2*CENTS_PER_OCTAVE}" maximum.q4="{2*CENTS_PER_OCTAVE}" value.q4="0"
                   minimum.q5="{-2*CENTS_PER_OCTAVE}" maximum.q5="{2*CENTS_PER_OCTAVE}" value.q5="0"
                   minimum.q6="{-2*CENTS_PER_OCTAVE}" maximum.q6="{2*CENTS_PER_OCTAVE}" value.q6="0"
                   minimum.like="{-2*CENTS_PER_OCTAVE}" maximum.like="{2*CENTS_PER_OCTAVE}" value.like="0"
                   snapInterval="25"
                   creationComplete="updateFredsVerticalCenter();"
                   change="ctlFredInterval_changeHandler(event);"
                   valueCommit="ctlFredInterval_playNote(event);"/>
        
        <i:NoteLabel id="fourBob"   alphas="2"  betas="0" intervalName="4*Bob" showOctave="false" left="25" height="12" 
                     visible="{grpFred.visible}" visible.narrowRange="false"/>
        <i:NoteLabel id="twoBob"    alphas="1"  betas="0" intervalName="2*Bob" showOctave="false" left="25" height="12" 
                     visible="{grpFred.visible}" visible.fred="true"/>
        <i:NoteLabel id="oneBob"    alphas="0"  betas="0" intervalName="1*Bob" showOctave="false" left="25" height="12" 
                     visible="{grpFred.visible}" visible.fred="true"/>
        <i:NoteLabel id="halfBob"   alphas="-1" betas="0" intervalName="½*Bob" showOctave="false" left="25" height="12" 
                     visible="{grpFred.visible}" visible.fred="true"/>
        <i:NoteLabel id="fourthBob" alphas="-2" betas="0" intervalName="¼*Bob" showOctave="false" left="25" height="12" 
                     visible="{grpFred.visible}" visible.narrowRange="false"/>
        
        <s:Button id="ctlFredButton"
                  label="Fred" 
                  right="0" verticalCenter="0"
                  rotation="270"
                  textAlign="center"
                  click="{fredSound.frequency = centsToHz(ctlBobInterval.value + ctlFredInterval.value); fredSound.start();}"
                  visible="true"
                  visible.wideRange="false"
                  enabled="false"/>
        
        <!-- first "octave" width indicator -->
        <s:Group id="octaveLine1" x="2" top="15" visible="false" visible.s2="true">            
            <s:RichText color="0x000000" backgroundColor="0xFFFFFF" kerning="on" lineHeight="120%" rotation="270" whiteSpaceCollapse="preserve" horizontalCenter="0" verticalCenter="-1" >
                <s:content><s:p whiteSpaceCollapse="collapse"><s:span>octave</s:span></s:p></s:content>
            </s:RichText>
            
            <s:Group x="1" y="0">
                <s:Line x="3.5" y="0.5" yTo.narrowRange="84" yTo.wideRange="42">
                    <s:stroke>
                        <s:SolidColorStroke caps="none" joints="miter" miterLimit="4" scaleMode="normal" weight="1"/>
                    </s:stroke>
                </s:Line>
                <s:Line x="0.5" xTo="7" y="0.5">
                    <s:stroke>
                        <s:SolidColorStroke caps="none" joints="miter" miterLimit="4" scaleMode="normal" weight="1"/>
                    </s:stroke>
                </s:Line>
                <s:Line x="0.5" xTo="7" y.narrowRange="84.5" y.wideRange="42">
                    <s:stroke>
                        <s:SolidColorStroke caps="none" joints="miter" miterLimit="4" scaleMode="normal" weight="1"/>
                    </s:stroke>
                </s:Line>
            </s:Group>
        </s:Group>
        
        <!-- second "octave" width indicator -->
        <s:Group id="octaveLine2" x="2" top="15" visible="false" top.narrowRange="100" top.wideRange="57">            
            <s:RichText color="0x000000" backgroundColor="0xFFFFFF" kerning="on" lineHeight="120%" rotation="270" whiteSpaceCollapse="preserve" horizontalCenter="0" verticalCenter="-1" >
                <s:content><s:p whiteSpaceCollapse="collapse"><s:span>octave</s:span></s:p></s:content>
            </s:RichText>
            
            <s:Group x="1" y="0">
                <s:Line x="3.5" y="0.5" yTo.narrowRange="84" yTo.wideRange="42">
                    <s:stroke>
                        <s:SolidColorStroke caps="none" joints="miter" miterLimit="4" scaleMode="normal" weight="1"/>
                    </s:stroke>
                </s:Line>
                <s:Line x="0.5" xTo="7" y="0.5">
                    <s:stroke>
                        <s:SolidColorStroke caps="none" joints="miter" miterLimit="4" scaleMode="normal" weight="1"/>
                    </s:stroke>
                </s:Line>
                <s:Line x="0.5" xTo="7" y.narrowRange="84.5" y.wideRange="42">
                    <s:stroke>
                        <s:SolidColorStroke caps="none" joints="miter" miterLimit="4" scaleMode="normal" weight="1"/>
                    </s:stroke>
                </s:Line>
            </s:Group>
        </s:Group>
        
        <!-- third "octave" width indicator -->
        <s:Group id="octaveLine3" x="2" top="15" visible="false" top.wideRange="99">            
            <s:RichText color="0x000000" backgroundColor="0xFFFFFF" kerning="on" lineHeight="120%" rotation="270" whiteSpaceCollapse="preserve" horizontalCenter="0" verticalCenter="-1" >
                <s:content><s:p whiteSpaceCollapse="collapse"><s:span>octave</s:span></s:p></s:content>
            </s:RichText>
            
            <s:Group x="1" y="0">
                <s:Line x="3.5" y="0.5" yTo="84" yTo.wideRange="42">
                    <s:stroke>
                        <s:SolidColorStroke caps="none" joints="miter" miterLimit="4" scaleMode="normal" weight="1"/>
                    </s:stroke>
                </s:Line>
                <s:Line x="0.5" xTo="7" y="0.5">
                    <s:stroke>
                        <s:SolidColorStroke caps="none" joints="miter" miterLimit="4" scaleMode="normal" weight="1"/>
                    </s:stroke>
                </s:Line>
                <s:Line x="0.5" xTo="7" y="84.5" y.wideRange="42">
                    <s:stroke>
                        <s:SolidColorStroke caps="none" joints="miter" miterLimit="4" scaleMode="normal" weight="1"/>
                    </s:stroke>
                </s:Line>
            </s:Group>
        </s:Group>
        
        <!-- fourth "octave" width indicator -->
        <s:Group id="octaveLine4" x="2" top="15" visible="false" top.wideRange="141">            
            <s:RichText color="0x000000" backgroundColor="0xFFFFFF" kerning="on" lineHeight="120%" rotation="270" whiteSpaceCollapse="preserve" horizontalCenter="0" verticalCenter="-1" >
                <s:content><s:p whiteSpaceCollapse="collapse"><s:span>octave</s:span></s:p></s:content>
            </s:RichText>
            
            <s:Group x="1" y="0">
                <s:Line x="3.5" y="0.5" yTo="84" yTo.wideRange="42">
                    <s:stroke>
                        <s:SolidColorStroke caps="none" joints="miter" miterLimit="4" scaleMode="normal" weight="1"/>
                    </s:stroke>
                </s:Line>
                <s:Line x="0.5" xTo="7" y="0.5">
                    <s:stroke>
                        <s:SolidColorStroke caps="none" joints="miter" miterLimit="4" scaleMode="normal" weight="1"/>
                    </s:stroke>
                </s:Line>
                <s:Line x="0.5" xTo="7" y="84.5" y.wideRange="42">
                    <s:stroke>
                        <s:SolidColorStroke caps="none" joints="miter" miterLimit="4" scaleMode="normal" weight="1"/>
                    </s:stroke>
                </s:Line>
            </s:Group>
        </s:Group>
    </i:IntervalSliderGroup>
    
    
    <mx:HRule id="ctlRule" 
              verticalCenter="{_fredsVerticalCenter}" height="1" 
              horizontalCenter="-20" horizontalCenter.wideRange="-30" 
              width="60%" width.wideRange="50%"
              visible="{grpFred.visible}"/>
    
    <!-- Question 1 -->
    <s:Panel id="ctlQuestion1" includeIn="s2" visible="false" visible.s2="true" verticalCenter="0" horizontalCenter="0" width="100%" height="96" 
             title="Two frequencies an &quot;octave&quot; apart have the relationship...?">
        <s:RadioButton x="10" y="10" label="2-to-1" groupName="grpQuestion1"/>
        <s:RadioButton x="10" y="36" label="3-to-1" groupName="grpQuestion1"/>
    </s:Panel>
    
    <!-- Question 2 -->
    <s:Panel id="ctlQuestion2" includeIn="q2" visible="false" visible.q2="true" verticalCenter="0" horizontalCenter="0" width="100%" height="96" 
             title="If a frequency is twice another's, what interval separates them?">
        <s:RadioButton x="10" y="10" label="A whole tone" groupName="grpQuestion2"/>
        <s:RadioButton x="10" y="36" label="An octave" groupName="grpQuestion2"/>
    </s:Panel>
    
    <!-- Question 3 -->
    <s:Panel id="ctlQuestion3" includeIn="fred" visible="false" visible.fred="true" verticalCenter="0" horizontalCenter="0" width="100%" height="96" 
             title="The frequency 3 octaves above Bob0 is called...?">
        <s:RadioButton x="10" y="10" label="8*Bob" groupName="grpQuestion3"/>
        <s:RadioButton x="10" y="36" label="Bob3" groupName="grpQuestion3"/>
    </s:Panel>
    
    <!-- Question 4 -->
    <s:Panel id="ctlQuestion4" includeIn="q4" visible="false" visible.q4="true" verticalCenter="0" horizontalCenter="0" width="100%" height="96" 
             title="The frequency 4 octaves above Bob0 is called...?">
        <s:RadioButton x="10" y="10" label="16*Bob" groupName="grpQuestion4"/>
        <s:RadioButton x="10" y="36" label="Bob4" groupName="grpQuestion4"/>
    </s:Panel>
    
    <!-- Question 5 -->
    <s:Panel id="ctlQuestion5" includeIn="q5" visible="false" visible.q5="true" verticalCenter="0" horizontalCenter="0" width="100%" height="96" 
             title="The frequency 3 octaves below Bob0 is called...?">
        <s:RadioButton x="10" y="10" label="1/8*Bob" groupName="grpQuestion5"/>
        <s:RadioButton x="10" y="36" label="Bob-3" groupName="grpQuestion5"/>
    </s:Panel>
    
    <!-- Question 6 -->
    <s:Panel id="ctlQuestion6" includeIn="q6" visible="false" visible.q6="true" verticalCenter="0" horizontalCenter="0" width="100%" height="96" 
             title="The frequency 4 octaves below Bob0 is called...?">
        <s:RadioButton x="10" y="10" label="Bob/16" groupName="grpQuestion6"/>
        <s:RadioButton x="10" y="36" label="Bob-4" groupName="grpQuestion6"/>
    </s:Panel>
    
    <!-- Meta-controls -->
    <igimc:StateButtonBar id="ctlState" x="0" y="300" width="365" height="20"/>
    
    
    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
    <!-- Code                                                                          -->
    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
    <fx:Script>
        <![CDATA[
            import com.igetitmusic.assert.Assert;
            import com.igetitmusic.JIMS_Sonoflash.*;
            import com.igetitmusic.music.Model;
            
            import flash.media.*;
            
            import mx.events.EffectEvent;
            
            
            //--------------------------------------------------------------------------
            //
            //  Constants
            //
            //--------------------------------------------------------------------------
            
            private const CENTS_PER_OCTAVE:Number = 1200;
            
            private const MAX_BOB:Number          =  CENTS_PER_OCTAVE;
            private const MIN_BOB:Number          = -MAX_BOB;
            
            private const FRED_HEIGHT:Number    = 180;
            
            private const MAX_FREQUENCY:Number    =  2*CENTS_PER_OCTAVE;
            private const MIN_FREQUENCY:Number    = -MAX_FREQUENCY;
            
            private const ME_CENTS:Number        = 582.5;
            private const RE_CENTS:Number        = 498.0;
            private const DO_CENTS:Number        = 315.6;
            private const LA_CENTS:Number        =   0.0;
            
            
            
            //--------------------------------------------------------------------------
            //
            //  Properties
            //
            //--------------------------------------------------------------------------
            
            //----------------------------------
            //  baseFrequency
            //----------------------------------
            
            private var baseFrequency:Number      =  440;        // 440Hz -- the A above middle C
            
            //----------------------------------
            //  bobSound
            //----------------------------------
            
            [Bindable]public var _bobSound:PingSound = new PingSound(440);
            public function get bobSound():PingSound { return _bobSound; }
            public function set bobSound(v:PingSound):void { _bobSound = v; }
            
            //----------------------------------
            //  fredSound
            //----------------------------------
            
            [Bindable]public var _fredSound:PingSound = new PingSound(440);
            public function get fredSound():PingSound { return _fredSound; }
            public function set fredSound(v:PingSound):void { _fredSound = v; }
            
            //--------------------------------------------------------------------------
            //
            //  Methods
            //
            //--------------------------------------------------------------------------
            
            //----------------------------------
            //  centsToHz
            //----------------------------------
            
            public function centsToHz(c:Number):Number {
                return (baseFrequency * Math.pow(2, (c/CENTS_PER_OCTAVE))); 
            }
            
            //----------------------------------
            //  fredsVerticalCenter
            //----------------------------------
            
            // Suitable for use in MXML statement: verticalCenter="{_fredsVerticalCenter}"
            [Bindable]private var _fredsVerticalCenter:Number = NaN;            
            public function get fredsVerticalCenter():Number { return _fredsVerticalCenter; }
            public function set fredsVerticalCenter(v:Number):void { _fredsVerticalCenter = v; }
            
            //----------------------------------
            //  bobsThumbsCenterY
            //----------------------------------
            
            // Suitable for use in MXML statement: y="{_bobsThumbsCenterY - ctlID.height}"
            [Bindable]private var _bobsThumbsCenterY:Number = NaN;            
            public function get bobsThumbsCenterY():Number { return _bobsThumbsCenterY; }
            public function set bobsThumbsCenterY(v:Number):void { _bobsThumbsCenterY = v; }
            
            //----------------------------------
            //  updateFredsVerticalCenter
            //----------------------------------
            
            // Called on any change to Bob's value (VALUE_COMMIT).
            public function updateFredsVerticalCenter():void {
                CONFIG::DEBUG {Assert.assertTrue("ctlBobInterval != null", ctlBobInterval != null);}
                CONFIG::DEBUG {Assert.assertTrue("ctlBobInterval.track != null", ctlBobInterval.track != null);}
                CONFIG::DEBUG {Assert.assertTrue("ctlBobInterval.thumb != null", ctlBobInterval.thumb != null);}
                CONFIG::DEBUG {Assert.assertTrue("grpBob != null", grpBob != null);}
                
                var trackRange:Number        = ctlBobInterval.maximum - ctlBobInterval.minimum;
                var normalized:Number        = (ctlBobInterval.value  - ctlBobInterval.minimum) / trackRange;
                
                bobsThumbsCenterY            = ((normalized - 0.0) * (ctlBobInterval.thumb.height - ctlBobInterval.track.height)) + grpBob.y;
                fredsVerticalCenter            =  (normalized - 0.5) * (ctlBobInterval.thumb.height - ctlBobInterval.track.height);
            }
            
            //----------------------------------
            //  doPlayBobThenFred
            //----------------------------------            
            
            public function doPlayBobThenFred():void {    
                CONFIG::DEBUG {Assert.assertTrue("playBobThenFred != null", playBobThenFred != null);}
                CONFIG::DEBUG {Assert.assertTrue("ctlBobInterval != null", ctlBobInterval != null);}
                CONFIG::DEBUG {Assert.assertTrue("ctlFredInterval != null", ctlFredInterval != null);}
                //if (isNaN(ctlBobInterval.value) || isNaN(ctlFredInterval.value)) return;
                
                // I can't seem to use the CallAction effect to invoke the declared animation
                // playBobThenFred.play() directly from within a transition, so I'm
                // defining and calling this method instead.
                playBobThenFred.play([this]);
            }
            
            //----------------------------------
            //  doPlaySmokeRiff
            //----------------------------------            
            
            public function doPlaySmokeRiff():void {    
                CONFIG::DEBUG {Assert.assertTrue("playSmokeRiff != null", playSmokeRiff != null);}
                CONFIG::DEBUG {Assert.assertTrue("grpBob != null", grpBob != null);}
                
                var wasGrpBobEnabled:Boolean = grpBob.enabled;
                grpBob.enabled = false;
                
                var endListener:Function = function endListener(e:EffectEvent):void {
                    grpBob.enabled = wasGrpBobEnabled;
                    playSmokeRiff.removeEventListener(EffectEvent.EFFECT_END, endListener);
                }
                
                playSmokeRiff.addEventListener(EffectEvent.EFFECT_END, endListener);
                
                playSmokeRiff.play([this]);
            }
            
            //----------------------------------
            //  ctlBobInterval_valueCommitHandler
            //----------------------------------
            
            // called whenever Bob's value changes for any reason (animation, user action, whatever)
            protected function ctlBobInterval_valueCommitHandler(event:Event):void {
                CONFIG::DEBUG {Assert.assertTrue("ctlBobInterval != null", ctlBobInterval != null);}
                CONFIG::DEBUG {Assert.assertTrue("ctlFredInterval != null", ctlFredInterval != null);}
                CONFIG::DEBUG {Assert.assertTrue("bobSound != null", bobSound != null);}
                CONFIG::DEBUG {Assert.assertTrue("fredSound != null", fredSound != null);}
                
                updateFredsVerticalCenter();
                if (isNaN(ctlBobInterval.value) || isNaN(ctlFredInterval.value)) return;
                
                bobSound.frequency = centsToHz(ctlBobInterval.value);
                fredSound.frequency = centsToHz(ctlBobInterval.value + ctlFredInterval.value);
                playBobThenFred.play([this]);
                
                // keep model's refFreq in sync w/ Bob's pitch, so that keyboard plays the right pitches
                Model.dataModel.refFreq = this.centsToHz(ctlBobInterval.value);
            }
            
            //----------------------------------
            //  ctlBobInterval_changeHandler
            //----------------------------------
            
            protected function ctlBobInterval_changeHandler(event:Event):void {
                CONFIG::DEBUG {Assert.assertTrue("ctlBobInterval != null", ctlBobInterval != null);}
                CONFIG::DEBUG {Assert.assertTrue("ctlFredInterval != null", ctlFredInterval != null);}
                CONFIG::DEBUG {Assert.assertTrue("bobSound != null", bobSound != null);}
                CONFIG::DEBUG {Assert.assertTrue("fredSound != null", fredSound != null);}
                
                updateFredsVerticalCenter();
                if (isNaN(ctlBobInterval.value) || isNaN(ctlFredInterval.value)) return;
                
                bobSound.frequency = centsToHz(ctlBobInterval.value);
                fredSound.frequency = centsToHz(ctlBobInterval.value + ctlFredInterval.value);
                playBobThenFred.play([this]);
            }
            
            //----------------------------------
            //  ctlFredInterval_changeHandler
            //----------------------------------
            
            // called when the user drags Fred's thumb
            protected function ctlFredInterval_changeHandler(event:Event):void {
                CONFIG::DEBUG {Assert.assertTrue("ctlBobInterval != null", ctlBobInterval != null);}
                CONFIG::DEBUG {Assert.assertTrue("ctlFredInterval != null", ctlFredInterval != null);}
                CONFIG::DEBUG {Assert.assertTrue("bobSound != null", bobSound != null);}
                CONFIG::DEBUG {Assert.assertTrue("fredSound != null", fredSound != null);}
                if (isNaN(ctlBobInterval.value) || isNaN(ctlFredInterval.value)) return;
                
                fredSound.frequency = centsToHz(ctlBobInterval.value + ctlFredInterval.value);
                playBobThenFred.play([this]);
            }
            
            //----------------------------------
            //  ctlFredInterval_playNote
            //----------------------------------
            
            protected function ctlFredInterval_playNote(event:Event):void {
                CONFIG::DEBUG {Assert.assertTrue("ctlBobInterval != null", ctlBobInterval != null);}
                CONFIG::DEBUG {Assert.assertTrue("ctlFredInterval != null", ctlFredInterval != null);}
                CONFIG::DEBUG {Assert.assertTrue("fredSound != null", fredSound != null);}
                if (isNaN(ctlBobInterval.value) || isNaN(ctlFredInterval.value)) return;
                
                fredSound.stop();
                fredSound.frequency = centsToHz(ctlBobInterval.value + ctlFredInterval.value);
                fredSound.start();
            }
            
            //--------------------------------------------------------------------------
            //
            //  Embedded Assets
            //
            //--------------------------------------------------------------------------
            
            // Define a class name for each embedded asset, so that it can be referred to by name
            [Embed("assets/audio/c01_earlier.mp3")]
            public const c01_earlier_MP3:Class;
            
            [Embed("assets/audio/c02_wasA.mp3")]
            public const c02_wasA_MP3:Class;
            
            [Embed("assets/audio/c03_relationshipFrequencies.mp3")]
            public const c03_relationshipFrequencies_MP3:Class;
            
            [Embed("assets/audio/c04_andThatThis.mp3")]
            public const c04_andThatThis_MP3:Class;
            
            [Embed("assets/audio/c05_isA.mp3")]
            public const c05_isA_MP3:Class;
            
            [Embed("assets/audio/c06_sequenceOfIntervals.mp3")]
            public const c06_sequenceOfIntervals_MP3:Class;
            
            [Embed("assets/audio/c07_weAlsoLearned.mp3")]
            public const c07_weAlsoLearned_MP3:Class;
            
            [Embed("assets/audio/c08_useTheseControls.mp3")]
            public const c08_useTheseControls_MP3:Class;
            
            [Embed("assets/audio/c09_beforeWeCanStudy.mp3")]
            public const c09_beforeWeCanStudy_MP3:Class;
            
            [Embed("assets/audio/c10_the1stIntervalToLearn.mp3")]
            public const c10_the1stIntervalToLearn_MP3:Class;
            
            [Embed("assets/audio/c11_isTheOctave.mp3")]
            public const c11_isTheOctave_MP3:Class;
            
            [Embed("assets/audio/c12_twoToOne.mp3")]
            public const c12_twoToOne_MP3:Class;
            
            [Embed("assets/audio/c13_if1SoundsFreq.mp3")]
            public const c13_if1SoundsFreq_MP3:Class;
            
            [Embed("assets/audio/c14_consider1TimesBob.mp3")]
            public const c14_consider1TimesBob_MP3:Class;
            
            [Embed("assets/audio/c15_and2TimesBob.mp3")]
            public const c15_and2TimesBob_MP3:Class;
            
            [Embed("assets/audio/c16_2BobIsTwice1Bob.mp3")]
            public const c16_2BobIsTwice1Bob_MP3:Class;
            
            [Embed("assets/audio/c17_soTheyAreOctaveApart.mp3")]
            public const c17_soTheyAreOctaveApart_MP3:Class;
            
            [Embed("assets/audio/c18_likewise.mp3")]
            public const c18_likewise_MP3:Class;
            
            [Embed("assets/audio/c19_soTheyAreOctaveApartToo.mp3")]
            public const c19_soTheyAreOctaveApartToo_MP3:Class;
            
            [Embed("assets/audio/c20_question1.mp3")]
            public const c20_question1_MP3:Class;
            
            [Embed("assets/audio/c21_question2.mp3")]
            public const c21_question2_MP3:Class;            
            
            [Embed("assets/audio/c22_theHumanEar.mp3")]
            public const c22_theHumanEar_MP3:Class;            
            
            [Embed("assets/audio/c22a_letsIncreaseFredsRange.mp3")]
            public const c22a_letsIncreaseFredsRange_MP3:Class;            
            
            [Embed("assets/audio/c23_nowFredsSlider.mp3")]
            public const c23_nowFredsSlider_MP3:Class;        
            
            [Embed("assets/audio/c24_one.mp3")]
            public const c24_one_MP3:Class;    
            
            [Embed("assets/audio/c25_two.mp3")]
            public const c25_two_MP3:Class;    
            
            [Embed("assets/audio/c26_three.mp3")]
            public const c26_three_MP3:Class;            
            
            [Embed("assets/audio/c27_four.mp3")]
            public const c27_four_MP3:Class;            
            
            [Embed("assets/audio/c27a_useFredsSlider.mp3")]
            public const c27a_useFredsSlider_MP3:Class;            
            
            [Embed("assets/audio/c28_fredUsesASimpler.mp3")]
            public const c28_fredUsesASimpler_MP3:Class;            
            
            [Embed("assets/audio/c29_heCallsOneTimesBob.mp3")]
            public const c29_heCallsOneTimesBob_MP3:Class;            
            
            [Embed("assets/audio/c30_bobZeroIsThe.mp3")]
            public const c30_bobZeroIsThe_MP3:Class;            
            
            [Embed("assets/audio/c31_low.mp3")]
            public const c31_low_MP3:Class;            
            
            [Embed("assets/audio/c32_orAnywhereInBetween.mp3")]
            public const c32_orAnywhereInBetween_MP3:Class;            
            
            [Embed("assets/audio/c32a_theFreqThats1OctHigher.mp3")]
            public const c32a_theFreqThats1OctHigher_MP3:Class;            
            
            [Embed("assets/audio/c33_fredCallsBob1.mp3")]
            public const c33_fredCallsBob1_MP3:Class;            
            
            [Embed("assets/audio/c33a_bob1IsOneOctHigher.mp3")]
            public const c33a_bob1IsOneOctHigher_MP3:Class;            
            
            [Embed("assets/audio/c34_4TimesBobIs.mp3")]
            public const c34_4TimesBobIs_MP3:Class;            
            
            [Embed("assets/audio/c35_soFredCallsItBob2.mp3")]
            public const c35_soFredCallsItBob2_MP3:Class;            
            
            [Embed("assets/audio/c36_1OctaveBelowBob0.mp3")]
            public const c36_1OctaveBelowBob0_MP3:Class;
            
            [Embed("assets/audio/c37_fredUsesNegative.mp3")]
            public const c37_fredUsesNegative_MP3:Class;            
            
            [Embed("assets/audio/c38_one4thTimesBob.mp3")]
            public const c38_one4thTimesBob_MP3:Class;            
            
            [Embed("assets/audio/c38a_soFredCallsItBobMinus2.mp3")]
            public const c39_soFredCallsItBobMinus2_MP3:Class;
            
            [Embed("assets/audio/c40_usingFredsOctaveNaming.mp3")]
            public const c40_usingFredsOctaveNaming_MP3:Class;
            
            [Embed("assets/audio/c41_q1freq3OctAbove.mp3")]
            public const c41_q1freq3OctAbove_MP3:Class;            
            
            [Embed("assets/audio/c42_q2freq4OctAbove.mp3")]
            public const c42_q2freq4OctAbove_MP3:Class;
            
            [Embed("assets/audio/c43_q3freq3OctBelow.mp3")]
            public const c43_q3freq3OctBelow_MP3:Class;        
            
            [Embed("assets/audio/c44_q4freq4OctBelow.mp3")]
            public const c44_q4freq4OctBelow_MP3:Class;
            
            [Embed("assets/audio/c39_iLikeFredsNaming.mp3")]
            public const c45_iLikeFredsNaming_MP3:Class;
        ]]>
    </fx:Script>
</s:Application>