New tape cleaner tool

Include new and ported/converted games, and old games/tools. Subjects about CP/M software goes in the CP/M Forum.
User avatar
thewiz
Posts: 137
Joined: 12 Aug 2012 16:08

Re: New tape cleaner tool

Post by thewiz »

Great work Bill.
THIS is what Memotech is doing now.
Martin A
Posts: 799
Joined: 09 Nov 2013 21:03

Re: New tape cleaner tool

Post by Martin A »

It's great to see someone getting somewhere with these, I've been sidetracked by another hardware project.
Bill B wrote: 30 Dec 2018 11:56 I assume that this is an earlier version of "Karate King 64" which is in Andy's distribution.
From a long distant memory, I seem to recall the 32k MTX500 version of the game was on one side of the tape, and a 64k version for the MTX512 or bigger was on the other.
Bill B
Posts: 593
Joined: 26 Jan 2014 16:31

Re: New tape cleaner tool

Post by Bill B »

Martin A wrote:I've been sidetracked by another hardware project.
So "spill the beans", your projects are always interesting.
Martin A
Posts: 799
Joined: 09 Nov 2013 21:03

Re: New tape cleaner tool

Post by Martin A »

Bill B wrote: 01 Jan 2019 15:23
Martin A wrote:I've been sidetracked by another hardware project.
So "spill the beans", your projects are always interesting.
I'll see what I can do photo wise (edit: see viewtopic.php?f=17&t=416). In the mean time these are the quick and dirty clean up tools in BBC Basic I did manage to write:

Program 1 - Decode the WAV file

Code: Select all

ON ERROR PROCe
VDU 22,06
filename$="@.WAVinput"
outfile$="@.output"
*spool @.dump
SYS "OS_File",13,filename$ TO ,,,,size%
PRINT "File Size ";size%;"(";~size%;")"
B%=OPENOUT outfile$
A%=OPENIN filename$
PROCdump(A%)
CLOSE#A%

A%=OPENIN filename$
PRINT "Header Data"
PRINT "Chunk ID       : ";FNinstr(A%,4)
PRINT "Chunk Size     : #";~FNinlong(A%)
type$=FNinstr(A%,4)

PRINT "Chunk Format   : ";type$
IF type$<>"WAVE" THEN ERROR &C0000,"Invalid file"
PRINT "Sub Chunk 1 ID : ";;FNinstr(A%,4)
PRINT "Sub Chunk Size : #";~FNinlong(A%)
PRINT "Audio Format   : ";FNinword(A%)
PRINT "Channels       : ";FNinword(A%)
rate%=FNinlong(A%)
PRINT "Sample Rate    : ";rate%

PRINT "Byte Rate      : ";FNinlong(A%)
PRINT "Block Align    : ";FNinword(A%)
bits%=FNinword(A%)
PRINT "Bits per Sample: ";bits%
PRINT "Sub Chunk 2 ID : ";;FNinstr(A%,4)
data%=FNinlong(A%)
PRINT "Sub Chunk Size : #";~data%
PRINT "Sample Data follows"
PRINT
one%=rate%/2400
zero%=rate%/1200
midval%=(one%+zero%)/2
PRINT"a 0 at 1200hz = ";zero%;" samples"
PRINT"a 1 at 2400hz = ";one%;" samples"
PRINT "Using ";midval%; " as middle value"
CASE bits% OF
WHEN 8:PROCdump8(data%,A%)
WHEN 16:PROCdump16(data%/2,A%)
OTHERWISE:ERROR &c0001,"Invalid sample length"
ENDCASE
*spool
*settype @.dump text
*settype @.output text
CLOSE#A%
CLOSE#B%
CHAIN "@.ToHex"
END

DEF PROCe
REPORT
PRINT"  at line ";ERL
*CLOSE
END

REM RAW DATA DUMP
DEF PROCdump(A%)
LOCAL X%,Y%,Z%,X$
FOR X%=0 TO 255 STEP 16
PRINTFNhex4(X%);" : ";
X$=": "
FOR Y%=0 TO 15
Z%=BGET#A%
PRINTFNhex2(Z%);" ";
IF Z%>127 THEN Z%-=128
IF Z%<32 OR Z%=127 THEN Z%=32
X$+=CHR$(Z%)
NEXT
PRINT X$
NEXT
ENDPROC

REM DUMP 8 BIT SAMPLES
DEF PROCdump8(X%,A%)
ENDPROC

