diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro
index 7d3cab5ba6ddbb8615f5eee9ce00d940159f6209..bd46c796eab39f71f3182e6e62eb591026e9929e 100644
--- a/qgroundcontrol.pro
+++ b/qgroundcontrol.pro
@@ -243,6 +243,7 @@ INCLUDEPATH += \
     src/ui/map \
     src/uas \
     src/comm \
+    src/audio \
     include/ui \
     src/input \
     src/lib/qmapcontrol \
@@ -479,7 +480,8 @@ HEADERS += \
     src/QGCFileDialog.h \
     src/QGCMessageBox.h \
     src/QGCComboBox.h \
-    src/QGCTemporaryFile.h
+    src/QGCTemporaryFile.h \
+    src/audio/QGCAudioWorker.h
 
 SOURCES += \
     src/main.cc \
@@ -618,7 +620,8 @@ SOURCES += \
     src/uas/QGXPX4UAS.cc \
     src/QGCFileDialog.cc \
     src/QGCComboBox.cc \
-    src/QGCTemporaryFile.cc
+    src/QGCTemporaryFile.cc \
+    src/audio/QGCAudioWorker.cpp
 
 
 #
diff --git a/src/GAudioOutput.cc b/src/GAudioOutput.cc
index a67d4564980987e748bb998a211c1cc01d1ff15c..78a2dd0de7afd5676426c3b52110037f98433d8f 100644
--- a/src/GAudioOutput.cc
+++ b/src/GAudioOutput.cc
@@ -33,28 +33,8 @@ This file is part of the QGROUNDCONTROL project
 #include <QApplication>
 #include <QSettings>
 #include "GAudioOutput.h"
-#include "MG.h"
-
 #include <QDebug>
-
-#if defined Q_OS_MAC && defined QGC_SPEECH_ENABLED
-#include <ApplicationServices/ApplicationServices.h>
-#endif
-
-// Speech synthesis is only supported with MSVC compiler
-#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
-// Documentation: http://msdn.microsoft.com/en-us/library/ee125082%28v=VS.85%29.aspx
-#include <sapi.h>
-#endif
-
-#if defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
-// Using eSpeak for speech synthesis: following https://github.com/mondhs/espeak-sample/blob/master/sampleSpeak.cpp
-#include <espeak/speak_lib.h>
-#endif
-
-#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
-ISpVoice *GAudioOutput::pVoice = NULL;
-#endif
+#include <QGC.h>
 
 /**
  * This class follows the singleton design pattern
@@ -78,134 +58,44 @@ GAudioOutput *GAudioOutput::instance()
     return _instance;
 }
 
-#define QGC_GAUDIOOUTPUT_KEY QString("QGC_AUDIOOUTPUT_")
-
 GAudioOutput::GAudioOutput(QObject *parent) : QObject(parent),
-    voiceIndex(0),
-    emergency(false),
-    muted(false)
+    muted(false),
+    thread(new QThread()),
+    worker(new QGCAudioWorker())
 {
-    // Load settings
-    QSettings settings;
-    muted = settings.value(QGC_GAUDIOOUTPUT_KEY + "muted", muted).toBool();
-
-
-#if defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
-    espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 500, NULL, 0); // initialize for playback with 500ms buffer and no options (see speak_lib.h)
-    espeak_VOICE *espeak_voice = espeak_GetCurrentVoice();
-    espeak_voice->languages = "en-uk"; // Default to British English
-    espeak_voice->identifier = NULL; // no specific voice file specified
-    espeak_voice->name = "klatt"; // espeak voice name
-    espeak_voice->gender = 2; // Female
-    espeak_voice->age = 0; // age not specified
-    espeak_SetVoiceByProperties(espeak_voice);
-#endif
-
-#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
-    pVoice = NULL;
-
-    if (FAILED(::CoInitialize(NULL)))
-    {
-        qDebug() << "ERROR: Creating COM object for audio output failed!";
-    }
-
-    else
-    {
-
-        HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);
-
-        if (FAILED(hr))
-        {
-            qDebug() << "ERROR: Initializing voice for audio output failed!";
-        }
-    }
-
-#endif
-
-    // Prepare regular emergency signal, will be fired off on calling startEmergency()
-    emergencyTimer = new QTimer();
-    connect(emergencyTimer, SIGNAL(timeout()), this, SLOT(beep()));
-
-    switch (voiceIndex)
-    {
-    case 0:
-        selectFemaleVoice();
-        break;
-
-    default:
-        selectMaleVoice();
-        break;
-    }
+    worker->moveToThread(thread);
+    connect(this, SIGNAL(textToSpeak(QString,int)), worker, SLOT(say(QString,int)));
+    thread->start();
 }
 
 GAudioOutput::~GAudioOutput()
 {
-#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
-    pVoice->Release();
-    pVoice = NULL;
-    ::CoUninitialize();
-#endif
+    thread->quit();
+    while (thread->isRunning()) {
+        QGC::SLEEP::usleep(100);
+    }
+    worker->deleteLater();
+    thread->deleteLater();
+    worker = NULL;
+    thread = NULL;
 }
 
 
 void GAudioOutput::mute(bool mute)
 {
-    if (mute != muted)
-    {
-        this->muted = mute;
-        QSettings settings;
-        settings.setValue(QGC_GAUDIOOUTPUT_KEY + "muted", this->muted);
-        emit mutedChanged(muted);
-    }
+    // XXX handle muting
 }
 
 bool GAudioOutput::isMuted()
 {
-    return this->muted;
+    // XXX return right stuff
+    return false;
 }
 
 bool GAudioOutput::say(QString text, int severity)
 {
-    if (!muted)
-    {
-        // TODO Add severity filter
-        Q_UNUSED(severity);
-        bool res = false;
-
-        if (!emergency)
-        {
-
-#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
-            pVoice->Speak(text.toStdWString().c_str(), SPF_ASYNC, NULL);
-
-#elif defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
-            // Set size of string for espeak: +1 for the null-character
-            unsigned int espeak_size = strlen(text.toStdString().c_str()) + 1;
-            espeak_Synth(text.toStdString().c_str(), espeak_size, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL);
-
-#elif defined Q_OS_MAC && defined QGC_SPEECH_ENABLED
-            // Slashes necessary to have the right start to the sentence
-            // copying data prevents SpeakString from reading additional chars
-            text = "\\" + text;
-            std::wstring str = text.toStdWString();
-            unsigned char str2[1024] = {};
-            memcpy(str2, text.toLatin1().data(), str.length());
-            SpeakString(str2);
-            res = true;
-
-#else
-            // Make sure there isn't an unused variable warning when speech output is disabled
-            Q_UNUSED(text);
-#endif
-        }
-
-        return res;
-    }
-
-    else
-    {
-        return false;
-    }
+    emit textToSpeak(text, severity);
+    return true;
 }
 
 /**
@@ -213,19 +103,8 @@ bool GAudioOutput::say(QString text, int severity)
  */
 bool GAudioOutput::alert(QString text)
 {
-    if (!emergency || !muted)
-    {
-        // Play alert sound
-        beep();
-        // Say alert message
-        say(text, 2);
-        return true;
-    }
-
-    else
-    {
-        return false;
-    }
+    emit textToSpeak(text, 2);
+    return true;
 }
 
 void GAudioOutput::notifyPositive()
