Class: DTAS::RGState

Inherits:
Object
  • Object
show all
Includes:
Serialize, Util
Defined in:
lib/dtas/rg_state.rb

Overview

:nodoc:

Constant Summary collapse

RG_MODE =
{
  # attribute name => method to use
  "album_gain" => :rg_vol_gain,
  "track_gain" => :rg_vol_gain,
  "album_peak" => :rg_vol_norm,
  "track_peak" => :rg_vol_norm,
}
RG_DEFAULT =
{
  "volume" => 1.0,
  # skip the effect if the adjustment is too small to be noticeable
  "gain_threshold" => 0.00000001, # in dB
  "norm_threshold" => 0.00000001,

  "preamp" => 0, # no extra adjustment
  # "mode" => "album_gain", # nil: off
  "mode" => nil, # nil: off
  "fallback_gain" => -6.0, # adjustment dB if necessary RG tag is missing
  "fallback_track" => true,
  "norm_level" => 1.0, # dBFS
}
SIVS =
RG_DEFAULT.keys

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Util

#db_to_linear, #linear_to_db

Methods included from Serialize

#ivars_to_hash

Constructor Details

#initializeRGState

Returns a new instance of RGState.



46
47
48
49
50
# File 'lib/dtas/rg_state.rb', line 46

def initialize
  RG_DEFAULT.each do |k,v|
    instance_variable_set("@#{k}", v)
  end
end

Class Method Details

.load(hash) ⇒ Object



52
53
54
55
56
# File 'lib/dtas/rg_state.rb', line 52

def self.load(hash)
  rv = new
  hash.each { |k,v| rv.__send__("#{k}=", v) } if hash
  rv
end

Instance Method Details

#effect(source) ⇒ Object

returns an array (for command-line argument) for the effect needed to apply ReplayGain this may return nil



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/dtas/rg_state.rb', line 110

def effect(source)
  unless @mode
    return @volume == 1.0 ? nil : to_sox_gain(vol_db)
  end
  rg = source.replaygain(@mode) or
    return rg_fallback_effect("ReplayGain tags missing for #@mode")
  val = rg.__send__(@mode)
  if ! val && @fallback_track && @mode =~ /\Aalbum_(\w+)/
    tag = "track_#$1"
    val = rg.__send__(tag) or
      return rg_fallback_effect("ReplayGain tag for #@mode missing")
    warn("tag for #@mode missing, using #{tag}")
  end
  # this may be nil if the adjustment is too small:
  __send__(RG_MODE[@mode], val)
end

#rg_fallback_effect(reason) ⇒ Object

The ReplayGain fallback adjustment value (in dB), in case a file is missing ReplayGain tags. This is useful to avoid damage to speakers, eardrums and amplifiers in case a file without then necessary ReplayGain tag slips into the queue



100
101
102
103
104
105
# File 'lib/dtas/rg_state.rb', line 100

def rg_fallback_effect(reason)
  val = (@fallback_gain || 0) + @preamp + vol_db
  return if val.abs < @gain_threshold
  warn(reason) if $DEBUG
  to_sox_gain(val)
end

#rg_vol_gain(val) ⇒ Object

returns a dB argument to the “gain” effect, nil if nothing found



81
82
83
84
85
# File 'lib/dtas/rg_state.rb', line 81

def rg_vol_gain(val)
  val = val.to_f + @preamp + vol_db
  return if val.abs < @gain_threshold
  to_sox_gain(val)
end

#rg_vol_norm(val) ⇒ Object

returns a DB argument to the “gain” effect



88
89
90
91
92
93
94
# File 'lib/dtas/rg_state.rb', line 88

def rg_vol_norm(val)
  n = @norm_level == 1.0 ? @volume : @norm_level
  diff = n - val.to_f
  return if (n - diff).abs < @norm_threshold
  diff += n
  to_sox_gain(linear_to_db(diff))
end

#to_hashObject



58
59
60
# File 'lib/dtas/rg_state.rb', line 58

def to_hash
  ivars_to_hash(SIVS)
end

#to_hshObject



66
67
68
69
# File 'lib/dtas/rg_state.rb', line 66

def to_hsh
  # no point in dumping default values, it's just a waste of space
  to_hash.delete_if { |k,v| RG_DEFAULT[k] == v }
end

#to_sox_gain(val) ⇒ Object



71
72
73
74
75
76
77
78
# File 'lib/dtas/rg_state.rb', line 71

def to_sox_gain(val)
  case val.infinite?
  when -1 then return 'gain -192'
  when 1 then return 'gain 192'
  else
    sprintf('gain %0.8g', val).freeze
  end
end

#vol_dbObject



62
63
64
# File 'lib/dtas/rg_state.rb', line 62

def vol_db
  linear_to_db(@volume)
end

#volume=(val) ⇒ Object



41
42
43
44
# File 'lib/dtas/rg_state.rb', line 41

def volume=(val)
  val = 0 if val.to_i < 0
  @volume = val.round(4)
end