Beispiel #1
0
        /// <summary>
        /// ACHTUNG: This function is deprecated!! Use the other AdjustVelocitiesHairpin(...).
        /// First creates a hairpin in the velocities from beginIndex to endIndex (non-inclusive),
        /// then adjusts all the remaining velocities in this VoiceDef by the finalFactor.
        /// endIndex must be greater than beginIndex + 1.
        /// The factors by which the velocities are multiplied change arithmetically: The velocities
        /// at beginIndex are multiplied by 1.0, and the velocities from endIndex to the end of the
        /// VoiceDef by finalFactor.
        /// Can be used to create a diminuendo or crescendo.
        /// </summary>
        /// <param name="beginDimIndex"></param>
        /// <param name="endDimIndex"></param>
        /// <param name="p"></param>
        public void AdjustVelocitiesHairpin(int beginIndex, int endIndex, double finalFactor)
        {
            Debug.Assert(((beginIndex + 1) < endIndex) && (finalFactor >= 0) && (endIndex <= Count));

            int nNonMidiChordDefs = GetNumberOfNonMidiOrInputChordDefs(beginIndex, endIndex);

            double factorIncrement = (finalFactor - 1.0) / (endIndex - beginIndex - nNonMidiChordDefs);
            double factor          = 1.0;

            for (int i = beginIndex; i < endIndex; ++i)
            {
                MidiChordDef iumdd = _uniqueDefs[i] as MidiChordDef;
                if (iumdd != null)
                {
                    iumdd.AdjustVelocities(factor);
                    factor += factorIncrement;
                }
            }

            for (int i = endIndex; i < _uniqueDefs.Count; ++i)
            {
                MidiChordDef iumdd = _uniqueDefs[i] as MidiChordDef;
                if (iumdd != null)
                {
                    iumdd.AdjustVelocities(factor);
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Stretch or compress all the durations in the list to fit the given total duration.
        /// This does not change the VoiceDef's MsPosition, but does affect its EndMsPosition.
        /// </summary>
        /// <param name="msDuration"></param>
        public void SetMsDuration(int msDuration)
        {
            Debug.Assert(msDuration > 0);

            List <int> relativeDurations = new List <int>();

            foreach (IUniqueDef iumdd in _uniqueDefs)
            {
                if (iumdd.MsDuration > 0)
                {
                    relativeDurations.Add(iumdd.MsDuration);
                }
            }

            List <int> newDurations = MidiChordDef.GetIntDurations(msDuration, relativeDurations, relativeDurations.Count);

            Debug.Assert(newDurations.Count == relativeDurations.Count);
            int i        = 0;
            int newTotal = 0;

            foreach (IUniqueDef iumdd in _uniqueDefs)
            {
                if (iumdd.MsDuration > 0)
                {
                    iumdd.MsDuration = newDurations[i];
                    newTotal        += iumdd.MsDuration;
                    ++i;
                }
            }

            Debug.Assert(msDuration == newTotal);

            SetMsPositions();
        }
Beispiel #3
0
        /// <summary>
        /// Creates a moving pan from startPanValue at startMsPosition to endPanValue at endMsPosition.
        /// Implemented using one pan value per MidiChordDef.
        /// This function does NOT change pan values outside the position range given in its arguments.
        /// </summary>
        public void SetPanGliss(int startMsPosition, int endMsPosition, int startPanValue, int endPanValue)
        {
            int beginIndex = FindIndexAtMsPosition(startMsPosition);
            int endIndex   = FindIndexAtMsPosition(endMsPosition);

            Debug.Assert(((beginIndex + 1) < endIndex) && (startPanValue >= 0) && (startPanValue <= 127) &&
                         (endPanValue >= 0) && (endPanValue <= 127) && (endIndex <= Count));

            int nNonMidiChordDefs = GetNumberOfNonMidiOrInputChordDefs(beginIndex, endIndex);

            double            increment = ((double)(endPanValue - startPanValue)) / (endIndex - beginIndex - nNonMidiChordDefs);
            int               panValue  = startPanValue;
            List <IUniqueDef> lmdds     = _uniqueDefs;

            for (int i = beginIndex; i < endIndex; ++i)
            {
                MidiChordDef iumdd = _uniqueDefs[i] as MidiChordDef;
                if (iumdd != null)
                {
                    iumdd.PanMsbs = new List <byte>()
                    {
                        (byte)panValue
                    };
                    panValue += (int)increment;
                }
            }
        }
Beispiel #4
0
        /// <summary>
        /// Creates a new TrkDef containing just the argument midiChordDef,
        /// then calls the other InsertInRest() function with the voiceDef as argument.
        /// </summary>
        public void InsertInRest(MidiChordDef midiChordDef)
        {
            List <IUniqueDef> iuds = new List <IUniqueDef>()
            {
                midiChordDef
            };
            TrkDef trkDefToInsert = new TrkDef(this.MidiChannel, iuds);

            InsertInRest(trkDefToInsert);
        }
Beispiel #5
0
 /// <summary>
 /// Multiplies each velocity value in the MidiChordDefs
 /// from beginIndex to (not including) endIndex by the argument factor.
 /// </summary>
 public void AdjustVelocities(int beginIndex, int endIndex, double factor)
 {
     CheckIndices(beginIndex, endIndex);
     for (int i = beginIndex; i < endIndex; ++i)
     {
         MidiChordDef iumdd = _uniqueDefs[i] as MidiChordDef;
         if (iumdd != null)
         {
             iumdd.AdjustVelocities(factor);
         }
     }
 }
Beispiel #6
0
        /// <summary>
        /// Sets the pitchwheelDeviation for MidichordDefs in the range beginIndex to (not including) endindex.
        /// Rests in the range dont change.
        /// </summary>
        public void SetPitchWheelDeviation(int beginIndex, int endIndex, int deviation)
        {
            CheckIndices(beginIndex, endIndex);

            for (int i = beginIndex; i < endIndex; ++i)
            {
                MidiChordDef mcd = this[i] as MidiChordDef;
                if (mcd != null)
                {
                    mcd.PitchWheelDeviation = M.MidiValue(deviation);
                }
            }
        }
Beispiel #7
0
        /// <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();
        }
Beispiel #8
0
        public MidiChord(int channel, MidiChordDef midiChordDef, OutputDevice midiOutputDevice)
            : base(channel, 0, midiChordDef.MsDuration)
        {
            _midiOutputDevice = midiOutputDevice;

            List<BasicMidiChordDef> basicMidiChordDefs = midiChordDef.BasicMidiChordDefs;
            Debug.Assert(basicMidiChordDefs.Count > 0);
            List<int> realBasicMidiChordDurations = MidiChordDef.GetIntDurations(MsDuration, midiChordDef.BasicChordDurations, basicMidiChordDefs.Count);

            var notesToStop = new SortedSet<byte>();
            int i = 0;
            foreach(BasicMidiChordDef basicMidiChordDef in midiChordDef.BasicMidiChordDefs)
            {
                this._basicMidiChords.Add(new BasicMidiChord(channel, this, basicMidiChordDef, realBasicMidiChordDurations[i++]));
                if(basicMidiChordDef.HasChordOff)
                {
                    foreach(byte note in basicMidiChordDef.Pitches)
                    {
                        if(!notesToStop.Contains(note))
                            notesToStop.Add(note);
                    }
                }
            }

            if(midiChordDef.Bank != null)
            {
                _bank = new BankControl(channel, (byte)midiChordDef.Bank);
            }
            if(midiChordDef.Patch != null)
            {
                _patch = new PatchControl(channel, (byte)midiChordDef.Patch);
            }

            // Moritz currently never repeats MidiChords, so the _repeat field is unnecessary.
            // However: the value of midiChordDef.Repeat is saved in SVG-MIDI files,
            // and may be used by the web AssistantPerformer.
            //_repeat = midiChordDef.Repeat;

            if(midiChordDef.PitchWheelDeviation != null)
            {
                _pitchWheelDeviation = new PitchWheelDeviation(channel, (byte)midiChordDef.PitchWheelDeviation);
            }
            if(midiChordDef.MidiChordSliderDefs != null)
                CreateSliders(channel, midiChordDef.MidiChordSliderDefs, MsDuration);

            SetMessagesDict();
        }
Beispiel #9
0
        /// <summary>
        /// Removes the pitchwheel commands (not the pitchwheelDeviations)
        /// from chords in the range beginIndex to (not including) endIndex.
        /// Rests in the range are not changed.
        /// </summary>
        public void RemoveScorePitchWheelCommands(int beginIndex, int endIndex)
        {
            CheckIndices(beginIndex, endIndex);

            for (int i = beginIndex; i < endIndex; ++i)
            {
                MidiChordDef iumdd = this[i] as MidiChordDef;
                if (iumdd != null)
                {
                    MidiChordDef umcd = iumdd as MidiChordDef;
                    if (umcd != null)
                    {
                        umcd.MidiChordSliderDefs.PitchWheelMsbs = new List <byte>();
                    }
                }
            }
        }
Beispiel #10
0
        public override IUniqueDef DeepClone()
        {
            MidiChordDef rval = new MidiChordDef();

            rval.MsPosition = this.MsPosition;
            // rval.MsDuration must be set after setting BasicMidiChordDefs See below.
            rval.Bank  = this.Bank;
            rval.Patch = this.Patch;
            rval.PitchWheelDeviation = this.PitchWheelDeviation;
            rval.HasChordOff         = this.HasChordOff;
            rval.Lyric = this.Lyric;
            rval.MinimumBasicMidiChordMsDuration = this.MinimumBasicMidiChordMsDuration; // required when changing a midiChord's duration
            rval.NotatedMidiPitches = new List <byte>(this.NotatedMidiPitches);          // the displayed noteheads
            // rval.MidiVelocity must be set after setting BasicMidiChordDefs See below.
            rval.OrnamentNumberSymbol = this.OrnamentNumberSymbol;                       // the displayed ornament number

            MidiChordSliderDefs m = this.MidiChordSliderDefs;
            List <byte>         pitchWheelMsbs      = NewListByteOrNull(m.PitchWheelMsbs);
            List <byte>         panMsbs             = NewListByteOrNull(m.PanMsbs);
            List <byte>         modulationWheelMsbs = NewListByteOrNull(m.ModulationWheelMsbs);
            List <byte>         expressionMsbs      = NewListByteOrNull(m.ExpressionMsbs);

            if (pitchWheelMsbs != null || panMsbs != null || modulationWheelMsbs != null || expressionMsbs != null)
            {
                rval.MidiChordSliderDefs = new MidiChordSliderDefs(pitchWheelMsbs, panMsbs, modulationWheelMsbs, expressionMsbs);
            }
            else
            {
                rval.MidiChordSliderDefs = null;
            }

            List <BasicMidiChordDef> newBs = new List <BasicMidiChordDef>();

            foreach (BasicMidiChordDef b in this.BasicMidiChordDefs)
            {
                List <byte> pitches    = new List <byte>(b.Pitches);
                List <byte> velocities = new List <byte>(b.Velocities);
                newBs.Add(new BasicMidiChordDef(b.MsDuration, b.BankIndex, b.PatchIndex, b.HasChordOff, pitches, velocities));
            }
            rval.BasicMidiChordDefs = newBs;

            rval.MsDuration   = this.MsDuration;
            rval.MidiVelocity = this.MidiVelocity; // needed for displaying dynamics (must be set *after* setting BasicMidiChordDefs)

            return(rval);
        }
Beispiel #11
0
        /// <summary>
        /// Creates an exponential change (per index) of pitchwheelDeviation from startMsPosition to endMsPosition,
        /// </summary>
        /// <param name="finale"></param>
        protected void AdjustPitchWheelDeviations(int startMsPosition, int endMsPosition, int startPwd, int endPwd)
        {
            double furies1StartPwdValue = startPwd, furies1EndPwdValue = endPwd;
            int    beginIndex = FindIndexAtMsPosition(startMsPosition);
            int    endIndex   = FindIndexAtMsPosition(endMsPosition);

            int nNonMidiChordDefs = GetNumberOfNonMidiOrInputChordDefs(beginIndex, endIndex);

            double pwdfactor = Math.Pow(furies1EndPwdValue / furies1StartPwdValue, (double)1 / (endIndex - beginIndex - nNonMidiChordDefs)); // f13.Count'th root of furies1EndPwdValue/furies1StartPwdValue -- the last pwd should be furies1EndPwdValue

            for (int i = beginIndex; i < endIndex; ++i)
            {
                MidiChordDef umc = _uniqueDefs[i] as MidiChordDef;
                if (umc != null)
                {
                    umc.PitchWheelDeviation = M.MidiValue((int)(furies1StartPwdValue * (Math.Pow(pwdfactor, i))));
                }
            }
        }
Beispiel #12
0
        /// <summary>
        /// From startMsPosition to (not including) endMsPosition,
        /// replace all MidiChordDefs or InputChordDefs by UniqueMidiRestDefs, then aglommerate the rests.
        /// </summary>
        public void Erase(int startMsPosition, int endMsPosition)
        {
            int beginIndex = FindIndexAtMsPosition(startMsPosition);
            int endIndex   = FindIndexAtMsPosition(endMsPosition);

            for (int i = beginIndex; i < endIndex; ++i)
            {
                MidiChordDef  mcd = this[i] as MidiChordDef;
                InputChordDef icd = this[i] as InputChordDef;
                IUniqueDef    iud = (mcd == null) ? (IUniqueDef)icd : (IUniqueDef)mcd;
                if (iud != null)
                {
                    RestDef umrd = new RestDef(iud.MsPosition, iud.MsDuration);
                    RemoveAt(i);
                    Insert(i, umrd);
                }
            }

            AgglomerateRests();
        }
Beispiel #13
0
        public OutputChordSymbol(Voice voice, MidiChordDef umcd, int minimumCrotchetDurationMS, float fontSize)
            : base(voice, umcd.MsDuration, umcd.MsPosition, minimumCrotchetDurationMS, fontSize)
        {
            _midiChordDef = umcd;

            _msDurationToNextBarline = umcd.MsDurationToNextBarline;

            SetNoteheadPitches(umcd.NotatedMidiPitches);

            if(umcd.OrnamentNumberSymbol != 0)
            {
                OrnamentText ornamentText = new OrnamentText(this, "~" + umcd.OrnamentNumberSymbol.ToString(), FontHeight);
                DrawObjects.Add(ornamentText);
            }

            if(umcd.Lyric != null)
            {
                LyricText lyric = new LyricText(this, umcd.Lyric, FontHeight);
                DrawObjects.Add(lyric);
            }
        }
Beispiel #14
0
        /// <summary>
        /// Transposes the UniqueDefs from the beginIndex upto (but not including) endIndex
        /// by an equally increasing amount, so that the final MidiChordDef or InputChordDef is transposed by glissInterval.
        /// beginIndex must be less than endIndex.
        /// glissInterval can be negative.
        /// </summary>
        public void StepwiseGliss(int beginIndex, int endIndex, int glissInterval)
        {
            CheckIndices(beginIndex, endIndex);
            Debug.Assert(beginIndex < endIndex);

            int nNonMidiChordDefs = GetNumberOfNonMidiOrInputChordDefs(beginIndex, endIndex);

            int    nSteps   = (endIndex - beginIndex - nNonMidiChordDefs);
            double interval = ((double)glissInterval) / nSteps;
            double step     = interval;

            for (int i = beginIndex; i < endIndex; ++i)
            {
                MidiChordDef    mcd  = _uniqueDefs[i] as MidiChordDef;
                InputChordDef   icd  = _uniqueDefs[i] as InputChordDef;
                IUniqueChordDef iucd = (mcd == null) ? (IUniqueChordDef)icd : (IUniqueChordDef)mcd;
                if (iucd != null)
                {
                    iucd.Transpose((int)Math.Round(interval));
                    interval += step;
                }
            }
        }
Beispiel #15
0
        /// Creates a hairpin in the velocities from startMsPosition to endMsPosition (non-inclusive).
        /// This function does NOT change velocities outside the range given in its arguments.
        /// There must be at least two IUniqueMidiDurationDefs in the msPosition range given in the arguments.
        /// The factors by which the velocities are multiplied change arithmetically:
        /// The velocity of the first IUniqueMidiDurationDefs is multiplied by startFactor, and the velocity
        /// of the last MidiChordDef in range by endFactor.
        /// Can be used to create a diminueno or crescendo.
        public void AdjustVelocitiesHairpin(int startMsPosition, int endMsPosition, double startFactor, double endFactor)
        {
            int beginIndex = FindIndexAtMsPosition(startMsPosition);
            int endIndex   = FindIndexAtMsPosition(endMsPosition);

            Debug.Assert(((beginIndex + 1) < endIndex) && (startFactor >= 0) && (endFactor >= 0) && (endIndex <= Count));

            int nNonMidiChordDefs = GetNumberOfNonMidiOrInputChordDefs(beginIndex, endIndex);

            double            factorIncrement = (endFactor - startFactor) / (endIndex - beginIndex - nNonMidiChordDefs);
            double            factor          = startFactor;
            List <IUniqueDef> lmdds           = _uniqueDefs;

            for (int i = beginIndex; i < endIndex; ++i)
            {
                MidiChordDef iumdd = _uniqueDefs[i] as MidiChordDef;
                if (iumdd != null)
                {
                    iumdd.AdjustVelocities(factor);
                    factor += factorIncrement;
                }
            }
        }
Beispiel #16
0
        private List<IUniqueDef> GetMidiChordDefs(List<int> pitches, List<int> durations)
        {
            Debug.Assert(pitches.Count == 96);
            Debug.Assert(durations.Count == 96);

            const int durationFactor = 48;	// the shortest note is 48ms

            List<IUniqueDef> defs = new List<IUniqueDef>();
            List<byte> velocities = new List<byte>() { (byte)127 };
            int msPosition = 0;
            for(int i = 0; i < 96; ++i)
            {
                List<byte> pitchesArg = new List<byte>() { (byte)pitches[i] };
                int msDuration = durations[i] * durationFactor;
                MidiChordDef midiChordDef = new MidiChordDef(pitchesArg, velocities, msDuration, true);
                midiChordDef.MsPositionReFirstUD = msPosition;
                defs.Add(midiChordDef);
                msPosition += msDuration;
            }
            return defs;
        }
Beispiel #17
0
        private IUniqueDef GetMidiChordDef(List<byte> chordIntervals, byte chordVelocity, int chordDuration, int relativePitch, int msPosition)
        {
            List<byte> pitches = GetPitches(relativePitch, chordIntervals);
            List<byte> velocities = GetVelocities(chordVelocity, chordIntervals.Count() + 1);

            IUniqueDef mcd = new MidiChordDef(pitches, velocities, chordDuration, true);
            mcd.MsPositionReFirstUD = msPosition;

            return mcd;
        }
Beispiel #18
0
 /// <summary>
 /// Returns true if the gamut.List contains all the pitches in the argument. Otherwise false. 
 /// </summary>
 public bool ContainsAllPitches(MidiChordDef mcd)
 {
     foreach(BasicMidiChordDef bmcd in mcd.BasicMidiChordDefs)
     {
         for(int i = 0; i < bmcd.Pitches.Count; ++i)
         {
             if(this.Contains(bmcd.Pitches[i]) == false)
             {
                 return false;
             }
         }
     }
     return true;
 }
Beispiel #19
0
        public override IUniqueDef DeepClone()
        {
            MidiChordDef rval = new MidiChordDef();

            rval.MsPosition = this.MsPosition;
            // rval.MsDuration must be set after setting BasicMidiChordDefs See below.
            rval.Bank = this.Bank;
            rval.Patch = this.Patch;
            rval.PitchWheelDeviation = this.PitchWheelDeviation;
            rval.HasChordOff = this.HasChordOff;
            rval.Lyric = this.Lyric;
            rval.MinimumBasicMidiChordMsDuration = this.MinimumBasicMidiChordMsDuration; // required when changing a midiChord's duration
            rval.NotatedMidiPitches = new List<byte>(this.NotatedMidiPitches); // the displayed noteheads
            // rval.MidiVelocity must be set after setting BasicMidiChordDefs See below.
            rval.OrnamentNumberSymbol = this.OrnamentNumberSymbol; // the displayed ornament number

            MidiChordSliderDefs m = this.MidiChordSliderDefs;
            List<byte> pitchWheelMsbs = NewListByteOrNull(m.PitchWheelMsbs);
            List<byte> panMsbs = NewListByteOrNull(m.PanMsbs);
            List<byte> modulationWheelMsbs = NewListByteOrNull(m.ModulationWheelMsbs);
            List<byte> expressionMsbs = NewListByteOrNull(m.ExpressionMsbs);
            if(pitchWheelMsbs != null || panMsbs != null || modulationWheelMsbs != null || expressionMsbs != null)
                rval.MidiChordSliderDefs = new MidiChordSliderDefs(pitchWheelMsbs, panMsbs, modulationWheelMsbs, expressionMsbs);
            else
                rval.MidiChordSliderDefs = null;

            List<BasicMidiChordDef> newBs = new List<BasicMidiChordDef>();
            foreach(BasicMidiChordDef b in this.BasicMidiChordDefs)
            {
                List<byte> pitches = new List<byte>(b.Pitches);
                List<byte> velocities = new List<byte>(b.Velocities);
                newBs.Add(new BasicMidiChordDef(b.MsDuration, b.BankIndex, b.PatchIndex, b.HasChordOff, pitches, velocities));
            }
            rval.BasicMidiChordDefs = newBs;

            rval.MsDuration = this.MsDuration;
            rval.MidiVelocity = this.MidiVelocity; // needed for displaying dynamics (must be set *after* setting BasicMidiChordDefs)

               return rval;
        }
Beispiel #20
0
        /// <summary>
        /// Returns either a new RestDef or a new MidiChordDef
        /// In both cases, MsPosition is set to zero, Lyric is set to null.
        /// </summary>
        private DurationDef GetDurationDef(int index)
        {
            DurationDef rval = null;
            BasicChordMidiSettings bcms = _basicChordMidiSettings;

            if(bcms.MidiPitches[index].Count == 0)
            {
                /// RestDefs are immutable, and have no MsPosition property.
                /// UniqueRestDefs are mutable RestDefs with both MsPositon and MsDuration properties.
                int restMsDuration = bcms.Durations[index];
                rval = new RestDef(0, restMsDuration);
            }
            else
            {
                /// Create a new MidiChordDef (with msPosition=0, lyric=null)
                bool hasChordOff = BoolOrDefaultValue(bcms.ChordOffs, index, M.DefaultHasChordOff); // true
                int duration = bcms.Durations[index];
                List<byte> rootMidiPitches = bcms.MidiPitches[index];
                List<byte> rootMidiVelocities = bcms.Velocities[index];

                byte? bankIndex = ByteOrNull(_bankIndices, index);
                byte? patchIndex = ByteOrNull(_patchIndices, index);
                byte pitchwheelDeviation = ByteOrDefaultValue(_pitchwheelDeviations, index, M.DefaultPitchWheelDeviation); // 2
                List<byte> pitchwheelEnvelope = ListByte(_pitchwheelEnvelopes, index);
                List<byte> panEnvelope = ListByte(_panEnvelopes, index);
                List<byte> modulationWheelEnvelope = ListByte(_modulationWheelEnvelopes, index);
                List<byte> expressionEnvelope = ListByte(_expressionEnvelopes, index);

                MidiChordSliderDefs midiChordSliderDefs =
                    new MidiChordSliderDefs(pitchwheelEnvelope,
                                            panEnvelope,
                                            modulationWheelEnvelope,
                                            expressionEnvelope);

                OrnamentSettings os = _ornamentSettings;
                List<BasicMidiChordDef> basicMidiChordDefs = new List<BasicMidiChordDef>();
                int ornamentNumber;
                if(os == null || _ornamentNumbers[index] == 0)
                {
                    ornamentNumber = 0;
                    BasicMidiChordDef bmcd = new BasicMidiChordDef(duration, bankIndex, patchIndex, hasChordOff, rootMidiPitches, rootMidiVelocities);
                    basicMidiChordDefs.Add(bmcd);
                }
                else
                {
                    ornamentNumber = _ornamentNumbers[index];
                    int ornamentMinMsDuration = IntOrDefaultValue(_ornamentMinMsDurations, index, M.DefaultOrnamentMinimumDuration); // 1

                    List<int> ornamentValues = os.OrnamentValues[_ornamentNumbers[index] - 1];

                    for(int i = 0; i < ornamentValues.Count; ++i)
                    {
                        int oIndex = ornamentValues[i] - 1;
                        bool oHasChordOff = BoolOrDefaultValue(os.BasicChordMidiSettings.ChordOffs, oIndex, M.DefaultHasChordOff);
                        int oDuration = os.BasicChordMidiSettings.Durations[oIndex];
                        List<byte> oMidiPitches = os.BasicChordMidiSettings.MidiPitches[oIndex];
                        List<byte> oVelocities = os.BasicChordMidiSettings.Velocities[oIndex];
                        byte? oBank = ByteOrNull(os.BankIndices, oIndex);
                        byte? oPatch = ByteOrNull(os.PatchIndices, oIndex);

                        BasicMidiChordDef bmcd = new BasicMidiChordDef(oDuration, oBank, oPatch, oHasChordOff, oMidiPitches, oVelocities);
                        basicMidiChordDefs.Add(bmcd);
                    }

                    // The basicMidiChordDefs currently contain the values from the ornaments form.
                    // All oBank and oPatch values will be null if the corresponding field in the ornament form was empty.
                    // The durations, pitches and velocities are relative to the main palette's values.

                    RemoveDuplicateBankAndPatchValues(basicMidiChordDefs);

                    if(basicMidiChordDefs[0].BankIndex == null)
                        basicMidiChordDefs[0].BankIndex = bankIndex; // can be null
                    if(basicMidiChordDefs[0].PatchIndex == null)
                        basicMidiChordDefs[0].PatchIndex = patchIndex;

                    Debug.Assert(basicMidiChordDefs[0].PatchIndex != null);

                    basicMidiChordDefs = Moritz.Spec.MidiChordDef.FitToDuration(basicMidiChordDefs, duration, ornamentMinMsDuration);

                    foreach(BasicMidiChordDef b in basicMidiChordDefs)
                    {
                        List<byte> combinedPitches = new List<byte>();
                        foreach(byte pitch in b.Pitches)
                        {
                            foreach(byte rootMidiPitch in rootMidiPitches)
                            {
                                combinedPitches.Add(M.MidiValue(rootMidiPitch + pitch));
                            }
                        }
                        b.Pitches = combinedPitches;

                        List<byte> combinedVelocities = new List<byte>();
                        foreach(byte velocity in b.Velocities)
                        {
                            foreach(byte rootMidiVelocity in rootMidiVelocities)
                            {
                                combinedVelocities.Add(M.MidiValue(rootMidiVelocity + velocity));
                            }
                        }
                        b.Velocities = combinedVelocities;
                    }
                }

                rval = new MidiChordDef(
                    duration,
                    pitchwheelDeviation,
                    hasChordOff,
                    rootMidiPitches,
                    rootMidiVelocities,
                    ornamentNumber,
                    midiChordSliderDefs,
                    basicMidiChordDefs);
            }
            return rval;
        }
Beispiel #21
0
        /// <summary>
        /// Sets _momentDefsListPerVerse to contain a list of MomentDefs for each verse.
        /// Each MomentDef is positioned with respect to the beginning of its verse, and contains
        /// a single MidiChordDef in its MidiChordDefs list.
        /// </summary>
        private void SetMomentDefsListPerVerse()
        {
            _momentDefsListPerVerse = new List<List<MomentDef>>();

            List<List<int>> momentDefMsWidthPerVerse = MomentDefMsWidthPerVerse;
            List<List<int>> midiChordDefMsDurPerVerse = MidiChordDefMsDurationsPerVerse;

            CheckWidths(momentDefMsWidthPerVerse, midiChordDefMsDurPerVerse);

            List<List<string>> lyricsPerVerse = LyricsPerVerse;
            List<byte> verseVelocities = new List<byte>() { (byte)64, (byte)75, (byte)90, (byte)105, (byte)120 };

            for(int verseIndex = 0; verseIndex < 5; ++verseIndex)
            {
                int momentMsPos = 0;

                List<int> momentMsWidth = momentDefMsWidthPerVerse[verseIndex];
                List<int> midiChordMsDur = midiChordDefMsDurPerVerse[verseIndex];
                List<string> lyrics = lyricsPerVerse[verseIndex];

                List<MomentDef> momentDefs = new List<MomentDef>();
                _momentDefsListPerVerse.Add(momentDefs);

                byte patch = (byte)(123 + verseIndex); // top 5 patches in bank 0
                List<byte> velocity = new List<byte>() { verseVelocities[verseIndex] };

                for(int syllableIndex = 0; syllableIndex < momentMsWidth.Count; ++syllableIndex)
                {
                    Debug.Assert(midiChordMsDur[syllableIndex] <= momentMsWidth[syllableIndex]);

                    MomentDef momentDef = new MomentDef(momentMsPos);
                    momentDef.MsWidth = momentMsWidth[syllableIndex];
                    momentDefs.Add(momentDef);

                    List<byte> pitch = new List<byte>() { (byte)syllableIndex }; // the syllables are organised like this in the soundfont.
                    int msDuration = midiChordMsDur[syllableIndex];

                    #region
                    MidiChordDef lmcd = new MidiChordDef();
                    lmcd.HasChordOff = true;
                    // Bank, and Patch are added to *every* chord so that performances can start anywhere.
                    // If the Assistant Performer is clever enough, repeated controls are not actually sent.
                    lmcd.Bank = (byte)(0);
                    lmcd.Patch = patch;
                    lmcd.Lyric = lyrics[syllableIndex];

                    // the following determine what is actually heard
                    List<byte> expressionMsbs = new List<byte>() { (byte)65 };
                    lmcd.MidiChordSliderDefs = new MidiChordSliderDefs(null, null, null, expressionMsbs);
                    lmcd.BasicMidiChordDefs.Add(new BasicMidiChordDef(msDuration, 0, patch, true, pitch, velocity));

                    lmcd.MsDuration = msDuration;

                    // these two attributes determine the symbols in the score.
                    lmcd.NotatedMidiPitches = new List<byte>() { 67 }; // display middle G, even though "pitch" is different.
                    lmcd.MidiVelocity = velocity[0]; // determines the visible dynamic symbol
                    #endregion

                    momentDef.MidiChordDefs.Add(lmcd);

                    momentMsPos += momentDef.MsWidth;
                }
            }
        }
Beispiel #22
0
        /// <summary>
        /// Returns a new MidiChordDef having msDuration, whose BasicMidiChordDefs are created from the MidiChordDefs and RestDefs in the Trk.
        /// BasicMidiChordDefs created from MidiChordDefs are the MidiChordDef's BasicMidiChordDef[0].
        /// BasicMidiChordDefs created from RestDefs have a single pitch (=0) and velocity=0.
        /// The durations of the returned BasicMidiChordDefs are in proportion to the durations of the MidiChordDefs and RestDefs in the Trk. 
        /// The Trk (which must contain at least one MidiChordDef) is not changed by calling this function.
        /// </summary>
        /// <param name="msDuration">The duration of the returned MidiChordDef</param>
        public MidiChordDef ToMidiChordDef(int msDuration)
        {
            List<BasicMidiChordDef> basicMidiChordDefs = new List<BasicMidiChordDef>();
            int bmcMsDuration = 0;
            byte? bmcBank = null;
            byte? bmcPatch = null;
            bool bmcHasChordOff = true;
            List<byte> restPitch = new List<byte>() { 0 };
            List<byte> restVelocity = new List<byte>() { 0 };
            List<byte> bmcPitches = null;
            List<byte> bmcVelocities = null;
            int totalDuration = 0;
            int nMidiChordDefs = 0;
            foreach(IUniqueDef iud in UniqueDefs)
            {
                MidiChordDef mcd = iud as MidiChordDef;
                RestDef restDef = iud as RestDef;

                if(mcd != null)
                {
                    bmcBank = mcd.BasicMidiChordDefs[0].BankIndex;
                    bmcPatch = mcd.BasicMidiChordDefs[0].PatchIndex;
                    bmcHasChordOff = mcd.BasicMidiChordDefs[0].HasChordOff;
                    bmcPitches = mcd.BasicMidiChordDefs[0].Pitches;
                    bmcVelocities = mcd.BasicMidiChordDefs[0].Velocities;
                    bmcMsDuration = mcd.MsDuration;
                    nMidiChordDefs++;
                }
                else if(restDef != null)
                {
                    bmcBank = null;
                    bmcPatch = null;
                    bmcHasChordOff = false;
                    bmcPitches = restPitch;
                    bmcVelocities = restVelocity;
                    bmcMsDuration = restDef.MsDuration;
                }

                if(iud is DurationDef)
                {
                    var basicMidiChordDef = new BasicMidiChordDef(bmcMsDuration, bmcBank, bmcPatch, bmcHasChordOff, bmcPitches, bmcVelocities);
                    totalDuration += bmcMsDuration;
                    basicMidiChordDefs.Add(basicMidiChordDef);
                }
            }

            Debug.Assert(nMidiChordDefs > 0, "Error: The original Trk must contain at least one MidiChordDef.");

            const byte pitchWheelDeviation = 2;
            const bool hasChordOff = true;
            const MidiChordSliderDefs midiChordSliderDefs = null;

            List<byte> rootMidiPitches = new List<byte>(basicMidiChordDefs[0].Pitches);
            List<byte> rootMidiVelocities = new List<byte>(basicMidiChordDefs[0].Velocities);

            MidiChordDef returnMCD = new MidiChordDef(totalDuration, pitchWheelDeviation, hasChordOff, rootMidiPitches, rootMidiVelocities,
                                                        nMidiChordDefs, midiChordSliderDefs, basicMidiChordDefs);

            returnMCD.MsDuration = msDuration;

            return returnMCD;
        }
Beispiel #23
0
        /// <summary>
        /// A deep clone!
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            MidiChordDef rval = new MidiChordDef();

            rval.MsPositionReFirstUD = this.MsPositionReFirstUD;
            // rval.MsDuration must be set after setting BasicMidiChordDefs See below.
            rval.Bank = this.Bank;
            rval.Patch = this.Patch;
            rval.PitchWheelDeviation = this.PitchWheelDeviation;
            rval.HasChordOff = this.HasChordOff;
            rval.BeamContinues = this.BeamContinues;
            rval.Lyric = this.Lyric;
            rval.MinimumBasicMidiChordMsDuration = MinimumBasicMidiChordMsDuration; // required when changing a midiChord's duration
            rval.NotatedMidiPitches = _notatedMidiPitches; // a clone of the displayed notehead pitches
            rval.NotatedMidiVelocities = _notatedMidiVelocities; // a clone of the displayed notehead velocities

            // rval.MidiVelocity must be set after setting BasicMidiChordDefs See below.
            rval.OrnamentNumberSymbol = this.OrnamentNumberSymbol; // the displayed ornament number

			rval.MidiChordSliderDefs = null;
			MidiChordSliderDefs m = this.MidiChordSliderDefs;
			if(m != null)
			{
				List<byte> pitchWheelMsbs = NewListByteOrNull(m.PitchWheelMsbs);
				List<byte> panMsbs = NewListByteOrNull(m.PanMsbs);
				List<byte> modulationWheelMsbs = NewListByteOrNull(m.ModulationWheelMsbs);
				List<byte> expressionMsbs = NewListByteOrNull(m.ExpressionMsbs);
				if(pitchWheelMsbs != null || panMsbs != null || modulationWheelMsbs != null || expressionMsbs != null)
					rval.MidiChordSliderDefs = new MidiChordSliderDefs(pitchWheelMsbs, panMsbs, modulationWheelMsbs, expressionMsbs);					
			}

            List<BasicMidiChordDef> newBs = new List<BasicMidiChordDef>();
            foreach(BasicMidiChordDef b in BasicMidiChordDefs)
            {
                List<byte> pitches = new List<byte>(b.Pitches);
                List<byte> velocities = new List<byte>(b.Velocities);
                newBs.Add(new BasicMidiChordDef(b.MsDuration, b.BankIndex, b.PatchIndex, b.HasChordOff, pitches, velocities));
            }
            rval.BasicMidiChordDefs = newBs;
            rval.MsDuration = this.MsDuration;

           return rval;
        }
Beispiel #24
0
        /// <summary>
        /// Returns a new Trk having msDuration and midiChannel, whose MidiChordDefs are created from this MidiChordDef's BasicMidiChordDefs.
        /// If a non-null gamut argument is given, a check is made (in the Trk constructor) to ensure that it contains
        /// all the pitches (having velocity greater than 1) in this MidiChordDef.
        /// Each new MidiChordDef has one BasicMidiChordDef, which is a copy of a BasicMidiChordDef from this MidiChordDef.
        /// The new MidiChordDef's notated pitches and velocities are the same as its BasicMidiChordDef's.
        /// The durations of the returned MidiChordDefs are in proportion to the durations of the original BasicMidichordDefs.
        /// This MidiChordDef is not changed by calling this function.
        /// </summary>
        /// <param name="msDuration">The duration of the returned Trk</param>
        /// <param name="midiChannel">The channel of the returned Trk</param>
        /// <param name="gamut">The gamut must contain all the pitches in this MidiChordDef.</param>
        public Trk ToTrk(int msDuration, int midiChannel)
        {
            List<IUniqueDef> iuds = new List<IUniqueDef>();
            foreach(BasicMidiChordDef bmcd in this.BasicMidiChordDefs)
            {
                // this constructor checks that pitches are in range 0..127, and velocities are in range 1..127.
                MidiChordDef mcd = new MidiChordDef(bmcd.Pitches, bmcd.Velocities, bmcd.MsDuration, bmcd.HasChordOff);
                mcd.BasicMidiChordDefs[0].BankIndex = bmcd.BankIndex;
                mcd.BasicMidiChordDefs[0].PatchIndex = bmcd.PatchIndex;
                mcd.BasicMidiChordDefs[0].HasChordOff = bmcd.HasChordOff;
                iuds.Add(mcd);
            }

            Trk trk = new Trk(midiChannel, 0, iuds);
            trk.MsDuration = msDuration; // calls Trk.SetMsPositionsReFirstUD();
            
            return trk;
        }