diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 7dcc39950b14aa906c510fd4a1d1d3cb80164633..2ea25648df0b7a80fa738b386594fe6c7289c8c0 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -2461,6 +2461,56 @@ void LLMenuGL::empty( void )
 	deleteAllChildren();
 }
 
+// erase group of items from menu
+void LLMenuGL::erase( S32 begin, S32 end, bool arrange/* = true*/)
+{
+	S32 items = mItems.size();
+
+	if ( items == 0 || begin >= end || begin < 0 || end > items )
+	{
+		return;
+	}
+
+	item_list_t::const_iterator start_position = mItems.begin();
+	std::advance(start_position, begin);
+
+	item_list_t::const_iterator end_position = mItems.begin();
+	std::advance(end_position, end);
+
+	for (item_list_t::const_iterator position_iter = start_position; position_iter != end_position; position_iter++)
+	{
+		LLUICtrl::removeChild(*position_iter);
+	}
+
+	mItems.erase(start_position, end_position);
+
+	if (arrange)
+	{
+		needsArrange();
+	}
+}
+
+// add new item at position
+void LLMenuGL::insert( S32 position, LLView * ctrl, bool arrange /*= true*/ )
+{
+	LLMenuItemGL * item = dynamic_cast<LLMenuItemGL *>(ctrl);
+
+	if (NULL == item || position < 0 || position >= mItems.size())
+	{
+		return;
+	}
+
+	item_list_t::const_iterator position_iter = mItems.begin();
+	std::advance(position_iter, position);
+	mItems.insert(position_iter, item);
+	LLUICtrl::addChild(item);
+
+	if (arrange)
+	{
+		needsArrange();
+	}
+}
+
 // Adjust rectangle of the menu
 void LLMenuGL::setLeftAndBottom(S32 left, S32 bottom)
 {
@@ -2502,7 +2552,8 @@ BOOL LLMenuGL::append( LLMenuItemGL* item )
 // add a separator to this menu
 BOOL LLMenuGL::addSeparator()
 {
-	LLMenuItemGL* separator = new LLMenuItemSeparatorGL();
+	LLMenuItemSeparatorGL::Params p;
+	LLMenuItemGL* separator = LLUICtrlFactory::create<LLMenuItemSeparatorGL>(p);
 	return addChild(separator);
 }
 
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 3e03232e928c7794630bd69e0afc417e3af07ec4..c57e0f0267662f41eee20ae47ac644358e0d392d 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -478,6 +478,12 @@ public:
 	// remove all items on the menu
 	void empty( void );
 
+	// erase group of items from menu
+	void erase( S32 begin, S32 end, bool arrange = true );
+
+	// add new item at position
+	void insert( S32 begin, LLView * ctrl, bool arrange = true );
+
 	void			setItemLastSelected(LLMenuItemGL* item);	// must be in menu
 	U32				getItemCount();				// number of menu items
 	LLMenuItemGL*	getItem(S32 number);		// 0 = first item
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index a0aa639ac6377f109dc018526ea5fe9136b0172a..8b45c44ed010437f3aa7fb0fd78614c4ce1cef1d 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -108,6 +108,7 @@
 #include "llviewerparcelmgr.h"
 #include "llviewerstats.h"
 #include "llvoavatarself.h"
+#include "llvoicevivox.h"
 #include "llworldmap.h"
 #include "pipeline.h"
 #include "llviewerjoystick.h"
@@ -8152,6 +8153,11 @@ public:
 	}
 };
 
+void handle_voice_morphing_subscribe()
+{
+	LLWeb::loadURLExternal(LLTrans::getString("voice_morphing_url"));
+}
+
 class LLToggleUIHints : public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
@@ -8337,7 +8343,15 @@ void initialize_menus()
 	
 	// Me > Movement
 	view_listener_t::addMenu(new LLAdvancedAgentFlyingInfo(), "Agent.getFlying");
