#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;
using System.ComponentModel;
using System.Diagnostics;
namespace Sanford.Multimedia.Midi
{
#region Channel Command Types
///
/// Defines constants for ChannelMessage types.
///
public enum ChannelCommand
{
///
/// Represents the note-off command type.
///
NoteOff = 0x80,
///
/// Represents the note-on command type.
///
NoteOn = 0x90,
///
/// Represents the poly pressure (aftertouch) command type.
///
PolyPressure = 0xA0,
///
/// Represents the controller command type.
///
Controller = 0xB0,
///
/// Represents the program change command type.
///
ProgramChange = 0xC0,
///
/// Represents the channel pressure (aftertouch) command
/// type.
///
ChannelPressure = 0xD0,
///
/// Represents the pitch wheel command type.
///
PitchWheel = 0xE0
}
#endregion
#region Controller Types
///
/// Defines constants for controller types.
///
public enum ControllerType
{
///
/// The Bank Select coarse.
///
BankSelect,
///
/// The Modulation Wheel coarse.
///
ModulationWheel,
///
/// The Breath Control coarse.
///
BreathControl,
///
/// The Foot Pedal coarse.
///
FootPedal = 4,
///
/// The Portamento Time coarse.
///
PortamentoTime,
///
/// The Data Entry Slider coarse.
///
DataEntrySlider,
///
/// The Volume coarse.
///
Volume,
///
/// The Balance coarse.
///
Balance,
///
/// The Pan position coarse.
///
Pan = 10,
///
/// The Expression coarse.
///
Expression,
///
/// The Effect Control 1 coarse.
///
EffectControl1,
///
/// The Effect Control 2 coarse.
///
EffectControl2,
///
/// The General Puprose Slider 1
///
GeneralPurposeSlider1 = 16,
///
/// The General Puprose Slider 2
///
GeneralPurposeSlider2,
///
/// The General Puprose Slider 3
///
GeneralPurposeSlider3,
///
/// The General Puprose Slider 4
///
GeneralPurposeSlider4,
///
/// The Bank Select fine.
///
BankSelectFine = 32,
///
/// The Modulation Wheel fine.
///
ModulationWheelFine,
///
/// The Breath Control fine.
///
BreathControlFine,
///
/// The Foot Pedal fine.
///
FootPedalFine = 36,
///
/// The Portamento Time fine.
///
PortamentoTimeFine,
///
/// The Data Entry Slider fine.
///
DataEntrySliderFine,
///
/// The Volume fine.
///
VolumeFine,
///
/// The Balance fine.
///
BalanceFine,
///
/// The Pan position fine.
///
PanFine = 42,
///
/// The Expression fine.
///
ExpressionFine,
///
/// The Effect Control 1 fine.
///
EffectControl1Fine,
///
/// The Effect Control 2 fine.
///
EffectControl2Fine,
///
/// The Hold Pedal 1.
///
HoldPedal1 = 64,
///
/// The Portamento.
///
Portamento,
///
/// The Sustenuto Pedal.
///
SustenutoPedal,
///
/// The Soft Pedal.
///
SoftPedal,
///
/// The Legato Pedal.
///
LegatoPedal,
///
/// The Hold Pedal 2.
///
HoldPedal2,
///
/// The Sound Variation.
///
SoundVariation,
///
/// The Sound Timbre.
///
SoundTimbre,
///
/// The Sound Release Time.
///
SoundReleaseTime,
///
/// The Sound Attack Time.
///
SoundAttackTime,
///
/// The Sound Brightness.
///
SoundBrightness,
///
/// The Sound Control 6.
///
SoundControl6,
///
/// The Sound Control 7.
///
SoundControl7,
///
/// The Sound Control 8.
///
SoundControl8,
///
/// The Sound Control 9.
///
SoundControl9,
///
/// The Sound Control 10.
///
SoundControl10,
///
/// The General Purpose Button 1.
///
GeneralPurposeButton1,
///
/// The General Purpose Button 2.
///
GeneralPurposeButton2,
///
/// The General Purpose Button 3.
///
GeneralPurposeButton3,
///
/// The General Purpose Button 4.
///
GeneralPurposeButton4,
///
/// The Effects Level.
///
EffectsLevel = 91,
///
/// The Tremelo Level.
///
TremeloLevel,
///
/// The Chorus Level.
///
ChorusLevel,
///
/// The Celeste Level.
///
CelesteLevel,
///
/// The Phaser Level.
///
PhaserLevel,
///
/// The Data Button Increment.
///
DataButtonIncrement,
///
/// The Data Button Decrement.
///
DataButtonDecrement,
///
/// The NonRegistered Parameter Fine.
///
NonRegisteredParameterFine,
///
/// The NonRegistered Parameter Coarse.
///
NonRegisteredParameterCoarse,
///
/// The Registered Parameter Fine.
///
RegisteredParameterFine,
///
/// The Registered Parameter Coarse.
///
RegisteredParameterCoarse,
///
/// The All Sound Off.
///
AllSoundOff = 120,
///
/// The All Controllers Off.
///
AllControllersOff,
///
/// The Local Keyboard.
///
LocalKeyboard,
///
/// The All Notes Off.
///
AllNotesOff,
///
/// The Omni Mode Off.
///
OmniModeOff,
///
/// The Omni Mode On.
///
OmniModeOn,
///
/// The Mono Operation.
///
MonoOperation,
///
/// The Poly Operation.
///
PolyOperation
}
#endregion
///
/// Represents MIDI channel messages.
///
[ImmutableObject(true)]
public sealed class ChannelMessage : ShortMessage
{
#region ChannelEventArgs Members
#region Constants
//
// Bit manipulation constants.
//
private const int MidiChannelMask = ~15;
private const int CommandMask = ~240;
///
/// Maximum value allowed for MIDI channels.
///
public const int MidiChannelMaxValue = 15;
#endregion
#region Construction
///
/// Initializes a new instance of the ChannelEventArgs class with the
/// specified command, MIDI channel, and data 1 values.
///
///
/// The command value.
///
///
/// The MIDI channel.
///
///
/// The data 1 value.
///
///
/// If midiChannel is less than zero or greater than 15. Or if
/// data1 is less than zero or greater than 127.
///
public ChannelMessage(ChannelCommand command, int midiChannel, int data1)
{
msg = 0;
msg = PackCommand(msg, command);
msg = PackMidiChannel(msg, midiChannel);
msg = PackData1(msg, data1);
#region Ensure
Debug.Assert(Command == command);
Debug.Assert(MidiChannel == midiChannel);
Debug.Assert(Data1 == data1);
#endregion
}
///
/// Initializes a new instance of the ChannelEventArgs class with the
/// specified command, MIDI channel, data 1, and data 2 values.
///
///
/// The command value.
///
///
/// The MIDI channel.
///
///
/// The data 1 value.
///
///
/// The data 2 value.
///
///
/// If midiChannel is less than zero or greater than 15. Or if
/// data1 or data 2 is less than zero or greater than 127.
///
public ChannelMessage(ChannelCommand command, int midiChannel,
int data1, int data2)
{
msg = 0;
msg = PackCommand(msg, command);
msg = PackMidiChannel(msg, midiChannel);
msg = PackData1(msg, data1);
msg = PackData2(msg, data2);
#region Ensure
Debug.Assert(Command == command);
Debug.Assert(MidiChannel == midiChannel);
Debug.Assert(Data1 == data1);
Debug.Assert(Data2 == data2);
#endregion
}
public ChannelMessage(int message)
{
this.msg = message;
}
#endregion
#region Methods
///
/// Returns a value for the current ChannelEventArgs suitable for use in
/// hashing algorithms.
///
///
/// A hash code for the current ChannelEventArgs.
///
public override int GetHashCode()
{
return msg;
}
///
/// Determines whether two ChannelEventArgs instances are equal.
///
///
/// The ChannelMessageEventArgs to compare with the current ChannelEventArgs.
///
///
/// true if the specified object is equal to the current
/// ChannelMessageEventArgs; otherwise, false.
///
public override bool Equals(object obj)
{
#region Guard
if(!(obj is ChannelMessage))
{
return false;
}
#endregion
ChannelMessage e = (ChannelMessage)obj;
return this.msg == e.msg;
}
///
/// Returns a value indicating how many bytes are used for the
/// specified ChannelCommand.
///
///
/// The ChannelCommand value to test.
///
///
/// The number of bytes used for the specified ChannelCommand.
///
internal static int DataBytesPerType(ChannelCommand command)
{
int result;
if(command == ChannelCommand.ChannelPressure ||
command == ChannelCommand.ProgramChange)
{
result = 1;
}
else
{
result = 2;
}
return result;
}
///
/// Unpacks the command value from the specified integer channel
/// message.
///
///
/// The message to unpack.
///
///
/// The command value for the packed message.
///
internal static ChannelCommand UnpackCommand(int message)
{
return (ChannelCommand)(message & DataMask & MidiChannelMask);
}
///
/// Unpacks the MIDI channel from the specified integer channel
/// message.
///
///
/// The message to unpack.
///
///
/// The MIDI channel for the pack message.
///
internal static int UnpackMidiChannel(int message)
{
return message & DataMask & CommandMask;
}
///
/// Packs the MIDI channel into the specified integer message.
///
///
/// The message into which the MIDI channel is packed.
///
///
/// The MIDI channel to pack into the message.
///
///
/// An integer message.
///
///
/// If midiChannel is less than zero or greater than 15.
///
internal static int PackMidiChannel(int message, int midiChannel)
{
#region Preconditons
if(midiChannel < 0 || midiChannel > MidiChannelMaxValue)
{
throw new ArgumentOutOfRangeException("midiChannel", midiChannel,
"MIDI channel out of range.");
}
#endregion
return (message & MidiChannelMask) | midiChannel;
}
///
/// Packs the command value into an integer message.
///
///
/// The message into which the command is packed.
///
///
/// The command value to pack into the message.
///
///
/// An integer message.
///
internal static int PackCommand(int message, ChannelCommand command)
{
return (message & CommandMask) | (int)command;
}
#endregion
#region Properties
///
/// Gets the channel command value.
///
public ChannelCommand Command
{
get
{
return UnpackCommand(msg);
}
}
///
/// Gets the MIDI channel.
///
public int MidiChannel
{
get
{
return UnpackMidiChannel(msg);
}
}
///
/// Gets the first data value.
///
public int Data1
{
get
{
return UnpackData1(msg);
}
}
///
/// Gets the second data value.
///
public int Data2
{
get
{
return UnpackData2(msg);
}
}
///
/// Gets the EventType.
///
public override MessageType MessageType
{
get
{
return MessageType.Channel;
}
}
#endregion
#endregion
}
}