示例#1
0
文件: Grp.cs 项目: notator/Moritz
 /// <summary>
 /// Used by Clone.
 /// </summary>
 public Grp(Gamut gamut, int midiChannel, int msPositionReContainer, List<IUniqueDef> clonedIUDs)
     : base(midiChannel, msPositionReContainer, clonedIUDs)
 {
     Debug.Assert(gamut != null && gamut.ContainsAllPitches(clonedIUDs));
     _gamut = gamut;
     SetBeamEnd();
 }
示例#2
0
        //rootOctave = 4;
        //pitchesPerChord = 6;
        //msDurationPerChord = 200; // dummy, durations are set from pitches below in the ctor
        //velocityFactor = 0.5; // dummy, velocities are set from absolute pitches below in the ctor
        /// <summary>
        /// An exception will be thrown if the gamut argument is null.
        /// </summary>
        /// <param name="gamut"></param>
        public TenorPaletteGrp(Gamut gamut)
            : base(gamut, 4, 6, 200, gamut.NPitchesPerOctave, 0.5)
        {
            _minimumVelocity = 20;
            _maximumVelocity = 127;
            _velocityPerAbsolutePitch = gamut.GetVelocityPerAbsolutePitch(_minimumVelocity, _maximumVelocity);

            base.SetVelocityPerAbsolutePitch(_velocityPerAbsolutePitch, (byte)_minimumVelocity);

            int minMsDuration = 200;
            int maxMsDuration = 300;
            SetDurationsFromPitches(maxMsDuration, minMsDuration, true);
        }
示例#3
0
        /// <summary>
        /// A MidiChordDef having msDuration, and containing an ornament having BasicMidiChordDefs with nPitchesPerChord.
        /// The notated pitch and the pitch of BasicMidiChordDefs[0] are set to rootNotatedPitch.
        /// The notated velocity of all pitches is set to 127.
        /// The root pitches of the BasicMidiChordDefs begin with rootNotatedPitch, and follow the ornamentEnvelope, using
        /// the ornamentEnvelope's values as indices in the gamut. Their durations are as equal as possible, to give the
        /// overall msDuration. If ornamentEnvelope is null, a single, one-note BasicMidiChordDef will be created.
        /// This constructor uses Gamut.GetChord(rootNotatedPitch, nPitchesPerChord) which returns pitches that are
        /// vertically spaced differently according to the absolute height of the rootNotatedPitch. The number of pitches
        /// in a chord may also be less than nPitchesPerChord (see gamut.GetChord(...) ).
        /// An exception is thrown if rootNotatedPitch is not in the gamut.
        /// </summary>        
        /// <param name="msDuration">The duration of this MidiChordDef</param>
        /// <param name="gamut">The gamut containing all the pitches.</param>
        /// <param name="rootNotatedPitch">The lowest notated pitch. Also the lowest pitch of BasicMidiChordDefs[0].</param>
        /// <param name="nPitchesPerChord">The chord density (some chords may have less pitches).</param>
        /// <param name="ornamentEnvelope">The ornament definition.</param>
        public MidiChordDef(int msDuration, Gamut gamut, int rootNotatedPitch, int nPitchesPerChord, Envelope ornamentEnvelope = null)
            : base(msDuration) 
        {
            NotatedMidiPitches = gamut.GetChord(rootNotatedPitch, nPitchesPerChord);
            var nmVelocities = new List<byte>();
            foreach(byte pitch in NotatedMidiPitches) // can be less than nPitchesPerChord
            {
                nmVelocities.Add(127);
            }
            NotatedMidiVelocities = nmVelocities;

            // Sets BasicMidiChords. If ornamentEnvelope == null, BasicMidiChords[0] is set to the NotatedMidiChord.
            SetOrnament(gamut, ornamentEnvelope);
        }
