Created
October 4, 2012 19:55
-
-
Save jangler/3836002 to your computer and use it in GitHub Desktop.
Amiga module reader
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
periods = ( | |
1712,1616,1525,1440,1357,1281,1209,1141,1077,1017, 961, 907, | |
856, 808, 762, 720, 678, 640, 604, 570, 538, 508, 480, 453, | |
428, 404, 381, 360, 339, 320, 302, 285, 269, 254, 240, 226, | |
214, 202, 190, 180, 170, 160, 151, 143, 135, 127, 120, 113, | |
107, 101, 95, 90, 85, 80, 76, 71, 67, 64, 60, 57 | |
) | |
def sum_bytes(b): | |
result = 0 | |
for i in range(len(b)): | |
result += b[i] << (8 * i) | |
return result | |
def null_bytes(n): | |
result = [] | |
for i in range(0, n): | |
result.append(0) | |
return bytes(result) | |
class Sample: | |
def __init__(self): | |
pass | |
def read_header(self, f): | |
self.name = f.read(22) | |
self.length = f.read(2) | |
self.finetune = f.read(1) | |
self.volume = f.read(1) | |
self.offset = f.read(2) | |
self.repeat = f.read(2) | |
def read_data(self, f): | |
self.data = f.read(sum_bytes(self.length)) | |
def create_new(self): | |
self.name = null_bytes(22) | |
self.length = null_bytes(2) | |
self.finetune = null_bytes(1) | |
self.volume = null_bytes(1) | |
self.offset = null_bytes(2) | |
self.repeat = null_bytes(2) | |
self.data = null_bytes(0) | |
def write_header(self, f): | |
f.write(self.name) | |
f.write(self.length) | |
f.write(self.finetune) | |
f.write(self.volume) | |
f.write(self.offset) | |
f.write(self.repeat) | |
def write_data(self, f): | |
f.write(self.data) | |
class Division: | |
def __init__(self): | |
pass | |
def read(self, f): | |
data = f.read(4) | |
self.sample = (data[0] & 0xf0) | ((data[2] & 0xf0) >> 4) | |
self.period = ((data[0] & 0x0f) << 8) | data[1] | |
self.effect = ((data[2] & 0x0f) << 8) | data[3] | |
def create_new(self): | |
self.sample = 0 | |
self.period = 0 | |
self.effect = 0 | |
def write(self, f): | |
b0 = (self.sample & 0xf0) | ((self.period & 0xf00) >> 8) | |
b1 = self.period & 0xff | |
b2 = ((self.sample & 0x0f) << 4) | ((self.effect & 0xf00) >> 8) | |
b3 = self.effect & 0xff | |
f.write(bytes((b0, b1, b2, b3))) | |
class Pattern: | |
def __init__(self): | |
pass | |
def read(self, f): | |
self.divisions = [] | |
for d in range(0, 64): | |
self.divisions.append([]) | |
for c in range(0, 4): | |
div = Division() | |
div.read(f) | |
self.divisions[d].append(div) | |
def create_new(self): | |
self.divisions = [] | |
for d in range(0, 64): | |
self.divisions.append([]) | |
for c in range(0, 4): | |
div = Division() | |
div.create_new() | |
self.divisions[d].append(div) | |
def write(self, f): | |
for d in range(0, 64): | |
for c in range(0, 4): | |
self.divisions[d][c].write(f) | |
class Module: | |
def __init__(self): | |
pass | |
def read(self, f): | |
self.title = f.read(20) | |
self.samples = [] | |
for i in range(0, 31): | |
sample = Sample() | |
sample.read_header(f) | |
self.samples.append(sample) | |
self.num_positions = f.read(1) | |
self.restart_pos = f.read(1) | |
self.pattern_table = bytearray(f.read(128)) | |
self.num_patterns = 0 | |
for i in range(0, 128): | |
if self.pattern_table[i] > self.num_patterns: | |
self.num_patterns = self.pattern_table[i] | |
self.num_patterns += 1 | |
self.initials = f.read(4) | |
self.patterns = [] | |
for i in range(0, self.num_patterns): | |
pattern = Pattern() | |
pattern.read(f) | |
self.patterns.append(pattern) | |
for i in range(0, 31): | |
self.samples[i].read_data(f) | |
def create_new(self): | |
self.title = null_bytes(20) | |
self.samples = [] | |
for i in range(0, 31): | |
sample = Sample() | |
sample.create_new() | |
self.samples.append(sample) | |
self.num_positions = bytes([1]) | |
self.restart_pos = null_bytes(1) | |
self.pattern_table = bytearray(null_bytes(128)) | |
self.num_patterns = 1 | |
self.initials = bytes('M.K.', 'utf-8') | |
self.patterns = [] | |
for i in range(0, self.num_patterns): | |
pattern = Pattern() | |
pattern.create_new() | |
self.patterns.append(pattern) | |
def write(self, f): | |
f.write(self.title) | |
for i in range(0, 31): | |
self.samples[i].write_header(f) | |
f.write(self.num_positions) | |
f.write(self.restart_pos) | |
f.write(bytes(self.pattern_table)) | |
f.write(self.initials) | |
for i in range(0, self.num_patterns): | |
self.patterns[i].write(f) | |
for i in range(0, 31): | |
self.samples[i].write_data(f) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment