Jump to content
IGNORED

Recovering bad cassette recordings


Recommended Posts

I've done some more tweaks to my tape tool (mltt-tape) and I can recover almost all of my bad recordings now.  Someone (Greg?) sent me a bunch of bad WAV files a couple of weeks ago and these are mostly all readable now.  Some of the errors I can't even figure out myself so have no way to write an algorithm for them.  e.g. There is a ONE bit somewhere in a sequence of ZEROs below but I can't be sure which bit the middle peak belongs to: 

AGV_vUezoiNJjUMgIhAu4i9Je39ZVLHcuLb0gTYGfsOQxYG9pgZzQAq-x0URUbiHLtLHaxKRyPFOWW8tHi8hRJLAJov3kWUoec9NzDvuxYnwYw0XusM2g3JJme7xq7kudsdXoLRYEFd4YCq2w1dyIMnhf5GSNjvorcQ=s2048?key=w0JT2YPuotBsG_yBOQAAvg


In this particular case, it this doesn't matter as the other copy of the data is good.  When both copies are impacted, it may be possible to figure it out. e.g.
 

Block 27
30 30 B3 C7 00 B6 00 0C 00......
8A 42 B7 C8 01 38 B3 C8 .B...8..
01 38 B6 00 80 80 80 94 .8......
C5 C5 C5 C5 C5 C5 C5 C5 ........
80 80 80 80 80 80 80 C6 ........
C6 C6 80 80 80 80 80 80 ........
80 80 80 80 80 80 80 95 ........
C4 C4 C4 [44 != C4] C4 C4 C4 C4 ...D....
*** Block 27 copies don't match
BAD checksum=CD copy 1, expected 4D
BAD checksum=CC copy 2, expected CD
*** Block 27, both copies have BAD checksum

Here the last block has two bad copies.  In one copy the 5th last byte is >44 and the checksum is >CD and in the second copy the byte is >C4 and the checksum is >CC.  From the surrounding bytes, it is most likely to be >C4 and the checksum is >CD.  So even some unrecoverable errors can be recovered by hand.

  • Like 15
Link to comment
Share on other sites

On 6/16/2024 at 6:02 AM, khanivore said:

I've done some more tweaks to my tape tool (mltt-tape) and I can recover almost all of my bad recordings now.  Someone (Greg?) sent me a bunch of bad WAV files a couple of weeks ago and these are mostly all readable now.  Some of the errors I can't even figure out myself so have no way to write an algorithm for them.  e.g. There is a ONE bit somewhere in a sequence of ZEROs below but I can't be sure which bit the middle peak belongs to: 

AGV_vUezoiNJjUMgIhAu4i9Je39ZVLHcuLb0gTYGfsOQxYG9pgZzQAq-x0URUbiHLtLHaxKRyPFOWW8tHi8hRJLAJov3kWUoec9NzDvuxYnwYw0XusM2g3JJme7xq7kudsdXoLRYEFd4YCq2w1dyIMnhf5GSNjvorcQ=s2048?key=w0JT2YPuotBsG_yBOQAAvg

 

Looks like a string of ONE's not ZERO's. 

 

Saving the picture, I measured about 98 pixels per 2 positive peaks, which is my bit period.  So a half bit period is about 49 pixels.  Backing up about (49/2) pixels from the peak gives me a starting point and shows about what the DC offset is (it should cross the axis there, but doesn't).  Using my starting point and 49 pixels / half bit as a guide, I read off the values. Using 'u' (up) and 'd' (down) to represent each half bit value, I get the sequence:

udududududduddddduuddudu  (and yes, that last 'd' barely squeeks out as a 'd')

A ZERO is either two Up's 'uu' or two Down's 'dd'.  Using the first two down's, 'dd' to sychronize to the waveform, it appears the first 'u' is the second half of a ONE sequence. Throwing out that first half bit and the half bit at the end, I break the sequence into bits as:

du du du du dd ud dd dd uu dd ud

I then start to parse.
 
1-1-1-1-0-1-X-

My parse detects an error at the 'X' position. I know that the signal should be changing up and down in a certain way.  A ONE should be a 'ud' or a 'du'.  A ZERO should be a 'uu' or 'dd'.  So far, Ok. But 'X', which looks like a 'dd' should not follow a ONE which has a 'ud' pattern.  The half bit at the end of the prior bit, should be opposite of the half bit at the beginning of the next bit.  In other works, the '1-X' pattern, which is 'ud-dd' shouldn't exist because the waveform should change sides on each side of the '-'.  But in this waveform ('d-d') they dont change sides.

There are quite a few ways to try and fix this.  For this sample, I decided to work the pattern backwards.  Up to the error.  This gives me:

1-1-1-1-0-1-X-0-0-0-1

Now I look at the possible values that X could take and the possible patterns and see if only one makes sense.

X=0 ('dd', 'uu')
X=1 ('ud', 'du')

With X=0, the 1-X-0 sequence would be:
ud-dd-dd (this is what's actually seen in data and triggered an error as invalid pattern)
or
ud-uu-dd (This is an acceptable pattern)
So there is an acceptable pattern with X=0.

With X=1, the 1-X-0 sequence would be:
ud-ud-dd,  (Not acceptable, the last half bit of X=1 conflicts with the first half of the bit that follows it)
or
ud-du-dd, (Not acceptable, the first half of the X=1 conflicts with the last half of the bit the proceeds it)

So I get only one possibility, that X=0.

   1  1  1  1  0  1  0  0  0  0  1

Link to comment
Share on other sites

Have you tried getting the DC offset (your zerocross variable) by averaging your 64 samples instead of using (min+max)/2?  I would be curious to see if that makes any difference in bit recognition.

 

Disregard.  That would only work if you have an equal number of peaks on both sides, such as two 1 bits, or two zero bits.  An average wouldn't work with mixed bits, 01 or 10.

 

Edited by chris36
Link to comment
Share on other sites

7 hours ago, chris36 said:

Have you tried getting the DC offset (your zerocross variable) by averaging your 64 samples instead of using (min+max)/2?  I would be curious to see if that makes any difference in bit recognition.

 

Disregard.  That would only work if you have an equal number of peaks on both sides, such as two 1 bits, or two zero bits.  An average wouldn't work with mixed bits, 01 or 10.

 

Yeah that idea of 64 samples was that there will always be at least one top and one bottom peak in that range.  But now that you mention it, the average over any 64-sample window should be zero as any combination should have equal areas above and below so maybe worth a look.

Link to comment
Share on other sites

8 hours ago, chris36 said:

So I get only one possibility, that X=0.

   1  1  1  1  0  1  0  0  0  0  1

Very good, I like your logic.  I'll have to work through it a bit more.  I did consider storing unknown bits and then revisiting them later so for example if at the end of a string of half-1 bits, there are an odd number of symbols then that implies X must be a one since half-1's must exist in pairs.

But for now I'm hopeful that this kind of disturbance is rare enough that it won't hit both copies of a block, so the backup block can be used to recover the original.

  • Like 3
Link to comment
Share on other sites

12 hours ago, khanivore said:

Yeah that idea of 64 samples was that there will always be at least one top and one bottom peak in that range.  But now that you mention it, the average over any 64-sample window should be zero as any combination should have equal areas above and below so maybe worth a look.

I thought so at first glance, but if you have 01 or 10 then the number of up's or down's won't match the number of their opposite.  So the average wouldn't be zero.

Link to comment
Share on other sites

  • 2 weeks later...

I did some refactoring on this to add timing recovery and it works a lot better now.  There's also a link in the readme to a hosted version if anyone is interested.

  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...