#region License /* Copyright (c) 2005 Leslie Sanford * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #endregion #region Contact /* * Leslie Sanford * Email: jabberdabber@hotmail.com */ #endregion using System; namespace Sanford.Multimedia.Midi { /// /// Provides easy to use functionality for time signature MetaMessages. /// public class TimeSignatureBuilder : IMessageBuilder { #region TimeSignature Members #region Constants // Default numerator value. private const byte DefaultNumerator = 4; // Default denominator value. private const byte DefaultDenominator = 2; // Default clocks per metronome click value. private const byte DefaultClocksPerMetronomeClick = 24; // Default thirty second notes per quarter note value. private const byte DefaultThirtySecondNotesPerQuarterNote = 8; #endregion #region Fields // The raw data making up the time signature meta message. private byte[] data = new byte[MetaMessage.TimeSigLength]; // The built time signature meta message. private MetaMessage result = null; // Indicates whether any of the properties have changed since the // last time the message was built. private bool changed = true; #endregion #region Construction /// /// Initializes a new instance of the TimeSignatureBuilder class. /// public TimeSignatureBuilder() { Numerator = DefaultNumerator; Denominator = DefaultDenominator; ClocksPerMetronomeClick = DefaultClocksPerMetronomeClick; ThirtySecondNotesPerQuarterNote = DefaultThirtySecondNotesPerQuarterNote; } /// /// Initializes a new instance of the TimeSignatureBuilder class with the /// specified MetaMessage. /// /// /// The MetaMessage to use for initializing the TimeSignatureBuilder class. /// /// /// If the specified MetaMessage is not a time signature type. /// /// /// The TimeSignatureBuilder uses the specified MetaMessage to /// initialize its property values. /// public TimeSignatureBuilder(MetaMessage message) { Initialize(message); } #endregion #region Methods /// /// Initializes the TimeSignatureBuilder with the specified MetaMessage. /// /// /// The MetaMessage to use for initializing the TimeSignatureBuilder. /// /// /// If the specified MetaMessage is not a time signature type. /// public void Initialize(MetaMessage message) { #region Require if(message.MetaType != MetaType.TimeSignature) { throw new ArgumentException("Wrong meta event type.", "message"); } #endregion data = message.GetBytes(); } #endregion #region Properties /// /// Gets or sets the numerator. /// /// /// Numerator is set to a value less than one. /// public byte Numerator { get { return data[0]; } set { #region Require if(value < 1) { throw new ArgumentOutOfRangeException("Numerator", value, "Numerator out of range."); } #endregion data[0] = value; changed = true; } } /// /// Gets or sets the denominator. /// /// /// Denominator is set to a value less than 2. /// /// /// Denominator is set to a value that is not a power of 2. /// public byte Denominator { get { return Convert.ToByte(Math.Pow(2, data[1])); } set { #region Require if(value < 2 || value > 32) { throw new ArgumentOutOfRangeException("Denominator must be between 2 and 32."); } else if((value & (value - 1)) != 0) { throw new ArgumentException("Denominator must be a power of 2."); } #endregion data[1] = Convert.ToByte(Math.Log(value, 2)); changed = true; } } /// /// Gets or sets the clocks per metronome click. /// /// /// Clocks per metronome click determines how many MIDI clocks occur /// for each metronome click. /// public byte ClocksPerMetronomeClick { get { return data[2]; } set { data[2] = value; changed = true; } } /// /// Gets or sets how many thirty second notes there are for each /// quarter note. /// public byte ThirtySecondNotesPerQuarterNote { get { return data[3]; } set { data[3] = value; changed = true; } } /// /// Gets the built message. /// public MetaMessage Result { get { return result; } } #endregion #endregion #region IMessageBuilder Members /// /// Builds the time signature MetaMessage. /// public void Build() { // If any of the properties have changed since the last time the // message was built. if(changed) { result = new MetaMessage(MetaType.TimeSignature, data); changed = false; } } #endregion } }