english greek

The Newbrain Forum

Anything about the Newbrain Home Computer

You are not logged in.

Add to: Mr. Wong Add to: Webnews Add to: Icio Add to: Oneview Add to: Folkd Add to: Yigg Add to: Linkarena Add to: Digg Add to: Del.icio.us Add to: Reddit Add to: Simpy Add to: StumbleUpon Add to: Slashdot Add to: Netscape Add to: Furl Add to: Yahoo Add to: Spurl Add to: Google Add to: Blinklist Add to: Blogmarks Add to: Diigo Add to: Technorati Add to: Newsvine Add to: Blinkbits Add to: Ma.Gnolia Add to: Smarking Add to: Netvouz Information

#1 09-02-2020 17:54:12

filbip
New member

(Hover for details)
Registered: 08-07-2015
Posts: 8
Reputation :   

Python digitalizer

Bonjour,
I managed to digitalize old tapes and encountered problems with the existing digitalizer.
I always received "ERROR 132" when reading these "tape" files from emulator. Even when digitalization was successful.

That's why I wrote this Python version. I am a beginner with Python but it is easy tu write a script that uses the wave library. The code is ugly but I could decode some of the old programs from audio cassettes.
I had the same problem of bad CRC (error 132) with raw "tape" version of files for emulator
That's why I ended converting decoded programs into disk version.
The "tape" version keeps the stream from the tape. The disk version is reordered and has no tape headers or leading zeroes.

I put it here for the record.
The script can be named degitalizeTape.py.
The input audio is PCM  signed 16bits, 44100 f/s in a file named "tape.wav".
The script can read many programs on one recorded wave file.


