Initial Commit

This commit is contained in:
Martin 2022-07-21 23:36:47 +02:00
commit 971e0b8038
1 changed files with 366 additions and 0 deletions

366
WAV2TAP.py Normal file
View File

@ -0,0 +1,366 @@
from tkinter import *
from tkinter import filedialog
from random import *
from scipy.io import wavfile #pip install scipy
import matplotlib.pyplot as plt
import os
PlotErrors = False
def wavfile_to_examples(wav_file):
"""Convenience wrapper around waveform_to_examples() for a common WAV format.
Args:
wav_file: String path to a file, or a file-like object. The file
is assumed to contain WAV audio data with signed 16-bit PCM samples.
Returns:
See waveform_to_examples.
"""
try:
sr, wav_data = wavfile.read(wav_file)
except IOError:
print("Error reading WAV file!")
print("The specified WAV file type is not supported by scipy.io.wavfile.read()")
sys.exit(1)
#if wav_data.dtype != np.int16:
# raise TypeError('Bad sample type: %r' % wav_data.dtype)
samples = wav_data / 32768.0 # Convert to [-1.0, +1.0]
return samples, sr
def DecodeTime(aT):
if aT > (1/250): # Silent
Bit = 'S'
else:
if aT > (1/800):
Bit = 'T'
else:
if aT > (1/1500):
Bit = '1'
else:
if aT > (1/3000):
Bit = '0'
else:
Bit = 'E'
return Bit
def GetName(aBlock):
if aBlock[0] == 1:
NameBlock = []
if aBlock[1] == 0xD3: # BASIC
for Byte in aBlock[4:12]:
if Byte != 0:
NameBlock.append(Byte)
else: # CHAOS
for Byte in aBlock[1:9]:
if Byte != 0:
NameBlock.append(Byte)
Name = ''.join([''.join(chr(ch)) for ch in NameBlock])
Name.replace('&','n')
else:
Name = ''
print(Name)
return Name.strip()
def WriteTAB(aBlocks, aFilename):
with open(aFilename,'wb') as TAB_file:
TAB_file.write(b'\xC3KC-TAPE by AF. ') # C3 4B 43 2D 54 41 50 45 20 62 79 20 41 46 2E 20
#Block = [b''.join(ch) for ch in aBlocks[0]]
for Block in aBlocks:
Bytes = bytes(Block[0:-1])
TAB_file.write(Bytes)
def WriteTABs(aBlocks, aPath):
Index = 1
NewFile = False
Filename = 'Errors.TAP'
TAB_file = open(Filename,"wb")
TAB_file.close()
for Block in aBlocks:
if not (len(Block) == 130):
print('Bad Block')
if Block[0] == 1:
Filename = os.path.join(aPath,str(Index).zfill(3) + '_' + GetName(Block) + '.TAP')
Index = Index + 1
NewFile = True
if NewFile:
if TAB_file.closed:
TAB_file = open(Filename,"wb")
else:
TAB_file.close()
TAB_file = open(Filename,"wb")
NewFile = False
if not TAB_file.closed:
Bytes = bytes(Block)
TAB_file.write(Bytes)
if Block[0] == 0xFF:
TAB_file.close()
def WriteRAW(aBlocks, aFilename):
with open(aFilename,'wb') as RAW_file:
for Block in aBlocks:
try:
Bytes = bytes(Block)
except:
print(Block)
RAW_file.write(Bytes)
#Block = [1, 211, 211, 211, 72]
#Block2 = bytes(Block) #[b''.join(bytes(abyte)) for abyte in Block]
fenster = Tk()
fenster.filename = ""
fenster.filename = filedialog.askopenfilename(initialdir = "", title = "Select file", filetypes =(("wav files","*.wav"),("all files","*")))
print(fenster.filename)
filename = fenster.filename
fenster.destroy()
if os.path.exists(filename) and not (os.path.isdir(filename)):
File = os.path.splitext(filename)[0]
Ext = os.path.splitext(filename)[1]
OutputFile = File + ".TAP"
RawFile = File + ".RAW"
Samples, Rate = wavfile_to_examples(filename)
#print(Samples[1:1000,0])
print('Samplerate: ',Rate)
AmplitudeL = 0;
BestChannel = 0;
for data in Samples[0:4410000]: #100s
if abs(data[0]) > AmplitudeL:
AmplitudeL = abs(data[0]);
print('Amplitude Links:',AmplitudeL)
AmplitudeR = 0;
for data in Samples[0:4410000]: #100s
if abs(data[1]) > AmplitudeR:
AmplitudeR = abs(data[1]);
print('Amplitude Rechts:',AmplitudeR)
if AmplitudeR > AmplitudeL:
BestChannel = 1;
Bitstream = []
Periode1 = 0
Periode2 = 0
LastData1 = 0
LastData2 = 0
LastData3 = 0
LastData4 = 0
LastData5 = 0
LastData = 0
NextData = 0
Min1 = 1.0
Max1 = -1.0
Min2 = 1.0
Max2 = -1.0
CalcSpeedError = True;
Speedfaktor = 1.0
EinsCount = 0
EinsTime = 0.0
UseDecoder = 0
EnableDecoder1 = True # Damit er nicht 2x bei der steigenden Flanke auslöst
EnableDecoder2 = True
SampeNr = -1
for data in Samples:
SampeNr = SampeNr + 1
Periode1 = Periode1 + 1
Periode2 = Periode2 + 1
Ellongation = data[BestChannel]
if Min1 > Ellongation:
Min1 = Ellongation
if Max1 < Ellongation:
Max1 = Ellongation
Zero1 = Min1 + ((Max1 - Min1) / 2)
if Min2 > Ellongation:
Min2 = Ellongation
if Max2 < Ellongation:
Max2 = Ellongation
Zero2 = Min2 + ((Max2 - Min2) / 2)
LastData = (LastData3 + LastData4 + LastData5) / 3
NextData = (Ellongation + LastData1 + LastData2) /3
if (Periode2 > 8) and (Zero2 > LastData) and (Zero2 < NextData):
EnableDecoder2 = True
if (EnableDecoder2) and (Periode2 > 8) and (Zero2 < LastData) and (Zero2 > NextData):
T = (Periode2 / Rate) * Speedfaktor
Periode2 = 0
EnableDecoder2 = False
EnableDecoder1 = True
Min2 = Ellongation
Max2 = Ellongation
Bit = DecodeTime(T);
if (UseDecoder == 0) and (Bit == 'T'):
UseDecoder = 2
#print('Decoder 2')
if UseDecoder == 2:
Bitstream.append([Bit,SampeNr-2]) # Nullstelle Speichern
if (Periode1 > 8) and (Zero1 < LastData) and (Zero1 > NextData):
EnableDecoder1 = True
if (EnableDecoder1) and (Periode1 > 8) and (Zero1 > LastData) and (Zero1 < NextData):
T = (Periode1 / Rate) * Speedfaktor
#print(Periode, Min, Max, Zero, LastData1, Ellongation )
Periode1 = 0
EnableDecoder1 = False
EnableDecoder2 = True
Min1 = Ellongation
Max1 = Ellongation
Bit = DecodeTime(T);
if (UseDecoder == 0) and (Bit == 'T'):
UseDecoder = 1
#print('Decoder 1')
if UseDecoder <= 1:
Bitstream.append([Bit,SampeNr-2]) # Nullstelle Speichern
if Bit == '1':
EinsCount = EinsCount + 1
EinsTime = EinsTime + T
if (EinsCount == 50):
UseDecoder = 0
EnableDecoder1 = True
EnableDecoder2 = True
if (CalcSpeedError):
Speedfaktor = (1/1200) / (EinsTime / EinsCount)
CalcSpeedError = False
else:
EinsCount = 0
EinsTime = 0.0
LastData5 = LastData4
LastData4 = LastData3
LastData3 = LastData2
LastData2 = LastData1
LastData1 = Ellongation
print('Speedfaktor = ', Speedfaktor)
#print(Bitstream[0:100])
EinsCount = 0;
FileFound = False
Blocknummer = 1
Bytenummer = 0
Block = []
Blocks = []
Byte = 0
Bitcounter = 0;
BlockFound = False;
BitstreamIndex = -1;
for Bit in Bitstream:
BitstreamIndex = BitstreamIndex + 1
if (Bit[0] == '1') :
EinsCount = EinsCount + 1
if (Bitcounter < 8):
#Byte = Byte | (1 << Bitcounter) # hier stehen die ersten bits richtig wenn nur 7bit
Byte = (Byte >> 1) | 0x80 # hier stehen die letzten bits richtig wenn nur 7bit
Bitcounter = Bitcounter + 1
else:
if (Bit[0] != 'T'):
EinsCount = 0
if Bit[0] == '0':
Byte = (Byte >> 1) # hier stehen die letzten bits richtig wenn nur 7bit
Bitcounter = Bitcounter + 1
#if Bit[0] == 'E':
# print('Fehlerhaftes Bit')
#if Bit[0] == 'S':
# print('Stille')
if (EinsCount > 300) and (Bit[0] == 'T'): #Newfile
FileFound = True;
print('File Found')
File = []
Block = []
BlockFound = False
Blocknummer = 1
Bytenummer = 0
IndexFehlerhaft = 0
if FileFound:
if ((Bytenummer == 130)):
if (Blocknummer == 1):
Name = [''.join(chr(ch)) for ch in Block[1:12]]
print(''.join(Name))
#print(chr(Block[1]))
Blocks.append(Block)
summe = 0
for byte in Block[1:-1]:
summe = summe + byte
summe = summe & 0xFF
if summe != Block [-1]:
print('%d Summe %d NOK Read %d' % (Block [0], summe, Block [-1]))
print(Block)
if (IndexFehlerhaft > 0) and (IndexFehlerhaft < 129):
print('Fehlerhaftes Byte konnte identifiziert werden', IndexFehlerhaft)
print('Gelesen wurde: ', Block[IndexFehlerhaft-1])
Block[IndexFehlerhaft-1] = (Block[IndexFehlerhaft-1] + ((Block[-1] - summe) & 0xFF)) & 0xFF
print('Sollte laut Summe sein: ', Block[IndexFehlerhaft-1])
summe = 0
for byte in Block[1:-1]:
summe = summe + byte
summe = summe & 0xFF
if summe == Block [-1]:
print('Korrigiert!')
else:
print('Mehr als einn Byte Fehlerhaft')
else:
print('%d OK' % Block [0])
#Name = [''.join(chr(ch)) for ch in Block[1:-1]]
#print(''.join(Name))
if Block[0] == 0xFF:
FileFound = False
Block = []
Blocknummer = Blocknummer + 1;
Bytenummer = 0
IndexFehlerhaft = 0
BlockFound = False
#print('Block ',Blocknummer)
if (not BlockFound) and (EinsCount > 50) and (Bit[0] == 'T'): # neuer Block
Bitcounter = 0
Bytenummer = 0
Byte = 0
BlockFound = True
else:
if Bit[0] == 'T' and BlockFound:
Block.append(Byte & 0xFF)
Bytenummer = Bytenummer + 1;
Byte = 0
if Bitcounter != 8:
print('Fehlerhafte Bytelänge %d im Block %d und Byte %d' % (Bitcounter,Blocknummer,Bytenummer))
if IndexFehlerhaft == 0:
IndexFehlerhaft = Bytenummer
else:
IndexFehlerhaft = -1
Bytelaenge = round(11*Rate/1200)
Stuetzstellen = [Bitstream[X][1] for X in range(BitstreamIndex-11, BitstreamIndex+1)]
Stuetzbits = ''.join([Bitstream[X][0] for X in range(BitstreamIndex-11, BitstreamIndex+1)])
#print(Stuetzstellen)
if PlotErrors:
plt.plot([X for X in range((Bit[1]-Bytelaenge),(Bit[1]))],Samples[(Bit[1]-Bytelaenge):(Bit[1]),BestChannel], "-b" , label=(('1/%d' % round(1200*Speedfaktor))+ Stuetzbits))
plt.plot(Stuetzstellen, [Samples[X,BestChannel] for X in Stuetzstellen], "or")# [Samples[Y,BestChannel] for Y in Bitstream[BitstreamIndex-11: BitstreamIndex+1][1]], "or")
plt.legend(loc='upper right')
plt.show()
Bitcounter = 0
#if Bit[0] == 'S':
# FileFound = False;
#print(Blocks)
#WriteTAB(Blocks, OutputFile)
WriteRAW(Blocks, RawFile)
WriteTABs(Blocks, os.path.dirname(os.path.abspath(OutputFile)))