Index: mythtv/libs/libmythtv/tv_play.h
===================================================================
--- mythtv/libs/libmythtv/tv_play.h	(revision 25125)
+++ mythtv/libs/libmythtv/tv_play.h	(working copy)
@@ -433,6 +433,7 @@
                                  const QStringList &actions);
 
     void ToggleUpmix(PlayerContext*);
+    void ToggleVuvuzela(PlayerContext*);
     void ChangeAudioSync(PlayerContext*, int dir, bool allowEdit = true);
     bool AudioSyncHandleAction(PlayerContext*, const QStringList &actions);
 
Index: mythtv/libs/libmythtv/audioplayer.cpp
===================================================================
--- mythtv/libs/libmythtv/audioplayer.cpp	(revision 25125)
+++ mythtv/libs/libmythtv/audioplayer.cpp	(working copy)
@@ -269,6 +269,23 @@
     return toggle;
 }
 
+bool AudioPlayer::ToggleVuvuzela(void)
+{
+    bool toggle = false;
+    m_lock.lock();
+    if (m_audioOutput)
+        toggle = m_audioOutput->ToggleVuvuzela();
+    if (m_parent->GetDecoder())
+        m_parent->GetDecoder()->SetDisablePassThrough(toggle);        
+    m_lock.unlock();
+    return toggle;
+}
+
+bool AudioPlayer::IsVuvuzela(void)
+{
+    return m_audioOutput ? m_audioOutput->IsVuvuzela() : false;
+}
+
 void AudioPlayer::SetStretchFactor(float factor)
 {
     m_stretchfactor = factor;
Index: mythtv/libs/libmythtv/tv_play.cpp
===================================================================
--- mythtv/libs/libmythtv/tv_play.cpp	(revision 25125)
+++ mythtv/libs/libmythtv/tv_play.cpp	(working copy)
@@ -4219,6 +4219,8 @@
         ToggleTimeStretch(ctx);
     else if (has_action("TOGGLEUPMIX", actions))
         ToggleUpmix(ctx);
+    else if (has_action("TOGGLEVUVUZELA", actions))
+        ToggleVuvuzela(ctx);
     else if (has_action("TOGGLESLEEP", actions))
         ToggleSleepTimer(ctx);
     else if (has_action("TOGGLERECORD", actions) && islivetv)
@@ -7874,6 +7876,20 @@
         SetOSDMessage(ctx, text);
 }
 
+void TV::ToggleVuvuzela(PlayerContext *ctx)
+{
+    if (!ctx->nvp || !ctx->nvp->HasAudioOut())
+        return;
+    QString text;
+    if (ctx->nvp->GetAudio()->ToggleVuvuzela())
+        text = tr("Vuvuzela Filter On");
+    else
+        text = tr("Vuvuzela Filter Off");
+
+    if (!browsemode)
+        SetOSDMessage(ctx, text);
+}
+
 // dir in 10ms jumps
 void TV::ChangeAudioSync(PlayerContext *ctx, int dir, bool allowEdit)
 {
@@ -9639,6 +9655,8 @@
         ToggleTimeStretch(actx);
     else if (action == "TOGGLEUPMIX")
         ToggleUpmix(actx);
+    else if (action == "TOGGLEVUVUZELA")
+        ToggleVuvuzela(actx);
     else if (action.left(13) == "ADJUSTSTRETCH")
     {
         bool floatRead;
@@ -9916,26 +9934,28 @@
 
     if (category == "DVD" && top && (ctx->GetState() == kState_WatchingDVD))
     {
-        osd->DialogAddButton(tr("DVD Root Menu"),        "JUMPTODVDROOTMENU");
-        osd->DialogAddButton(tr("DVD Title Menu"),       "JUMPTODVDTITLEMENU");
-        osd->DialogAddButton(tr("DVD Chapter Menu"),     "JUMPTODVDCHAPTERMENU");
+        osd->DialogAddButton(tr("DVD Root Menu"),          "JUMPTODVDROOTMENU");
+        osd->DialogAddButton(tr("DVD Title Menu"),         "JUMPTODVDTITLEMENU");
+        osd->DialogAddButton(tr("DVD Chapter Menu"),       "JUMPTODVDCHAPTERMENU");
     }
     else if (category == "GUIDE" && top)
-        osd->DialogAddButton(tr("Program Guide"),        "GUIDE");
+        osd->DialogAddButton(tr("Program Guide"),          "GUIDE");
     else if (category == "EDITCHANNEL" && top)
-        osd->DialogAddButton(tr("Edit Channel"),         "EDIT");
+        osd->DialogAddButton(tr("Edit Channel"),           "EDIT");
     else if (category == "EDITRECORDING" && top)
-        osd->DialogAddButton(tr("Edit Recording"),       "EDIT");
+        osd->DialogAddButton(tr("Edit Recording"),         "EDIT");
     else if (category == "TOGGLEBROWSE" && top && !db_browse_always)
-        osd->DialogAddButton(tr("Enable Browse Mode"),   "TOGGLEBROWSE");
+        osd->DialogAddButton(tr("Enable Browse Mode"),     "TOGGLEBROWSE");
     else if ( category == "PREVCHAN" && top)
-        osd->DialogAddButton(tr("Previous Channel"),     "PREVCHAN");
+        osd->DialogAddButton(tr("Previous Channel"),       "PREVCHAN");
     else if (category == "AUDIOSYNC" && top)
-        osd->DialogAddButton(tr("Adjust Audio Sync"),    "TOGGLEAUDIOSYNC");
+        osd->DialogAddButton(tr("Adjust Audio Sync"),      "TOGGLEAUDIOSYNC");
     else if (category == "TOGGLEUPMIX" && top)
-        osd->DialogAddButton(tr("Toggle Audio Upmixer"), "TOGGLEUPMIX");
+        osd->DialogAddButton(tr("Toggle Audio Upmixer"),   "TOGGLEUPMIX");
+    else if (category == "TOGGLEVUVUZELA" && top)
+        osd->DialogAddButton(tr("Toggle Vuvuzela Filter"), "TOGGLEVUVUZELA");
     else if (category == "MANUALZOOM"  && mainCtx && top)
-        osd->DialogAddButton(tr("Manual Zoom Mode"),     "TOGGLEMANUALZOOM");
+        osd->DialogAddButton(tr("Manual Zoom Mode"),       "TOGGLEMANUALZOOM");
     else if (category == "TRANSCODE")
         title = FillOSDMenuTranscode(ctx, osd, select, level);
     else if (category == "COMMSKIP")
Index: mythtv/libs/libmythtv/tvosdmenuentry.cpp
===================================================================
--- mythtv/libs/libmythtv/tvosdmenuentry.cpp	(revision 25125)
+++ mythtv/libs/libmythtv/tvosdmenuentry.cpp	(working copy)
@@ -1,6 +1,7 @@
 #include "tvosdmenuentry.h"
 #include "mythdb.h"
 #include "mythverbose.h"
+#include "mythcorecontext.h"
 
 #define LOC QString("OSDMenuEntry:")
 #define LOC_ERR QString("OSDMenuEntry Error:")
@@ -243,6 +244,12 @@
         "AUDIOSYNC",          1,  1,  1,  1, "Audio Sync"));
     curMenuEntries.append(new TVOSDMenuEntry(
         "TOGGLEUPMIX",        1,  1,  1,  1, "Toggle Upmixer"));