@@ -261,16 +140,16 @@ void GAudioOutput::notifyNegative()
  */
 bool GAudioOutput::startEmergency()
 {
-    if (!emergency)
-    {
-        emergency = true;
+//    if (!emergency)
+//    {
+//        emergency = true;
 
-        // Beep immediately and then start timer
-        if (!muted) beep();
+//        // Beep immediately and then start timer
+//        if (!muted) beep();
 
-        emergencyTimer->start(1500);
-        QTimer::singleShot(5000, this, SLOT(stopEmergency()));
-    }
+//        emergencyTimer->start(1500);
+//        QTimer::singleShot(5000, this, SLOT(stopEmergency()));
+//    }
 
     return true;
 }
@@ -283,11 +162,11 @@ bool GAudioOutput::startEmergency()
  */
 bool GAudioOutput::stopEmergency()
 {
-    if (emergency)
-    {
-        emergency = false;
-        emergencyTimer->stop();
-    }
+//    if (emergency)
+//    {
+//        emergency = false;
+//        emergencyTimer->stop();
+//    }
 
     return true;
 }
@@ -304,26 +183,3 @@ void GAudioOutput::beep()
         //m_media->play();
     }
 }
-
-void GAudioOutput::selectFemaleVoice()
-{
-#if defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
-    // FIXME: Enable selecting a female voice on all platforms
-    //this->voice = register_cmu_us_slt(NULL);
-#endif
-}
-
-void GAudioOutput::selectMaleVoice()
-{
-#if defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
-    // FIXME: Enable selecting a male voice on all platforms
-    //this->voice = register_cmu_us_rms(NULL);
-#endif
-}
-
-QStringList GAudioOutput::listVoices(void)
-{
-    // No voice selection is currently supported, so just return an empty list
-    QStringList l;
-    return l;
-}
diff --git a/src/GAudioOutput.h b/src/GAudioOutput.h
index dbf3b60beb6d91261ab47dd65499362600c8ca02..ce21c904f2d6fe1e2a5f5adf5919f126e0d936f2 100644
--- a/src/GAudioOutput.h
+++ b/src/GAudioOutput.h
@@ -34,31 +34,10 @@ This file is part of the PIXHAWK project
 
 #include <QObject>
 #include <QTimer>
