Index: audiooutputbase.h
===================================================================
--- audiooutputbase.h	(revision 16313)
+++ audiooutputbase.h	(working copy)
@@ -50,6 +50,21 @@
                              int   audio_samplerate,
                              bool  audio_passthru,
                              void *audio_codec = NULL);
+
+    // For software pre-amplification.
+    virtual bool IsPreAmpEnabled() const;
+	virtual void SetPreAmp(bool enabled);
+    virtual void EnablePreAmp();
+    virtual void DisablePreAmp();
+    virtual void SetPreAmpGain(float gain);
+    virtual void SetPreAmpFactor(float factor);
+    virtual float GetPreAmpGain() const;
+    virtual float GetPreAmpFactor() const;
+    virtual void ResetClippingMonitor();
+    virtual bool HasClippingOccurred() const;
+    virtual float GetMaxOutput() const;
+    virtual float GetMaxClipFreePreAmpGain() const;
+    virtual float GetMaxClipFreePreAmpFactor() const;
     
     // do AddSamples calls block?
     virtual void SetBlocking(bool blocking);
@@ -104,6 +119,7 @@
 
     int GetAudioData(unsigned char *buffer, int buf_size, bool fill_buffer);
 
+    void ApplyPreAmp(void *buffer, int samples, int sample_bytes);
     void _AddSamples(void *buffer, bool interleaved, int samples, long long timecode);
  
     void KillAudio();
@@ -161,6 +177,11 @@
     float src_out[AUDIO_SRC_OUT_SIZE];
     short tmp_buff[AUDIO_TMP_BUF_SIZE];
 
+    // pre-amplification
+    bool pre_amp_enabled;
+    float pre_amp_factor;
+    float pre_amp_max_output;
+
     // timestretch
     soundtouch::SoundTouch    *pSoundStretch;
     AudioOutputDigitalEncoder *encoder;
Index: audiooutputbase.cpp
===================================================================
--- audiooutputbase.cpp	(revision 16313)
+++ audiooutputbase.cpp	(working copy)
@@ -2,6 +2,8 @@
 #include <cstdio>
 #include <cstdlib>
 #include <cmath>
+#include <climits>
+#include <cfloat>
 
 // POSIX headers
 #include <pthread.h>
@@ -50,6 +52,9 @@
     need_resampler(false),
 
     src_ctx(NULL),
+    
+    pre_amp_enabled(false),     pre_amp_factor(1.0),
+    pre_amp_max_output(0.0),
 
     pSoundStretch(NULL),        
     encoder(NULL),
@@ -846,6 +851,34 @@
     return len;
 }
 
+#define __APPLY_PRE_AMP(TYPE,MIN,MAX) \
+	{ \
+	TYPE *buf = (TYPE *)buffer; \
+    for ( int i = 0; i < samples; ++i ) \
+    { \
+        float f = (float)buf[i] / (float)MAX; \
+        f *= pre_amp_factor; \
+        float a = abs(f); \
+        if ( a > pre_amp_max_output ) pre_amp_max_output = a; \
+        if ( f >= 1.0 ) buf[i] = MAX; \
+        else if ( f <= -1.0 ) buf[i] = MIN; \
+        else buf[i] = (TYPE)round(f*MAX); \
+    } \
+	}
+void AudioOutputBase::ApplyPreAmp(void *buffer, int samples, int sample_bytes)
+{
+    if ( !pre_amp_enabled ) return;
+    // NOTE: This only handles 1, 2 or 4 byte samples.
+    if ( sample_bytes == 4 )
+		__APPLY_PRE_AMP(int,INT_MIN,INT_MAX)
+    else if ( sample_bytes == 2 )
+		__APPLY_PRE_AMP(short,SHRT_MIN,SHRT_MAX)
+    else if ( sample_bytes == 1 )
+		__APPLY_PRE_AMP(char,CHAR_MIN,CHAR_MAX)
+    return;
+}
+#undef __APPLY_PRE_AMP
+
 void AudioOutputBase::_AddSamples(void *buffer, bool interleaved, int samples, 
                                   long long timecode)
 {
@@ -854,7 +887,18 @@
     int len; // = samples * audio_bytes_per_sample;
     int audio_bytes = audio_bits / 8;
     int org_waud = waud;
-    
+
+    if ( interleaved )
+        // Apply to the single buffer if we're interleaved.
+        ApplyPreAmp(buffer,samples*source_audio_channels,audio_bytes);
+    else
+    {
+        // Otherwise, apply to each channel individually.
+        void **bufs = (void**)buffer;
+        for ( int i = 0; i < source_audio_channels; ++i )
+            ApplyPreAmp(bufs[i],samples,audio_bytes);
+    }
+
     int afree = audiofree(false);
 
     int abps = (encoder) ?
@@ -1345,5 +1389,79 @@
     return 0;
 }
 