示例#4
0
文件: Grp.cs 项目: notator/Moritz
        /// <summary>
        /// Grp objects own unique IUniqueDefs, but can share Gamuts. The Gamut may not be null.
        /// </summary>
        /// <param name="gamut">can not be null</param>
        /// <param name="rootOctave">must be greater than or equal to 0</param>
        /// <param name="nPitchesPerChord">must be greater than 0</param>
        /// <param name="msDurationPerChord">must be greater than 0</param>
        /// <param name="nChords">must be greater than 0</param>
        /// <param name="velocityFactor">must be greater than 0.0</param>
        public Grp(Gamut gamut, int rootOctave, int nPitchesPerChord, int msDurationPerChord, int nChords, double velocityFactor)
            : base(0, 0, new List<IUniqueDef>())
        {
            Debug.Assert(gamut != null);
            Debug.Assert(rootOctave >= 0);
            Debug.Assert(nPitchesPerChord > 0);
            Debug.Assert(msDurationPerChord > 0);
            Debug.Assert(nChords > 0);
            Debug.Assert(velocityFactor > 0.0);

            _gamut = gamut;

            for(int i = 0; i < nChords; ++i)
            {
                int rootNotatedPitch;
                if(i == 0)
                {
                    rootNotatedPitch = gamut.AbsolutePitchHierarchy[i] + (12 * rootOctave);
                    rootNotatedPitch = (rootNotatedPitch <= gamut.MaxPitch) ? rootNotatedPitch : gamut.MaxPitch;
                }
                else
                {
                    List<byte> previousPitches = ((MidiChordDef)_uniqueDefs[i - 1]).BasicMidiChordDefs[0].Pitches;
                    if(previousPitches.Count > 1)
                    {
                        rootNotatedPitch = previousPitches[1];
                    }
                    else
                    {
                        rootNotatedPitch = gamut.AbsolutePitchHierarchy[i];
                        while(rootNotatedPitch < previousPitches[0])
                        {
                            rootNotatedPitch += 12;
                            if(rootNotatedPitch > gamut.MaxPitch)
                            {
                                rootNotatedPitch = gamut.MaxPitch;
                                break;
                            }
                        }
                    }
                }
                MidiChordDef mcd = new MidiChordDef(msDurationPerChord, gamut, rootNotatedPitch, nPitchesPerChord, null);
                mcd.AdjustVelocities(velocityFactor);
                _uniqueDefs.Add(mcd);
            }

            SetBeamEnd();
        }
示例#5
0
        /// <summary>
        /// A BasicMidiChordDef having density notes. Absent fields are set to 0 or null.
        /// Note that the number of pitches returned can be less than nPitches. Pitches that would be higher than 127 are
        /// simply not added to the returned list.
        /// All pitches are given velocity = 127.
        /// The pitches are found using the function gamut.GetChord(rootPitch, density). See that function for further documentation.
        /// </summary>
        /// <param name="msDuration">The duration</param>
        /// <param name="gamut"></param>
        /// <param name="rootPitch">The lowest pitch</param>
        /// <param name="density">The number of pitches. The actual number created can be smaller.</param>
        public BasicMidiChordDef(int msDuration, Gamut gamut, int rootPitch, int density)
        {
            #region conditions
            Debug.Assert(density > 0 && density <= 12);
            Debug.Assert(rootPitch >= 0 && rootPitch <= 127);
            Debug.Assert(msDuration > 0);
            #endregion conditions

            _msDuration = msDuration; // read-only!

            Pitches = gamut.GetChord(rootPitch, density);
            var newVelocities = new List<byte>();
            foreach(byte pitch in Pitches) // can be less than nPitchesPerChord
            {
                newVelocities.Add(127);
            }
            Velocities = newVelocities;
        }
示例#6
0
        /// <summary>
        /// Returns a new, related TenorPaletteGrp whose Gamut has the new pitchHierarchyIndex % 22.
        /// Throws an exception if this.Gamut == null.
        /// </summary>
        /// <param name="pitchHierarchyIndex">the pitchHierarchyIndex of the returned TenorPaletteGrp's Gamut (will be treated % 22)</param>
        internal TenorPaletteGrp RelatedPitchHierarchyGrp(int pitchHierarchyIndex)
        {
            pitchHierarchyIndex %= 22;

            Debug.Assert(Gamut != null);

            Gamut gamut = new Gamut(pitchHierarchyIndex, Gamut.BasePitch, Gamut.NPitchesPerOctave);

            TenorPaletteGrp newTenorPaletteGrp = new TenorPaletteGrp(gamut);

            return newTenorPaletteGrp;
        }
