bleskodev / rubyripper

Fork of the original rubyripper from code.google.com/p/rubyripper + some bugs fixes
125 stars 21 forks source link

Combine rips from multiple hw? #642

Open davidedelvento opened 9 months ago

davidedelvento commented 9 months ago

I have a large number (about 100) of Audio CDs which I bought more than 30 years ago. They probably weren't the highest quality made even at that time, since they were part of a collection which was sold on newsstands at a discounted price compared to what one would pay at music stores on those days. I always kept them in their case, so they are not scratched, however they are showing the sign of their age and having lots of clicks, skips and long silent section when played with my Audio CD reader (a Sony SACD player, FWIW).

It's a really nice collection, and I would love to keep it alive. I am trying to recover them with rubyripper and I am seeing lots of irrecoverable sectors. As such, I am wondering if it would make sense to attempt reading the disks from different computers and/or CD readers. I can imagine that some hardware may be able to read some sectors better than others and I am trying to navigate this possibility. I see two scenarios:

  1. One CD reader is "the best" and reads everything that any other reads, plus something more
  2. No one CD reader is "the best", for example one can read sector A but not sector B, and another can read sector B but not sector A (even after retries).

Questions:

davidedelvento commented 8 months ago

I was hoping for someone to chime in on this, but since nobody did here are my findings and sort-of-answers to my own questions should anybody be wondering the same.

CD reader

Awesomeness

Typically rubyripper is able to save CDs which are close to unreadable on regular audio CD players! For example CDs that have a high level of noise, or long section which the audio CD reader plays as silent because it can't decode them. When read only once, rubyripper reports hundreds of errors (I'll say more about counting later), i.e. more than one error per second. When using the "best CD reader" as discussed above, and setting a decently high number of re-tries (I'm using 60 at the moment), these disks are almost fully recovered, with only a handful of errors per piece!! The downside is that it takes about 24 hours a disk, but it's a one-off thing I can live with. So big thank you @bleskodev for resurrecting rubyripper!

The root of my question is still open.

At this level of error, it might be an academic question, but still interesting, in my opinion. Consider these excerpts from two ripping of the same disk. These are actually from two different CD readers, both with 60 retries, taking a day each, so not easy to say "just increase the number of retries 10x or at least 2x and see them reduced or disappearing.

Track  1
Irrecoverable sectors at the following times:
4414:57:69
5047:23:39
6784:44:12
11308:24:72

Track  1
Irrecoverable sectors at the following times:
1766:36:60
3584:26:66
3836:53:57
5273:11:03
8450:28:36
10407:20:24
12622:24:00

If my understanding of these numbers is correct, these irrecoverable sectors are at different sectors (and times) between the two different rips. I am still wondering if there is a way to "merge" the two rips (either in "raw" for with some data which is not currently saved, or even from the finished wav file) into an errorless one. I mean, in this particular case it does not matter but the question still stand.

Counting errors

In case it can be useful to others, I wrote this tiny script counting errors in the logs, very useful when you have hundreds and want to know if CD reader A or B is better. Nothing that you can't write yourself in 120 seconds, but for people who don't code or don't have two minutes to spare....

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("file")
parser.add_argument("--verbose", "-v", action='store_true', default=False)
args = parser.parse_args()

irrecoverable_section = False
count = 0
grand_tot = 0
for l in open(args.file):
    line = l.strip()
    if irrecoverable_section:
        count+=1
        if args.verbose:
            print(line)
        if l.startswith("\n"):
            print("Total", count)
            if not args.verbose:
                print()
            grand_tot+=count
            count = 0
            irrecoverable_section = False
    elif line.startswith("Track"):
        print(line)
    elif line.startswith("Irrecoverable"):
        print(line)
        irrecoverable_section = True
print("Grand total irrecoverable errors:", grand_tot)

You need to have python installed (on some systems invoked as python3) and have a command line prompt such as xterm or similar to run.