+    if (gCoreContext->GetNumSetting("AdvancedAudioSettings", false) &&
+        gCoreContext->GetNumSetting("VuvuzelaFilter", false))
+    {
+        curMenuEntries.append(new TVOSDMenuEntry(
+            "TOGGLEVUVUZELA",        1,  1,  1,  1, "Toggle Vuvuzela Filter"));
+    }
     curMenuEntries.append(new TVOSDMenuEntry(
         "TIMESTRETCH",        1,  1,  1,  1, "Time Stretch"));
     curMenuEntries.append(new TVOSDMenuEntry(
Index: mythtv/libs/libmythtv/audioplayer.h
===================================================================
--- mythtv/libs/libmythtv/audioplayer.h	(revision 25125)
+++ mythtv/libs/libmythtv/audioplayer.h	(working copy)
@@ -33,6 +33,8 @@
     float GetStretchFactor(void) { return m_stretchfactor;   }
     void  SetStretchFactor(float factor);
     bool  ToggleUpmix(void);
+    bool  ToggleVuvuzela(void);
+    bool  IsVuvuzela(void);
     long long GetAudioTime(void);
 
     bool      IsMuted(void) { return GetMuteState() == kMuteAll; }
Index: mythtv/libs/libmyth/audiooutputbase.h
===================================================================
--- mythtv/libs/libmyth/audiooutputbase.h	(revision 25125)
+++ mythtv/libs/libmyth/audiooutputbase.h	(working copy)
@@ -17,6 +17,7 @@
 // MythTV headers
 #include "audiooutput.h"
 #include "audiooutputsettings.h"
+#include "audiooutpututil.h"
 #include "samplerate.h"
 #include "mythverbose.h"
 
@@ -50,6 +51,8 @@
 
     virtual bool CanPassthrough(void) const;
     virtual bool ToggleUpmix(void);
+    virtual bool ToggleVuvuzela(void);
+    virtual bool IsVuvuzela(void) { return vuvuzela; }
 
     virtual void Reset(void);
 
@@ -211,6 +214,10 @@
     /** main audio buffer */
     uchar audiobuffer[kAudioRingBufferSize];
     uint memory_corruption_test3;
+
+    //Vuvuzela filter
+    bool vuvuzela, last_vuvuzela;
+    AudioOutputUtil::Notch *notch_instance;
 };
 
 #endif
Index: mythtv/libs/libmyth/audiooutpututil.h
===================================================================
--- mythtv/libs/libmyth/audiooutpututil.h	(revision 25125)
+++ mythtv/libs/libmyth/audiooutpututil.h	(working copy)
@@ -5,9 +5,64 @@
 #include "mythverbose.h"
 #include "audiooutputsettings.h"
 
+#define IIR_NUM_COEFFICIENTS    (3)     // Assumed biquads
+
 class AudioOutputUtil
 {
  public:
+ 
+    //Notch Filter / IRR transformation
+    // Parameters
+    typedef struct
+    {
+        uint N;
+        uint num_biquads;
+        float b[IIR_NUM_COEFFICIENTS];
+        float a[IIR_NUM_COEFFICIENTS];
+    } IIR_Parameters;
+    
+    // State information
+    typedef struct
+    {
+        float a[IIR_NUM_COEFFICIENTS];
+        float b[IIR_NUM_COEFFICIENTS];
+        float x_mem[IIR_NUM_COEFFICIENTS];
+        float y_mem[IIR_NUM_COEFFICIENTS];
+    } IIR_State;
+
+    // Instance
+    typedef struct
+    {
+        IIR_Parameters parameters;
+        IIR_State state;
+    } IIR;
+
+    // Parameters
+    typedef struct
+    {
+        uint N;
+        float frequency;        // Notch frequency
+    } Notch_Parameters;
+
+    // State information
+
+    typedef struct
+    {
+        float pole_position;
+        float frequency_offset;
+        float a1s;
+        float a2;
+        float depth_factor;
+    } Notch_State;
+
+    // Instance
+    typedef struct
+    {
+        Notch_Parameters parameters;
+        Notch_State state;
+        IIR iir;
+    } Notch;
+
     static int  toFloat(AudioFormat format, void *out, void *in, int bytes);
     static int  fromFloat(AudioFormat format, void *out, void *in, int bytes);
     static void MonoToStereo(void *dst, void *src, int samples);
@@ -15,6 +70,8 @@
                              bool music, bool upmix);
     static void MuteChannel(int obits, int channels, int ch,
                             void *buffer, int bytes);
+    static void notch_update(Notch &instance, float fs);
+    static void notch_execute(Notch &instance, float *in, float *out);
 };
 
 #endif