# digitalize.py for Grundy Newbrain tapes # reads a test.wav file (44100, 16bit signed) as input
# writes a file <name>.bas # # The record on tape is made of blocks
# The first block contains only the name of the file
# Each following block contains a maximum of 1024 bytes of data/program
# data are in reverse order on tape blocks
# structure of a block:
#   many "pilot" sequences: longHigh-shortLow-shortHigh-longLow
#                         or longLow-shortHigh-shortLow-longHigh
#   1 zero byte
#   2 bytes containing the length of data in block
#   n bytes of data (up to 1024)
#   3 bytes crc??
#   9 zero bytes, end of block
#
import wave
with wave.open("tape.wav", "rb") as wav_file:    # Open WAV file in read-only mode.
   # Get basic information.
   n_channels = wav_file.getnchannels()      # Number of channels. (1=Mono, 2=Stereo).
   sample_width = wav_file.getsampwidth()    # Sample width in bytes.
   framerate = wav_file.getframerate()       # Frame rate.
   n_frames = wav_file.getnframes()          # Number of frames.
   comp_type = wav_file.getcomptype()        # Compression type (only supports "NONE").
   comp_name = wav_file.getcompname()        # Compression name.

   print("channels=", n_channels,  sep='')
   print("framerate=", framerate, sep='')
   print("n_frames=", n_frames,  sep='')

   prevVal = -1
   cnt=0
   bit=""
   bitPos=0
   bitString = bytearray('0000000000', 'ascii')
   nBlock=0
   nPilot=0
   nZero=0
   blockLen=0
   blockBuf=""
   filename=""
   nFile=0
   fSign=0
   
   def getName(): # Extract name in block #1
       global blockBuf, blockLen, filename, nFile
       filename=""
       nameLen = ord(blockBuf[2])*256 + ord(blockBuf[1])
       if nameLen > 0:
           i = 0
           while i < nameLen:
               filename += blockBuf[3+i]
               i += 1
       else:
            nFile += 1
            filename="unknown"+str(nFile)
       print("name =",filename, nameLen, "blockLen =", blockLen)
       filename += ".bas"
       return
       
   def blockFound(): # End of block reached. Write block to file
       global blockBuf, blockLen, nBlock, filename, outFile
       if nBlock == 1: # first block, filename
           if blockLen < 80: # Not a first block if too large
               getName()
               print("filename =",filename)
               outFile=open(filename, "wb")
               outFile.close()
           else:   
               nBlock=0 # Ready to read another file
       else:
           dataLen = ord(blockBuf[2])*256 + ord(blockBuf[1])
           print("writing block", nBlock, "length",dataLen)
           outFile=open(filename, "ab")
           i = dataLen+3
           while i > 3: # block recorded in reverse order on tape !! Reordered here
               i -= 1
               ch=ord(blockBuf[i])
               outFile.write(ch.to_bytes(1, byteorder='big'))
           outFile.close()
           if blockLen < 1024: # Last block < 1024bytes
               nBlock=0 # Ready to read another file
       return

   def byteFound(): # Ten bits: 1xxxxxxxx0
       global bitString,  nZero
       global nPilot,  blockLen,  blockBuf, nBlock
       if bitString[0] == 1 and bitString[9] == 0:
           n=bitString[1]*128+bitString[2]*64+bitString[3]*32+bitString[4]*16+bitString[5]*8+bitString[6]*4+bitString[7]*2+bitString[8]
           blockLen += 1
           blockBuf += chr(n)
           if n == 0:
               nZero += 1
               if nZero > 8:
                   print("end of block",nBlock,"found, length", blockLen)
                   nZero=0
                   nPilot=0
                   blockFound()
                   blockBuf=""
                   blockLen=0
           else:
               nZero=0
       else:
           print("ERROR",bitString)
           nZero=0
           nPilot=0
           blockBuf=""
           blockLen=0
           nBlock=0
       return

   def bitFound(bitVal):
       global bitPos
       global bitString
       bitString[bitPos]=bitVal
       bitPos=bitPos+1
       if bitPos == 10:
           byteFound()
           bitPos = 0
       return

   def chunkFound(length, level):
   #
   # Chunks are
   # short low value  (s)
   # short high value (S)
   # long low value   (l)
   # long high value  (L)
   #
   # short if less than 14 frames else long... Simple
   #
   # pilot (many before blocks): "LsSl"
   # bit zero: "Ll"
   # bit one:  "SsSs"
   #
       global bit,  bitPos
       global nPilot,  nBlock,  inHeader,  blockLen,  blockBuf, fSign
       chunk=" "
       if length < 14:
            #type=short
           if (level == 1):
               chunk="S"
           else:
               chunk="s"
       else:
           #type=long
           if (level == 1):
               chunk="L"
           else:
               chunk="l"
       bit += chunk
       #print ("bit", bit, len(bit))
       if (bit=="LsSl" or bit=="lSsL"):
           if nPilot == 0:
               print("pilots",bit,"frame",  fn)
               nBlock += 1
               blockLen=0
               blockBuf=""
               if fSign == 0: # No sign change once found
                   if bit=="LsSl":
                       fSign=1
                   else:
                       fSign=-1
           nPilot += 1
           bitPos = 0
           bit=""
       if nPilot:
           if fSign==1: # Pilot beginning was high value, bits too
               if (bit=="Ll"):
                   #print("    found ZERO",  fn)
                   bitFound(0)
                   bit=""
               if (bit=="SsSs"):
                   #print("    found ONE",  fn)
                   bitFound(1)
                   bit=""
               if (len(bit)==2):
                   if (bit!="Ll" and bit!="Ss" and bit!="Ls"):
                       #print("throw", bit,  fn)
                       bit=chunk
                       bitPos=0
           else: # Pilot beginning was low value, bits too
               if (bit=="lL"):
                   #print("    found ZERO",  fn)
                   bitFound(0)
                   bit=""
               if (bit=="sSsS"):
                   #print("    found ONE",  fn)
                   bitFound(1)
                   bit=""
               if (len(bit)==2):
                   if (bit!="lL" and bit!="sS" and bit!="lS"):
                       #print("throw", bit,  fn)
                       bit=chunk
                       bitPos=0
       else: # searching pilot
           if (len(bit)==2):
               if (bit!="lS" and bit!="Ls"):
                   #print("throw", bit,  fn)
                   bit=chunk
                   bitPos=0
       if (len(bit) > 3):
           #print("throw", bit,  fn)
           bit=chunk
           bitPos=0
       return

   for fn in range(1, n_frames):
      frame = int.from_bytes(wav_file.readframes(1), byteorder='little', signed=True)   # Read 1 new frame.
      if (frame > 3000):
          val=1
      else:
           if (frame < -3000):
               val=-1
           else:
               val=0
      if (prevVal != val):
           if (cnt >3):
             #print(fn, cnt, prevVal)
             chunkFound(cnt, prevVal)
           prevVal=val
           cnt=1
      else:
           cnt=cnt+1

 


Add to: Mr. Wong Add to: Webnews Add to: Icio Add to: Oneview Add to: Folkd Add to: Yigg Add to: Linkarena Add to: Digg Add to: Del.icio.us Add to: Reddit Add to: Simpy Add to: StumbleUpon Add to: Slashdot Add to: Netscape Add to: Furl Add to: Yahoo Add to: Spurl Add to: Google Add to: Blinklist Add to: Blogmarks Add to: Diigo Add to: Technorati Add to: Newsvine Add to: Blinkbits Add to: Ma.Gnolia Add to: Smarking Add to: Netvouz Information

Forum Tools

Board information

Board statistics
Total number of registered users: 141
Total number of topics: 105
Total number of polls: 0
Total number of posts: 376
User information
Newest registered user: pigivi
Registered users online: 1
Guests online: 1048
Online: 
ellvis

Powered by Agora 1.0.4 Acropolis

© Copyright 2007 - 2008 Joomla Me!. All rights reserved.

Powered by Elxis - Open Source CMS.
Copyright (C) 2006-2020 Elxis.org. All rights reserved.