示例#7
0
        /// <summary>
        /// Returns a new, related TenorPaletteGrp having the new domain % 12.
        /// </summary>
        /// <param name="domain">the the number of chords in the returned TenorPaletteGrp, and the nPitchesPerOctave of its Gamut (will be treated % 12)</param>
        internal TenorPaletteGrp RelatedDomainGrp(int domain)
        {
            domain %= 12;

            Gamut gamut = new Gamut(Gamut.RelativePitchHierarchyIndex, Gamut.BasePitch, domain);

            TenorPaletteGrp newTenorPaletteGrp = new TenorPaletteGrp(gamut);

            return newTenorPaletteGrp;
        }
示例#8
0
        /// <summary>
        /// Returns a new, related TenorPaletteGrp whose Gamut has the new basePitch % 12.
        /// Throws an exception if this.Gamut == null.
        /// </summary>
        /// <param name="basePitch">the basePitch of the returned TenorPaletteGrp's Gamut (will be treated % 12)</param>
        internal TenorPaletteGrp RelatedBasePitchGrp(int basePitch)
        {
            basePitch %= 12;

            Debug.Assert(Gamut != null);

            Gamut gamut = new Gamut(Gamut.RelativePitchHierarchyIndex, basePitch, Gamut.NPitchesPerOctave);

            TenorPaletteGrp newTenorPaletteGrp = new TenorPaletteGrp(gamut);

            return newTenorPaletteGrp;
        }
示例#9
0
        private byte DoTranspose(byte initialValue, Gamut gamut, int steps)
        {
            int index = gamut.IndexOf(initialValue);
            int newIndex = index + steps;
            newIndex = (newIndex >= 0) ? newIndex : 0;
            newIndex = (newIndex < gamut.Count) ? newIndex : gamut.Count - 1;

            return (byte)gamut[newIndex];
        }
示例#10
0
文件: Grp.cs 项目: notator/Moritz
        /// <summary>
        /// Returns the index of a pitch in the same octave as the pitch at pitchIndexInOldGamut.
        /// </summary>
        /// <param name="oldGamut">may not be null</param>
        /// <param name="newGamut">may not be null</param>
        /// <param name="pitchIndexInOldGamut"></param>
        /// <returns></returns>
        private int GetPitchIndexInNewGamut(Gamut oldGamut, Gamut newGamut, int pitchIndexInOldGamut)
        {
            Debug.Assert(oldGamut != null && newGamut != null);

            int oldNPitchesPerOctave = oldGamut.NPitchesPerOctave;
            int octave = pitchIndexInOldGamut / oldNPitchesPerOctave;
            int oldPitchIndexInOctave = pitchIndexInOldGamut - (octave * oldNPitchesPerOctave);
            int newNPitchesPerOctave = newGamut.NPitchesPerOctave;

            // find the minimum angular distance between the oldPitchIndexInOctave and any newPitchIndexInOctave
            double oldRadians = oldPitchIndexInOctave * ((2 * Math.PI) / oldNPitchesPerOctave);
            int newPitchIndexInOctave = 0;
            double currentMinDelta = Double.MaxValue;
            for(int i = 0; i < newNPitchesPerOctave; ++i)
            {
                double newRadians = i * ((2 * Math.PI) / newNPitchesPerOctave);
                double delta1Abs = (newRadians > oldRadians) ? newRadians - oldRadians : oldRadians - newRadians;
                double oldRadiansPlus2pi = oldRadians + (2 * Math.PI);
                double delta2Abs = (newRadians > oldRadiansPlus2pi) ? newRadians - oldRadiansPlus2pi : oldRadiansPlus2pi - newRadians;
                double minDelta = (delta1Abs < delta2Abs) ? delta1Abs : delta2Abs;
                if(minDelta < currentMinDelta)
                {
                    currentMinDelta = minDelta;
                    newPitchIndexInOctave = i;
                }
            }

            int newPitchIndex = newPitchIndexInOctave + (octave * newNPitchesPerOctave);
            newPitchIndex = (newPitchIndex < newGamut.Count) ? newPitchIndex : newGamut.Count - 1;

            return newPitchIndex;
        }
