Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- # coding: utf8
- import wave as wave_lib
- from array import array
- from functools import partial
- READ_FRAMES_PER_BLOCK = 64 * 1024
- OSCILLATOR_RATE = 14318180
- SAM_CPU_SLOW_DIVISOR = 16
- BIT0_LENGTH = 813 * SAM_CPU_SLOW_DIVISOR
- BIT1_LENGTH = 435 * SAM_CPU_SLOW_DIVISOR
- AVERAGE_BIT_LENGTH = (BIT0_LENGTH + BIT1_LENGTH) / 2
- class TapeError(Exception):
- pass
- def iter_samples(wave):
- samplewidth = wave.getsampwidth()
- try:
- typecode = {1: 'b', 2: 'h', 4: 'i'}[samplewidth]
- except KeyError:
- raise ValueError('Unsupported samplewidth: {0}'.format(samplewidth))
- for frames in iter(partial(wave.readframes, READ_FRAMES_PER_BLOCK), ''):
- for value in array(typecode, frames):
- yield value
- class PushbackIterator(object):
- NOTHING = object()
- def __init__(self, iterable):
- self.iterator = iter(iterable)
- self.pushed_value = self.NOTHING
- def __iter__(self):
- return self
- def next(self):
- result = self.pushed_value
- if result is self.NOTHING:
- return next(self.iterator)
- else:
- self.pushed_value = self.NOTHING
- return result
- def push_value(self, value):
- self.pushed_value = value
- class Tape(object):
- def __init__(self, filename):
- self.wave = wave_lib.open(filename)
- if self.wave.getnchannels() != 1:
- raise TapeError(
- 'unsupported number of channels: {0}'.format(
- self.wave.getnchannels()
- )
- )
- self.cycles_per_frame = OSCILLATOR_RATE / self.wave.getframerate()
- self.samples = PushbackIterator(iter_samples(self.wave))
- def __enter__(self):
- return self
- def __exit__(self, *_args):
- self.close()
- def close(self):
- self.wave.close()
- def pulse_in(self):
- length = self.cycles_per_frame
- sign = next(self.samples) < 0
- for sample in self.samples:
- if (sample < 0) != sign:
- self.samples.push_value(sample)
- break
- length += self.cycles_per_frame
- if length > (OSCILLATOR_RATE / 2):
- break
- return sign, length
- def bit_in(self):
- _, pulse1_width = self.pulse_in()
- while True:
- pulse0_width = pulse1_width
- phase, pulse1_width = self.pulse_in()
- cycle_width = pulse0_width + pulse1_width
- if phase and (BIT1_LENGTH / 2) <= cycle_width <= (BIT0_LENGTH * 2):
- break
- return int(cycle_width < AVERAGE_BIT_LENGTH)
- def byte_in(self):
- result = 0
- for _ in xrange(8):
- result = (result >> 1) | (0x80 if self.bit_in() else 0)
- return result
- def block_sync(self):
- byte = 0
- while True:
- byte = (byte >> 1) | (0x80 if self.bit_in() else 0)
- # print '{0:08b}'.format(byte)
- if byte == 0x3c:
- break
- def block_in(self):
- self.block_sync()
- block = [self.byte_in(), self.byte_in()]
- block.extend(self.byte_in() for _ in xrange(block[1]))
- expected_sum = self.byte_in()
- block_sum = sum(block) & 0xff
- if expected_sum != block_sum:
- print block
- raise TapeError(
- 'Wrong block checksum: expected {0}, got {1}'.format(
- expected_sum, block_sum
- )
- )
- block.append(expected_sum)
- return block
- def main():
- #filename = 'HelloWorld1 xroar.wav'
- filename = 'HelloWorld1 origin.wav'
- tape = Tape(filename)
- print tape.block_in()
- print tape.block_in()
- print tape.block_in()
- if __name__ == '__main__':
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement