Working for text files, errors on binary files
This commit is contained in:
		
							
								
								
									
										71
									
								
								decode.py
									
									
									
									
									
								
							
							
						
						
									
										71
									
								
								decode.py
									
									
									
									
									
								
							@@ -33,6 +33,7 @@ VERSION = '0.1'
 | 
			
		||||
DESCRIPTION = 'Decodes a file using the manchester encoding'
 | 
			
		||||
 | 
			
		||||
FRAME_DELIMITER = 126 # (01111110)
 | 
			
		||||
FRAME_DELIMITER_EVERY_BYTES = 64
 | 
			
		||||
PREAMBLE_DURATION = 128
 | 
			
		||||
ZERO_POINT = 0 # The 0 value: values less than this are considered 0, more than this 1
 | 
			
		||||
 | 
			
		||||
@@ -46,17 +47,21 @@ class Main:
 | 
			
		||||
		# Open input audio file
 | 
			
		||||
		self.audioSource = wave.open(inputFile,'r')
 | 
			
		||||
 | 
			
		||||
		try:
 | 
			
		||||
			self.syncWithClock()
 | 
			
		||||
			self._log.info("Sync: clock duration is {}".format(self.clockDuration))
 | 
			
		||||
			self.waitForStart()
 | 
			
		||||
			#self._log.info("Found start of data")
 | 
			
		||||
		except ValueError as e:
 | 
			
		||||
			self._log.error("Ran out of input data before completing initialization!")
 | 
			
		||||
		# Open output file
 | 
			
		||||
		with open(outputFile,'wb') as outf:
 | 
			
		||||
			self.outputSink = outf
 | 
			
		||||
 | 
			
		||||
		#self.decodeFile()
 | 
			
		||||
			try:
 | 
			
		||||
				self.syncWithClock()
 | 
			
		||||
				self._log.info("Found clock: clock duration is {}".format(self.clockDuration))
 | 
			
		||||
				self.waitForStart()
 | 
			
		||||
				self._log.info("Synced to first byte: start decoding actual data")
 | 
			
		||||
				self.decodeActualData()
 | 
			
		||||
			except ValueError as e:
 | 
			
		||||
				self._log.error("Ran out of input data before completing initialization!")
 | 
			
		||||
 | 
			
		||||
		self.audioSource.close()
 | 
			
		||||
		self.outputSink.close()
 | 
			
		||||
 | 
			
		||||
	def syncWithClock(self):
 | 
			
		||||
		# Uses the preamble to obtain the clock duration
 | 
			
		||||