示例#11
0
        /// <summary>
        /// All the pitches in the MidiChordDef must be contained in the gamut.
        /// Transposes the pitches in NotatedMidiPitches, and all BasicMidiChordDef.Pitches by
        /// the number of steps in the gamut. Negative values transpose down.
        /// The vertical velocity sequence remains unchanged except when notes are removed.
        /// It is not an error if Midi values would exceed the range of the gamut.
        /// In this case, they are silently coerced to the bottom or top notes of the gamut respectively.
        /// Duplicate top and bottom gamut pitches are removed.
        /// </summary>
        public void TransposeStepsInGamut(Gamut gamut, int steps)
        {
            #region conditions
            Debug.Assert(gamut != null);
            foreach(BasicMidiChordDef bmcd in BasicMidiChordDefs)
            {
                foreach(int pitch in bmcd.Pitches)
                {
                    Debug.Assert(gamut.Contains(pitch));
                }
            }
            #endregion conditions

            int bottomMostPitch = gamut[0];
            int topMostPitch = gamut[gamut.Count - 1];

            foreach(BasicMidiChordDef bmcd in BasicMidiChordDefs)
            {
                List<byte> pitches = bmcd.Pitches;
                List<byte> velocities = bmcd.Velocities;
                for(int i = 0; i < pitches.Count; ++i)
                {
                    pitches[i] = DoTranspose(pitches[i], gamut, steps);
                }
                RemoveDuplicateNotes(pitches, velocities);
            }

            SetNotatedValuesFromFirstBMCD();
        }
示例#12
0
        /// <summary>
        /// Sets an ornament having the shape and number of elements in the ornamentEnvelope.
        /// If ornamentEnvelope == null, BasicMidiChords[0] is set to the NotatedMidiChord.
        /// using the NotatedMidiPitches as the first chord.
        /// Uses the current Gamut.
        /// Replaces any existing ornament.
        /// Sets the OrnamentNumberSymbol to the number of BasicMidiChordDefs.
        /// </summary>
        /// <param name="ornamentEnvelope"></param>
        public void SetOrnament(Gamut gamut, Envelope ornamentEnvelope)
        {
            Debug.Assert(gamut != null);
            List<int> basicMidiChordRootPitches = gamut.PitchSequence(_notatedMidiPitches[0], ornamentEnvelope);
            // If ornamentEnvelope is null, basicMidiChordRootPitches will only contain rootNotatedpitch.

            BasicMidiChordDefs = new List<BasicMidiChordDef>();
            foreach(int rootPitch in basicMidiChordRootPitches)
            {
                BasicMidiChordDef bmcd = new BasicMidiChordDef(1000, gamut, rootPitch, _notatedMidiPitches.Count);
                BasicMidiChordDefs.Add(bmcd);
            }
            this.MsDuration = _msDuration; // resets the BasicMidiChordDef msDurations.

            if(basicMidiChordRootPitches.Count > 1)
            {
                _ornamentNumberSymbol = basicMidiChordRootPitches.Count;
            }
        }
示例#13
0
 /// <summary>
 /// Calls the other SetOrnament function
 /// </summary>
 /// <param name="ornamentShape"></param>
 /// <param name="nOrnamentChords"></param>
 public void SetOrnament(Gamut gamut, IReadOnlyList<byte> ornamentShape, int nOrnamentChords)
 {
     int nPitchesPerOctave = gamut.NPitchesPerOctave;
     Envelope ornamentEnvelope = new Envelope(ornamentShape, 127, nPitchesPerOctave, nOrnamentChords);
     SetOrnament(gamut, ornamentEnvelope);
 }