+#include <QThread>
 #include <QStringList>
-#ifdef Q_OS_MAC
-//#include <MediaObject>
-//#include <AudioOutput>
-#endif
-#ifdef Q_OS_LINUX
-//#include <phonon/MediaObject>
-//#include <phonon/AudioOutput>
-#endif
-#ifdef Q_OS_WIN
-//#include <Phonon/MediaObject>
-//#include <Phonon/AudioOutput>
-#endif
-
-/* For Snow leopard and later
-#if defined Q_OS_MAC & defined QGC_SPEECH_ENABLED
-#include <NSSpeechSynthesizer.h>
-#endif
-   */
-
-
-#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
-// Documentation: http://msdn.microsoft.com/en-us/library/ee125082%28v=VS.85%29.aspx
-#include <sapi.h>
-#endif
+
+#include <QGCAudioWorker.h>
 
 /**
  * @brief Audio Output (speech synthesizer and "beep" output)
@@ -91,10 +70,10 @@ public slots:
     bool startEmergency();
     /** @brief Stop emergency sound */
     bool stopEmergency();
-    /** @brief Select female voice */
-    void selectFemaleVoice();
-    /** @brief Select male voice */
-    void selectMaleVoice();
+//    /** @brief Select female voice */
+//    void selectFemaleVoice();
+//    /** @brief Select male voice */
+//    void selectMaleVoice();
     /** @brief Play emergency sound once */
     void beep();
     /** @brief Notify about positive event */
@@ -106,23 +85,12 @@ public slots:
 
 signals:
     void mutedChanged(bool);
+    bool textToSpeak(QString text, int severity = 1);
 
 protected:
-#if defined Q_OS_MAC && defined QGC_SPEECH_ENABLED
-    //NSSpeechSynthesizer
-#endif
-#if defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
-    //cst_voice* voice; ///< The flite voice object
-#endif
-#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
-    static ISpVoice *pVoice;
-#endif
-    int voiceIndex;   ///< The index of the flite voice to use (awb, slt, rms)
-    //Phonon::MediaObject *m_media; ///< The output object for audio
-    //Phonon::AudioOutput *m_audioOutput;
-    bool emergency;   ///< Emergency status flag
-    QTimer *emergencyTimer;
     bool muted;
+    QThread* thread;
+    QGCAudioWorker* worker;
 private:
     GAudioOutput(QObject *parent = NULL);
     ~GAudioOutput();