-	
+
+	// Communicate > Voice morphing > Subscribe...
+	commit.add("Communicate.VoiceMorphing.Subscribe", boost::bind(&handle_voice_morphing_subscribe));
+	LLVivoxVoiceClient * voice_clientp = LLVivoxVoiceClient::getInstance();
+	enable.add("Communicate.VoiceMorphing.NoVoiceMorphing.Check"
+		, boost::bind(&LLVivoxVoiceClient::onCheckVoiceEffect, voice_clientp, "NoVoiceMorphing"));
+	commit.add("Communicate.VoiceMorphing.NoVoiceMorphing.Click"
+		, boost::bind(&LLVivoxVoiceClient::onClickVoiceEffect, voice_clientp, "NoVoiceMorphing"));
+
 	// World menu
 	view_listener_t::addMenu(new LLWorldAlwaysRun(), "World.AlwaysRun");
 	view_listener_t::addMenu(new LLWorldCreateLandmark(), "World.CreateLandmark");
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 5e121bbcee6caa1f148037c5a6317c6768ede785..f3342b7ff18bd07150802bef3faec719b828e9d1 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -34,6 +34,7 @@
 #include "llvoavatarself.h"
 #include "llbufferstream.h"
 #include "llfile.h"
+#include "llmenugl.h"
 #ifdef LL_STANDALONE
 # include "expat.h"
 #else
@@ -70,6 +71,9 @@
 
 #define USE_SESSION_GROUPS 0
 
+extern LLMenuBarGL* gMenuBarView;
+extern void handle_voice_morphing_subscribe();
+
 const F32 VOLUME_SCALE_VIVOX = 0.01f;
 
 const F32 SPEAKING_TIMEOUT = 1.f;
@@ -6739,10 +6743,106 @@ void LLVivoxVoiceClient::removeObserver(LLVoiceEffectObserver* observer)
 	mVoiceFontObservers.erase(observer);
 }
 
