/// <summary> /// Creates a BasicMidiChordDef having the original base pitch, /// but in which the top-bottom order of the prime intervals is reversed. /// Velocities remain in the same order, bottom to top. They are not inverted. /// </summary> /// <returns></returns> public BasicMidiChordDef Inversion() { List <byte> pitches = Pitches; // default if Pitches.Count == 1 if (Pitches.Count > 1) { List <byte> intervals = new List <byte>(); for (int i = 1; i < Pitches.Count; ++i) { intervals.Add((byte)(Pitches[i] - Pitches[i - 1])); } intervals.Reverse(); pitches = new List <byte>() { Pitches[0] }; for (int i = 0; i < intervals.Count; ++i) { byte interval = intervals[i]; pitches.Add((byte)(pitches[pitches.Count - 1] + interval)); } } BasicMidiChordDef invertedBMCD = new BasicMidiChordDef(MsDuration, BankIndex, PatchIndex, HasChordOff, pitches, Velocities); return(invertedBMCD); }
public BasicMidiChordDef(BasicMidiChordDef original, int msDuration) { _msDuration = msDuration; // read-only! BankIndex = original.BankIndex; PatchIndex = original.PatchIndex; HasChordOff = original.HasChordOff; Pitches = new List <byte>(original.Pitches); Velocities = new List <byte>(original.Velocities); }
public BasicMidiChordDef(BasicMidiChordDef original, int msDuration) { _msDuration = msDuration; // read-only! BankIndex = original.BankIndex; PatchIndex = original.PatchIndex; HasChordOff = original.HasChordOff; Pitches = new List<byte>(original.Pitches); Velocities = new List<byte>(original.Velocities); }
public BasicMidiChord(int channel, MidiChord midiChord, BasicMidiChordDef bmcd, int realMsDuration) { MidiChord = midiChord; //MsPosition = bmcd.MsPosition; MsDuration = realMsDuration; if(bmcd.BankIndex != null) { BankControl = new BankControl(channel, (byte)bmcd.BankIndex); } if(bmcd.PatchIndex != null) { PatchControl = new PatchControl(channel, (byte)bmcd.PatchIndex); } ChordOn = new ChordOn(this); SetChordOn(channel, bmcd.Pitches, bmcd.Velocities); if(bmcd.HasChordOff) { ChordOff = new ChordOff(this); SetChordOff(channel, bmcd.Pitches); } }
/// <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; }
/// <summary> /// Creates a BasicMidiChordDef having the original base pitch, /// but in which the top-bottom order of the prime intervals is reversed. /// Velocities remain in the same order, bottom to top. They are not inverted. /// </summary> /// <returns></returns> public BasicMidiChordDef Inversion() { List<byte> pitches = Pitches; // default if Pitches.Count == 1 if(Pitches.Count > 1) { List<byte> intervals = new List<byte>(); for(int i = 1; i < Pitches.Count; ++i) { intervals.Add((byte)(Pitches[i] - Pitches[i - 1])); } intervals.Reverse(); pitches = new List<byte>() { Pitches[0] }; for(int i = 0; i < intervals.Count; ++i) { byte interval = intervals[i]; pitches.Add((byte)(pitches[pitches.Count - 1] + interval)); } } BasicMidiChordDef invertedBMCD = new BasicMidiChordDef(_msDuration, BankIndex, PatchIndex, HasChordOff, pitches, Velocities); return invertedBMCD; }
/// <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; }
/// <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; } }