diff --git a/src/audio/QGCAudioWorker.cpp b/src/audio/QGCAudioWorker.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..eac54d57166174d3ae8f8371a1af7f82260edcb9
--- /dev/null
+++ b/src/audio/QGCAudioWorker.cpp
@@ -0,0 +1,143 @@
+#include <QSettings>
+#include <QDebug>
+
+#include "QGC.h"
+#include "QGCAudioWorker.h"
+
+#if defined Q_OS_MAC && defined QGC_SPEECH_ENABLED
+#include <ApplicationServices/ApplicationServices.h>
+#endif
+
+// Speech synthesis is only supported with MSVC compiler
+#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
+// Documentation: http://msdn.microsoft.com/en-us/library/ee125082%28v=VS.85%29.aspx
+#include <sapi.h>
+#endif
+
+#if defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
+// Using eSpeak for speech synthesis: following https://github.com/mondhs/espeak-sample/blob/master/sampleSpeak.cpp
+#include <espeak/speak_lib.h>
+#endif
+
+#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
+ISpVoice *GAudioOutput::pVoice = NULL;
+#endif
+
+#define QGC_GAUDIOOUTPUT_KEY QString("QGC_AUDIOOUTPUT_")
+
+QGCAudioWorker::QGCAudioWorker(QObject *parent) :
+    QObject(parent),
+    voiceIndex(0),
+    emergency(false),
+    muted(false)
+{
+    // Load settings
+    QSettings settings;
+    muted = settings.value(QGC_GAUDIOOUTPUT_KEY + "muted", muted).toBool();
+
+
+#if defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
+    espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 500, NULL, 0); // initialize for playback with 500ms buffer and no options (see speak_lib.h)
+    espeak_VOICE *espeak_voice = espeak_GetCurrentVoice();
+    espeak_voice->languages = "en-uk"; // Default to British English
+    espeak_voice->identifier = NULL; // no specific voice file specified
+    espeak_voice->name = "klatt"; // espeak voice name
+    espeak_voice->gender = 2; // Female
+    espeak_voice->age = 0; // age not specified
+    espeak_SetVoiceByProperties(espeak_voice);
+#endif
+
+#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
+    pVoice = NULL;
+
+    if (FAILED(::CoInitialize(NULL)))
+    {
+        qDebug() << "ERROR: Creating COM object for audio output failed!";
+    }
+
+    else
+    {
+
+        HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);
+
+        if (FAILED(hr))
+        {
+            qDebug() << "ERROR: Initializing voice for audio output failed!";
+        }
+    }
+
+#endif
+
+    // Prepare regular emergency signal, will be fired off on calling startEmergency()
+    emergencyTimer = new QTimer();
+    connect(emergencyTimer, SIGNAL(timeout()), this, SLOT(beep()));
+}
+
+QGCAudioWorker::~QGCAudioWorker()
+{
+#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
+    pVoice->Release();
+    pVoice = NULL;
+    ::CoUninitialize();
+#endif
+}
+
+void QGCAudioWorker::say(QString text, int severity)
+{
+    qDebug() << "TEXT" << text;
+    if (!muted)
+    {
+        // TODO Add severity filter
+        Q_UNUSED(severity);
+        bool res = false;
+
+        if (!emergency)
+        {
+
+    #if defined _MSC_VER && defined QGC_SPEECH_ENABLED
+            pVoice->Speak(text.toStdWString().c_str(), SPF_ASYNC, NULL);
+
+    #elif defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
+            // Set size of string for espeak: +1 for the null-character
+            unsigned int espeak_size = strlen(text.toStdString().c_str()) + 1;
+            espeak_Synth(text.toStdString().c_str(), espeak_size, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL);
+
+    #elif defined Q_OS_MAC && defined QGC_SPEECH_ENABLED
+            // Slashes necessary to have the right start to the sentence
+            // copying data prevents SpeakString from reading additional chars
+            text = "\\" + text;
+            std::wstring str = text.toStdWString();
+            unsigned char str2[1024] = {};
+            memcpy(str2, text.toLatin1().data(), str.length());
+            SpeakString(str2);
+
+            // Block the thread while busy
+            // because we run in our own thread, this doesn't
+            // halt the main application
+            while (SpeechBusy()) {
+                QGC::SLEEP::msleep(100);
+            }
+
+    #else
+            // Make sure there isn't an unused variable warning when speech output is disabled
+            Q_UNUSED(text);
+    #endif
+        }
+    }
+}
+
+void QGCAudioWorker::mute(bool mute)
+{
+    if (mute != muted)
+    {
+        this->muted = mute;
+        QSettings settings;
+        settings.setValue(QGC_GAUDIOOUTPUT_KEY + "muted", this->muted);
+//        emit mutedChanged(muted);
+    }
+}
+
+bool QGCAudioWorker::isMuted()
+{
+    return this->muted;
+}
diff --git a/src/audio/QGCAudioWorker.h b/src/audio/QGCAudioWorker.h
new file mode 100644
index 0000000000000000000000000000000000000000..749dd6147df1955985106bb7f7aa037b364a988c
--- /dev/null
+++ b/src/audio/QGCAudioWorker.h
@@ -0,0 +1,51 @@
+#ifndef QGCAUDIOWORKER_H
+#define QGCAUDIOWORKER_H
+
+#include <QObject>
+#include <QTimer>
+
+/* For Snow leopard and later
+#if defined Q_OS_MAC & defined QGC_SPEECH_ENABLED
+#include <NSSpeechSynthesizer.h>
+#endif
+   */
+
+
+#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
+// Documentation: http://msdn.microsoft.com/en-us/library/ee125082%28v=VS.85%29.aspx
+#include <sapi.h>
+#endif
+
+class QGCAudioWorker : public QObject
+{
+    Q_OBJECT
+public:
+    explicit QGCAudioWorker(QObject *parent = 0);
+    ~QGCAudioWorker();
+
+    void mute(bool mute);
+    bool isMuted();
+
+signals:
+
+public slots:
+    /** @brief Say this text if current output priority matches */
+    void say(QString text, int severity = 1);
+
+protected:
+#if defined Q_OS_MAC && defined QGC_SPEECH_ENABLED
+    //NSSpeechSynthesizer
+#endif
+#if defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
+    //cst_voice* voice; ///< The flite voice object
+#endif
+#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
+    static ISpVoice *pVoice;
+#endif
+    int voiceIndex;   ///< The index of the flite voice to use (awb, slt, rms)
+    bool emergency;   ///< Emergency status flag
+    QTimer *emergencyTimer;
+    bool muted;
+};
+
+#endif // QGCAUDIOWORKER_H