/// <summary> /// Play an single tone on a given channel /// </summary> /// <param name="tone">A RttlTone object</param> /// <param name="channel">Any PWN pin</param> public void PlayTone(RttlTone tone, PWM channel) { if (tone.Note != 0) { channel.SetPulse(tone.Period, tone.Period / 2); Thread.Sleep(tone.GetDelay(Tempo)); channel.SetDutyCycle(0); } else { channel.SetDutyCycle(0); Thread.Sleep(tone.GetDelay(Tempo)); } }
/// <summary> /// Plays a raw RTTL string by converting it into PWN tones /// Derived from http://code.google.com/p/rogue-code/source/browse/Arduino/libraries/Tone/trunk/examples/RTTTL/RTTTL.pde /// and Ian Lintner's port to C# https://github.com/ianlintner/Netduino-Ring-Tone-Player /// </summary> public void Play(PWM channel) { char[] charParserArray; //used for parsing the current section const int defaultDuration = 4; const int defaultOctave = 6; var tone = new RttlTone(); foreach (var rttlNote in _rttlNotes) { charParserArray = rttlNote.ToLower().ToCharArray(); // Parse each note... and play it! for (var i = 0; i < rttlNote.Length; i++) { var durationParseNumber = 0; int currentScale; var currentNote = 0; const int octaveOffset = 0; // first, get note duration, if available while (i < charParserArray.Length && IsDigit(charParserArray[i])) { //construct the duration durationParseNumber = (durationParseNumber * 10) + (charParserArray[i++] - '0'); } var currentDuration = durationParseNumber > 0 ? durationParseNumber : defaultDuration; // c is first note i.e. c = 1 // b = 12 // pause or undefined = 0 if (i < charParserArray.Length) { switch (charParserArray[i]) { case 'c': currentNote = 1; break; case 'd': currentNote = 3; break; case 'e': currentNote = 5; break; case 'f': currentNote = 6; break; case 'g': currentNote = 8; break; case 'a': currentNote = 10; break; case 'b': currentNote = 12; break; case 'p': currentNote = 0; break; default: currentNote = 0; break; } } i++; // process whether the note is sharp if (i < charParserArray.Length && charParserArray[i] == '#') { currentNote++; i++; } // is it dotted note, divide the duration in half if (i < charParserArray.Length && charParserArray[i] == '.') { currentDuration += currentDuration / 2; i++; } // now, get octave if (i < charParserArray.Length && IsDigit(charParserArray[i])) { currentScale = charParserArray[i] - '0'; i++; } else { currentScale = defaultOctave; } //offset if necessary currentScale += octaveOffset; // Setup the tone by calculating the note's location in the RTTTL note array tone.SetTone((uint)RttlNotes[(currentScale - 1) * 12 + currentNote], (uint)currentDuration); // Play the tone PlayTone(tone, channel); } } }