Ticket #4804: libs_libmyth-preamp-patch-ticket-4804.patch

File libs_libmyth-preamp-patch-ticket-4804.patch, 7.4 KB (added by Erik Hovland <erik@…>, 16 years ago)

This patch is the same patch, but against trunk as of 2008-04-14

  • libs/libmyth/audiooutput.h

    Ticket 4804 is an enhancement to MythTV to provide a pre-amp feature. This is
    
    From: Erik Hovland <erik@hovland.org>
    
    the first step towards having native ReplayGain support in MythMusic.
    ---
    
     libs/libmyth/audiooutput.h       |   15 +++++
     libs/libmyth/audiooutputbase.cpp |  122 ++++++++++++++++++++++++++++++++++++++
     libs/libmyth/audiooutputbase.h   |   22 +++++++
     3 files changed, 157 insertions(+), 2 deletions(-)
    
    diff --git a/libs/libmyth/audiooutput.h b/libs/libmyth/audiooutput.h
    index 7b7901f..10b4cec 100644
    a b class MPUBLIC AudioOutput : public VolumeBase, public OutputListeners 
    3131    virtual void SetStretchFactor(float factor);
    3232    virtual float GetStretchFactor(void) const { return 1.0f; }
    3333
     34    // For software pre-amplification.
     35    virtual bool IsPreAmpEnabled() const { return false; }
     36    virtual void SetPreAmp(bool enabled) { return; }
     37    virtual void EnablePreAmp() { return; }
     38    virtual void DisablePreAmp() { return; }
     39    virtual void SetPreAmpGain(float gain) { return; }
     40    virtual void SetPreAmpFactor(float factor) { return; }
     41    virtual float GetPreAmpGain() const { return 0.0; }
     42    virtual float GetPreAmpFactor() const { return 1.0; }
     43    virtual void ResetClippingMonitor() { return; }
     44    virtual bool HasClippingOccurred() const { return false; }
     45    virtual float GetMaxOutput() const { return 1.0; }
     46    virtual float GetMaxClipFreePreAmpGain() const { return 0.0; }
     47    virtual float GetMaxClipFreePreAmpFactor() const { return 1.0; }
     48
    3449    // do AddSamples calls block?
    3550    virtual void SetBlocking(bool blocking) = 0;
    3651   
  • libs/libmyth/audiooutputbase.cpp

    diff --git a/libs/libmyth/audiooutputbase.cpp b/libs/libmyth/audiooutputbase.cpp
    index 1135016..d6a63f1 100644
    a b  
    11// Std C headers
    22#include <cmath>
     3#include <climits>
     4#include <cfloat>
    35
    46// POSIX headers
    57#include <pthread.h>
    AudioOutputBase::AudioOutputBase(const AudioSettings &settings) : 
    4648    need_resampler(false),
    4749
    4850    src_ctx(NULL),
     51   
     52    pre_amp_enabled(false),     pre_amp_factor(1.0),
     53    pre_amp_max_output(0.0),
    4954
    5055    pSoundStretch(NULL),
    5156    encoder(NULL),
    bool AudioOutputBase::AddSamples(char *buffers[], int samples, 
    750755    return true;
    751756}
    752757
     758#define __APPLY_PRE_AMP(TYPE,MIN,MAX) \
     759{ \
     760    TYPE *buf = (TYPE *)buffer; \
     761    for ( int i = 0; i < samples; ++i ) \
     762    { \
     763        float f = (float)buf[i] / (float)MAX; \
     764        f *= pre_amp_factor; \
     765        float a = abs(f); \
     766        if ( a > pre_amp_max_output ) pre_amp_max_output = a; \
     767        if ( f >= 1.0 ) buf[i] = MAX; \
     768        else if ( f <= -1.0 ) buf[i] = MIN; \
     769        else buf[i] = (TYPE)round(f*MAX); \
     770    } \
     771}
     772
     773void AudioOutputBase::ApplyPreAmp(void *buffer, int samples, int sample_bytes)
     774{
     775    if ( !pre_amp_enabled ) return;
     776    // NOTE: This only handles 1, 2 or 4 byte samples.
     777    if ( sample_bytes == 4 )
     778        __APPLY_PRE_AMP(int,INT_MIN,INT_MAX)
     779    else if ( sample_bytes == 2 )
     780        __APPLY_PRE_AMP(short,SHRT_MIN,SHRT_MAX)
     781    else if ( sample_bytes == 1 )
     782        __APPLY_PRE_AMP(char,CHAR_MIN,CHAR_MAX)
     783
     784    return;
     785}
     786#undef __APPLY_PRE_AMP
     787
    753788bool AudioOutputBase::AddSamples(char *buffer, int samples, long long timecode)
    754789{
    755790    // NOTE: This function is not threadsafe
    void AudioOutputBase::_AddSamples(void *buffer, bool interleaved, int samples, 
    860895    int audio_bytes = audio_bits / 8;
    861896    int org_waud = waud;
    862897
     898    if ( interleaved )
     899        // Apply to the single buffer if we're interleaved.
     900        ApplyPreAmp(buffer,samples*source_audio_channels,audio_bytes);
     901    else
     902    {
     903        // Otherwise, apply to each channel individually.
     904        void **bufs = (void**)buffer;
     905        for ( int i = 0; i < source_audio_channels; ++i )
     906            ApplyPreAmp(bufs[i],samples,audio_bytes);
     907    }
     908
    863909    int afree = audiofree(false);
    864910
    865911    int abps = (encoder) ?
    int AudioOutputBase::readOutputData(unsigned char*, int) 
    13501396    return 0;
    13511397}
    13521398
    1353 /* vim: set expandtab tabstop=4 shiftwidth=4: */
     1399bool AudioOutputBase::IsPreAmpEnabled() const
     1400{
     1401    return pre_amp_enabled;
     1402}
    13541403
     1404void AudioOutputBase::SetPreAmp(bool enabled)
     1405{
     1406        pre_amp_enabled = enabled;
     1407        return;
     1408}
     1409
     1410void AudioOutputBase::EnablePreAmp()
     1411{
     1412    pre_amp_enabled = true;
     1413    return;
     1414}
     1415
     1416void AudioOutputBase::DisablePreAmp()
     1417{
     1418    pre_amp_enabled = false;
     1419    return;
     1420}
     1421
     1422void AudioOutputBase::SetPreAmpGain(float gain)
     1423{
     1424    pre_amp_factor = pow(10.0,gain/20.0);
     1425    return;
     1426}
     1427
     1428void AudioOutputBase::SetPreAmpFactor(float factor)
     1429{
     1430    if ( factor >= 0 ) pre_amp_factor = factor;
     1431    return;
     1432}
     1433
     1434float AudioOutputBase::GetPreAmpGain() const
     1435{
     1436    if ( pre_amp_factor <= 0 ) return -1.0*FLT_MAX;
     1437    return 20.0*log(pre_amp_factor)/log(10.0);
     1438}
     1439
     1440float AudioOutputBase::GetPreAmpFactor() const
     1441{
     1442    return pre_amp_factor;
     1443}
     1444
     1445void AudioOutputBase::ResetClippingMonitor()
     1446{
     1447    pre_amp_max_output = 0.0;
     1448    return;
     1449}
     1450
     1451bool AudioOutputBase::HasClippingOccurred() const
     1452{
     1453    return pre_amp_max_output > 1.0;
     1454}
     1455
     1456float AudioOutputBase::GetMaxOutput() const
     1457{
     1458    return pre_amp_max_output;
     1459}
     1460
     1461float AudioOutputBase::GetMaxClipFreePreAmpGain() const
     1462{
     1463    float max_factor = GetMaxClipFreePreAmpFactor();
     1464    if ( max_factor <= 0 ) return -1.0*FLT_MAX;
     1465    return 20.0*log(max_factor)/log(10.0);
     1466}
     1467
     1468float AudioOutputBase::GetMaxClipFreePreAmpFactor() const
     1469{
     1470    if ( pre_amp_max_output == 0 ) return FLT_MAX;
     1471    return pre_amp_factor / pre_amp_max_output;
     1472}
     1473
     1474/* vim: set expandtab tabstop=4 shiftwidth=4: */
  • libs/libmyth/audiooutputbase.h

    diff --git a/libs/libmyth/audiooutputbase.h b/libs/libmyth/audiooutputbase.h
    index 4806d31..1662a56 100644
    a b class AudioOutputBase : public AudioOutput 
    6464
    6565    virtual void GetBufferStatus(uint &fill, uint &total) const;
    6666
    67     //  Only really used by the AudioOutputNULL object
     67     // For software pre-amplification.
     68     virtual bool IsPreAmpEnabled() const;
     69     virtual void SetPreAmp(bool enabled);
     70     virtual void EnablePreAmp();
     71     virtual void DisablePreAmp();
     72     virtual void SetPreAmpGain(float gain);
     73     virtual void SetPreAmpFactor(float factor);
     74     virtual float GetPreAmpGain() const;
     75     virtual float GetPreAmpFactor() const;
     76     virtual void ResetClippingMonitor();
     77     virtual bool HasClippingOccurred() const;
     78     virtual float GetMaxOutput() const;
     79     virtual float GetMaxClipFreePreAmpGain() const;
     80     virtual float GetMaxClipFreePreAmpFactor() const;
    6881
     82    //  Only really used by the AudioOutputNULL object
    6983    virtual void bufferOutputData(bool y){ buffer_output_data_for_use = y; }
    7084    virtual int readOutputData(unsigned char *read_buffer, int max_length);
    7185
    class AudioOutputBase : public AudioOutput 
    91105
    92106    int GetAudioData(unsigned char *buffer, int buf_size, bool fill_buffer);
    93107
     108    void ApplyPreAmp(void *buffer, int samples, int sample_bytes);
    94109    void _AddSamples(void *buffer, bool interleaved, int samples, long long timecode);
    95110
    96111    void OutputAudioLoop(void);
    class AudioOutputBase : public AudioOutput 
    144159    bool need_resampler;
    145160    SRC_STATE *src_ctx;
    146161
     162    // pre-amplification
     163    bool pre_amp_enabled;
     164    float pre_amp_factor;
     165    float pre_amp_max_output;
     166
    147167    // timestretch
    148168    soundtouch::SoundTouch    *pSoundStretch;
    149169    AudioOutputDigitalEncoder *encoder;