+// method checks the item in VoiceMorphing menu for appropriate current voice font
+bool LLVivoxVoiceClient::onCheckVoiceEffect(const std::string& voice_effect_name)
+{
+	LLVoiceEffectInterface * effect_interfacep = LLVoiceClient::instance().getVoiceEffectInterface();
+	if (NULL != effect_interfacep)
+	{
+		const LLUUID& currect_voice_effect_id = effect_interfacep->getVoiceEffect();
+
+		if (currect_voice_effect_id.isNull())
+		{
+			if (voice_effect_name == "NoVoiceMorphing")
+			{
+				return true;
+			}
+		}
+		else
+		{
+			const LLSD& voice_effect_props = effect_interfacep->getVoiceEffectProperties(currect_voice_effect_id);
+			if (voice_effect_props["name"].asString() == voice_effect_name)
+			{
+				return true;
+			}
+		}
+	}
+
+	return false;
+}
+
+// method changes voice font for selected VoiceMorphing menu item
+void LLVivoxVoiceClient::onClickVoiceEffect(const std::string& voice_effect_name)
+{
+	LLVoiceEffectInterface * effect_interfacep = LLVoiceClient::instance().getVoiceEffectInterface();
+	if (NULL != effect_interfacep)
+	{
+		if (voice_effect_name == "NoVoiceMorphing")
+		{
+			effect_interfacep->setVoiceEffect(LLUUID());
+			return;
+		}
+		const voice_effect_list_t& effect_list = effect_interfacep->getVoiceEffectList();
+		if (!effect_list.empty())
+		{
+			for (voice_effect_list_t::const_iterator it = effect_list.begin(); it != effect_list.end(); ++it)
+			{
+				if (voice_effect_name == it->first)
+				{
+					effect_interfacep->setVoiceEffect(it->second);
+					return;
+				}
+			}
+		}
+	}
+}
+
+// it updates VoiceMorphing menu items in accordance with purchased properties 
+void LLVivoxVoiceClient::updateVoiceMorphingMenu()
+{
+	if (mVoiceFontListDirty)
+	{
+		LLVoiceEffectInterface * effect_interfacep = LLVoiceClient::instance().getVoiceEffectInterface();
+		if (effect_interfacep)
+		{
+			const voice_effect_list_t& effect_list = effect_interfacep->getVoiceEffectList();
+			if (!effect_list.empty())
+			{
+				LLMenuGL * voice_morphing_menup = gMenuBarView->findChildMenuByName("VoiceMorphing", TRUE);
+
+				if (NULL != voice_morphing_menup)
+				{
+					S32 items = voice_morphing_menup->getItemCount();
+					if (items > 0)
+					{
+						voice_morphing_menup->erase(1, items - 3, false);
+
+						S32 pos = 1;
+						for (voice_effect_list_t::const_iterator it = effect_list.begin(); it != effect_list.end(); ++it)
+						{
+							LLMenuItemCheckGL::Params p;
+							p.name = it->first;
+							p.label = it->first;
+							p.on_check.function(boost::bind(&LLVivoxVoiceClient::onCheckVoiceEffect, this, it->first));
+							p.on_click.function(boost::bind(&LLVivoxVoiceClient::onClickVoiceEffect, this, it->first));
+							LLMenuItemCheckGL * voice_effect_itemp = LLUICtrlFactory::create<LLMenuItemCheckGL>(p);
+							voice_morphing_menup->insert(pos++, voice_effect_itemp, false);
+						}
+
+						voice_morphing_menup->needsArrange();
+					}
+				}
+			}
+		}
+	}
+}
+
 void LLVivoxVoiceClient::notifyVoiceFontObservers()
 {
 	LL_DEBUGS("Voice") << "Notifying voice effect observers. Lists changed: " << mVoiceFontListDirty << LL_ENDL;
 
+	updateVoiceMorphingMenu();
+
 	for (voice_font_observer_set_t::iterator it = mVoiceFontObservers.begin();
 		 it != mVoiceFontObservers.end();
 		 )
diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h
index 69f33df94b02ea151556f36f7177a88dd59eb889..574027de42eba7ed61a990cc93d635a1a80143c6 100644
--- a/indra/newview/llvoicevivox.h
+++ b/indra/newview/llvoicevivox.h
@@ -246,6 +246,8 @@ public:
 
 	//@}
 
+	bool onCheckVoiceEffect(const std::string& voice_effect_name);
+	void onClickVoiceEffect(const std::string& voice_effect_name);
 
 protected:
 	//////////////////////
@@ -854,6 +856,7 @@ private:
 	void accountGetTemplateFontsSendMessage();
 	void sessionSetVoiceFontSendMessage(sessionState *session);
 
+	void updateVoiceMorphingMenu();
 	void notifyVoiceFontObservers();
 
 	typedef enum e_voice_font_type
diff --git a/indra/newview/skins/default/xui/en/floater_voice_effect.xml b/indra/newview/skins/default/xui/en/floater_voice_effect.xml
index 35cb2670d0904187dfcd55e9cd06c0df45a4f27d..146c3d7e30daf841c6afdb1b8c80320cf85dbd14 100644
--- a/indra/newview/skins/default/xui/en/floater_voice_effect.xml
+++ b/indra/newview/skins/default/xui/en/floater_voice_effect.xml
@@ -5,12 +5,13 @@
  height="500"
  name="voice_effects"
  help_topic="voice_effects"
- title="VOICE MORPHING"
+ title="VOICE MORPHING PREVIEW"
  background_visible="true"
  label="Places"
  layout="topleft"
  min_height="360"
  min_width="200"
+ save_rect="true"
  width="300">
   <string name="no_voice_effect">
     (No Voice Morph)
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 8d5e3f0b5d9fc2c4c867cb5b8d9495122f81bfed..10fd8138d248ea434dec6ec5508599f587bf35cd 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -268,17 +268,36 @@
              parameter="conversation" />
         </menu_item_check>
         <menu_item_separator/>
-        <menu_item_check
-         label="Voice morphing..."
-         name="ShowVoice"
+        <menu
+         label="Voice morphing"
+         name="VoiceMorphing"
          visibility_control="VoiceMorphingEnabled">
-            <menu_item_check.on_check
-             function="Floater.Visible"
-             parameter="voice_effect" />
-            <menu_item_check.on_click
-             function="Floater.Toggle"
-             parameter="voice_effect" />
-        </menu_item_check>
+            <menu_item_check
+             label="No voice morphing"
+             name="NoVoiceMorphing">
+                <menu_item_check.on_check
+                 function="Communicate.VoiceMorphing.NoVoiceMorphing.Check" />
+                <menu_item_check.on_click
+                 function="Communicate.VoiceMorphing.NoVoiceMorphing.Click" />
+            </menu_item_check>
+            <menu_item_separator/>
+            <menu_item_check
+             label="Preview..."
+             name="Preview">
+                <menu_item_check.on_check
+                 function="Floater.Visible"
+                 parameter="voice_effect" />
+                <menu_item_check.on_click
+                 function="Floater.Toggle"
+                 parameter="voice_effect" />
+            </menu_item_check>
+            <menu_item_call
+             label="Subscribe..."
+             name="Subscribe">
+                <menu_item_call.on_click
+                 function="Communicate.VoiceMorphing.Subscribe" />
+            </menu_item_call>
+        </menu>
         <menu_item_check
          label="Gestures..."
          name="Gestures"