/// <summary> /// Plays musical notes. See also: http://netmftoolbox.codeplex.com/wikipage?title=Toolbox.NETMF.Hardware.Speaker /// </summary> /// <example><![CDATA[ /// Octave and tone commands: /// Ooctave Sets the current octave (0 - 9). /// < or > Moves up or down one octave. /// A - G Plays the specified note in the current octave. /// Nnote Plays a specified note (0 - 84) in the seven octave /// range (0 is a rest). /// /// Duration and tempo commands: /// Llength Sets the length of each note (1 - 64). L1 is whole note, /// L2 is half note, etc. /// ML Sets music legato. /// MN Sets music normal. /// MS Sets music staccato. /// Ppause Specifies a pause (1 - 64). P1 is a whole-note pause, /// P2 is a half-note pause, etc. /// Ttempo Sets the tempo in quarter notes per minute (32 - 255). /// /// Mode commands: /// MF Plays music in foreground. /// MB Plays music in background. /// /// Suffix commands: /// # or + Turns preceding note into a sharp. /// - Turns preceding note into a flat. /// . Plays the preceding note 3/2 as long as specified. /// /// See also: http://netmftoolbox.codeplex.com/wikipage?title=Toolbox.NETMF.Hardware.Speaker /// ]]></example> /// <param name="CommandString">A string expression that contains one or more of the PLAY commands.</param> public void Play(string CommandString) { // Used at many other points to read three digits byte Digit1; byte Digit2; byte Digit3; // We handle commands in upper string CommandString = CommandString.ToUpper() + " "; // The additional spaces makes it more easy to parse the string :-) // Loop through all the commands for (var CSCounter = 0; CSCounter < CommandString.Length; ++CSCounter) { switch (CommandString[CSCounter]) { case 'O': // Need to change the Octave to a specific number ++CSCounter; this._PlayOctave = (byte)(CommandString[CSCounter] - 48); // 48 = 0, 49 = 1, 50 = 2, etc. break; case '>': // Need to change the Octave one up ++this._PlayOctave; break; case '<': // Need to change the Octave one down --this._PlayOctave; break; case 'A': // Needs to play the A note case 'B': // Needs to play the B note case 'C': // Needs to play the C note case 'D': // Needs to play the D note case 'E': // Needs to play the E note case 'F': // Needs to play the F note case 'G': // Needs to play the G note case 'N': // Needs to play a specific note byte BaseNote = 0; byte BaseLength = this._PlayLength; if (CommandString[CSCounter] == 'C') { BaseNote = (byte)(this._PlayOctave * 12 + 0 + 1); } else if (CommandString[CSCounter] == 'D') { BaseNote = (byte)(this._PlayOctave * 12 + 2 + 1); } else if (CommandString[CSCounter] == 'E') { BaseNote = (byte)(this._PlayOctave * 12 + 4 + 1); } else if (CommandString[CSCounter] == 'F') { BaseNote = (byte)(this._PlayOctave * 12 + 5 + 1); } else if (CommandString[CSCounter] == 'G') { BaseNote = (byte)(this._PlayOctave * 12 + 7 + 1); } else if (CommandString[CSCounter] == 'A') { BaseNote = (byte)(this._PlayOctave * 12 + 9 + 1); } else if (CommandString[CSCounter] == 'B') { BaseNote = (byte)(this._PlayOctave * 12 + 11 + 1); } else if (CommandString[CSCounter] == 'N') { Digit1 = (byte)CommandString[CSCounter + 1]; Digit2 = (byte)CommandString[CSCounter + 2]; if (Digit2 > 47 && Digit2 < 58) { // 48 = 0, 59 = 9 BaseNote = (byte)((Digit2 - 48) + ((Digit1 - 48) * 10)); CSCounter = CSCounter + 2; } else { BaseNote = (byte)(Digit1 - 48); CSCounter = CSCounter + 1; } } if (CommandString[CSCounter + 1] == '#' || CommandString[CSCounter + 1] == '+') { // Turns preceding note into a sharp. ++BaseNote; ++CSCounter; } if (CommandString[CSCounter + 1] == '-') { // Turns preceding note into a flat. --BaseNote; ++CSCounter; } if (CommandString[CSCounter + 1] == '.') { // Plays the preceding note 3/2 as long as specified. BaseLength = (byte)(BaseLength / 2 * 3); ++CSCounter; } this._PlayNote(BaseNote, this._PlayTempo, BaseLength); break; case 'L': // Sets the length of each note (1 - 64). L1 is whole note, L2 is half note, etc. Digit1 = (byte)CommandString[CSCounter + 1]; Digit2 = (byte)CommandString[CSCounter + 2]; if (Digit2 > 47 && Digit2 < 58) { // 48 = 0, 59 = 9 this._PlayLength = (byte)((Digit2 - 48) + ((Digit1 - 48) * 10)); CSCounter = CSCounter + 2; } else { this._PlayLength = (byte)(Digit1 - 48); CSCounter = CSCounter + 1; } break; case 'M': // Changes mode ++CSCounter; if (CommandString[CSCounter] == 'N') { this._PlayMode = _PlayModes.Normal; } else if (CommandString[CSCounter] == 'L') { this._PlayMode = _PlayModes.Legato; } else if (CommandString[CSCounter] == 'S') { this._PlayMode = _PlayModes.Staccato; } else if (CommandString[CSCounter] == 'B') { this._PlayBackground(CommandString.Substring(CSCounter + 1)); return; } break; case 'P': // Specifies a pause (1 - 64). P1 is a whole-note pause, P2 is a half-note pause, etc. Digit1 = (byte)CommandString[CSCounter + 1]; Digit2 = (byte)CommandString[CSCounter + 2]; if (Digit2 > 47 && Digit2 < 58) { // 48 = 0, 59 = 9 this._PlayNote(0, this._PlayTempo, (byte)((Digit2 - 48) + ((Digit1 - 48) * 10))); CSCounter = CSCounter + 2; } else { this._PlayNote(0, this._PlayTempo, (byte)(Digit1 - 48)); CSCounter = CSCounter + 1; } break; case 'T': // Sets the tempo in quarter notes per minute (32 - 255). Digit1 = (byte)CommandString[CSCounter + 1]; Digit2 = (byte)CommandString[CSCounter + 2]; Digit3 = (byte)CommandString[CSCounter + 3]; if (Digit2 > 47 && Digit2 < 58 && Digit3 > 47 && Digit3 < 58) { // 48 = 0, 59 = 9 this._PlayTempo = (byte)((Digit3 - 48) + ((Digit2 - 48) * 10) + ((Digit1 - 48) * 100)); CSCounter = CSCounter + 3; } else if (Digit2 > 47 && Digit2 < 58) { this._PlayTempo = (byte)((Digit2 - 48) + ((Digit1 - 48) * 10)); CSCounter = CSCounter + 2; } else { this._PlayTempo = (byte)(Digit1 - 48); CSCounter = CSCounter + 1; } break; } // Triggers the event if (this.OnPlay != null) { this.OnPlay(0, (uint)(CommandString.Length - CSCounter - 1), new DateTime()); } } }
/// <summary> /// Plays musical notes. See also: http://netmftoolbox.codeplex.com/wikipage?title=Toolbox.NETMF.Hardware.Speaker /// </summary> /// <example><![CDATA[ /// Octave and tone commands: /// Ooctave Sets the current octave (0 - 6). /// < or > Moves up or down one octave. /// A - G Plays the specified note in the current octave. /// Nnote Plays a specified note (0 - 84) in the seven octave /// range (0 is a rest). /// /// Duration and tempo commands: /// Llength Sets the length of each note (1 - 64). L1 is whole note, /// L2 is half note, etc. /// ML Sets music legato. /// MN Sets music normal. /// MS Sets music staccato. /// Ppause Specifies a pause (1 - 64). P1 is a whole-note pause, /// P2 is a half-note pause, etc. /// Ttempo Sets the tempo in quarter notes per minute (32 - 255). /// /// Mode commands: /// MF Plays music in foreground. /// MB Plays music in background. /// /// Suffix commands: /// # or + Turns preceding note into a sharp. /// - Turns preceding note into a flat. /// . Plays the preceding note 3/2 as long as specified. /// /// See also: http://netmftoolbox.codeplex.com/wikipage?title=Toolbox.NETMF.Hardware.Speaker /// ]]></example> /// <param name="CommandString">A string expression that contains one or more of the PLAY commands.</param> public void Play(string CommandString) { // Used at many other points to read three digits byte Digit1; byte Digit2; byte Digit3; // We handle commands in upper string CommandString = CommandString.ToUpper() + " "; // The additional spaces makes it more easy to parse the string :-) // Loop through all the commands for (var CSCounter = 0; CSCounter < CommandString.Length; ++CSCounter) { switch (CommandString[CSCounter]) { case 'O': // Need to change the Octave to a specific number ++CSCounter; this._PlayOctave = (byte)(CommandString[CSCounter] - 48); // 48 = 0, 49 = 1, 50 = 2, etc. break; case '>': // Need to change the Octave one up ++this._PlayOctave; break; case '<': // Need to change the Octave one down --this._PlayOctave; break; case 'A': // Needs to play the A note case 'B': // Needs to play the B note case 'C': // Needs to play the C note case 'D': // Needs to play the D note case 'E': // Needs to play the E note case 'F': // Needs to play the F note case 'G': // Needs to play the G note case 'N': // Needs to play a specific note byte BaseNote = 0; byte BaseLength = this._PlayLength; if (CommandString[CSCounter] == 'C') BaseNote = (byte)(this._PlayOctave * 12 + 0 + 1); else if (CommandString[CSCounter] == 'D') BaseNote = (byte)(this._PlayOctave * 12 + 2 + 1); else if (CommandString[CSCounter] == 'E') BaseNote = (byte)(this._PlayOctave * 12 + 4 + 1); else if (CommandString[CSCounter] == 'F') BaseNote = (byte)(this._PlayOctave * 12 + 5 + 1); else if (CommandString[CSCounter] == 'G') BaseNote = (byte)(this._PlayOctave * 12 + 7 + 1); else if (CommandString[CSCounter] == 'A') BaseNote = (byte)(this._PlayOctave * 12 + 9 + 1); else if (CommandString[CSCounter] == 'B') BaseNote = (byte)(this._PlayOctave * 12 + 11 + 1); else if (CommandString[CSCounter] == 'N') { Digit1 = (byte)CommandString[CSCounter + 1]; Digit2 = (byte)CommandString[CSCounter + 2]; if (Digit2 > 47 && Digit2 < 58) { // 48 = 0, 59 = 9 BaseNote = (byte)((Digit2 - 48) + ((Digit1 - 48) * 10)); CSCounter = CSCounter + 2; } else { BaseNote = (byte)(Digit1 - 48); CSCounter = CSCounter + 1; } } if (CommandString[CSCounter + 1] == '#' || CommandString[CSCounter + 1] == '+') { // Turns preceding note into a sharp. ++BaseNote; ++CSCounter; } if (CommandString[CSCounter + 1] == '-') { // Turns preceding note into a flat. --BaseNote; ++CSCounter; } if (CommandString[CSCounter + 1] == '.') { // Plays the preceding note 3/2 as long as specified. BaseLength = (byte)(BaseLength / 2 * 3); ++CSCounter; } this._PlayNote(BaseNote, this._PlayTempo, BaseLength); break; case 'L': // Sets the length of each note (1 - 64). L1 is whole note, L2 is half note, etc. Digit1 = (byte)CommandString[CSCounter + 1]; Digit2 = (byte)CommandString[CSCounter + 2]; if (Digit2 > 47 && Digit2 < 58) { // 48 = 0, 59 = 9 this._PlayLength = (byte)((Digit2 - 48) + ((Digit1 - 48) * 10)); CSCounter = CSCounter + 2; } else { this._PlayLength = (byte)(Digit1 - 48); CSCounter = CSCounter + 1; } break; case 'M': // Changes mode ++CSCounter; if (CommandString[CSCounter] == 'N') this._PlayMode = _PlayModes.Normal; else if (CommandString[CSCounter] == 'L') this._PlayMode = _PlayModes.Legato; else if (CommandString[CSCounter] == 'S') this._PlayMode = _PlayModes.Staccato; else if (CommandString[CSCounter] == 'B') { this._PlayBackground(CommandString.Substring(CSCounter + 1)); return; } break; case 'P': // Specifies a pause (1 - 64). P1 is a whole-note pause, P2 is a half-note pause, etc. Digit1 = (byte)CommandString[CSCounter + 1]; Digit2 = (byte)CommandString[CSCounter + 2]; if (Digit2 > 47 && Digit2 < 58) { // 48 = 0, 59 = 9 this._PlayNote(0, this._PlayTempo, (byte)((Digit2 - 48) + ((Digit1 - 48) * 10))); CSCounter = CSCounter + 2; } else { this._PlayNote(0, this._PlayTempo, (byte)(Digit1 - 48)); CSCounter = CSCounter + 1; } break; case 'T': // Sets the tempo in quarter notes per minute (32 - 255). Digit1 = (byte)CommandString[CSCounter + 1]; Digit2 = (byte)CommandString[CSCounter + 2]; Digit3 = (byte)CommandString[CSCounter + 3]; if (Digit2 > 47 && Digit2 < 58 && Digit3 > 47 && Digit3 < 58) { // 48 = 0, 59 = 9 this._PlayTempo = (byte)((Digit3 - 48) + ((Digit2 - 48) * 10) + ((Digit1 - 48) * 100)); CSCounter = CSCounter + 3; } else if (Digit2 > 47 && Digit2 < 58) { this._PlayTempo = (byte)((Digit2 - 48) + ((Digit1 - 48) * 10)); CSCounter = CSCounter + 2; } else { this._PlayTempo = (byte)(Digit1 - 48); CSCounter = CSCounter + 1; } break; } // Triggers the event if (this.OnPlay != null) this.OnPlay(0, (uint)(CommandString.Length - CSCounter - 1), new DateTime()); } }