Index: mythtv/libs/libmyth/audiooutputbase.cpp
===================================================================
--- mythtv/libs/libmyth/audiooutputbase.cpp	(revision 25125)
+++ mythtv/libs/libmyth/audiooutputbase.cpp	(working copy)
@@ -94,7 +94,9 @@
     memory_corruption_test0(0xdeadbeef),
     memory_corruption_test1(0xdeadbeef),
     memory_corruption_test2(0xdeadbeef),
-    memory_corruption_test3(0xdeadbeef)
+    memory_corruption_test3(0xdeadbeef),
+    vuvuzela(false),            last_vuvuzela(false),
+    notch_instance(NULL)
 {
     src_in = (float *)AOALIGN(src_in_buf);
     // The following are not bzero() because MS Windows doesn't like it.
@@ -240,6 +242,26 @@
 }
 
 /**
+ * Toggle Vuvuzela filter
+ */
+bool AudioOutputBase::ToggleVuvuzela(void)
+{
+    // Reset audiobuffer now to prevent click
+    audio_buflock.lock();
+    avsync_lock.lock();
+    waud = raud = 0;
+
+    vuvuzela = !vuvuzela;
+    const AudioSettings settings(format, source_channels, codec,
+                                 source_samplerate, passthru);
+    audio_buflock.unlock();
+    avsync_lock.unlock();
+    Reconfigure(settings);
+
+    return vuvuzela;
+}
+
+/**
  * (Re)Configure AudioOutputBase
  *
  * Must be called from concrete subclasses
@@ -303,6 +325,7 @@
                         settings.use_passthru == passthru &&
                         lneeds_upmix == needs_upmix && lreenc == reenc &&
                         lsource_channels == source_channels &&
+                        last_vuvuzela == vuvuzela &&
                         lneeds_downmix == needs_downmix;
 
     if (general_deps)
@@ -311,6 +334,8 @@
         return;
     }
 
+    last_vuvuzela          = vuvuzela;
+
     KillAudio();
 
     QMutexLocker lock(&audio_buflock);
@@ -328,6 +353,7 @@
     needs_downmix          = lneeds_downmix;
     format                 = output_format   = settings.format;
     source_samplerate      = samplerate      = settings.samplerate;
+    vuvuzela               = last_vuvuzela;
 
     killaudio = pauseaudio = false;
     was_paused = true;
@@ -415,7 +441,7 @@
     // Turn on float conversion?
     if (need_resampler || needs_upmix || needs_downmix ||
         stretchfactor != 1.0f || (internal_vol && SWVolume()) ||
-        (enc && output_format != FORMAT_S16) ||
+        (enc && output_format != FORMAT_S16) || vuvuzela ||
         !output_settings->IsSupportedFormat(output_format))
     {
         VBAUDIO("Audio processing enabled");
@@ -426,6 +452,13 @@
             output_format = output_settings->BestSupportedFormat();
     }
 
+    if (vuvuzela)
+    {
+        VBAUDIO("Vuvuzela filter enabled. Go Socceroos Go!");
+        if (!notch_instance)
+            notch_instance = new AudioOutputUtil::Notch;
+    }
+
     if (passthru)
         channels = 2; // IEC958 bitstream - 2 ch
 
@@ -560,8 +593,14 @@
         src_ctx = NULL;
     }
 
-    needs_upmix = need_resampler = enc = false;
+    if (notch_instance)
+    {
+        delete notch_instance;
+        notch_instance = NULL;
+    }
 
+    needs_upmix = need_resampler = enc = vuvuzela = false;
+
     CloseDevice();
 
     killAudioLock.unlock();
@@ -943,6 +982,19 @@
             return false; // would overflow
     }
 
+    if (vuvuzela && notch_instance)
+    {
+        notch_instance->parameters.N = frames * channels;
+
+            // Notch frequency
+        notch_instance->parameters.frequency = 235.0f;
+        AudioOutputUtil::notch_update (*notch_instance, (float)source_samplerate);
+        AudioOutputUtil::notch_execute (*notch_instance, src_in, src_out);
+        notch_instance->parameters.frequency = 465.0f;  // 1st harmonic
+        AudioOutputUtil::notch_update (*notch_instance, (float)source_samplerate);
+        AudioOutputUtil::notch_execute (*notch_instance, src_out, src_in);
+    }
+
     // Perform downmix if necessary
     if (needs_downmix)
         if(AudioOutputDownmix::DownmixFrames(source_channels, channels,
Index: mythtv/libs/libmyth/audiooutput.h
===================================================================
--- mythtv/libs/libmyth/audiooutput.h	(revision 25125)
+++ mythtv/libs/libmyth/audiooutput.h	(working copy)
@@ -69,6 +69,8 @@
     virtual int readOutputData(unsigned char *read_buffer, int max_length) = 0;
 
     virtual bool ToggleUpmix(void) = 0;
+    virtual bool ToggleVuvuzela(void) = 0;
+    virtual bool IsVuvuzela(void) = 0;
 
   protected:
     void Error(const QString &msg);
Index: mythtv/libs/libmyth/audiooutpututil.cpp
===================================================================
--- mythtv/libs/libmyth/audiooutpututil.cpp	(revision 25125)
+++ mythtv/libs/libmyth/audiooutpututil.cpp	(working copy)
@@ -610,3 +610,122 @@
     else
         _MuteChannel((int *)buffer, channels, ch, frames);
 }
+
+#define IIR_NUM_COEFFICIENTS				(3)	// Assumed biquads
+
+static void iir_update (AudioOutputUtil::IIR &instance)
+{
+	// Clear the filter state
+    bzero(&instance.state.x_mem[0], IIR_NUM_COEFFICIENTS * sizeof(float));
+    bzero(&instance.state.y_mem[0], IIR_NUM_COEFFICIENTS * sizeof(float));
+    
+    memcpy(&instance.state.b[0], &instance.parameters.b[0],
+           IIR_NUM_COEFFICIENTS * sizeof(float));
+    memcpy(&instance.state.a[0], &instance.parameters.a[0],
+           IIR_NUM_COEFFICIENTS * sizeof(float));
+}
+
+/* Notch filter (c) 2010 Hydrix & Jean-Yves Avenard */
+/* www.hydrix.com */
+
+// Processes a single block of samples with a single IIR biquad stage
+//    N                   M
+//   SUM a(k+1) y(n-k) = SUM b(k+1) x(n-k)      for 1<=n<=length(x)
+//   k=0                 k=0
+// where N=length(a)-1 and M=length(b)-1.
+// Vector s is the initial state of the system. The final state is also returned
+// The state vector is a column vector whose length is equal to the
+// 	length of the longest coefficient vector minus one.
+static void iir_biquad (float* x, float* y,
+                        float* a, float* b,
+                        float* x_mem, float* y_mem,
+                        unsigned int N)
+{
+   // Direct Form I
+   //               N+1               N+1
+   //		y(n) = - SUM a(k) y(n-k) + SUM b(k) x(n-k)  for 0 <= n <length(x)
+   //               k=1               k=0
+    unsigned int n = 0;
+    unsigned int k = 0;
+    float y_n_minus_k = 0.0f;
+    float x_n_minus_k = 0.0f;
+    for (n = 0; n < N; n++)
+    {
+        y[n] = x[n] * b[0];
+
+        for (k = 1; k < IIR_NUM_COEFFICIENTS; k++)
+        {
+            signed int n_minus_k = n - k;
+            if (n_minus_k >= 0)
+            {
+                x_n_minus_k = x[n_minus_k];
+                y_n_minus_k = y[n_minus_k];
+            }
+            else
+            {
+                x_n_minus_k = x_mem[-n_minus_k-1];
+                y_n_minus_k = y_mem[-n_minus_k-1];
+            }
+
+            y[n] -= a[k] * y_n_minus_k;
+            y[n] += b[k] * x_n_minus_k;
+        }
+    }
+
+	// Save input and output state, latest first
+    unsigned int state_offset = N - 1;
+    for (n=0; n < (IIR_NUM_COEFFICIENTS-1); n++)
+    {
+        x_mem[n] = x[state_offset];
+        y_mem[n] = y[state_offset];
+        state_offset--;
+    }
+}
+
+static void iir_execute(AudioOutputUtil::IIR &instance, float* x, float* y)
+{
+    iir_biquad(x, y,
+               &instance.state.a[0], &instance.state.b[0],
+               &instance.state.x_mem[0], &instance.state.y_mem[0],
+               instance.parameters.N);
+}
+
+// Notch filter
+#define PI_FLOAT                    (3.14159265358979f)
+
+void AudioOutputUtil::notch_update (Notch &instance, float fs)
+{
+    instance.state.pole_position = 0.99f;
+    instance.state.frequency_offset = 0.0f; // in normalised frequency (1.0 = fs)
+    instance.state.a1s = -instance.state.pole_position;
+    instance.state.a2 = -(instance.state.pole_position * instance.state.pole_position);
+    instance.state.depth_factor = 1.0f;
+
+	// Calculate filter coefficients
+	// Direct-form IIR
+	// Ref: http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt and others
+    float normalised_notch_frequency = (2.0f * instance.parameters.frequency / fs);
+    normalised_notch_frequency += instance.state.frequency_offset;
+    float frequency_factor = -2.0f * cosf(PI_FLOAT * normalised_notch_frequency);
+    float a1 = frequency_factor * instance.state.a1s;
+    float a2 = instance.state.a2;
+    float b1 = frequency_factor * instance.state.depth_factor;
+    float b2 = instance.state.depth_factor * instance.state.depth_factor;
+    instance.iir.parameters.N = instance.parameters.N;
+    instance.iir.parameters.a[0] = 1.0f;
+    instance.iir.parameters.a[1] = -a1;
+    instance.iir.parameters.a[2] = -a2;
+    instance.iir.parameters.b[0] = 1.0f;
+    instance.iir.parameters.b[1] = b1;
+    instance.iir.parameters.b[2] = b2;
+
+	// Initialise the IIR stage
+    iir_update(instance.iir);
+}
+
+// Processes a single block of samples
+void AudioOutputUtil::notch_execute (Notch &instance, float *in, float *out)
+{
+    // Apply the rejection filter
+    iir_execute(instance.iir, in, out);
+}
Index: mythtv/programs/mythfrontend/globalsettings.cpp
===================================================================
--- mythtv/programs/mythfrontend/globalsettings.cpp	(revision 25125)
+++ mythtv/programs/mythfrontend/globalsettings.cpp	(working copy)
@@ -219,6 +219,17 @@
     return gc;
 }
 