REM DUMP 16 BIT SAMPLES
DEF PROCdump16(X%,A%)
LOCAL Y%,Z%,O%,M%,C%,S%,L%
O%=0
M%=60:C%=20
S%=0
FOR Y%=1 TO X%
Z%=FNinword(A%)
IF Z%>&7FFF THEN Z%=Z%-&FFFF
IF ABS(Z%)>M% THEN
M%=ABS(Z%)
C%=M%/3
PRINT "Peak volume increased to ";M%;" cut off increased to ";C%
ENDIF
IF ABS(Z%)<C% THEN Z%=0
REM P.Z%;
IF Z%<0 AND O%>=0 THEN
REM  PRINT "Negative edge: Sample ";Y%
  L%=Y%-S%
  IF L%>midval% THEN
      IF L%>1000 THEN BPUT#B%,10
    BPUT#B%,49
    IF L%>(zero%*2) THEN
      PRINT "Invalid 1 -  too long "; L%
    ELSE
      PRINT "1";
    ENDIF
  ELSE
    BPUT#B%,48
    IF L%<(one%/3) THEN
      PRINT "Invalid 0 - too short "; L%
    ELSE
      PRINT "0";
    ENDIF
  ENDIF
S%=Y%
ENDIF
O%=Z%
NEXT

ENDPROC

DEF FNhex2(Z%)
=RIGHT$("0"+STR$~Z%,2)

DEF FNhex4(Z%)
=RIGHT$("000"+STR$~Z%,4)

DEF FNinstr(X%,Y%)
LOCAL Z%,X$
X$=""
FOR Z%=1 TO Y%
X$+=CHR$(BGET#X%)
NEXT
=X$

DEF FNinlong(X%)
LOCAL Y%,Z%
Z%=0
FOR Y%=1 TO 4
Z%=Z%>>>8
Z%+=(BGET#X%)<<24
NEXT
=Z%


DEF FNinword(X%)
LOCAL Z%
Z%=BGET#X%
Z%+=(BGET#X%)<<8
=Z%
If the dynamic volume control detection doesn't help, that bit can be disabled, and C% the cut-off value can be set manually, and M% the maximum volume is ignored.

The output file is a string of decoded 0's and 1's something like this

Code: Select all

1000010000000001000000000000000000000000000000000000000000000000000000000000000001000100000000010000100000000000000000000000000000000000000000000000000000000000000000000000100000000001000100000000000000000000111001000000000010100000000000100000000011100001110000000000000000000000000000000110000000000011000000000001100000011111100000010100001111100110100000011
10101000011
111010010010000000001111010101111111000000000000000000011000000000011000011100101111100110101
1000011001100100
1010000000000000000000100111111110100111111111111101
111
1000100100000000000110110
1000100011
10000011110111
1000000100100000000001111
111
1
1
11
1
1
111
1
1
11
1
100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111110010100111001011110010111010100100001010000010001100100011001000000100000001000000010000000100000001000000010000000100010011110001111101110010111100100
I've cut this off at the end of the header, but you can see at the end the binary that there's the long block of zero's for timing, then something that could be an #FF byte followed by some ASCII

On screen, and also saved to the "dump" file is a report on the raw data

Code: Select all

File Size 21249836(1443F2C)File Size 21249836(1443F2C)
0000 : 52 49 46 46 24 3F 44 01 57 41 56 45 66 6D 74 20 : RIFF$?D WAVEfmt 
0010 : 10 00 00 00 01 00 01 00 00 7D 00 00 00 FA 00 00 :          }   z  
0020 : 02 00 10 00 64 61 74 61 00 3F 44 01 00 00 00 00 :     data ?D     
0030 : 00 00 00 00 FF FF 02 00 FF FF 00 00 00 00 FF FF :                 
0040 : 02 00 FF FF 00 00 00 00 00 00 00 00 00 00 01 00 :                 
0050 : FE FF 02 00 FF FF 00 00 01 00 FE FF 02 00 FE FF : ~         ~   ~ 
0060 : 03 00 FD FF 02 00 FE FF 02 00 FE FF 02 00 FF FF :   }   ~   ~     
0070 : 00 00 01 00 FE FF 02 00 FF FF 00 00 02 00 FD FF :     ~         } 
0080 : 03 00 FE FF 00 00 01 00 FF FF 01 00 00 00 FF FF :   ~             
0090 : 00 00 00 00 00 00 02 00 FD FF 02 00 FF FF FF FF :         }       
00A0 : 02 00 FF FF 00 00 01 00 FE FF 01 00 00 00 00 00 :         ~       
00B0 : 01 00 FD FF 04 00 FC FF 03 00 FF FF FF FF 02 00 :   }   |         
00C0 : FE FF 02 00 FE FF 02 00 FE FF 03 00 FC FF 04 00 : ~   ~   ~   |   
00D0 : FC FF 04 00 FD FF 02 00 FE FF 02 00 FE FF 02 00 : |   }   ~   ~   
00E0 : FE FF 01 00 00 00 FF FF 02 00 FE FF 01 00 FF FF : ~         ~     
00F0 : 01 00 00 00 FF FF 01 00 FF FF 01 00 00 00 00 00 :                 

