OSDN Git Service

RAD-464: Speech plugin improvements, ability to set speech rate, and 3D sound
authorLatif Khalifa <latifer@streamgrid.net>
Tue, 4 Mar 2014 14:21:11 +0000 (15:21 +0100)
committerLatif Khalifa <latifer@streamgrid.net>
Tue, 4 Mar 2014 14:21:11 +0000 (15:21 +0100)
Radegast/Core/Media/Speech.cs
plugins/Radegast.Plugin.Speech/RadSpeech/PluginControl.cs
plugins/Radegast.Plugin.Speech/RadSpeechWin/WinSynth.cs

index 5167df8..d5ed8ea 100644 (file)
@@ -61,6 +61,16 @@ namespace Radegast.Media
         }
 
         /// <summary>
+        /// If truee use FMODEx 3D sound
+        /// </summary>
+        private static bool surround = false;
+        public static bool Surround
+        {
+            set { surround = value; }
+            get { return surround; }
+        }
+
+        /// <summary>
         /// Creates a new sound object
         /// </summary>
         /// <param name="system">Sound system</param>
@@ -98,13 +108,19 @@ namespace Radegast.Media
             filename = speakfile;
 
             // Set flags to determine how it will be played.
-            FMOD.MODE mode = FMOD.MODE.SOFTWARE | FMOD.MODE._3D;
+            FMOD.MODE mode = FMOD.MODE.SOFTWARE;
+
+            if (Surround)
+            {
+                mode |= FMOD.MODE._3D;
+
+                // Set coordinate space interpretation.
+                if (global)
+                    mode |= FMOD.MODE._3D_WORLDRELATIVE;
+                else
+                    mode |= FMOD.MODE._3D_HEADRELATIVE;
+            }
 
-            // Set coordinate space interpretation.
-            if (global)
-                mode |= FMOD.MODE._3D_WORLDRELATIVE;
-            else
-                mode |= FMOD.MODE._3D_HEADRELATIVE;
 
             System.Threading.AutoResetEvent done = new System.Threading.AutoResetEvent(false);
 
@@ -133,30 +149,33 @@ namespace Radegast.Media
                         volume = 1.0f;
                         FMODExec(channel.setVolume(volume));
 
-                        // Set attenuation limits so distant people get a little softer,
-                        // but not TOO soft
-                        if (compress)
-                            FMODExec(sound.set3DMinMaxDistance(
-                                    2f,       // Any closer than this gets no louder
-                                    3.5f));     // Further than this gets no softer.
-                        else
-                            FMODExec(sound.set3DMinMaxDistance(
-                                    2f,       // Any closer than this gets no louder
-                                    10f));     // Further than this gets no softer.
-
-                        // Set speaker position.
-                        position = FromOMVSpace(speakerPos);
-                        FMODExec(channel.set3DAttributes(
-                           ref position,
-                           ref ZeroVector));
-
-                        Logger.Log(
-                            String.Format(
-                                "Speech at <{0:0.0},{1:0.0},{2:0.0}>",
-                                position.x,
-                                position.y,
-                                position.z),
-                            Helpers.LogLevel.Debug);
+                        if (Surround)
+                        {
+                            // Set attenuation limits so distant people get a little softer,
+                            // but not TOO soft
+                            if (compress)
+                                FMODExec(sound.set3DMinMaxDistance(
+                                        2f,       // Any closer than this gets no louder
+                                        3.5f));     // Further than this gets no softer.
+                            else
+                                FMODExec(sound.set3DMinMaxDistance(
+                                        2f,       // Any closer than this gets no louder
+                                        10f));     // Further than this gets no softer.
+
+                            // Set speaker position.
+                            position = FromOMVSpace(speakerPos);
+                            FMODExec(channel.set3DAttributes(
+                               ref position,
+                               ref ZeroVector));
+
+                            Logger.Log(
+                                String.Format(
+                                    "Speech at <{0:0.0},{1:0.0},{2:0.0}>",
+                                    position.x,
+                                    position.y,
+                                    position.z),
+                                Helpers.LogLevel.Debug);
+                        }
 
                         // SET a handler for when it finishes.
                         FMODExec(channel.setCallback(endCallback));