+static HostCheckBox *VuvuzelaFilter()
+{
+    HostCheckBox *gc = new HostCheckBox("VuvuzelaFilter");
+    gc->setLabel(QObject::tr("Enable vuvuzela filter"));
+    gc->setValue(false);
+    gc->setHelpText(QObject::tr("With this option enabled, a dedicated vuvuzela "
+                                "filter option will be accessible in the playback "
+                                "menu"));
+    return gc;
+}
+
 static HostCheckBox *MythControlsVolume()
 {
     HostCheckBox *gc = new HostCheckBox("MythControlsVolume");
@@ -3301,6 +3312,7 @@
     settings4->addChild(srcqualityoverride);
     settings4->addChild(sub4);
 
+    group2->addChild(VuvuzelaFilter());
     group2->addChild(settings4);
     group2->addChild(Audio48kOverride());
     group2->addChild(settings3);
Index: mythtv/programs/mythtranscode/transcode.cpp
===================================================================
--- mythtv/programs/mythtranscode/transcode.cpp	(revision 25125)
+++ mythtv/programs/mythtranscode/transcode.cpp	(working copy)
@@ -186,7 +186,16 @@
         // Do nothing
         return false;
     }
-
+    virtual bool ToggleVuvuzela(void)
+    {
+        // Do nothing
+        return false;
+    }
+    virtual bool IsVuvuzela(void)
+    {
+        // Do nothing
+        return false;
+    }
     virtual void SetSWVolume(int new_volume, bool save)
     {
         // Do nothing

