/// <summary>
    /// Speak back text
    /// </summary>
    /// <param name="text">Text to speak</param>
    /// <param name="queue">If you want to chain together speak command or cancel current</param>
    /// <param name="crossLocale">Locale of voice</param>
    /// <param name="pitch">Pitch of voice</param>
    /// <param name="speakRate">Speak Rate of voice (All) (0.0 - 2.0f)</param>
    /// <param name="volume">Volume of voice (iOS/WP) (0.0-1.0)</param>
    public void Speak(string text, bool queue = false, CrossLocale? crossLocale = null, float? pitch = null, float? speakRate = null, float? volume = null)
    {
      
      if (string.IsNullOrWhiteSpace(text))
        return;

      if (speechSynthesizer == null)
        Init();

      var localCode = crossLocale.HasValue &&
                      !string.IsNullOrWhiteSpace(crossLocale.Value.Language) ?
                      crossLocale.Value.Language :
                      AVSpeechSynthesisVoice.CurrentLanguageCode;

        
      pitch = !pitch.HasValue ? 1.0f : pitch;

      if (!volume.HasValue)
        volume = 1.0f;
      else if (volume > 1.0f)
        volume = 1.0f;
      else if (volume < 0.0f)
        volume = 0.0f;

      var divid = UIDevice.CurrentDevice.CheckSystemVersion(8, 0) ? 8.0f : 4.0f;
      if (!speakRate.HasValue)
          speakRate = AVSpeechUtterance.MaximumSpeechRate / divid; //normal speech, default is fast
      else if (speakRate.Value > AVSpeechUtterance.MaximumSpeechRate)
        speakRate = AVSpeechUtterance.MaximumSpeechRate;
      else if (speakRate.Value < AVSpeechUtterance.MinimumSpeechRate)
        speakRate = AVSpeechUtterance.MinimumSpeechRate;

      var voice = AVSpeechSynthesisVoice.FromLanguage(localCode);
      if(voice == null)
      {
        Console.WriteLine("Locale not found for voice: " + localCode + " is not valid using default.");
        voice = AVSpeechSynthesisVoice.FromLanguage(AVSpeechSynthesisVoice.CurrentLanguageCode);
      }

      if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
      {
        var dummyUtterance = new AVSpeechUtterance(" ");
        dummyUtterance.Voice = voice;
        speechSynthesizer.SpeakUtterance(dummyUtterance);
      }

      var speechUtterance = new AVSpeechUtterance(text)
      {
        Rate = speakRate.Value,
        Voice = voice,
        Volume = volume.Value,
        PitchMultiplier = pitch.Value
      };

      if (!queue && speechSynthesizer.Speaking)
        speechSynthesizer.StopSpeaking(AVSpeechBoundary.Word);

      speechSynthesizer.SpeakUtterance(speechUtterance);
    }
    /// <summary>
    /// Speak back text
    /// </summary>
    /// <param name="text">Text to speak</param>
    /// <param name="queue">If you want to chain together speak command or cancel current</param>
    /// <param name="crossLocale">Locale of voice</param>
    /// <param name="pitch">Pitch of voice</param>
    /// <param name="speakRate">Speak Rate of voice (All) (0.0 - 2.0f)</param>
    /// <param name="volume">Volume of voice (iOS/WP) (0.0-1.0)</param>
    public void Speak(string text, bool queue = false, CrossLocale? crossLocale = null, float? pitch = null, float? speakRate = null, float? volume = null)
    {
      this.text = text;
      this.language = crossLocale;
      this.pitch = pitch == null ? 1.0f : pitch.Value;
      this.speakRate = speakRate == null ? 1.0f : speakRate.Value;
      this.queue = queue;

      if (textToSpeech == null || !initialized)
      {
        Init();
      }
      else
      {
        Speak();
      }
    }
    /// <summary>
    /// Speak back text
    /// </summary>
    /// <param name="text">Text to speak</param>
    /// <param name="queue">If you want to chain together speak command or cancel current</param>
    /// <param name="crossLocale">Locale of voice</param>
    /// <param name="pitch">Pitch of voice</param>
    /// <param name="speakRate">Speak Rate of voice (All) (0.0 - 2.0f)</param>
    /// <param name="volume">Volume of voice (iOS/WP) (0.0-1.0)</param>
    public async void Speak(string text, bool queue = false, CrossLocale? crossLocale = null, float? pitch = null, float? speakRate = null, float? volume = null)
    {
      if (string.IsNullOrWhiteSpace(text))
        return;

      if (speechSynthesizer == null)
        Init();

#if !NETFX_CORE
      if (!queue)
        speechSynthesizer.CancelAll();
#endif
      var localCode = string.Empty;

      //nothing fancy needed here
      if(pitch == null && speakRate == null && volume == null)
      {
        if(crossLocale.HasValue && !string.IsNullOrWhiteSpace(crossLocale.Value.Language))
        {
          localCode = crossLocale.Value.Language;
#if NETFX_CORE
          var voices = from voice in SpeechSynthesizer.AllVoices
                        where (voice.Language == localCode 
                        && voice.Gender.Equals(VoiceGender.Female))
                        select voice;
          speechSynthesizer.Voice =(voices.Any() ? voices.ElementAt(0) : SpeechSynthesizer.DefaultVoice);
       
#else
          var voices = from voice in InstalledVoices.All
                       where (voice.Language == localCode 
                         && voice.Gender.Equals(VoiceGender.Female))
                         select voice;
          speechSynthesizer.SetVoice(voices.Any() ? voices.ElementAt(0) : InstalledVoices.Default);
#endif
        }
        else
        {
#if NETFX_CORE
          speechSynthesizer.Voice = SpeechSynthesizer.DefaultVoice;
#else
          speechSynthesizer.SetVoice(InstalledVoices.Default);
#endif
        }

#if NETFX_CORE
        try
        {
          var stream = await speechSynthesizer.SynthesizeTextToStreamAsync(text);
          element.SetSource(stream, stream.ContentType);
          element.Play();
        }
        catch(Exception ex)
        {
          Debug.WriteLine("Unable to playback stream: " + ex);
        }
#else
        speechSynthesizer.SpeakTextAsync(text);
#endif
        return;
      }

      if(crossLocale.HasValue && !string.IsNullOrWhiteSpace(crossLocale.Value.Language))
      {
         localCode = crossLocale.Value.Language;
#if NETFX_CORE
        var voices = from voice in SpeechSynthesizer.AllVoices
                     where (voice.Language == localCode
                     && voice.Gender.Equals(VoiceGender.Female))
                     select voice;
#else
        var voices = from voice in InstalledVoices.All
                     where (voice.Language == localCode 
                         && voice.Gender.Equals(VoiceGender.Female))
                         select voice;
#endif
        if (!voices.Any())
        {
#if NETFX_CORE
          localCode = SpeechSynthesizer.DefaultVoice.Language;
#else
          localCode = InstalledVoices.Default.Language;
#endif
        }
      }
      else
      {
#if NETFX_CORE
        localCode = SpeechSynthesizer.DefaultVoice.Language;
#else
        localCode = InstalledVoices.Default.Language;
#endif
      }


       if (!volume.HasValue)
        volume = 100.0f;
      else if (volume.Value > 1.0f)
        volume = 100.0f;
      else if (volume.Value < 0.0f)
        volume = 0.0f;
       else
         volume = volume.Value * 100.0f;

      var pitchProsody = "default";
      //var test = "x-low", "low", "medium", "high", "x-high", or "default";
      if(!pitch.HasValue)
        pitchProsody = "default";
      else if(pitch.Value >=  1.6f)
        pitchProsody = "x-high";
      else if(pitch.Value >= 1.1f)
        pitchProsody = "high";
      else if(pitch.Value >= .9f)
        pitchProsody = "medium";
      else if(pitch.Value >= .4f)
        pitchProsody = "low";
      else 
        pitchProsody = "x-low";

     
      string ssmlText = "<speak version=\"1.0\" ";
      ssmlText += "xmlns=\"http://www.w3.org/2001/10/synthesis\" xml:lang=\"" + localCode + "\">";
      ssmlText += "<prosody pitch=\""+pitchProsody+"\" volume=\""+volume.Value +"\" rate=\""+ speakRate.Value+"\" >" + text + "</prosody>";
      ssmlText += "</speak>";

#if NETFX_CORE
      try{
      var stream = await speechSynthesizer.SynthesizeSsmlToStreamAsync(ssmlText);
      element.SetSource(stream, stream.ContentType);
      element.Play();
      }
      catch(Exception ex)
      {
        Debug.WriteLine("Unable to playback stream: " + ex);
      }
#else
      speechSynthesizer.SpeakSsmlAsync(ssmlText);
#endif
      
    }