示例#14
0
 private void OppositePitches(Gamut gamut, Gamut oppositeGamut, List<byte> pitches)
 {
     for(int i = 0; i < pitches.Count; ++i)
     {
         int pitchIndex = gamut.IndexOf(pitches[i]);
         // N.B. it is not necessarily true that gamut.Count == oppositeGamut.Count.
         pitchIndex = (pitchIndex < oppositeGamut.Count) ? pitchIndex : oppositeGamut.Count - 1;
         pitches[i] = (byte)oppositeGamut[pitchIndex];
     }
 }
示例#15
0
        /// <summary>
        /// 1. Creates a new, opposite gamut from the argument Gamut (see Gamut.Opposite()).
        /// 2. Clones this MidiChordDef, and replaces the clone's pitches by the equivalent pitches in the opposite Gamut.
        /// 3. Returns the clone.
        /// </summary>
        public MidiChordDef Opposite(Gamut gamut)
        {
            #region conditions
            Debug.Assert(gamut != null);
            #endregion conditions

            int relativePitchHierarchyIndex = (gamut.RelativePitchHierarchyIndex + 11) % 22;
            Gamut oppositeGamut = new Gamut(relativePitchHierarchyIndex, gamut.BasePitch, gamut.NPitchesPerOctave);
            MidiChordDef oppositeMCD = (MidiChordDef)Clone();

            #region conditions
            Debug.Assert(gamut[0] == oppositeGamut[0]);
            Debug.Assert(gamut.NPitchesPerOctave == oppositeGamut.NPitchesPerOctave);
            // N.B. it is not necessarily true that gamut.Count == oppositeGamut.Count.
            #endregion conditions

            // Substitute the oppositeMCD's pitches by the equivalent pitches in the oppositeGamut.
            OppositePitches(gamut, oppositeGamut, oppositeMCD.NotatedMidiPitches);
            foreach(BasicMidiChordDef bmcd in oppositeMCD.BasicMidiChordDefs)
            {
                OppositePitches(gamut, oppositeGamut, bmcd.Pitches);
            }

            return oppositeMCD;
        }
