/// <summary> /// The palette has created new values for all the arguments, so this /// constructor simply transfers those values to the new MidiChordDef. /// msPosition is set to 0, lyric is set to null. /// </summary> public MidiChordDef( int msDuration, // the total duration (this should be the sum of the durations of the basicMidiChordDefs) byte pitchWheelDeviation, // default is M.DefaultPitchWheelDeviation (=2) bool hasChordOff, // default is M.DefaultHasChordOff (=true) List<byte> midiPitches, // the pitches that are displayed in the score int ornamentNumberSymbol, // is 0 when there is no ornament MidiChordSliderDefs midiChordSliderDefs, // can contain empty lists List<BasicMidiChordDef> basicMidiChordDefs) : base(msDuration) { foreach(byte pitch in midiPitches) Debug.Assert(pitch == M.MidiValue((int)pitch), "Pitch out of range."); _msPosition = 0; _msDuration = msDuration; _pitchWheelDeviation = pitchWheelDeviation; _hasChordOff = hasChordOff; _displayedMidiPitches = midiPitches; // midiVelocities are handled via the basicMidiChordDefs _lyric = null; _ornamentNumberSymbol = ornamentNumberSymbol; _lyric = null; MidiChordSliderDefs = midiChordSliderDefs; BasicMidiChordDefs = basicMidiChordDefs; CheckTotalDuration(); }
/// <summary> /// The palette has created new values for all the arguments, so this /// constructor simply transfers those values to the new MidiChordDef. /// msPosition is set to 0, lyric is set to null. /// </summary> public MidiChordDef( int msDuration, // the total duration (this should be the sum of the durations of the basicMidiChordDefs) byte pitchWheelDeviation, // default is M.DefaultPitchWheelDeviation (=2) bool hasChordOff, // default is M.DefaultHasChordOff (=true) List <byte> midiPitches, // the pitches that are displayed in the score int ornamentNumberSymbol, // is 0 when there is no ornament MidiChordSliderDefs midiChordSliderDefs, // can contain empty lists List <BasicMidiChordDef> basicMidiChordDefs) : base(msDuration) { foreach (byte pitch in midiPitches) { Debug.Assert(pitch == M.MidiValue((int)pitch), "Pitch out of range."); } _msPosition = 0; _msDuration = msDuration; _pitchWheelDeviation = pitchWheelDeviation; _hasChordOff = hasChordOff; _displayedMidiPitches = midiPitches; // midiVelocities are handled via the basicMidiChordDefs _lyric = null; _ornamentNumberSymbol = ornamentNumberSymbol; _lyric = null; MidiChordSliderDefs = midiChordSliderDefs; BasicMidiChordDefs = basicMidiChordDefs; CheckTotalDuration(); }
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); }
/// <summary> /// Note that, unlike Rests, MidiChordDefs do not have a msDuration attribute. /// Their msDuration is deduced from the contained BasicMidiChords. /// Patch indices already set in the BasicMidiChordDefs take priority over those set in the main MidiChordDef. /// However, if BasicMidiChordDefs[0].PatchIndex is null, and this.Patch is set, BasicMidiChordDefs[0].PatchIndex is set to Patch. /// The same is true for Bank settings. /// The AssistantPerformer therefore only needs to look at BasicMidiChordDefs to find Bank and Patch changes. /// While constructing Tracks, the AssistantPerformer should monitor the current Bank and/or Patch, so that it can decide /// whether or not to actually construct and send bank and/or patch change messages. /// </summary> public void WriteSvg(SvgWriter w) { w.WriteStartElement("score", "midiChord", null); Debug.Assert(BasicMidiChordDefs != null && BasicMidiChordDefs.Count > 0); if (BasicMidiChordDefs[0].BankIndex == null && Bank != null) { BasicMidiChordDefs[0].BankIndex = Bank; } if (BasicMidiChordDefs[0].PatchIndex == null && Patch != null) { BasicMidiChordDefs[0].PatchIndex = Patch; } if (HasChordOff == false) { w.WriteAttributeString("hasChordOff", "0"); } if (PitchWheelDeviation != null && PitchWheelDeviation != M.DefaultPitchWheelDeviation) { w.WriteAttributeString("pitchWheelDeviation", PitchWheelDeviation.ToString()); } if (MinimumBasicMidiChordMsDuration != M.DefaultMinimumBasicMidiChordMsDuration) { w.WriteAttributeString("minBasicChordMsDuration", MinimumBasicMidiChordMsDuration.ToString()); } w.WriteStartElement("basicChords"); foreach (BasicMidiChordDef basicMidiChord in BasicMidiChordDefs) // containing basic <midiChord> elements { basicMidiChord.WriteSVG(w); } w.WriteEndElement(); if (MidiChordSliderDefs != null) { MidiChordSliderDefs.WriteSVG(w); // writes sliders element } w.WriteEndElement(); // score:midiChord }
/// <summary> /// This constructor creates a MidiChordDef at msPosition 0, lyric = null, containing a single BasicMidiChordDef and no sliders. /// </summary> public MidiChordDef(List<byte> pitches, List<byte> velocities, int msPosition, int msDuration, bool hasChordOff) : base(msDuration) { foreach(byte pitch in pitches) Debug.Assert(pitch == M.MidiValue((int)pitch), "Pitch out of range."); _msPosition = msPosition; _hasChordOff = hasChordOff; _minimumBasicMidiChordMsDuration = 1; // not used (this is not an ornament) _displayedMidiPitches = pitches; // midiVelocity is handled via the BasicMidiChordDefs _ornamentNumberSymbol = 0; MidiChordSliderDefs = null; byte? bank = null; byte? patch = null; BasicMidiChordDefs.Add(new BasicMidiChordDef(msDuration, bank, patch, hasChordOff, pitches, velocities)); CheckTotalDuration(); }
/// <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; }
private void CreateSliders(int channel, MidiChordSliderDefs sliderDefs, int msDuration) { if(sliderDefs.ModulationWheelMsbs != null && sliderDefs.ModulationWheelMsbs.Count > 0) this._modulationWheelSlider = new MidiModulationWheelSlider(sliderDefs.ModulationWheelMsbs, channel, msDuration); if(sliderDefs.PanMsbs != null && sliderDefs.PanMsbs.Count > 0) this._panSlider = new MidiPanSlider(sliderDefs.PanMsbs, channel, msDuration); if(sliderDefs.PitchWheelMsbs != null && sliderDefs.PitchWheelMsbs.Count > 0) this._pitchWheelSlider = new MidiPitchWheelSlider(sliderDefs.PitchWheelMsbs, channel, msDuration); if(sliderDefs.ExpressionMsbs != null && sliderDefs.ExpressionMsbs.Count > 0) this._expressionSlider = new MidiExpressionSlider(sliderDefs.ExpressionMsbs, channel, msDuration); }
/// <summary> /// Constructor used when creating a list of DurationDef templates from a Palette. /// The palette has created new values for all the arguments, so this constructor simply transfers /// those values to the new MidiChordDef. MsPositionReFirstIUD is set to 0, lyric is set to null. /// </summary> public MidiChordDef( int msDuration, // the total duration (this should be the sum of the durations of the basicMidiChordDefs) byte pitchWheelDeviation, // default is M.DefaultPitchWheelDeviation (=2) bool hasChordOff, // default is M.DefaultHasChordOff (=true) List<byte> rootMidiPitches, // the pitches defined in the root chord settings (displayed, by default, in the score). List<byte> rootMidiVelocities, // the velocities defined in the root chord settings (displayed, by default, in the score). int ornamentNumberSymbol, // is 0 when there is no ornament MidiChordSliderDefs midiChordSliderDefs, // can be null or contain empty lists List<BasicMidiChordDef> basicMidiChordDefs) : base(msDuration) { Debug.Assert(rootMidiPitches.Count <= rootMidiVelocities.Count); foreach(byte pitch in rootMidiPitches) { AssertIsMidiValue(pitch); } _msPositionReFirstIUD = 0; _msDuration = msDuration; _pitchWheelDeviation = pitchWheelDeviation; _hasChordOff = hasChordOff; _notatedMidiPitches = rootMidiPitches; _notatedMidiVelocities = rootMidiVelocities; _ornamentNumberSymbol = ornamentNumberSymbol; MidiChordSliderDefs = midiChordSliderDefs; BasicMidiChordDefs = basicMidiChordDefs; CheckTotalDuration(); }
private void SetSliderEnvelope(int domain, List<byte> pitchWheelBytes, List<byte> panBytes, List<byte> modulationBytes, List<byte> expressionBytes) { #region condition if(domain != 127) { throw new ArgumentException($"{nameof(domain)} must be 127."); } #endregion condition if(MidiChordSliderDefs == null) { MidiChordSliderDefs = new MidiChordSliderDefs(null, null, null, null); } if(pitchWheelBytes != null) { MidiChordSliderDefs.PitchWheelMsbs = pitchWheelBytes; } else if(panBytes != null) { MidiChordSliderDefs.PanMsbs = panBytes; } else if(modulationBytes != null) { MidiChordSliderDefs.ModulationWheelMsbs = modulationBytes; } else if(expressionBytes != null) { MidiChordSliderDefs.ExpressionMsbs = expressionBytes; } }