Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for retaining existing album gain via CLI argument #6

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ tags are already present in the files. If you have files which had loudness
levels calculated using the old ReplayGain algorithm, you can use this option
to recalculate using the EBU R128 algorithm.

`-p`/`--preserve-album-gain` causes regainer to preserve existing album gain.
This is useful if you for example have multi-disc albums that have discs mastered
at different loudness levels. NOTE: Using `-f` overrides this argument.

`-j N` specifies the number of parallel jobs to run. By default it will
use all CPUs available on the system. You can use this to reduce the amount
of CPU that regainer will use.
Expand Down
40 changes: 29 additions & 11 deletions regainer.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ def format_opus_gain(self, value):
if value < -32768 or value > 32767:
raise ValueError('Opus gain value out of range')
return "{:d}".format(value)


def read_gain_id3(self):
need_update = False
Expand Down Expand Up @@ -730,13 +730,18 @@ async def scan_album_gain(self):
gain_scanner = GainScanner()
self.gain = await gain_scanner.scan_album(included)

async def scan_gain(self):
album_task = asyncio.ensure_future(self.scan_album_gain())
track_tasks = [track.scan_gain() for track in self.tracks]
async def scan_gain(self, skip_album_scan=False):
tasks = [track.scan_gain() for track in self.tracks]

if not skip_album_scan:
album_task = asyncio.ensure_future(self.scan_album_gain())
tasks.append(album_task)

await asyncio.gather(album_task, *track_tasks)
await asyncio.gather(*tasks)

if not skip_album_scan:
self.gain.album_peak = max([t.gain.peak for t in self.tracks])

self.gain.album_peak = max([t.gain.peak for t in self.tracks])
for track in self.tracks:
track.gain.album_loudness = self.gain.album_loudness
track.gain.album_peak = self.gain.album_peak
Expand All @@ -745,30 +750,35 @@ async def write_tags(self):
track_tasks = [track.write_tags() for track in self.tracks]
await asyncio.gather(*track_tasks)

async def scan(self, force=False, skip_save=False):
async def scan(self, force=False, skip_save=False, preserve_album_gain=False):
await self.read_tags()

need_scan = False
skip_album_scan = False
for track in self.tracks:
if track.gain.loudness is None or track.gain.peak is None:
need_scan = True
if self.gain.album_loudness is None:
self.gain.album_loudness = track.gain.album_loudness
if self.gain.album_loudness != track.gain.album_loudness:
need_scan = True
need_scan = need_scan or not preserve_album_gain
skip_album_scan = preserve_album_gain
if self.gain.album_peak is None:
self.gain.album_peak = track.gain.album_peak
if self.gain.album_peak != track.gain.album_peak:
need_scan = True
need_scan = need_scan or not preserve_album_gain
skip_album_scan = preserve_album_gain
if self.gain.album_loudness is None or self.gain.album_peak is None:
need_scan = True
skip_album_scan = False
if force:
need_scan = True
skip_album_scan = False

need_save = any([track.tagger.need_album_update for track in self.tracks])

if need_scan:
await self.scan_gain()
await self.scan_gain(skip_album_scan)
need_save = True

if need_save:
Expand All @@ -781,6 +791,8 @@ async def scan(self, force=False, skip_save=False):
print(track.gain)
if need_scan:
print("Rescanned loudness")
if skip_album_scan:
print("Preserving missmatching album gains")
if need_save:
if not skip_save:
print("Updated tags")
Expand Down Expand Up @@ -808,6 +820,12 @@ def main(argv=None):
Recalculate the ReplayGain values even if valid tags are already
present in the files.
''')
parser.add_argument('-p', '--preserve-album-gain', default=False, action='store_true',
help='''
Preserve existing album ReplayGain values even if they missmatch within files.
Using this option will preserve different album gain values for given files.
Using -f/--force overrides this arguments.
''')
parser.add_argument('-j', '--jobs', type=int,
default=multiprocessing.cpu_count(),
help='''
Expand Down Expand Up @@ -855,7 +873,7 @@ def main(argv=None):

tasks = []
albums = [Album(album, job_sem) for album in args.album]
tasks += [album.scan(force=args.force, skip_save=args.dry_run)
tasks += [album.scan(force=args.force, skip_save=args.dry_run, preserve_album_gain=args.preserve_album_gain)
for album in albums]
tracks = [Track(track, job_sem) for track in args.track]
tasks += [track.scan(force=args.force, skip_save=args.dry_run)
Expand Down