Added per disc album_gain support

This commit is contained in:
Samuel Nilsson 2019-02-06 09:27:24 +01:00
parent 7438cd50f6
commit 3d842db8d8

View file

@ -83,7 +83,7 @@ class Backend(object):
def compute_track_gain(self, items):
raise NotImplementedError()
def compute_album_gain(self, album):
def compute_album_gain(self, items):
# TODO: implement album gain in terms of track gain of the
# individual tracks which can be used for any backend.
raise NotImplementedError()
@ -125,15 +125,14 @@ class Bs1770gainBackend(Backend):
output = self.compute_gain(items, False)
return output
def compute_album_gain(self, album):
def compute_album_gain(self, items):
"""Computes the album gain of the given album, returns an
AlbumGain object.
"""
# TODO: What should be done when not all tracks in the album are
# supported?
supported_items = album.items()
output = self.compute_gain(supported_items, True)
output = self.compute_gain(items, True)
if not output:
raise ReplayGainError(u'no output from bs1770gain')
@ -316,15 +315,15 @@ class CommandBackend(Backend):
output = self.compute_gain(supported_items, False)
return output
def compute_album_gain(self, album):
def compute_album_gain(self, items):
"""Computes the album gain of the given album, returns an
AlbumGain object.
"""
# TODO: What should be done when not all tracks in the album are
# supported?
supported_items = list(filter(self.format_supported, album.items()))
if len(supported_items) != len(album.items()):
supported_items = list(filter(self.format_supported, items))
if len(supported_items) != len(items):
self._log.debug(u'tracks are of unsupported format')
return AlbumGain(None, [])
@ -521,8 +520,8 @@ class GStreamerBackend(Backend):
return ret
def compute_album_gain(self, album):
items = list(album.items())
def compute_album_gain(self, items):
items = list(items)
self.compute(items, True)
if len(self._file_tags) != len(items):
raise ReplayGainError(u"Some items in album did not receive tags")
@ -777,22 +776,20 @@ class AudioToolsBackend(Backend):
item.artist, item.title, rg_track_gain, rg_track_peak)
return Gain(gain=rg_track_gain, peak=rg_track_peak)
def compute_album_gain(self, album):
def compute_album_gain(self, items):
"""Compute ReplayGain values for the requested album and its items.
:rtype: :class:`AlbumGain`
"""
self._log.debug(u'Analysing album {0}', album)
# The first item is taken and opened to get the sample rate to
# initialize the replaygain object. The object is used for all the
# tracks in the album to get the album values.
item = list(album.items())[0]
item = list(items)[0]
audiofile = self.open_audio_file(item)
rg = self.init_replaygain(audiofile, item)
track_gains = []
for item in album.items():
for item in items:
audiofile = self.open_audio_file(item)
rg_track_gain, rg_track_peak = self._title_gain(rg, audiofile)
track_gains.append(
@ -836,9 +833,11 @@ class ReplayGainPlugin(BeetsPlugin):
'backend': u'command',
'targetlevel': 89,
'r128': ['Opus'],
'per_disc': False
})
self.overwrite = self.config['overwrite'].get(bool)
self.per_disc = self.config['per_disc'].get(bool)
backend_name = self.config['backend'].as_str()
if backend_name not in self.backends:
raise ui.UserError(
@ -919,6 +918,21 @@ class ReplayGainPlugin(BeetsPlugin):
self._log.debug(u'applied r128 album gain {0}', album.r128_album_gain)
def store_album_gain_item_level(self, items, album_gain):
for item in items:
item.rg_album_gain = album_gain.gain
item.rg_album_peak = album_gain.peak
item.store()
self._log.debug(u'applied album gain {0}, peak {1}',
item.rg_album_gain, item.rg_album_peak)
def store_album_r128_gain_item_level(self, items, album_gain):
for item in items:
item.r128_album_gain = album_gain.gain
item.store()
self._log.debug(u'applied r128 album gain {0}',
item.r128_album_gain)
def handle_album(self, album, write, force=False):
"""Compute album and track replay gain store it in all of the
album's items.
@ -946,29 +960,45 @@ class ReplayGainPlugin(BeetsPlugin):
backend_instance = self.r128_backend_instance
store_track_gain = self.store_track_r128_gain
store_album_gain = self.store_album_r128_gain
store_album_gain_item_level = self.store_album_r128_gain_item_level
else:
backend_instance = self.backend_instance
store_track_gain = self.store_track_gain
store_album_gain = self.store_album_gain
store_album_gain_item_level = self.store_album_gain_item_level
try:
album_gain = backend_instance.compute_album_gain(album)
if len(album_gain.track_gains) != len(album.items()):
raise ReplayGainError(
u"ReplayGain backend failed "
u"for some tracks in album {0}".format(album)
)
discs = dict()
if self.per_disc:
for item in album.items():
if discs.get(item.disc) is None:
discs[item.disc] = []
discs[item.disc].append(item)
else:
discs[1] = album.items()
store_album_gain(album, album_gain.album_gain)
for item, track_gain in zip(album.items(), album_gain.track_gains):
store_track_gain(item, track_gain)
if write:
item.try_write()
except ReplayGainError as e:
self._log.info(u"ReplayGain error: {0}", e)
except FatalReplayGainError as e:
raise ui.UserError(
u"Fatal replay gain error: {0}".format(e))
for discnumber in discs:
try:
items = discs[discnumber]
album_gain = backend_instance.compute_album_gain(items)
if len(album_gain.track_gains) != len(items):
raise ReplayGainError(
u"ReplayGain backend failed "
u"for some tracks in album {0}".format(album)
)
if len(items) == len(album.items()):
store_album_gain(album, album_gain.album_gain)
else:
store_album_gain_item_level(items, album_gain.album_gain)
for item, track_gain in zip(items, album_gain.track_gains):
store_track_gain(item, track_gain)
if write:
item.try_write()
except ReplayGainError as e:
self._log.info(u"ReplayGain error: {0}", e)
except FatalReplayGainError as e:
raise ui.UserError(
u"Fatal replay gain error: {0}".format(e))
def handle_track(self, item, write, force=False):
"""Compute track replay gain and store it in the item.