Header Data
Chunk ID       : RIFF
Chunk Size     : #1443F24
Chunk Format   : WAVE
Sub Chunk 1 ID : fmt 
Sub Chunk Size : #10
Audio Format   : 1
Channels       : 1
Sample Rate    : 32000
Byte Rate      : 64000
Block Align    : 2
Bits per Sample: 16
Sub Chunk 2 ID : data
Sub Chunk Size : #1443F00

Sample Data follows
a 0 at 1200hz = 26 samples
a 1 at 2400hz = 13 samples
Using 19 as middle value
Invalid 1 -  too long 1205
0Invalid 0 - too short 2
001Invalid 0 - too short 2
00Invalid 0 - too short 4
00000100000Invalid 0 - too short 3
Invalid 0 - too short 2
0Invalid 0 - too short 2
00Invalid 0 - too short 3
000000Invalid 0 - too short 4
Invalid 0 - too short 4
00000Invalid 0 - too short 2
Invalid 0 - too short 3
Invalid 0 - too short 3
Invalid 0 - too short 2
Invalid 0 - too short 2
00Invalid 0 - too short 2
Invalid 0 - too short 3
Invalid 0 - too short 2
Invalid 0 - too short 3
0Invalid 0 - too short 4
Invalid 0 - too short 3
Invalid 0 - too short 2
Invalid 0 - too short 2
Invalid 0 - too short 4
0Invalid 0 - too short 3
Invalid 0 - too short 3
Invalid 0 - too short 2
Invalid 0 - too short 3
Invalid 0 - too short 2
00Invalid 0 - too short 4
Invalid 0 - too short 4
Invalid 0 - too short 2
000Invalid 0 - too short 4
Invalid 0 - too short 2
000Invalid 0 - too short 2
0Invalid 0 - too short 2
Invalid 0 - too short 2
100Invalid 0 - too short 2
Peak volume increased to 103 cut off increased to 34
1Invalid 0 - too short 2
Peak volume increased to 118 cut off increased to 39
000Invalid 0 - too short 3
000010Invalid 0 - too short 3
00100Invalid 0 - too short 2
Invalid 0 - too short 3
0Invalid 0 - too short 4
000Invalid 0 - too short 4
Invalid 0 - too short 2
Invalid 0 - too short 3
Invalid 0 - too short 2
Invalid 0 - too short 2
Invalid 0 - too short 2
Invalid 0 - too short 3
0Invalid 0 - too short 3
0Invalid 0 - too short 2
Invalid 0 - too short 3
Peak volume increased to 135 cut off increased to 45
Invalid 0 - too short 2
000Invalid 0 - too short 2
Invalid 0 - too short 3
Peak volume increased to 155 cut off increased to 51
Invalid 0 - too short 3
Invalid 0 - too short 3
0Invalid 0 - too short 3
0000000000Peak volume increased to 190 cut off increased to 63
Invalid 0 - too short 3
Invalid 0 - too short 3
Invalid 0 - too short 4
Invalid 0 - too short 4
Invalid 0 - too short 3
0Invalid 0 - too short 3
Peak volume increased to 203 cut off increased to 67
Invalid 0 - too short 3
0Invalid 0 - too short 4
0Invalid 0 - too short 4
0Invalid 0 - too short 3
Peak volume increased to 208 cut off increased to 69
Invalid 0 - too short 3
Both files are of course considerably longer than this!

Program 2 then takes the output file of 0's and 1's and attempt to produce a binary file

Code: Select all

ON ERROR PROCe
VDU 22,06
*spool @.byte
filename$="@.output"
A%=OPENIN filename$
Z%=OPENOUT "@.FILE/MTX"
F%=0
WHILE NOT F%
PROCscan0(A%)
PROCoutput(A%)
ENDWHILE
CLOSE#Z%
CLOSE#A%
*spool
*settype @.byte text
END

DEF PROCscan0(A%)
LOCAL B%,C%,D%
C%=0
D%=0
REPEAT
  IF NOT EOF#A% THEN
    B%=BGET#A%
    IF B%=ASC"0" THEN
      C%+=1
    ELSE
      IF B%=ASC"1" THEN
        IF C%>255 THEN
          D%=1
        ELSE
          C%=0
        ENDIF
      ELSE
        C%=0
      ENDIF
    ENDIF
  ELSE
    F%=1
    D%=1
  ENDIF
UNTIL D% OR EOF#A%
ENDPROC