index b0df38a..db03f4e 100644 (file)
@@ -68,7 +68,7 @@ namespace RadegastSpeech
 
             // Get configuration settings, and initialize if not found.
             config = instance.GlobalSettings["plugin.speech"] as OSDMap;
-            
+
             if (config == null)
             {
                 config = new OSDMap();
@@ -77,23 +77,109 @@ namespace RadegastSpeech
                 config["properties"] = new OSDMap();
                 config["substitutions"] = new OSDMap();
                 instance.GlobalSettings["plugin.speech"] = config;
-                instance.GlobalSettings.Save();
             }
 
-            // Add our enable/disable item to the Plugin Menu.
-            ToolsMenu = instance.MainForm.PluginsMenu;
+            OSDMap props = (OSDMap)config["properties"];
+            if (props["voice_speed"] == "")
+            {
+                props["voice_speed"] = "medium";
+            }
 
-            SpeechButton = new ToolStripMenuItem("Speech", null, OnSpeechMenuButtonClicked);
-            ToolsMenu.DropDownItems.Add(SpeechButton);
+            #region Buttons on the plugin menu
+            // SpeechButton = new ToolStripMenuItem("Speech", null, OnSpeechMenuButtonClicked);
+            SpeechButton = new ToolStripMenuItem("Speech");
+            instance.MainForm.PluginsMenu.DropDownItems.Add(SpeechButton);
 
             SpeechButton.Checked = config["enabled"].AsBoolean();
 
-            ToolsMenu.Visible = true;
+            // Enabled sub menu
+            {
+                ToolStripMenuItem button = new ToolStripMenuItem("Enabled", null, (sender, e) =>
+                {
+                    OnSpeechMenuButtonClicked(SpeechButton, EventArgs.Empty);
+                    ((ToolStripMenuItem)sender).Checked = SpeechButton.Checked;
+                });
+
+                button.Checked = SpeechButton.Checked;
+
+                SpeechButton.DropDownItems.Add(button);
+            }
+
+            SpeechButton.DropDownItems.Add(new ToolStripSeparator());
+
+            // Voice rate
+            {
+                ToolStripMenuItem slowButton = new ToolStripMenuItem("Slow");
+                if (props["voice_speed"] == "slow") slowButton.Checked = true;
+                ToolStripMenuItem mediumButton = new ToolStripMenuItem("Medium");
+                if (props["voice_speed"] == "medium") mediumButton.Checked = true;
+                ToolStripMenuItem fastButton = new ToolStripMenuItem("Fast");
+                if (props["voice_speed"] == "fast") fastButton.Checked = true;
+
+                slowButton.Click += (sender, e) =>
+                {
+                    slowButton.Checked = !slowButton.Checked;
+                    if (slowButton.Checked)
+                    {
+                        props["voice_speed"] = "slow";
+                        mediumButton.Checked = false;
+                        fastButton.Checked = false;
+                    }
+                };
+
+                mediumButton.Click += (sender, e) =>
+                {
+                    mediumButton.Checked = !mediumButton.Checked;
+                    if (mediumButton.Checked)
+                    {
+                        props["voice_speed"] = "medium";
+                        slowButton.Checked = false;
+                        fastButton.Checked = false;
+                    }
+                };
+
+                fastButton.Click += (sender, e) =>
+                {
+                    fastButton.Checked = !fastButton.Checked;
+                    if (fastButton.Checked)
+                    {
+                        props["voice_speed"] = "fast";
+                        slowButton.Checked = false;
+                        mediumButton.Checked = false;
+                    }
+                };
+
+                SpeechButton.DropDownItems.Add(slowButton);
+                SpeechButton.DropDownItems.Add(mediumButton);
+                SpeechButton.DropDownItems.Add(fastButton);
+            }
+
+            SpeechButton.DropDownItems.Add(new ToolStripSeparator());
+
+            // 3D Sound sub menu
+            {
+                ToolStripMenuItem button = new ToolStripMenuItem("3D Sound", null, (sender, e) =>
+                {
+                    var me = (ToolStripMenuItem)sender;
+                    me.Checked = !me.Checked;
+                    config["3d_sound"] = me.Checked;
+                    instance.GlobalSettings.Save();
+                    Radegast.Media.Speech.Surround = me.Checked;
+                });
+
+                button.Checked = config["3d_sound"].AsBoolean();
+                Radegast.Media.Speech.Surround = button.Checked;
+
+                SpeechButton.DropDownItems.Add(button);
+            }
+            #endregion Buttons on the plugin menu
 
             if (SpeechButton.Checked)
             {
                 Initialize();
             }
