lib/dtas/rg_state.rb in dtas-0.12.1 vs lib/dtas/rg_state.rb in dtas-0.13.0

- old
+ new

@@ -1,7 +1,8 @@ -# Copyright (C) 2013-2015 all contributors <dtas-all@nongnu.org> -# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt) +# Copyright (C) 2013-2016 all contributors <dtas-all@nongnu.org> +# License: GPL-3.0+ (https://www.gnu.org/licenses/gpl-3.0.txt) +# frozen_string_literal: true # # provides support for generating appropriate effects for ReplayGain # MAYBE: account for non-standard reference loudness (89.0 dB is standard) require_relative '../dtas' require_relative 'serialize' @@ -17,10 +18,11 @@ "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 @@ -32,10 +34,17 @@ } SIVS = RG_DEFAULT.keys SIVS.each { |iv| attr_accessor iv } + undef_method :volume= + + def volume=(val) + val = 0 if val.to_i < 0 + @volume = val.round(4) + end + def initialize RG_DEFAULT.each do |k,v| instance_variable_set("@#{k}", v) end end @@ -48,48 +57,63 @@ def to_hash ivars_to_hash(SIVS) end + def vol_db + linear_to_db(@volume) + end + 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 + 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 + # returns a dB argument to the "gain" effect, nil if nothing found def rg_vol_gain(val) - val = val.to_f + @preamp + val = val.to_f + @preamp + vol_db return if val.abs < @gain_threshold - sprintf('gain %0.8g', val) + to_sox_gain(val) end # returns a DB argument to the "gain" effect def rg_vol_norm(val) - diff = @norm_level - val.to_f - return if (@norm_level - diff).abs < @norm_threshold - diff += @norm_level - sprintf('gain %0.8g', linear_to_db(diff)) + 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 # 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 def rg_fallback_effect(reason) - @fallback_gain or return - val = @fallback_gain + @preamp + val = (@fallback_gain || 0) + @preamp + vol_db return if val.abs < @gain_threshold warn(reason) if $DEBUG - "gain #{val}" + to_sox_gain(val) end # returns an array (for command-line argument) for the effect needed # to apply ReplayGain # this may return nil def effect(source) - return unless @mode - rg = source.replaygain or - return rg_fallback_effect("ReplayGain tags missing") + 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")