@@ -88,13 +93,53 @@ class Main:
 | 
			
		||||
				self._log.info("Found first frame delimiter")
 | 
			
		||||
				return
 | 
			
		||||
 | 
			
		||||
	#def decodeFile():
 | 
			
		||||
		# From the bit after the FRAME_DELIMITER on, there is the real data. Decode and write to file
 | 
			
		||||
	def decodeActualData(self):
 | 
			
		||||
		# From the bit after the FRAME_DELIMITER on, there is the actual data. Decode at groups of 8 bytes and write to file
 | 
			
		||||
		position = 0 # We already consumed the first delimiter
 | 
			
		||||
		try:
 | 
			
		||||
			while True:
 | 
			
		||||
				expectFrameDelimiter = position > 0 and position % FRAME_DELIMITER_EVERY_BYTES == 0
 | 
			
		||||
				if expectFrameDelimiter:
 | 
			
		||||
					decodedByte = self.decodeByte(True)
 | 
			
		||||
					if decodedByte != FRAME_DELIMITER:
 | 
			
		||||
						raise ValueError('Expecting a frame delimiter, found {}'.format(decodedByte))
 | 
			
		||||
					self._log.info('Found frame delimiter')
 | 
			
		||||
 | 
			
		||||
		#try:
 | 
			
		||||
				decodedByte = self.decodeByte(False)
 | 
			
		||||
				try:
 | 
			
		||||
					self.outputSink.write(bytes([decodedByte]))
 | 
			
		||||
				except Exception as e:
 | 
			
		||||
					self._log.error(e)
 | 
			
		||||
				position = position + 1
 | 
			
		||||
 | 
			
		||||
		except ValueError as e:
 | 
			
		||||
			# Stream finished
 | 
			
		||||
			# If last byte isn't a frame delimiter, throw error
 | 
			
		||||
			self._log.info(e)
 | 
			
		||||
 | 
			
		||||
	def decodeByte(self, expectFrameDelimiter=False):
 | 
			
		||||
		# Decodes a byte (to be used _after_ the first frame delimiter was found)
 | 
			
		||||
		decodedByte = 0
 | 
			
		||||
		for x in range(8):
 | 
			
		||||
			value = self.decodeBit()
 | 
			
		||||
 | 
			
		||||
			# Shift the byte to left
 | 
			
		||||
			decodedByte = decodedByte >> 1
 | 
			
		||||
 | 
			
		||||
			# Truncate the length to 8 bits
 | 
			
		||||
			decodedByte = decodedByte & 255 # 0 11111111
 | 
			
		||||
			# Add the read bit in the least significant position
 | 
			
		||||
			if value:
 | 
			
		||||
				decodedByte = decodedByte + 128 #10000000
 | 
			
		||||
 | 
			
		||||
			if decodedByte == 248 and not expectFrameDelimiter: # 248 = 11111000
 | 
			
		||||
				self._log.info("Here")
 | 
			
		||||
				# We found 5 1s: ignore next 0: has been added to avoid a real 01111110 byte to be interpreted as frame delimiter
 | 
			
		||||
				if self.decodeBit():
 | 
			
		||||
					# Should be 0!
 | 
			
		||||
					raise ValueError('Found xx0111111 while not expecting a delimiter!')
 | 
			
		||||
		return decodedByte
 | 
			
		||||
 | 
			
		||||
		#except ValueError as e:
 | 
			
		||||
			# Completed reading file
 | 
			
		||||
 | 
			
		||||
	def decodeBit(self):
 | 
			
		||||
		# Decodes a bit. Searches for the phase invertion at 75% to 125% of the clock cycle
 | 
			
		||||
 
 | 
			
		||||
@@ -33,6 +33,7 @@ VERSION = '0.1'
 | 
			
		||||
DESCRIPTION = 'Encodes a file using the manchester encoding and outputs it as audio file'
 | 
			
		||||
 | 
			
		||||
FRAME_DELIMITER = 126 # (01111110)
 | 
			
		||||
FRAME_DELIMITER_EVERY_BYTES = 64
 | 
			
		||||
PREAMBLE_DURATION = 128
 | 
			
		||||
AUDIO_VOLUME = 16384 # 0 to 32767
 | 
			
		||||
AUDIO_BITRATE = 44100
 | 
			
		||||
@@ -69,13 +70,13 @@ class Main:
 | 
			
		||||
				if not byte:
 | 
			
		||||
					# Finished reading file
 | 
			
		||||
					# Terminate with delimiter and exit
 | 
			
		||||
					self.encodeByte(FRAME_DELIMITER, encode_frame_delimiter=False)
 | 
			
		||||
					#self.encodeByte(FRAME_DELIMITER, encode_frame_delimiter=False)
 | 
			
		||||
					break
 | 
			
		||||
				byte = byte[0]
 | 
			
		||||
 | 
			
		||||
				# Every 64 bytes, outputs a frame delimiter: 01111110
 | 
			
		||||
				# This is used by receiver to syncronize to the start of a byte
 | 
			
		||||
				if position % 64 == 0:
 | 
			
		||||
				if position % FRAME_DELIMITER_EVERY_BYTES == 0:
 | 
			
		||||
					self.encodeByte(FRAME_DELIMITER, encode_frame_delimiter=False)
 | 
			
		||||
				position = position + 1
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user