示例#16
0
        /// <summary>
        /// Creates a list of TenorPaletteGrps, each of which has the same relativePitchHierarchyIndex.
        /// </summary>
        private List<Grp> GetTenorPaletteGrpList(int relativePitchHierarchyIndex)
        {
            const int gamutBasePitch = 0;
            List<Grp> grps = new List<Grp>();

            for(int i = 0, domain = 12; domain >= 1; --domain, ++i) // domain is both Gamut.PitchesPerOctave and nChords per Grp
            {
                Gamut gamut = new Gamut(relativePitchHierarchyIndex, gamutBasePitch, domain);

                TenorPaletteGrp tpg = new TenorPaletteGrp(gamut);

                #region begin test code 1 Shear and permute
                tpg.Shear(0, -1 * (gamut.NPitchesPerOctave));
                tpg.SetVelocitiesForGamut();

                if(domain % 2 != 0)
                {
                    tpg.Permute(1, 7);
                }
                #endregion end test code 1

                #region begin test code 2 transpose chords to the same absolute root pitch
                //for(int iudIndex = 0; iudIndex < tpg.Count; ++iudIndex)
                //{
                //    tpg.TransposeChordDownToAbsolutePitch(iudIndex, 0);
                //}
                #endregion end test code 2

                #region begin test code 3, adjust velocities
                //if(domain % 2 != 0)
                //{
                //    tpg.AdjustVelocities(0.5);
                //}
                #endregion

                #region begin test code 4, adjust velocities
                //if(domain % 2 != 0 && tpg.Count > 1)
                //{
                //    tpg.AdjustVelocitiesHairpin(0, tpg.Count - 1, 0.5, 1.0);
                //}
                #endregion

                #region begin test code 5, related Grps
                //if(domain % 2 != 0 && tpg.Count > 1)
                //{
                //    TenorPaletteGrp previousTpg = (TenorPaletteGrp)grps[i - 1];
                //    //tpg = previousTpg.RelatedPitchHierarchyGrp(previousTpg.Gamut.RelativePitchHierarchyIndex + 11);
                //    //tpg = previousTpg.RelatedBasePitchGrp(11);
                //    tpg = previousTpg.RelatedDomainGrp(6);
                //}
                #endregion

                #region begin test code 6, timeWarp
                //if(domain % 2 != 0 && tpg.Count > 1)
                //{
                //    tpg.TimeWarp(new Envelope(new List<int>() { 4, 7, 2 }, 7, 7, tpg.Count), 20);
                //}
                #endregion

                #region begin test code 7, SetPitchWheelSliders
                //Envelope env = new Envelope(new List<int>() { 0,8 }, 8, 127, tpg.Count);
                //tpg.SetPitchWheelSliders(env);
                #endregion

                #region begin test code 8, SetPanGliss
                //if(tpg.Count > 1)
                //{
                //    if(domain % 2 != 0)
                //    {
                //        tpg.SetPanGliss(0, tpg.Count - 1, 127, 0);
                //    }
                //    else
                //    {
                //        tpg.SetPanGliss(0, tpg.Count - 1, 0, 127);
                //    }
                //}
                #endregion

                #region begin test code 8, set inverse velocities
                //if(domain % 2 != 0 && tpg.Count > 1)
                //{
                //    TenorPaletteGrp prevTpg = (TenorPaletteGrp)grps[i - 1];
                //    Gamut prevGamut = prevTpg.Gamut;
                //    tpg = new TenorPaletteGrp(prevGamut); // identical to prevTpg
                //    // inverse velocityPerAbsolutePitch
                //    List<byte> velocityPerAbsolutePitch = prevGamut.GetVelocityPerAbsolutePitch(20, 127, prevGamut.NPitchesPerOctave - 1);
                //    tpg.SetVelocityPerAbsolutePitch(velocityPerAbsolutePitch, 20);
                //}
                #endregion

                #region begin test code 8, set Gamut (pitches
                //if(domain % 2 != 0 && tpg.Count > 1)
                //{
                //    TenorPaletteGrp prevTpg = (TenorPaletteGrp)grps[i - 1];
                //    Gamut prevGamut = prevTpg.Gamut;
                //    tpg = new TenorPaletteGrp(prevGamut); // identical to prevTpg

                //    int newRelativePitchHierarchyIndex = prevGamut.RelativePitchHierarchyIndex + 11;
                //    int newBasePitch = prevGamut.BasePitch;
                //    int newNPitchesPerOctave = 8;
                //    Gamut gamut1 = new Gamut(newRelativePitchHierarchyIndex, newBasePitch, newNPitchesPerOctave);
                //    tpg.Gamut = gamut1; // sets the pitches, velocities are still those of the original pitches.

                //    // reverse the velocityperAbsolutePitch hierarchy re the prevGamut.
                //    List<byte> velocityPerAbsolutePitch = prevGamut.GetVelocityPerAbsolutePitch(20, 127, prevGamut.NPitchesPerOctave - 1);
                //    tpg.SetVelocityPerAbsolutePitch(velocityPerAbsolutePitch, 20);
                //}
                #endregion

                grps.Add(tpg);
            }

            return (grps);
        }
示例#17
0
        /// <summary>
        /// The rootPitch and all the pitches in the MidiChordDef must be contained in the gamut.
        /// The vertical velocity sequence remains unchanged except when notes are removed because they are duplicates.
        /// Calculates the number of steps to transpose, and then calls TransposeStepsInGamut.
        /// When this function returns, rootPitch is the lowest pitch in both BasicMidiChordDefs[0] and NotatedMidiPitches.
        /// </summary>
        public void TransposeToRootInGamut(Gamut gamut, int rootPitch)
        {
            #region conditions
            Debug.Assert(gamut != null);
            Debug.Assert(gamut.Contains(rootPitch));
            Debug.Assert(gamut.Contains(BasicMidiChordDefs[0].Pitches[0]));
            #endregion conditions

            int stepsToTranspose = gamut.IndexOf(rootPitch) - gamut.IndexOf(BasicMidiChordDefs[0].Pitches[0]);

            // checks that all the pitches are in the gamut.
            TransposeStepsInGamut(gamut, stepsToTranspose);
        }