#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
}
}