Changeset d20dd24295a3f43ad2cdec0fcd8a83793cb45bde

Show
Ignore:
Timestamp:
06/17/07 15:54:20 (1 year ago)
Author:
Laurent Aimar <fenrir@videolan.org>
git-committer:
Laurent Aimar <fenrir@videolan.org> 1182088460 +0000
git-parent:

[ef2723ee44a031e8c0f6c5437fff7d40ffad971a]

git-author:
Laurent Aimar <fenrir@videolan.org> 1182088460 +0000
Message:

Added replay gain support (audio-replay-gain-mode track or album to activate
it, disabled by default)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • include/vlc_aout.h

    r70a8bb9 rd20dd24  
    271271    /* Mixer information */ 
    272272    byte_t *                p_first_byte_to_mix; 
     273    audio_replay_gain_t     replay_gain; 
     274    float                   f_multiplier; 
    273275 
    274276    /* If b_restart == 1, the input pipeline will be re-created. */ 
  • include/vlc_es.h

    r9ab64bc rd20dd24  
    4646 
    4747/** 
     48 * audio replay gain description 
     49 */ 
     50#define AUDIO_REPLAY_GAIN_MAX (2) 
     51#define AUDIO_REPLAY_GAIN_TRACK (0) 
     52#define AUDIO_REPLAY_GAIN_ALBUM (1) 
     53typedef struct 
     54{ 
     55    /* true if we have the peak value */ 
     56    vlc_bool_t pb_peak[AUDIO_REPLAY_GAIN_MAX]; 
     57    /* peak value where 1.0 means full sample value */ 
     58    float      pf_peak[AUDIO_REPLAY_GAIN_MAX]; 
     59 
     60    /* true if we have the gain value */ 
     61    vlc_bool_t pb_gain[AUDIO_REPLAY_GAIN_MAX]; 
     62    /* gain value in dB */ 
     63    float      pf_gain[AUDIO_REPLAY_GAIN_MAX]; 
     64} audio_replay_gain_t; 
     65 
     66/** 
    4867 * audio format description 
    4968 */ 
     
    174193    extra_languages_t *p_extra_languages; 
    175194 
    176     audio_format_t audio; 
     195    audio_format_t  audio; 
     196    audio_replay_gain_t audio_replay_gain; 
    177197    video_format_t video; 
    178198    subs_format_t  subs; 
     
    209229 
    210230    memset( &fmt->audio, 0, sizeof(audio_format_t) ); 
     231    memset( &fmt->audio_replay_gain, 0, sizeof(audio_replay_gain_t) ); 
    211232    memset( &fmt->video, 0, sizeof(video_format_t) ); 
    212233    memset( &fmt->subs, 0, sizeof(subs_format_t) ); 
     
    268289{ 
    269290    if( fmt->psz_language ) free( fmt->psz_language ); 
    270     fmt->psz_language = NULL; 
    271291 
    272292    if( fmt->psz_description ) free( fmt->psz_description ); 
    273     fmt->psz_description = NULL; 
    274293 
    275294    if( fmt->i_extra > 0 ) free( fmt->p_extra ); 
    276     fmt->i_extra = 0; 
    277     fmt->p_extra = NULL; 
    278295 
    279296    if( fmt->video.p_palette ) 
    280297        free( fmt->video.p_palette ); 
    281     fmt->video.p_palette = NULL; 
    282298 
    283299    if( fmt->subs.psz_encoding ) free( fmt->subs.psz_encoding ); 
    284     fmt->subs.psz_encoding = NULL; 
    285  
    286     if( fmt->i_extra_languages && fmt->p_extra_languages ) { 
    287         int i = 0; 
    288         while( i < fmt->i_extra_languages ) { 
     300 
     301    if( fmt->i_extra_languages > 0 && fmt->p_extra_languages ) 
     302    { 
     303        int i; 
     304        for( i = 0; i < fmt->i_extra_languages; i++ ) 
     305        { 
    289306            if( fmt->p_extra_languages[i].psz_language ) 
    290307                free( fmt->p_extra_languages[i].psz_language ); 
    291308            if( fmt->p_extra_languages[i].psz_description ) 
    292309                free( fmt->p_extra_languages[i].psz_description ); 
    293             i++; 
    294310        } 
    295311        free(fmt->p_extra_languages); 
    296312    } 
    297     fmt->i_extra_languages = 0; 
    298     fmt->p_extra_languages = NULL; 
     313 
     314    /* es_format_Clean can be called multiple times */ 
     315    memset( fmt, 0, sizeof(*fmt) ); 
    299316} 
    300317#endif 
  • include/vlc_input.h

    ra8a47dd rd20dd24  
    197197 
    198198/***************************************************************************** 
     199 * Meta data helpers 
     200 *****************************************************************************/ 
     201static inline void vlc_audio_replay_gain_MergeFromMeta( audio_replay_gain_t *p_dst, 
     202                                                        const vlc_meta_t *p_meta ) 
     203{ 
     204    int i; 
     205    if( !p_meta ) 
     206        return; 
     207 
     208    for( i = 0; i < p_meta->i_extra; i++ ) 
     209    { 
     210        const char *psz_name = p_meta->ppsz_extra_name[i]; 
     211        const char *psz_value = p_meta->ppsz_extra_value[i]; 
     212 
     213        if( !strcasecmp( psz_name, "REPLAYGAIN_TRACK_GAIN" ) || 
     214            !strcasecmp( psz_name, "RG_RADIO" ) ) 
     215        { 
     216            p_dst->pb_gain[AUDIO_REPLAY_GAIN_TRACK] = VLC_TRUE; 
     217            p_dst->pf_gain[AUDIO_REPLAY_GAIN_TRACK] = atof( psz_value ); 
     218        } 
     219        else if( !strcasecmp( psz_name, "REPLAYGAIN_TRACK_PEAK" ) || 
     220                 !strcasecmp( psz_name, "RG_PEAK" ) ) 
     221        { 
     222            p_dst->pb_peak[AUDIO_REPLAY_GAIN_TRACK] = VLC_TRUE; 
     223            p_dst->pf_peak[AUDIO_REPLAY_GAIN_TRACK] = atof( psz_value ); 
     224        } 
     225        else if( !strcasecmp( psz_name, "REPLAYGAIN_ALBUM_GAIN" ) || 
     226                 !strcasecmp( psz_name, "RG_AUDIOPHILE" ) ) 
     227        { 
     228            p_dst->pb_gain[AUDIO_REPLAY_GAIN_ALBUM] = VLC_TRUE; 
     229            p_dst->pf_gain[AUDIO_REPLAY_GAIN_ALBUM] = atof( psz_value ); 
     230        } 
     231        else if( !strcasecmp( psz_name, "REPLAYGAIN_ALBUM_PEAK" ) ) 
     232        { 
     233            p_dst->pb_peak[AUDIO_REPLAY_GAIN_ALBUM] = VLC_TRUE; 
     234            p_dst->pf_peak[AUDIO_REPLAY_GAIN_ALBUM] = atof( psz_value ); 
     235        } 
     236    } 
     237} 
     238 
     239/***************************************************************************** 
    199240 * Seek point: (generalisation of chapters) 
    200241 *****************************************************************************/ 
  • include/vlc_meta.h

    r8919d21 rd20dd24  
    210210        for( j = 0; j < dst->i_extra; j++ ) 
    211211        { 
    212             if( !strcmp( dst->ppsz_extra_name[i], src->ppsz_extra_name[i] ) ) 
     212            if( !strcmp( dst->ppsz_extra_name[j], src->ppsz_extra_name[i] ) ) 
    213213            { 
    214                 free( dst->ppsz_extra_value[i] ); 
    215                 dst->ppsz_extra_value[i] = strdup( src->ppsz_extra_value[i] ); 
     214                free( dst->ppsz_extra_value[j] ); 
     215                dst->ppsz_extra_value[j] = strdup( src->ppsz_extra_value[i] ); 
    216216                break; 
    217217            } 
    218             if( j >= dst->i_extra ) 
    219                 vlc_meta_AddExtra( dst, src->ppsz_extra_name[i], src->ppsz_extra_value[i] ); 
    220218        } 
     219        if( j >= dst->i_extra ) 
     220            vlc_meta_AddExtra( dst, src->ppsz_extra_name[i], src->ppsz_extra_value[i] ); 
    221221    } 
    222222} 
  • modules/audio_mixer/float32.c

    rd3fe7f2 rd20dd24  
    6161    } 
    6262 
     63    /* Use the trivial mixer when we can */ 
    6364    if ( p_aout->i_nb_inputs == 1 && p_aout->mixer.f_multiplier == 1.0 ) 
    6465    { 
    65         /* Tell the trivial mixer to go for it. */ 
    66         return -1; 
     66        int i; 
     67        for( i = 0; i < p_aout->i_nb_inputs; i++ ) 
     68        { 
     69            if( p_aout->pp_inputs[i]->f_multiplier != 1.0 ) 
     70                break; 
     71        } 
     72        if( i >= p_aout->i_nb_inputs ) 
     73            return -1; 
    6774    } 
    6875 
    6976    p_aout->mixer.pf_do_work = DoWork; 
    70  
    7177    return 0; 
    7278} 
     
    110116static void DoWork( aout_instance_t * p_aout, aout_buffer_t * p_buffer ) 
    111117{ 
    112     int i_nb_inputs = p_aout->i_nb_inputs; 
    113     float f_multiplier = p_aout->mixer.f_multiplier; 
     118    const int i_nb_inputs = p_aout->i_nb_inputs; 
     119    const float f_multiplier_global = p_aout->mixer.f_multiplier; 
     120    const int i_nb_channels = aout_FormatNbChannels( &p_aout->mixer.mixer ); 
    114121    int i_input; 
    115     int i_nb_channels = aout_FormatNbChannels( &p_aout->mixer.mixer ); 
    116122 
    117123    for ( i_input = 0; i_input < i_nb_inputs; i_input++ ) 
     
    119125        int i_nb_words = p_buffer->i_nb_samples * i_nb_channels; 
    120126        aout_input_t * p_input = p_aout->pp_inputs[i_input]; 
     127        float f_multiplier = f_multiplier_global * p_input->f_multiplier; 
     128 
    121129        float * p_out = (float *)p_buffer->p_buffer; 
    122130        float * p_in = (float *)p_input->p_first_byte_to_mix; 
  • src/audio_output/aout_internal.h

    r70a8bb9 rd20dd24  
    125125 
    126126/* From dec.c */ 
    127 #define aout_DecNew(a, b, c) __aout_DecNew(VLC_OBJECT(a), b, c
    128 aout_input_t * __aout_DecNew( vlc_object_t *, aout_instance_t **, audio_sample_format_t * ); 
     127#define aout_DecNew(a, b, c, d) __aout_DecNew(VLC_OBJECT(a), b, c, d
     128aout_input_t * __aout_DecNew( vlc_object_t *, aout_instance_t **, audio_sample_format_t *, audio_replay_gain_t * ); 
    129129int aout_DecDelete ( aout_instance_t *, aout_input_t * ); 
    130130aout_buffer_t * aout_DecNewBuffer( aout_instance_t *, aout_input_t *, size_t ); 
  • src/audio_output/dec.c

    r70a8bb9 rd20dd24  
    4646 *****************************************************************************/ 
    4747static aout_input_t * DecNew( vlc_object_t * p_this, aout_instance_t * p_aout, 
    48                               audio_sample_format_t * p_format ) 
     48                              audio_sample_format_t *p_format, 
     49                              audio_replay_gain_t *p_replay_gain ) 
    4950{ 
    5051    aout_input_t * p_input; 
     
    8384        goto error; 
    8485    } 
     86    memset( p_input, 0, sizeof(aout_input_t) ); 
    8587 
    8688    vlc_mutex_init( p_aout, &p_input->lock ); 
     
    9193    memcpy( &p_input->input, p_format, 
    9294            sizeof(audio_sample_format_t) ); 
     95    if( p_replay_gain ) 
     96        p_input->replay_gain = *p_replay_gain; 
    9397 
    9498    p_aout->pp_inputs[p_aout->i_nb_inputs] = p_input; 
     
    167171aout_input_t * __aout_DecNew( vlc_object_t * p_this, 
    168172                              aout_instance_t ** pp_aout, 
    169                               audio_sample_format_t * p_format ) 
     173                              audio_sample_format_t * p_format, 
     174                              audio_replay_gain_t *p_replay_gain ) 
    170175{ 
    171176    if ( *pp_aout == NULL ) 
     
    192197    } 
    193198 
    194     return DecNew( p_this, *pp_aout, p_format ); 
     199    return DecNew( p_this, *pp_aout, p_format, p_replay_gain ); 
    195200} 
    196201 
  • src/audio_output/input.c

    r3b7381f rd20dd24  
    3131#include <stdlib.h>                            /* calloc(), malloc(), free() */ 
    3232#include <string.h> 
     33#include <math.h> 
    3334 
    3435#include <vlc_input.h>                 /* for input_thread_t and i_pts_delay */ 
     
    5253static int EqualizerCallback( vlc_object_t *, char const *, 
    5354                              vlc_value_t, vlc_value_t, void * ); 
    54  
     55static int ReplayGainCallback( vlc_object_t *, char const *, 
     56                               vlc_value_t, vlc_value_t, void * ); 
     57static void ReplayGainSelect( aout_instance_t *, aout_input_t * ); 
    5558/***************************************************************************** 
    5659 * aout_InputNew : allocate a new input and rework the filter pipeline 
     
    161164        text.psz_string = _("Audio visualizations"); 
    162165        var_Change( p_aout, "audio-visual", VLC_VAR_SETTEXT, &text, NULL ); 
     166    } 
     167 
     168    if( var_Type( p_aout, "audio-replay-gain-mode" ) == 0 ) 
     169    { 
     170        module_config_t *p_config; 
     171        int i; 
     172 
     173        p_config = config_FindConfig( VLC_OBJECT(p_aout), "audio-replay-gain-mode" ); 
     174        if( p_config && p_config->i_list ) 
     175        { 
     176            var_Create( p_aout, "audio-replay-gain-mode", 
     177                        VLC_VAR_STRING | VLC_VAR_DOINHERIT ); 
     178 
     179            text.psz_string = _("Replay gain"); 
     180            var_Change( p_aout, "audio-replay-gain-mode", VLC_VAR_SETTEXT, &text, NULL ); 
     181 
     182            for( i = 0; i < p_config->i_list; i++ ) 
     183            { 
     184                val.psz_string = (char *)p_config->ppsz_list[i]; 
     185                text.psz_string = (char *)p_config->ppsz_list_text[i]; 
     186                var_Change( p_aout, "audio-replay-gain-mode", VLC_VAR_ADDCHOICE, 
     187                            &val, &text ); 
     188            } 
     189 
     190            var_AddCallback( p_aout, "audio-replay-gain-mode", ReplayGainCallback, NULL ); 
     191        } 
     192    } 
     193    if( var_Type( p_aout, "audio-replay-gain-preamp" ) == 0 ) 
     194    { 
     195        var_Create( p_aout, "audio-replay-gain-preamp", 
     196                    VLC_VAR_FLOAT | VLC_VAR_DOINHERIT ); 
     197    } 
     198    if( var_Type( p_aout, "audio-replay-gain-default" ) == 0 ) 
     199    { 
     200        var_Create( p_aout, "audio-replay-gain-default", 
     201                    VLC_VAR_FLOAT | VLC_VAR_DOINHERIT ); 
     202    } 
     203    if( var_Type( p_aout, "audio-replay-gain-peak-protection" ) == 0 ) 
     204    { 
     205        var_Create( p_aout, "audio-replay-gain-peak-protection", 
     206                    VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); 
    163207    } 
    164208 
     
    367411                                     * p_input->input.i_rate 
    368412                                     / p_input->input.i_frame_length) ); 
     413 
     414    ReplayGainSelect( p_aout, p_input ); 
     415 
    369416    /* Success */ 
    370417    p_input->b_error = VLC_FALSE; 
     
    659706    var_Destroy( p_aout, "audio-visual" ); 
    660707 
     708    var_Destroy( p_aout, "audio-replay-gain-mode" ); 
     709    var_Destroy( p_aout, "audio-replay-gain-default" ); 
     710    var_Destroy( p_aout, "audio-replay-gain-preamp" ); 
     711    var_Destroy( p_aout, "audio-replay-gain-peak-protection" ); 
     712 
    661713    /* error flag */ 
    662714    p_input->b_error = 1; 
     
    818870    return VLC_SUCCESS; 
    819871} 
     872 
     873static int ReplayGainCallback( vlc_object_t *p_this, char const *psz_cmd, 
     874                               vlc_value_t oldval, vlc_value_t newval, void *p_data ) 
     875{ 
     876    aout_instance_t *p_aout = (aout_instance_t *)p_this; 
     877    int i; 
     878 
     879    vlc_mutex_lock( &p_aout->mixer_lock ); 
     880    for( i = 0; i < p_aout->i_nb_inputs; i++ ) 
     881        ReplayGainSelect( p_aout, p_aout->pp_inputs[i] ); 
     882    vlc_mutex_unlock( &p_aout->mixer_lock ); 
     883 
     884    return VLC_SUCCESS; 
     885} 
     886 
     887static void ReplayGainSelect( aout_instance_t *p_aout, aout_input_t *p_input ) 
     888{ 
     889    char *psz_replay_gain = var_GetString( p_aout, "audio-replay-gain-mode" ); 
     890    int i_mode; 
     891    int i_use; 
     892    float f_gain; 
     893 
     894    p_input->f_multiplier = 1.0; 
     895 
     896    if( !psz_replay_gain ) 
     897        return; 
     898 
     899    /* Find select mode */ 
     900    if( !strcmp( psz_replay_gain, "track" ) ) 
     901        i_mode = AUDIO_REPLAY_GAIN_TRACK; 
     902    else if( !strcmp( psz_replay_gain, "album" ) ) 
     903        i_mode = AUDIO_REPLAY_GAIN_ALBUM; 
     904    else 
     905        i_mode = AUDIO_REPLAY_GAIN_MAX; 
     906 
     907    /* If the select mode is not available, prefer the other one */ 
     908    i_use = i_mode; 
     909    if( i_use != AUDIO_REPLAY_GAIN_MAX && !p_input->replay_gain.pb_gain[i_use] ) 
     910    { 
     911        for( i_use = 0; i_use < AUDIO_REPLAY_GAIN_MAX; i_use++ ) 
     912        { 
     913            if( p_input->replay_gain.pb_gain[i_use] ) 
     914                break; 
     915        } 
     916    } 
     917 
     918    /* */ 
     919    if( i_use != AUDIO_REPLAY_GAIN_MAX ) 
     920        f_gain = p_input->replay_gain.pf_gain[i_use] + var_GetFloat( p_aout, "audio-replay-gain-preamp" ); 
     921    else if( i_mode != AUDIO_REPLAY_GAIN_MAX ) 
     922        f_gain = var_GetFloat( p_aout, "audio-replay-gain-default" ); 
     923    else 
     924        f_gain = 0.0; 
     925    p_input->f_multiplier = pow( 10.0, f_gain / 20.0 ); 
     926 
     927    /* */ 
     928    if( p_input->replay_gain.pb_peak[i_use] && 
     929        var_GetBool( p_aout, "audio-replay-gain-peak-protection" ) && 
     930        p_input->replay_gain.pf_peak[i_use] * p_input->f_multiplier > 1.0 ) 
     931    { 
     932        p_input->f_multiplier = 1.0f / p_input->replay_gain.pf_peak[i_use]; 
     933    } 
     934 
     935    free( psz_replay_gain ); 
     936} 
     937 
  • src/input/decoder.c

    r954866c rd20dd24  
    416416    } 
    417417 
     418    /* Copy ourself the input replay gain */ 
     419    if( fmt->i_cat == AUDIO_ES ) 
     420    { 
     421        int i; 
     422        for( i = 0; i < AUDIO_REPLAY_GAIN_MAX; i++ ) 
     423        { 
     424            if( !p_dec->fmt_out.audio_replay_gain.pb_peak[i] ) 
     425            { 
     426                p_dec->fmt_out.audio_replay_gain.pb_peak[i] = fmt->audio_replay_gain.pb_peak[i]; 
     427                p_dec->fmt_out.audio_replay_gain.pf_peak[i] = fmt->audio_replay_gain.pf_peak[i]; 
     428            } 
     429            if( !p_dec->fmt_out.audio_replay_gain.pb_gain[i] ) 
     430            { 
     431                p_dec->fmt_out.audio_replay_gain.pb_gain[i] = fmt->audio_replay_gain.pb_gain[i]; 
     432                p_dec->fmt_out.audio_replay_gain.pf_gain[i] = fmt->audio_replay_gain.pf_gain[i]; 
     433            } 
     434        } 
     435    } 
    418436    return p_dec; 
    419437} 
     
    887905 
    888906        p_sys->p_aout_input = 
    889             aout_DecNew( p_dec, &p_sys->p_aout, &format ); 
     907            aout_DecNew( p_dec, &p_sys->p_aout, &format, &p_dec->fmt_out.audio_replay_gain ); 
    890908        if( p_sys->p_aout_input == NULL ) 
    891909        { 
  • src/libvlc-module.c

    rb271b9f rd20dd24  
    220220#define AUDIO_VISUAL_LONGTEXT N_( \ 
    221221    "This adds visualization modules (spectrum analyzer, etc.).") 
     222 
     223 
     224#define AUDIO_REPLAY_GAIN_MODE_TEXT N_( \ 
     225    "Replay gain mode" ) 
     226#define AUDIO_REPLAY_GAIN_MODE_LONGTEXT N_( \ 
     227    "Select the replay gain mode" ) 
     228#define AUDIO_REPLAY_GAIN_PREAMP_TEXT N_( \ 
     229    "Replay preamp" ) 
     230#define AUDIO_REPLAY_GAIN_PREAMP_LONGTEXT N_( \ 
     231    "This allows you to change the default target level (89 dB) " \ 
     232    "for stream with replay gain information" ) 
     233#define AUDIO_REPLAY_GAIN_DEFAULT_TEXT N_( \ 
     234    "Default replay gain" ) 
     235#define AUDIO_REPLAY_GAIN_DEFAULT_LONGTEXT N_( \ 
     236    "This is the gain used for stream without replay gain information" ) 
     237#define AUDIO_REPLAY_GAIN_PEAK_PROTECTION_TEXT N_( \ 
     238    "Peak protection" ) 
     239#define AUDIO_REPLAY_GAIN_PEAK_PROTECTION_LONGTEXT N_( \ 
     240    "Protect against sound clipping" ) 
     241 
     242static const char *ppsz_replay_gain_mode[] = { "none", "track", "album" }; 
     243static const char *ppsz_replay_gain_mode_text[] = { N_("None"), N_("Track"), N_("Album") }; 
    222244 
    223245/***************************************************************************** 
     
    12931315    add_integer( "audio-desync", 0, NULL, DESYNC_TEXT, 
    12941316                 DESYNC_LONGTEXT, VLC_TRUE ); 
     1317 
     1318    /* FIXME TODO create a subcat replay gain ? */ 
     1319    add_string( "audio-replay-gain-mode", ppsz_replay_gain_mode[0], NULL, AUDIO_REPLAY_GAIN_MODE_TEXT, 
     1320                AUDIO_REPLAY_GAIN_MODE_LONGTEXT, VLC_FALSE ); 
     1321        change_string_list( ppsz_replay_gain_mode, ppsz_replay_gain_mode_text, 0 ); 
     1322    add_float( "audio-replay-gain-preamp", 0.0, NULL, 
     1323               AUDIO_REPLAY_GAIN_PREAMP_TEXT, AUDIO_REPLAY_GAIN_PREAMP_LONGTEXT, VLC_FALSE ); 
     1324    add_float( "audio-replay-gain-default", -7.0, NULL, 
     1325               AUDIO_REPLAY_GAIN_DEFAULT_TEXT, AUDIO_REPLAY_GAIN_DEFAULT_LONGTEXT, VLC_FALSE ); 
     1326    add_bool( "audio-replay-gain-peak-protection", VLC_TRUE, NULL, 
     1327              AUDIO_REPLAY_GAIN_PEAK_PROTECTION_TEXT, AUDIO_REPLAY_GAIN_PEAK_PROTECTION_LONGTEXT, VLC_TRUE ); 
     1328 
    12951329    set_subcategory( SUBCAT_AUDIO_AOUT ); 
    12961330    add_module( "aout", "audio output", NULL, NULL, AOUT_TEXT, AOUT_LONGTEXT,