+
+            instance.GlobalSettings.Save();
         }
 
         /// <summary>
index 9c3d0a6..608e214 100644 (file)
@@ -25,8 +25,27 @@ namespace RadegastSpeech
         private PromptVolume promptVol = PromptVolume.Loud;
         private string[] BeepNames;
         private OSDMap voiceProperties;
+        PromptRate voiceRate
+        {
+            get
+            {
+                if (voiceProperties != null)
+                {
+                    string voiceSpeed = voiceProperties["voice_speed"];
+                    if (!string.IsNullOrEmpty(voiceSpeed))
+                    {
+                        switch (voiceSpeed)
+                        {
+                            case "fast": return PromptRate.Fast;
+                            case "slow": return PromptRate.Slow;
+                        }
+                    }
+                }
+                return PromptRate.Medium;
+            }
+        }
 
-        internal WinSynth( PluginControl pc, string[] beeps)
+        internal WinSynth(PluginControl pc, string[] beeps)
         {
             BeepNames = beeps;
             voiceProperties = pc.config["properties"] as OSDMap;
@@ -49,13 +68,13 @@ namespace RadegastSpeech
         internal void Halt()
         {
         }
-        
+
         internal void Speak(QueuedSpeech utterance, string outputfile)
         {
             if (syn == null) return;
 
             // Got something to say.  Initialize temp file.
-            StartSpeech(utterance.voice, outputfile );
+            StartSpeech(utterance.voice, outputfile);
 
             // Play the beep, if there is one.
             if (utterance.beep != BeepType.None)
@@ -85,7 +104,7 @@ namespace RadegastSpeech
 
             // Close the temporary WAV file.
             FinishSpeech();
-       }
+        }
 
         private void StartSpeech(AssignedVoice vb, string outputfile)
         {
@@ -125,19 +144,24 @@ namespace RadegastSpeech
         private void SaySegment(QueuedSpeech utterance)
         {
             PromptStyle body = new PromptStyle();
+            /* User preference now
             switch (utterance.voice.rateModification)
             {
-                case 00: body.Rate = PromptRate.Medium; break;
+                case 00: body.Rate = PromptRate.Fast; break;
                 case +1: body.Rate = PromptRate.Fast; break;
-                case -1: body.Rate = PromptRate.Slow; break;
+                case -1: body.Rate = PromptRate.Medium; break;
             }
+            */
+
+            body.Rate = voiceRate;
+
             switch (utterance.voice.pitchModification)
             {
                 case 00: body.Emphasis = PromptEmphasis.Moderate; break;
                 case +1: body.Emphasis = PromptEmphasis.Strong; break;
                 case -1: body.Emphasis = PromptEmphasis.Reduced; break;
             }
+
             pb.StartStyle(body);
             pb.StartSentence();
             pb.AppendText(utterance.message);
@@ -152,9 +176,9 @@ namespace RadegastSpeech
         private void SayPrompt(string text)
         {
             PromptStyle intro = new PromptStyle();
-            intro.Rate = PromptRate.Fast;
-            intro.Volume = promptVol - 1;
-            intro.Emphasis = PromptEmphasis.Reduced;
+            intro.Rate = voiceRate;
+            //intro.Volume = promptVol - 1;
+            intro.Emphasis = PromptEmphasis.Moderate;
             pb.StartStyle(intro);
             pb.StartSentence();
             pb.AppendText(text + ":");
@@ -213,7 +237,7 @@ namespace RadegastSpeech
                     // Check for additional information about this voice
                     if (voiceProperties != null)
                     {
-                        string propString = voiceProperties[ v.VoiceInfo.Name ].AsString();
+                        string propString = voiceProperties[v.VoiceInfo.Name].AsString();
                         if (propString != null)
                         {
                             // Properties are a series of blank-separated keywords