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: 117
Joined: 12 Aug 2012 16:08

Re: New tape cleaner tool

Post by thewiz » 31 Dec 2018 10:41

Great work Bill.
THIS is what Memotech is doing now.

Martin A
Posts: 334
Joined: 09 Nov 2013 21:03

Re: New tape cleaner tool

Post by Martin A » 01 Jan 2019 12:17

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: 134
Joined: 26 Jan 2014 16:31

Re: New tape cleaner tool

Post by Bill B » 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.

Martin A
Posts: 334
Joined: 09 Nov 2013 21:03

Re: New tape cleaner tool

Post by Martin A » 01 Jan 2019 22:23

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: 499
Joined: 24 Dec 2012 03:01
Location: Looking forward to summer, in Somerset, UK

Re: New tape cleaner tool

Post by 1024MAK » 02 Jan 2019 17:42

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...!

Post Reply