DEF PROCoutput(A%)
LOCAL B%,C%,D%,V%,D$
D%=0
C%=0
V%=0
D$=""
REPEAT
  IF NOT EOF#A%
    B%=BGET#A%
    IF B%>=32 THEN
      D$=CHR$(B%)+D$
      V%+=(B%-48)<<C%
      C%+=1
      IF C%=8 THEN
        PRINT D$;" - ";RIGHT$("0"+STR$~V%,2);" ";
        BPUT#Z%,V%
        IF V%>32 AND V%<127 THEN VDU V%
        PRINT
        C%=0
        V%=0
        D$=""
      ENDIF
    ELSE
      PRINT
      PRINT"BREAK"
      VDU 7
      PRINT
      PRINT
      D%=1
    ENDIF
  ELSE
    F%=1
    D%=1
  ENDIF
UNTIL D% OR EOF#A%
ENDPROC



DEF PROCe
REPORT
PRINT"  at line ";ERL
*CLOSE
END
That outputs a possible MTX file to disc for testing, the on screen byte output is again saved for inspection, and on the test WAV starts like this:

Code: Select all

11111111 - FF 
01010011 - 53 S
01001110 - 4E N
01001111 - 4F O
01010111 - 57 W
01000010 - 42 B
01000001 - 41 A
01001100 - 4C L
01001100 - 4C L
00100000 - 20 
00100000 - 20 
00100000 - 20 
00100000 - 20 
00100000 - 20 
00100000 - 20 
00100000 - 20 
11110010 - F2 
11111000 - F8 
01001110 - 4E N
01001111 - 4F O

BREAK


00000000 - 00 
00000000 - 00 
00000000 - 00 
00000000 - 00 
00000000 - 00 
00000000 - 00 
00000000 - 00 
00000000 - 00 
There's no prizes fog guessing what the test WAV file was ! :D
User avatar
1024MAK
Posts: 757
Joined: 24 Dec 2012 03:01
Location: Looking forward to summer, in Somerset, UK

Re: New tape cleaner tool

Post by 1024MAK »

Martin A wrote: 01 Jan 2019 22:23 There's no prizes fog guessing what the test WAV file was ! :D
We’re sorry sir, your prize melted in the post...!
:!: Standby alert :!:
“There are four lights!”
Step up to red alert. Sir, are you absolutely sure? It does mean changing the bulb :!:
Looking forward to summer in Somerset later in the year :D

Not as many MTXs as Dave! :lol:
Bill B
Posts: 593
Joined: 26 Jan 2014 16:31

Re: New tape cleaner tool

Post by Bill B »

A work in progress. In order to make any progress on the remaining audio files I felt I need to be able to see what I am doing. I am therefore developing a "TapeView" program which can display the audio signal as well as decode it. Below shows testing on one of the files I had already made progress on "blind".

TapeView is written in C++. I am running it on Linux, but it is written using a cross-platform toolkit (wxWidgets), so it should be possible to compile it for Windows.

TapeView testing.
TapeView testing.
TapeView.png (51.32 KiB) Viewed 14417 times
Bill B
Posts: 593
Joined: 26 Jan 2014 16:31

Re: New tape cleaner tool

Post by Bill B »

A not so nice case, Spot the missing data bit :( This is why I thought visualisation would be helpful.

TapeView002.png
TapeView002.png (49.76 KiB) Viewed 14415 times
Bill B
Posts: 593
Joined: 26 Jan 2014 16:31

Re: New tape cleaner tool

Post by Bill B »

Doing threshold crossing on the slope of the original signal (lower curve) effectively picks out the peaks and troughs of the original values (upper curve). This seems to give some results.

This audio file seems to contain at least four programs "INTERUPT" "2*INTERUPTS", "INTER4" and "INTER5". My version of MEMU with audio file support will load the first three from the attached partially cleaned version. The last one fails with "SE.B" :(

They seem to be experiments with sprite animation from machine code, rather than anything complete. Paul can you advise?

TapeView003.png
TapeView003.png (50.68 KiB) Viewed 14411 times
Attachments
Interrupts.zip
(69.11 KiB) Downloaded 567 times
User avatar
1024MAK
Posts: 757
Joined: 24 Dec 2012 03:01
Location: Looking forward to summer, in Somerset, UK

Re: New tape cleaner tool

Post by 1024MAK »

Now where is that clapping smilie when you need it?

:D

Mark
:!: Standby alert :!:
“There are four lights!”
Step up to red alert. Sir, are you absolutely sure? It does mean changing the bulb :!:
Looking forward to summer in Somerset later in the year :D

Not as many MTXs as Dave! :lol:
Martin A
Posts: 799
Joined: 09 Nov 2013 21:03

Re: New tape cleaner tool

Post by Martin A »

That is clever, so much more readable output than my program's stream of 0s and 1s.
Post Reply