/// <summary> /// Called when one of the properties change value. /// </summary> /// <param name="newTimeDivision">Non-null when changed.</param> /// <param name="newPpqn">Non-null when changed.</param> /// <param name="newSmpte">Non-null when changed.</param> protected virtual void OnValueChanged(int?newTimeDivision, int?newPpqn, SmpteTimeBase newSmpte) { if (newTimeDivision.HasValue) { _timeDivision = newTimeDivision.Value; // test for smpte time if (((short)_timeDivision) < 0) { var fps = SmpteTime.ToFrameRate(Math.Abs((sbyte)((_timeDivision & 0xFF00) >> 8))); var subsPerFrame = _timeDivision & 0x00FF; _smpte = new SmpteTimeBase(fps, subsPerFrame); _ppqn = 0; } else { ThrowIfNotAMultipleOf24(newTimeDivision.Value, "TimeDivision"); _ppqn = _timeDivision; _smpte = null; } } if (newPpqn.HasValue) { Check.IfArgumentOutOfRange(newPpqn.Value, 0, ushort.MaxValue, "PulsesPerQuarterNote"); ThrowIfNotAMultipleOf24(newPpqn.Value, "PulsesPerQuarterNote"); _ppqn = newPpqn.Value; _timeDivision = _ppqn; _smpte = null; } if (newSmpte != null) { _timeDivision = (-(SmpteTime.FromFrameRate(newSmpte.FramesPerSecond) << 8)) | (newSmpte.SubFramesPerFrame & 0xFF); _ppqn = 0; _smpte = newSmpte; } }
/// <summary> /// Factory method for Midi file compatible values. /// </summary> /// <param name="timeDivision">Must not be zero.</param> /// <param name="tempo">Can be zero.</param> /// <returns>Never returns null.</returns> public static MidiTimeBase Create(int timeDivision, int tempo) { Check.IfArgumentOutOfRange(timeDivision, short.MinValue, ushort.MaxValue, "timeDivision"); if (timeDivision == 0) { throw new ArgumentException("The timeDivision value can not be zero.", "timeDivision"); } var midiTimeBase = new MidiTimeBase(); if (((short)timeDivision) < 0) { var fps = SmpteTime.ToFrameRate(Math.Abs((sbyte)((timeDivision & 0xFF00) >> 8))); var frames = timeDivision & 0x00FF; midiTimeBase.SmpteTime = new SmpteTime(0, 0, 0, frames, fps); } else { midiTimeBase.MillisecondResolution = tempo / timeDivision; } return(midiTimeBase); }