+bool AudioOutputBase::IsPreAmpEnabled() const
+{
+    return pre_amp_enabled;
+}
+
+void AudioOutputBase::SetPreAmp(bool enabled)
+{
+	pre_amp_enabled = enabled;
+	return;
+}
+
+void AudioOutputBase::EnablePreAmp()
+{
+    pre_amp_enabled = true;
+    return;
+}
+
+void AudioOutputBase::DisablePreAmp()
+{
+    pre_amp_enabled = false;
+    return;
+}
+
+void AudioOutputBase::SetPreAmpGain(float gain)
+{
+    pre_amp_factor = pow(10.0,gain/20.0);
+    return;
+}
+
+void AudioOutputBase::SetPreAmpFactor(float factor)
+{
+    if ( factor >= 0 ) pre_amp_factor = factor;
+    return;
+}
+
+float AudioOutputBase::GetPreAmpGain() const
+{
+    if ( pre_amp_factor <= 0 ) return -1.0*FLT_MAX;
+    return 20.0*log(pre_amp_factor)/log(10.0);
+}
+
+float AudioOutputBase::GetPreAmpFactor() const
+{
+    return pre_amp_factor;
+}
+
+void AudioOutputBase::ResetClippingMonitor()
+{
+    pre_amp_max_output = 0.0;
+    return;
+}
+
+bool AudioOutputBase::HasClippingOccurred() const
+{
+    return pre_amp_max_output > 1.0;
+}
+
+float AudioOutputBase::GetMaxOutput() const
+{
+    return pre_amp_max_output;
+}
+
+float AudioOutputBase::GetMaxClipFreePreAmpGain() const
+{
+    float max_factor = GetMaxClipFreePreAmpFactor();
+    if ( max_factor <= 0 ) return -1.0*FLT_MAX;
+    return 20.0*log(max_factor)/log(10.0);
+}
+
+float AudioOutputBase::GetMaxClipFreePreAmpFactor() const
+{
+    if ( pre_amp_max_output == 0 ) return FLT_MAX;
+    return pre_amp_factor / pre_amp_max_output;
+}
+
 /* vim: set expandtab tabstop=4 shiftwidth=4: */
-
Index: audiooutput.h
===================================================================
--- audiooutput.h	(revision 16313)
+++ audiooutput.h	(working copy)
@@ -36,6 +36,21 @@
                              int audio_samplerate,
                              bool audio_passthru,
                              void* audio_codec = NULL) = 0;
+
+    // For software pre-amplification.
+    virtual bool IsPreAmpEnabled() const { return false; }
+	virtual void SetPreAmp(bool enabled) { return; }
+    virtual void EnablePreAmp() { return; }
+	virtual void DisablePreAmp() { return; }
+    virtual void SetPreAmpGain(float gain) { return; }
+    virtual void SetPreAmpFactor(float factor) { return; }
+    virtual float GetPreAmpGain() const { return 0.0; }
+    virtual float GetPreAmpFactor() const { return 1.0; }
+    virtual void ResetClippingMonitor() { return; }
+    virtual bool HasClippingOccurred() const { return false; }
+    virtual float GetMaxOutput() const { return 1.0; }
+    virtual float GetMaxClipFreePreAmpGain() const { return 0.0; }
+    virtual float GetMaxClipFreePreAmpFactor() const { return 1.0; }
     
     virtual void SetStretchFactor(float factor);
     virtual float GetStretchFactor(void) { return 1.0f; }
