367 lines
12 KiB
Python
367 lines
12 KiB
Python
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)))
|
|
|
|
|
|
|